/**
 * @brief PrepareData
 *
 *  Prepare data to be written to file
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void PrepareData(BackupDataType *data)
{
  _backup_u8_ *ptr;
  _backup_u32_ driverVer;
  
  driverVer = (_backup_u32_)UG31XX_DRIVER_VERSION;
  UG31_LOGN("[%s]: Driver version = %d (%d)\n", __func__, (int)driverVer, UG31XX_DRIVER_VERSION);

  upi_memcpy(&data->backupCustomerSelfDef[0], (_backup_u8_ *)&data->sysData->ggbParameter->customerSelfDef, CELL_PARAMETER_STRING_LENGTH);
  UG31_LOGN("[%s]: CustomerSelfDef = %s\n", __func__,
            data->backupCustomerSelfDef);
  upi_memcpy(&data->backupProjectSelfDef[0], (_backup_u8_ *)&data->sysData->ggbParameter->projectSelfDef, CELL_PARAMETER_STRING_LENGTH);
  UG31_LOGN("[%s]: ProjectSelfDef = %s\n", __func__,
            data->backupProjectSelfDef);
  
  ptr = data->backupBuffer;
  upi_memcpy(ptr, (_backup_u8_ *)data->capData->encriptTable, (_upi_u32_)data->capData->tableSize);
  ptr = ptr + data->capData->tableSize;
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->rmFromIC, sizeof(data->sysData->rmFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->rmFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->fccFromIC, sizeof(data->sysData->fccFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->fccFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->timeTagFromIC, sizeof(data->sysData->timeTagFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->timeTagFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->tableUpdateIdxFromIC, sizeof(data->sysData->tableUpdateIdxFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->tableUpdateIdxFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->deltaCapFromIC, sizeof(data->sysData->deltaCapFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->deltaCapFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->adc1ConvTime, sizeof(data->sysData->adc1ConvTime)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->adc1ConvTime)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->rsocFromIC, sizeof(data->sysData->rsocFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->rsocFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->cycleCount, sizeof(data->sysData->cycleCount)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->cycleCount)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->ccOffset, sizeof(data->sysData->ccOffset)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->ccOffset)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->predictRsoc, sizeof(data->sysData->predictRsoc)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->predictRsoc)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->standbyDsgRatio, sizeof(data->sysData->standbyDsgRatio)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->standbyDsgRatio)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->backupVolt1, sizeof(data->backupVolt1)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->backupVolt1)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->backupVolt2, sizeof(data->backupVolt2)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->backupVolt2)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->capData->preDsgCharge, sizeof(data->capData->preDsgCharge)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->capData->preDsgCharge)/sizeof(_backup_u8_);
  upi_memcpy(ptr, &data->backupCustomerSelfDef[0], CELL_PARAMETER_STRING_LENGTH);
  ptr = ptr + CELL_PARAMETER_STRING_LENGTH;
  upi_memcpy(ptr, &data->backupProjectSelfDef[0], CELL_PARAMETER_STRING_LENGTH);
  ptr = ptr + CELL_PARAMETER_STRING_LENGTH;
  upi_memcpy(ptr, (_backup_u8_ *)&driverVer, sizeof(driverVer)/sizeof(_backup_u8_));
}
/**
 * @brief UpiWriteSuspendResumeData
 *
 *  Write suspend / resume data to file
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void UpiWriteSuspendResumeData(BackupDataType *data)
{
  _backup_bool_ rtn;
  _backup_u8_ *buf;
  _backup_u32_ size;
  _backup_u32_ cmpResult;

  size = sizeof(BackupSuspendDataType)*BACKUP_MAX_LOG_SUSPEND_DATA;
  #ifndef UG31XX_SHELL_ALGORITHM
    buf = (_backup_u8_ *)&UpiWriteSuspendResumeData_buf[0];
  #else   ///< else of UG31XX_SHELL_ALGORITHM
    buf = (_backup_u8_ *)upi_malloc(size);
  #endif  ///< end of UG31XX_SHELL_ALGORITHM

  #if defined (uG31xx_OS_WINDOWS)
    rtn = read_backup_file(data->suspendFileName, (_upi_u8_ *)buf, size);
  #else  ///< else of defined (uG31xx_OS_WINDOWS)
    rtn = read_backup_file(ptrSuspendFileName, (_upi_u8_ *)buf, size);
  #endif ///< end of defined (uG31xx_OS_WINDOWS)
  UG31_LOGN("[%s]: Read suspend / resume data from file -> %d\n", __func__, rtn);
  
  if(rtn != _UPI_TRUE_)
  {
    #if defined (uG31xx_OS_WINDOWS)
      rtn = write_backup_file(data->suspendFileName, (_upi_u8_ *)(&data->backupSuspendData[0]), size);
    #else  ///< else of defined (uG31xx_OS_WINDOWS)
      rtn = write_backup_file(ptrSuspendFileName, (_upi_u8_ *)(&data->backupSuspendData[0]), size);
    #endif ///< end of defined (uG31xx_OS_WINDOWS)
    UG31_LOGN("[%s]: Write suspend / resume data to file -> %d\n", __func__, rtn);
    #ifdef  UG31XX_SHELL_ALGORITHM
      upi_free(buf);
    #endif  ///< end of UG31XX_SHELL_ALGORITHM
    return;
  }

  cmpResult = upi_memcmp(buf, (_backup_u8_ *)(&data->backupSuspendData[0]), size);
  UG31_LOGN("[%s]: Compare suspend / resume data with file -> %d\n", __func__, (int)cmpResult);
  
  if(cmpResult != 0)
  {
    #if defined (uG31xx_OS_WINDOWS)
      rtn = write_backup_file(data->suspendFileName, (_upi_u8_ *)(&data->backupSuspendData[0]), size);
    #else  ///< else of defined (uG31xx_OS_WINDOWS)
      rtn = write_backup_file(ptrSuspendFileName, (_upi_u8_ *)(&data->backupSuspendData[0]), size);
    #endif ///< end of defined (uG31xx_OS_WINDOWS)
    UG31_LOGN("[%s]: Write suspend / resume data to file -> %d\n", __func__, rtn);
  }
  #ifdef  UG31XX_SHELL_ALGORITHM
    upi_free(buf);
  #endif  ///< end of UG31XX_SHELL_ALGORITHM
}
/**
 * @brief UpiBackupVoltage
 *
 *  Backup voltage points for abnormal battery checking
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void UpiBackupVoltage(BackupDataType *data)
{
  _backup_s32_ tmp32;

  /// [AT-PM] : Cumulate delta Q ; 01/22/2014
  tmp32 = (_backup_s32_)data->measData->stepCap;
  tmp32 = tmp32*data->measData->curr;
  if(tmp32 < 0)
  {
    tmp32 = 0;
  }
  else
  {
    tmp32 = (_backup_s32_)data->measData->stepCap;
  }
  tmp32 = tmp32 + data->backupDeltaQ;
  data->backupDeltaQ = (_backup_u16_)tmp32;

  /// [AT-PM] : Update voltage point 1 ; 01/22/2014
  data->backupVolt1 = (_backup_u16_)data->measData->bat1Voltage;
  UG31_LOGN("[%s]: Update backup voltage point 1 = %d (%d)\n", __func__, data->backupVolt1, data->backupDeltaQ);
  
  /// [AT-PM] : Check delta Q ; 01/22/2014
  tmp32 = data->sysData->ggbParameter->ILMD;
  tmp32 = tmp32*BACKUP_VOLTAGE_DELTA_Q_THRESHOLD/CONST_PERCENTAGE;
  if(data->backupDeltaQ < 0)
  {
    tmp32 = tmp32*(-1);
    if(data->backupDeltaQ > tmp32)
    {
      UG31_LOGN("[%s]: data->backupDeltaQ not reach threshold %d\n", __func__, tmp32);
      return;
    }
  }
  else
  {
    if(data->backupDeltaQ < tmp32)
    {
      UG31_LOGN("[%s]: data->backupDeltaQ not reach threshold %d\n", __func__, tmp32);
      return;
    }
  }

  /// [AT-PM] : Update voltage point 2 ; 01/22/2014
  data->backupVolt2 = data->backupVolt1;
  data->backupDeltaQ = 0;
  UG31_LOGI("[%s]: Update backup voltage point 2 = %d (%d)\n", __func__, data->backupVolt1, data->backupDeltaQ);
}
/**
 * @brief CreateBackupBuffer
 *
 *  Create buffer for backup file operation
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void CreateBackupBuffer(BackupDataType *data)
{
  /// [AT-PM] : Count total size to be written to file ; 07/12/2013
  data->backupBufferSize = data->capData->tableSize;
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->rmFromIC);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->fccFromIC);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->timeTagFromIC);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->tableUpdateIdxFromIC);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->deltaCapFromIC);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->adc1ConvTime);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->rsocFromIC);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->cycleCount);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->ccOffset);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->predictRsoc);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->sysData->standbyDsgRatio);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->backupVolt1);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->backupVolt2);
  data->backupBufferSize = data->backupBufferSize + sizeof(data->capData->preDsgCharge);
  data->backupBufferSize = data->backupBufferSize + CELL_PARAMETER_STRING_LENGTH;
  data->backupBufferSize = data->backupBufferSize + CELL_PARAMETER_STRING_LENGTH;
  data->backupBufferSize = data->backupBufferSize + sizeof(_backup_u32_);     ///< [AT-PM] : Used for driver version ; 11/07/2013
  UG31_LOGN("[%s]: Total %d bytes need to be created for written to file.\n", __func__, data->backupBufferSize);

  /// [AT-PM] : Set memory buffer ; 07/12/2013
  if(data->backupBufferSize > MAX_BACKUP_BUFFER_SIZE)
  {
    UG31_LOGE("[%s]: Exceed maximum backup buffer size\n", __func__);
    data->backupBufferSize = MAX_BACKUP_BUFFER_SIZE;
  }
  upi_memset(data->backupBuffer, 0, (_upi_u32_)data->backupBufferSize);
}
/**
 * @brief UpiSaveResumeData
 *
 *  Save resume data for backup
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void UpiSaveResumeData(BackupDataType *data)
{
  data->backupSuspendData[data->backupSuspendIdx].afterCapData = *(data->capData);
  data->backupSuspendData[data->backupSuspendIdx].afterMeasData = *(data->measData);
  UG31_LOGN("[%s]: Save resume data to buffer %d\n", __func__, data->backupSuspendIdx);

  data->backupSuspendIdx = data->backupSuspendIdx + 1;
  if(data->backupSuspendIdx >= BACKUP_MAX_LOG_SUSPEND_DATA)
  {
    data->backupSuspendIdx = 0;
    while(data->backupSuspendIdx < (BACKUP_MAX_LOG_SUSPEND_DATA - 1))
    {
      upi_memcpy(&data->backupSuspendData[data->backupSuspendIdx], 
                 &data->backupSuspendData[data->backupSuspendIdx + 1], 
                 sizeof(BackupSuspendDataType));
      data->backupSuspendIdx = data->backupSuspendIdx + 1;
    }

    upi_memset(&data->backupSuspendData[data->backupSuspendIdx], 0, sizeof(BackupSuspendDataType));
    UG31_LOGN("[%s]: Next suspend / resume data buffer is %d\n", __func__, data->backupSuspendIdx);
  }
}
/**
 * @brief UpiFreeBackupData
 *
 *  Free memory for BackupDataType
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void UpiFreeBackupData(BackupDataType *data)
{
  /// [AT-PM] : Memory buffer for backup file ; 12/03/2013

  /// [AT-PM] : Memory buffer for suspend/resume data ; 12/03/2013
  data->backupSuspendIdx = BACKUP_MAX_LOG_SUSPEND_DATA;
  while(data->backupSuspendIdx)
  {
    data->backupSuspendIdx = data->backupSuspendIdx - 1;
    UG31_LOGN("[%s]: data->backupSuspendData[%d] = %d\n", __func__, 
              data->backupSuspendIdx, (int)&data->backupSuspendData[data->backupSuspendIdx]);
  }
}
void read_file(struct file *fp, _upi_u8_ *data, _upi_u8_ size)
{  
  mm_segment_t oldFS;
  loff_t pos;
  _upi_s32_ rtn;
  _upi_u8_ idx;

  oldFS = get_fs();
  set_fs(get_ds());

  pos = 0;
  idx = 0;
  rtn = 1;
  UG31_LOGN("[%s]: Read file ->", __func__);
  while(idx < size)
  {
    rtn = (_upi_s32_)vfs_read(fp, (char *)(&data[idx]), 1, &pos);
    ug31_printk(LOG_LEVEL_NOTICE, " %02x", data[idx]);
    
    idx = idx + 1;
    if(rtn != 1)
    {
      break;
    }
  }
  ug31_printk(LOG_LEVEL_NOTICE, "\n");

  if(rtn != 1)
  {
    UG31_LOGE("[%s]: Read file fail.\n", __func__);
  }
  else
  {
    UG31_LOGN("[%s]: Read %d (%d) bytes from file\n", __func__, idx, size);
  }

  set_fs(oldFS);
}
/**
 * @brief UpiInitBackupData
 *
 *  Initialize memory buffer of BackupDataType structure
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void UpiInitBackupData(BackupDataType *data)
{
  /// [AT-PM] : Backup data in GGB file ; 12/10/2013
  data->backupNacLmdAdjustCfg = (_backup_u32_)data->sysData->ggbParameter->NacLmdAdjustCfg;
  
  /// [AT-PM] : Memory buffer for backup file ; 12/03/2013
  data->backupFileRetryCnt = 0;
  CreateBackupBuffer(data);

  /// [AT-PM] : Memory buffer for suspend/resume data ; 12/03/2013
  data->backupSuspendIdx = BACKUP_MAX_LOG_SUSPEND_DATA;
  while(data->backupSuspendIdx)
  {
    data->backupSuspendIdx = data->backupSuspendIdx - 1;
    upi_memset(&data->backupSuspendData[data->backupSuspendIdx], 0, sizeof(BackupSuspendDataType));
    UG31_LOGN("[%s]: data->backupSuspendData[%d] = %d\n", __func__, 
              data->backupSuspendIdx, (int)(&data->backupSuspendData[data->backupSuspendIdx]));
  }

  /// [AT-PM] : Initialize backup voltage variables ; 01/24/2014
  data->backupVolt1 = 0;
  data->backupVolt2 = 0;
  data->backupDeltaQ = 0;
}
  extern _upi_bool_ write_backup_file(char *filename, _upi_u8_ *data, _upi_u32_ size)
#endif  ///< end of uG31xx_OS_WINDOWS
{
  #ifndef uG31xx_BOOT_LOADER
  
    #ifndef CONFIG_ASUS_ENGINEER_MODE

    #ifdef  UG31XX_USE_SHELL_AP_FOR_FILE_OP
  
      struct subprocess_info *sub_info;
      char *argv[] = {shell_ap_name, "BACKUP_FILE", "WRITE", filename, NULL};
      char *env[] = {NULL};
      int rtn;
    
      sub_info = NULL;
      sub_info = call_usermodehelper_setup(argv[0], argv, env, GFP_ATOMIC);
      if(sub_info == NULL)
      {
        return (_UPI_FALSE_);
      }
      UG31_LOGN("[%s]: call_usermodehelper_setup() done (%d - %d - %d)\n", __func__, (int)sub_info, (int)data, (int)size);
    
      rtn = call_usermodehelper_exec(sub_info, UMH_WAIT_PROC);
      UG31_LOGN("[%s]: call_usermodehelper_exec() = %d\n", __func__, rtn);
      return ((rtn == 0) ? _UPI_TRUE_ : _UPI_FALSE_);
  
    #else   ///< else of UG31XX_USE_SHELL_AP_FOR_FILE_OP

      #ifdef  UG31XX_USE_DAEMON_AP_FOR_FILE_OP

        if(get_file_op_status() & UG31XX_KERNEL_FILE_FINISH)
        {
          clear_file_op_status_bit(UG31XX_KERNEL_FILE_EXIST);
          clear_file_op_status_bit(UG31XX_KERNEL_FILE_READ);
          set_file_op_status_bit(UG31XX_KERNEL_FILE_WRITE);
          return (_UPI_FALSE_);
        }

        if(get_file_op_status() & UG31XX_USER_FILE_WRITE)
        {
          clear_file_op_status_bit(UG31XX_KERNEL_FILE_EXIST);
          clear_file_op_status_bit(UG31XX_KERNEL_FILE_WRITE);
          set_file_op_status_bit(UG31XX_KERNEL_FILE_READ);
          set_file_op_status_bit(UG31XX_KERNEL_FILE_FINISH);
          return (_UPI_TRUE_);
        }
        
        clear_file_op_status_bit(UG31XX_KERNEL_FILE_EXIST);
        clear_file_op_status_bit(UG31XX_KERNEL_FILE_READ);
        set_file_op_status_bit(UG31XX_KERNEL_FILE_WRITE);
        set_file_op_status_bit(UG31XX_KERNEL_FILE_FINISH);
        return (_UPI_FALSE_);

      #else   ///< else of UG31XX_USE_DAEMON_AP_FOR_FILE_OP
      
        struct file *fp;
        _upi_u8_ retry;
        
        retry = 3;
        while(retry)
        {
          fp = filp_open(filename, O_CREAT | O_RDWR, 0644);
          if(!is_err(fp))
          {
            break;
          }
        
          retry = retry - 1;
        }
        if(retry == 0)
        {
          return (_UPI_FALSE_);
        }
        
        /// [AT-PM] : Write data to file ; 02/21/2013
        write_file(fp, data, size);

        filp_close(fp, _UPI_NULL_);

      #endif  ///< end of UG31XX_USE_DAEMON_AP_FOR_FILE_OP

    #endif  ///< end of UG31XX_USE_SHELL_AP_FOR_FILE_OP
    
    #else
    int backup_tag = BACKUP_BATTERY_KEY;
    if (ug31xx_save_config_data("ug31xx", data, size)) {
        UG31_LOGE("[%s]: fail to write Intel UMIP data\n", __func__);
        return (_UPI_FALSE_);
    }
    return (_UPI_TRUE_);
    #endif

  #endif  ///< end of uG31xx_BOOT_LOADER
  
  return (_UPI_TRUE_);
}
  _upi_bool_ is_file_exist(char *filename)
#endif  ///< end of uG31xx_OS_WINDOWS
{
  #ifndef uG31xx_BOOT_LOADER

    #ifndef CONFIG_ASUS_ENGINEER_MODE

    #ifdef  UG31XX_USE_SHELL_AP_FOR_FILE_OP

      struct subprocess_info *sub_info;
      char *argv[] = {shell_ap_name, "BACKUP_FILE", "EXIST", filename, NULL};
      char *env[] = {NULL};
      int rtn;

      sub_info = NULL;
      sub_info = call_usermodehelper_setup(argv[0], argv, env, GFP_ATOMIC);
      if(sub_info == NULL)
      {
        return (_UPI_FALSE_);
      }
      UG31_LOGN("[%s]: call_usermodehelper_setup() done (%d)\n", __func__, (int)sub_info);

      rtn = call_usermodehelper_exec(sub_info, UMH_WAIT_PROC);
      UG31_LOGN("[%s]: call_usermodehelper_exec() = %d\n", __func__, rtn);
      return ((rtn == 0) ? _UPI_TRUE_ : _UPI_FALSE_);
      
    #else   ///< else of UG31XX_USE_SHELL_AP_FOR_FILE_OP

      #ifdef  UG31XX_USE_DAEMON_AP_FOR_FILE_OP

        if(get_file_op_status() & UG31XX_KERNEL_FILE_FINISH)
        {
          set_file_op_status_bit(UG31XX_KERNEL_FILE_EXIST);
          return (_UPI_FALSE_);
        }

        if(get_file_op_status() & UG31XX_USER_FILE_EXIST)
        {
          clear_file_op_status_bit(UG31XX_KERNEL_FILE_EXIST);
          set_file_op_status_bit(UG31XX_KERNEL_FILE_READ);
          set_file_op_status_bit(UG31XX_KERNEL_FILE_FINISH);
          return (_UPI_TRUE_);        
        }

        set_file_op_status_bit(UG31XX_KERNEL_FILE_EXIST);
        set_file_op_status_bit(UG31XX_KERNEL_FILE_FINISH);
        return (_UPI_FALSE_);
        
      #else   ///< else of UG31XX_USE_DAEMON_AP_FOR_FILE_OP
      
        struct file *fp;
        _upi_u8_ retry;
        
        retry = 3;
        while(retry)
        {
          fp = filp_open(filename, O_RDONLY, 0644);
          if(!is_err(fp))
          {
            break;
          }
        
          retry = retry - 1;
        }
        if(retry == 0)
        {
          return (_UPI_FALSE_);
        }

        filp_close(fp, _UPI_NULL_);

      #endif  ///< end of UG31XX_USE_DAEMON_AP_FOR_FILE_OP
      
    #endif  ///< end of UG31XX_USE_SHELL_AP_FOR_FILE_OP
    
    #else
    _upi_u8_ backup_tag = 0;
    if (ug31xx_read_backup_tag("ug31xx", &backup_tag))
        return (_UPI_FALSE_);
    if (backup_tag != BACKUP_BATTERY_KEY)
        return (_UPI_FALSE_);
    return (_UPI_TRUE_);
    #endif

  #endif  ///< end of uG31xx_BOOT_LOADER
  
  return (_UPI_TRUE_);
}
/**
 * @brief UpiSaveSuspendData
 *
 *  Save suspend data for backup
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void UpiSaveSuspendData(BackupDataType *data)
{
  data->backupSuspendData[data->backupSuspendIdx].beforeCapData = *(data->capData);
  data->backupSuspendData[data->backupSuspendIdx].beforeMeasData = *(data->measData);  
  UG31_LOGN("[%s]: Save suspend data to buffer %d\n", __func__, data->backupSuspendIdx);
}
/**
 * @brief UpiBackupData
 *
 *  Backup data from IC to system routine
 *
 * @para  data  address of BackupDataType
 * @return  _UPI_NULL_
 */
void UpiBackupData(BackupDataType *data)
{
  _backup_bool_ rtnBool;
  _backup_u8_ rtnU8;

  #ifndef UG31XX_BACKUP_FILE_ENABLE
    rtnBool = _UPI_TRUE_;
    data->backupFileSts = BACKUP_FILE_STS_COMPARE;
  #endif  ///< end of UG31XX_BACKUP_FILE_ENABLE
  
  switch(data->backupFileSts)
  {
    case  BACKUP_FILE_STS_CHECKING:
      /// [AT-PM] : Check backup file existed or not ; 02/21/2013
      rtnBool = is_file_exist(data->backupFileName);
      UG31_LOGN("[%s]: is_file_exist() = %d.\n", __func__, rtnBool);
      if(rtnBool == BACKUP_BOOL_TRUE)
      {
        data->backupFileSts = BACKUP_FILE_STS_EXIST;
        data->backupFileRetryCnt = 0;
      }
      else
      {
        data->backupFileRetryCnt = data->backupFileRetryCnt + 1;
        UG31_LOGN("[%s]: Check backup file retry count = %d\n", __func__, data->backupFileRetryCnt);
        if(data->backupFileRetryCnt > RETRY_CHECKING_THRESHOLD)
        {
          data->backupFileSts = BACKUP_FILE_STS_NOT_EXIST;
          UG31_LOGE("[%s]: Backup file is not exist.\n", __func__);
        }
      }
      break;
    case  BACKUP_FILE_STS_NOT_EXIST:
      /// [AT-PM] : Create backup file ; 02/21/2013
      PrepareData(data);
      rtnBool = create_backup_file(data->backupFileName, data->backupBuffer, data->backupBufferSize);
      UG31_LOGN("[%s]: create_backup_file() = %d.\n", __func__, rtnBool);
      if(rtnBool == BACKUP_BOOL_TRUE)
      {
        data->backupFileSts = BACKUP_FILE_STS_EXIST;
        data->icDataAvailable = BACKUP_BOOL_TRUE;
      }
      else
      {
        UG31_LOGE("[%s]: Create backup file fail.\n", __func__);
      }
      break;
    case  BACKUP_FILE_STS_EXIST:
      data->backupFileSts = BACKUP_FILE_STS_COMPARE;
    case  BACKUP_FILE_STS_COMPARE:
      if(data->icDataAvailable == BACKUP_BOOL_TRUE)
      {
        /// [AT-PM] : Check content of file is consist with IC or not ; 02/21/2013
        rtnU8 = CheckBackupFile(data);
        UG31_LOGN("[%s]: CheckBackupFile() = %d.\n", __func__, rtnU8);
        if(rtnU8 == CHECK_BACKUP_FILE_STS_VERSION_MISMATCH)
        {
          data->backupFileSts = BACKUP_FILE_STS_UPDATE_BY_VERSION;
        }
        else if(rtnU8 == CHECK_BACKUP_FILE_STS_NEED_UPDATE)
        {
          data->backupFileSts = BACKUP_FILE_STS_UPDATE;
        }
        else if(rtnU8 == CHECK_BACKUP_FILE_STS_PASS)
        {
          data->backupFileSts = BACKUP_FILE_STS_COMPARE;
        }
        else
        {
          data->backupFileSts = BACKUP_FILE_STS_UPDATE;
        }
      }
      else
      {
        data->backupFileSts = BACKUP_FILE_STS_CHECKING;
      }
      break;
    case  BACKUP_FILE_STS_UPDATE:
    case  BACKUP_FILE_STS_UPDATE_BY_VERSION:
      if(data->icDataAvailable == BACKUP_BOOL_TRUE)
      {
        rtnU8 = UpdateBackupFile(data);
        UG31_LOGN("[%s]: UpdateBackupFile() = %d.\n", __func__, rtnU8);
        if(rtnU8 == CHECK_BACKUP_FILE_STS_PASS)
        {
          if(data->backupFileSts == BACKUP_FILE_STS_UPDATE_BY_VERSION)
          {
            data->backupFileSts = BACKUP_FILE_STS_VERSION_MISMATCH;
          }
          else
          {
            data->backupFileSts = BACKUP_FILE_STS_COMPARE;
          }
        }
      }
      else
      {
        data->backupFileSts = BACKUP_FILE_STS_CHECKING;
      }
      break;
    default:
      /// [AT-PM] : Un-known state ; 02/21/2013
      data->backupFileSts = BACKUP_FILE_STS_NOT_EXIST;
      break;
  }
}
/**
 * @brief CheckBackupFile
 *
 *  Check backup file is consisted with IC or not
 *
 * @para  data  address of BackupDataType
 * @return  CHECK_BACKUP_FILE_STS
 */
_backup_u8_ CheckBackupFile(BackupDataType *data)
{
  CapacityDataType *orgCapData;
  SystemDataType *orgSysData;
  _upi_bool_ rtn;
  _backup_u32_ driverVer;
  _backup_u8_ rtnU8;
  _backup_u16_ volt1;
  _backup_u16_ volt2;

  /// [AT-PM] : Create buffer ; 02/21/2013
  #ifndef UG31XX_SHELL_ALGORITHM
    orgCapData = &CheckBackupFile_orgCapData;
    orgSysData = &CheckBackupFile_orgSysData;
  #else   ///< else of UG31XX_SHELL_ALGORITHM
    orgCapData = (CapacityDataType *)upi_malloc(sizeof(CapacityDataType));
    orgSysData = (SystemDataType *)upi_malloc(sizeof(SystemDataType));
  #endif  ///< end of UG31XX_SHELL_ALGORITHM
  upi_memcpy(orgCapData, data->capData, sizeof(CapacityDataType));
  upi_memcpy(orgSysData, data->sysData, sizeof(SystemDataType));
  volt1 = data->backupVolt1;
  volt2 = data->backupVolt2;

  /// [AT-PM] : Get data from file ; 02/21/2013
  rtn = read_backup_file(data->backupFileName, data->backupBuffer, data->backupBufferSize);
  if(rtn == _UPI_FALSE_)
  {
    UG31_LOGD("[%s]: Read data from backup file fail.\n", __func__);
    #ifdef  UG31XX_SHELL_ALGORITHM
      upi_free(orgCapData);
      upi_free(orgSysData);
    #endif  ///< end of UG31XX_SHELL_ALGORITHM
    return (CHECK_BACKUP_FILE_STS_READ_FAIL);
  }
  driverVer = ConvertData(data);

  /// [AT-PM] : Following information is not checked ; 02/21/2013
  data->sysData->rmFromIC = orgSysData->rmFromIC;
  data->sysData->timeTagFromIC = orgSysData->timeTagFromIC;
  data->sysData->deltaCapFromIC = orgSysData->deltaCapFromIC;
  data->sysData->adc1ConvTime = orgSysData->adc1ConvTime;
  data->capData->preDsgCharge = orgCapData->preDsgCharge;
  
  /// [AT-PM] : Check data ; 02/21/2013
  if(driverVer != UG31XX_DRIVER_VERSION)
  {
    UG31_LOGN("[%s]: Backup file version mismatched.\n", __func__);
    rtnU8 = CHECK_BACKUP_FILE_STS_VERSION_MISMATCH;
  }
  else if((upi_memcmp(data->backupCustomerSelfDef, data->sysData->ggbParameter->customerSelfDef, CELL_PARAMETER_STRING_LENGTH) != 0) ||
           (upi_memcmp(data->backupProjectSelfDef, data->sysData->ggbParameter->projectSelfDef, CELL_PARAMETER_STRING_LENGTH) != 0))
  {
    UG31_LOGN("[%s]: Backup file cell information mismatched.\n", __func__);
    rtnU8 = CHECK_BACKUP_FILE_STS_VERSION_MISMATCH;
  }
  else if((upi_memcmp(orgCapData, data->capData, sizeof(CapacityDataType)) != 0) ||
          (upi_memcmp(orgSysData, data->sysData, sizeof(SystemDataType)) != 0) ||
          (volt1 != data->backupVolt1) ||
          (volt2 != data->backupVolt2))
  {
    UG31_LOGN("[%s]: Backup file needs to be updated\n", __func__);
    rtnU8 = CHECK_BACKUP_FILE_STS_NEED_UPDATE;
  }
  else
  {
    rtnU8 = CHECK_BACKUP_FILE_STS_PASS;
  }
  #ifdef  UG31XX_SHELL_ALGORITHM
    upi_free(orgCapData);
    upi_free(orgSysData);
  #endif  ///< end of UG31XX_SHELL_ALGORITHM
  return (rtnU8);
}