Skip to content

# 6.6. J6X OTA升级端介绍

J6X 对外提供 libupdate.so，其中包含升级所需API， API定义请参考 OTA api

## 6.6.1. ota_tool 使用

ota_tool 是使用 libupdate.so API 实现的一个工具，用于板端手动发起OTA升级。ota_tool 可作为 OTA Service 开发时的 Sample 参考，代码位于 hbre/otaupdate/src/ota_tool。

    ota_tool Usage:
       -v, --version                      get this library's version,
                                              system version,
                                              antirollback version
       -b, --boot                         check ota update status when boot.
       -s, --setpartition [partition]     set A/B slot partition, 0--A; 1--B.
       -g, --getpartition                 get A/B slot partition, 0--A; 1--B.
       -p, --package [package_path]       specify the path of package, the package paths can be relative or absolute, it's length must be smaller than 64 bytes.
       -n, --noreboot                     request ota without reboot.
       -c, --checksign                    signature check.
       -i, --signature                    signature information file.
       -f, --force                        reboot to recovery mode and start force upgrading automatically.
       -h, --help                         Display this help screen.

使用ota_tool进行升级前，需要将OTA升级包上传至板端。

参数介绍：

- -h 用于获取帮助信息

- -v 用于获取 libupdate.so 版本、当前系统软件版本、antirollback版本

- -b 用于启动升级结果检查（系统启动后会自动启动，用户无需关心）

- -s 设置下次启动 A/B slot

- -g 获取当前 A/B slot

- -p 指定升级包

- -n 升级成功后不自动重启

- -c 使能签名检查

- -i 指定签名文件（必须跟在-p后面）

- -f 强制进入recovery模式升级

举例：

    ota_tool -p all_in_one_full.zip

## 6.6.2. ota_tool 实现

ota_tool 使用C语言实现，源码仅 otainterface.c 一个文件。 实现了获取系统软件版本、升级结果检查、设置/获取ab slot、OTA升级、强制升级、OTA包签名校验等功能。

main函数前半部分都在解析参数，如果-f参数传入，则调用 otarecovery_command_write 将升级包信息写入文件 /ota/ota_tool_force_upgrade 后重启SoC。

若-c参数传入，则使用传入的签名文件对升级包进行签名校验。

最后，调用 ota_update_all_img 启动升级。

### 6.6.2.1. ota_update_all_img

    static int32_t ota_update_all_img(const char *zip_path)
    {
         int32_t progress = 0;

         uint8_t             slot = 0;
         uint8_t             next_slot = 0;
         int32_t             ret = 0;
         ota_update_result_e result = 0;
         char                part_name[ARRAY_32] = { 0 };

         ret = otaGetPartition(&slot);
         if (ret < 0) {
                 return ret;
         }

         if (slot == 2) {
                 next_slot = 0;
                 printf("The slot [%d] to be burned\n", next_slot);
         } else {
                 next_slot = 1 - slot;
                 printf("The slot [%d] to be burned\n", next_slot);
         }

         ret = otaInitLib();
         if (ret < 0) {
                 printf("error:init failed!\n");
                 return ret;
         }

         ret = otaRequestStart(zip_path, OTA_TOOL);
         if (ret < 0) {
                 printf("error: start ota update failed!\n");
                 ret = -1;
                 goto err;
         }
         while (otaGetResult() != OTA_UPGRADE_SUCCESS && otaGetResult() != OTA_UPGRADE_FAILED) {
                 progress = otaGetProgress();
                 result = otaGetResult();
                 otaGetUpdatingImageName(part_name, sizeof(part_name));

                 if (result == UPGRADE_FAILED) {
                         printf("error: ota update failed!\n");
                         ret = -1;
                         break;
                 }
                 OTA_show_Process_Bar(part_name, progress,
                                      "OTA is upgrading ...");
                 usleep(100 * 1000);
         }

    err:
         if (otaGetResult() == OTA_UPGRADE_SUCCESS) {
                 ret = otaSetPartition(next_slot);
                 if (ret < 0) {
                         printf("error: set partition failed!\n");
                         return ret;
                 }
                 if (g_is_reboot == true) {
                         printf("reboot system!\n");
                         ota_system_exe("reboot");
                 } else {
                         printf("ota update success and waiting for reboot!\n");
                 }
         }
         otaDeinitLib();

         return ret;
    }

1. 调用 otaGetPartition 获取当前所在 ab slot

2. 调用 otaInitLib 初始化 libupdate.so

3. 调用 otaRequestStart 并传入升级包和owner(OTA_TOOL)，开始升级

4. 等待 otaGetResult 的结果为 OTA_UPGRADE_SUCCESS 或 OTA_UPGRADE_FAILED 。等待过程中，调用 otaGetProgress 、 otaGetResult 、 otaGetUpdatingImageName 获取升级进度、升级结果、正在升级的镜像，并调用 OTA_show_Process_Bar 打印到控制台

5. 若升级结果 otaGetResult 为 OTA_UPGRADE_SUCCESS ，则认为升级成功，调用 otaSetPartition 设置 ab slot 到对向 slot ，然后重启 SoC

升级流程结束重启后，应启动 ota_tool -b 对升级结果进行检查校验，并进行后续操作。

### 6.6.2.2. ota_boot_check

J6 启动后，会启动一个 hobot-otatool.service 服务，该服务调用了 ota_tool -b ，该选项会检查 /ota/ota_tool_force_upgrade 文件是否存在，若存在，则进入升级流程（该进程会重新调用升级命令）。 若该文件不存在，则进入升级校验流程 ota_boot_check

    int32_t ota_boot_check(void)
    {
         int32_t               ret = 0;
         enum ota_update_owner owner = 0;

         if ((ret = otaInitLib()) != 0) {
                 printf("error: init failed!\n");
                 goto exit;
         }

         if ((ret = otaGetOwnerFlag(&owner)) != 0) {
                 printf("error: Get owner flag failed!\n");
                 goto exit;
         }

         if (owner == NORMAL_BOOT) {
                 printf("Normal boot\n");
                 if ((ret = otaMarkOTASuccessful()) != 0) {
                         printf("error: mark boot success failed\n");
                 }
                 return ret;
         }

         if (owner != OTA_TOOL) {
                 printf("ota_tool is not owner, owner is [%d]\n", owner);
                 return 0;
         }

         if ((ret = otaCheckUpdate()) != 0) {
                 printf("error: boot check failed\n");
                 goto exit;
         }

         if ((ret = otaMarkOTASuccessful()) != 0) {
                 printf("error: mark boot success failed\n");
                 goto exit;
         }

         if ((ret = otaPartitionSync()) != 0) {
                 printf("error: partition sync failed\n");
                 goto exit;
         }

         ret = otaDeinitLib();

    exit:
         otaClearFlags();
         return ret;
    }

1. 调用 otaInitLib

2. 调用 otaGetOwnerFlag 获取升级owner

3. 若 owner 为 NORMAL_BOOT ，则调用 otaMarkOTASuccessful 标记启动成功，然后退出。

4. 若 owner 不为 OTA_TOOL ，则正常退出。

5. 调用 otaCheckUpdate 获取升级结果。若升级结果异常，则调用 otaClearFlags 清除 OTA 标记，终止OTA流程。

6. 调用 otaMarkOTASuccessful 标记启动成功。

7. 调用 otaPartitionSync 进行 AB 分区、 BAK 分区同步。