1 Star 0 Fork 4.9K

丛林 / docs

forked from OpenHarmony / docs 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
subsys-ota-guide.md 31.96 KB
一键复制 编辑 原始数据 按行查看 历史
shawn_he 提交于 2022-08-05 11:06 . update doc

OTA Update

Introduction

Over the Air (OTA) is a technology that makes it easier for you to remotely update devices, such as IP cameras. Currently, the mini and small systems support update using a full package, but not a differential package. A full package contains all content of a new system, and a differential package contains the differences between the old and new systems.

Constraints

  • Only the open-source suites for devices powered by Hi3861, Hi3518E V300, and Hi3516D V300 are supported.

  • Devices developed based on Hi3518E V300 and Hi3516D V300 must support the SD card in the Virtual Festival of Aerobatic Teams (VFAT) format.

    NOTE: Generation of update packages can only be performed on the Linux system.

Generating a Public/Private Key Pair

  1. Download the OpenSSL tool, install it on a Windows PC, and configure environment variables.

  2. Use the OpenSSL tool to generate a public/private key pair.

  3. Keep the private key file properly as this file stores the private key used to sign the update package. You need to specify the private key file in the command used for preparing the update package. The public key is used to verify the signature of the update package during the upgrade, and it is stored as follows:

    For the mini and small systems, the generated public key is preset in the code. The vendor needs to implement the HotaHalGetPubKey API to obtain the key. For the standard system, the generated public key is stored in the ./device/hisilicon/hi3516dv300/build/updater_config/signing_cert.crt file.

  4. For the mini and small systems that use the Hi3518E V300 or Hi3516D V300 suite, also use the content in public_arr.txt to replace the content in g_pub_key in the device\hisilicon\third_party\uboot\u-boot-2020.01\product\hiupdate\verify\update_public_key.c file of the U-Boot module.

    Example configuration for the public key of the U-Boot module:

    static unsigned char g_pub_key[PUBKEY_LEN] = {
        0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01,
        0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E,
    }

Generating an Update Package

Mini and Small Systems

  1. Create the target_package folder with the following directory structure:

     target_package
     ├── OTA.tag
     ├── config
     ├── {component_1}
     ├── {component_2}
     ├── ...
     ├── {component_N}
     └── updater_config
         └── updater_specified_config.xml
  2. Place the components to be updated, including the image file (for example, rootfs.img), as {component_N} in the root directory of the target_package folder.

  3. Configure the updater_specified_config.xml file in the update_config folder.

    Example configuration of the updater_specified_config.xml file:

    <?xml version="1.0"?>
    <package>
        <head name="Component header information">
            <info fileVersion="01" prdID="hisi" softVersion="OpenHarmony x.x" date="202x.xx.xx" time="xx:xx:xx">head info</info>
        </head>
        <group name="Component information">
        <component compAddr="ota_tag" compId="27" resType="5" compType="0" compVer="1.0">./OTA.tag</component>
        <component compAddr="config" compId="23" resType="5" compType="0" compVer="1.0">./config</component>
        <component compAddr="bootloader" compId="24" resType="5" compType="0" compVer="1.0">./u-boot-xxxx.bin</component>
        </group>
    </package>

    Table 1 Description of nodes in the component configuration file

    Type

    Node Name

    Node Label

    Mandatory

    Description

    Header information (head node)

    info

    /

    Yes

    Content of this node: head info

    fileVersion

    Yes

    This field is reserved and does not affect the generation of the update package.

    prdID

    Yes

    This field is reserved and does not affect the generation of the update package.

    softVersion

    Yes

    Software version number, that is, the version number of the update package. The version number must be within the range specified by VERSION.mbn. Otherwise, an update package will not be generated.

    date

    Yes

    Date when the update package is generated. This field is reserved and does not affect the generation of the update package.

    time

    Yes

    Time when the update package is generated. This field is reserved and does not affect the generation of the update package.

    Component information (group node)

    component

    /

    Yes

    Content of this node: path of the component or image file to be packed into the update package. It is the root directory of the version package by default.

    compAddr

    Yes

    Name of the partition corresponding to the component, for example, system or vendor.

    compId

    Yes

    Component ID, which must be unique.

    resType

    Yes

    This field is reserved and does not affect the generation of the update package.

    compType

    Yes

    Image type, which can be a full or differential package. The value 0 indicates a full package, and value 1 indicates a differential package.

    NOTE: As mini and small systems do not support update using a differential package, compType must be set to 0, other than 1. For mini and small systems, an update package cannot be created by changing partitions.

  4. Create the OTA.tag file, which contains the magic number of the update package. The magic number is as follows:

    package_type:ota1234567890qwertw
  5. Create the config file, and configure the bootargs and bootcmd information in the file.

    Example configuration:

    setenv bootargs 'mem=128M console=ttyAMA0,115200 root=/dev/mmcblk0p3 rw rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M
    (u-boot.bin),9M(kernel.bin),50M(rootfs_ext4.img),50M(userfs.img)' setenv bootcmd 'mmc read 0x0 0x82000000 0x800 0x4800;bootm 0x82000000'
  6. Generate the update package.

    python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem -nz -nl2x
    • ./target_package/: path of target_package
    • ./output_package/: output path of the update package
    • -pk ./rsa_private_key3072.pem: path of the private key file
    • -nz: not zip mode
    • -nl2: non-standard system mode

Standard System

  1. Create the target_package folder with the following directory structure:

    target_package
    ├── {component_1}
    ├── {component_2}
    ├── ...
    ├── {component_N}
    └── updater_config
            ├── BOARD.list
            ├── VERSION.mbn
            └── updater_specified_config.xml
  2. Place the components to be updated, including the image file (for example, system.img), as {component_N} in the root directory of the target_package folder.

  3. Configure the component configuration file in the update_config folder.

  4. Configure the list of products supported by the current update package in BOARD.list in the update_config folder.

    Example configuration:

    HI3516
    HI3518
  5. Configure the versions supported by the current update package in VERSION.mbn in the update_config folder.

    Version number format: Hi3516DV300-eng 10 QP1A.XXXXXX.{Major version number (6 digits)}.XXX{Minor version number (3 digits)}

    For example, Hi3516DV300-eng 10 QP1A.190711.020, where 190711 is the major version number, and 020 is the minor version number.

    Example configuration:

    Hi3516DV300-eng 10 QP1A.190711.001
    Hi3516DV300-eng 10 QP1A.190711.020
    Hi3518DV300-eng 10 QP1A.190711.021
  6. For update using an incremental (differential) package, also prepare a source version package (source_package) in the same format as the target version package (target_package), and then compress it as a .zip file, that is, source_package.zip.

  7. If you create an update package with partitions changed, also provide the partition table file named partition_file.xml. You can specify the file using the -pf parameter. For details about the configuration nodes, see the description below.

    The partition table is generated with the image. The format is as follows:

    <?xml version="1.0" encoding="GB2312" ?>
    <Partition_Info>
    <Part Sel="1" PartitionName="Image 1" FlashType="Flash type" FileSystem="File system type" Start="Start address of the partition" Length="Size of the partition" SelectFile="Actual path of the image"/>
    <Part Sel="1" PartitionName="Image 2" FlashType="Flash type" FileSystem="File system type" Start="Start address of the partition" Length="Size of the partition" SelectFile="Actual path of the image"/>
    </Partition_Info>

    Table 2 Description of labels in the partition table

    Label

    Description

    Sel

    Whether the partition is effective. The value 1 indicates that the partition is effective, and value 0 indicates the opposite.

    PartitionName

    Partition name, for example, fastboot or boot.

    FlashType

    Flash type, for example, emmc or ufs.

    FileSystem

    File system type, for example, ext3/4 or f2fs. The value can also be none.

    Start

    Start address of the partition, in MB. The start address of all partitions is 0.

    Length

    Size of the partition, in MB.

    SelectFile

    Actual path of the image or file.

  8. Generate the update package.

    Full package

    Run the following command:

    python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem
    • ./target_package/: path of target_package
    • ./output_package/: output path of the update package
    • -pk ./rsa_private_key3072.pem: path of the private key file

    Incremental (differential) package

    Run the following command:

    python build_update.py ./target_package/ ./output_package/  -s ./source_package.zip  -pk ./rsa_private_key3072.pem
    • ./target_package/: path of target_package
    • ./output_package/: output path of the update package
    • -s ./source_package.zip: path of the source_package.zip file. For update using a differential package, use the -s parameter to specify the source version package.
    • -pk ./rsa_private_key3072.pem: path of the private key file

    Update package with partitions changed

    Run the following command:

    python build_update.py  ./target_package/ ./output_package/  -pk ./rsa_private_key3072.pem  -pf ./partition_file.xml
    • ./target_package/: path of target_package
    • ./output_package/: output path of the update package
    • -pk ./rsa_private_key3072.pem: path of the private key file
    • -pf ./partition_file.xml: path of the partition table file

Uploading the Update Package

Upload the update package to the vendor's OTA server.

Downloading the Update Package

  1. Download the update package from the OTA server.
  2. (Optional) Insert an SD card (with a capacity greater than 100 MB) if the device is developed based on Hi3518E V300 or Hi3516D V300.

Integrating OTA Update Capabilities

  1. For mini and small systems

    • If a vendor requests OTA capabilities, use the dynamic library libhota.so and include the header files hota_partition.h and hota_updater.h in base\update\ota_lite\interfaces\kits.

    • The libhota.so source code is stored in base\update\ota_lite\frameworks\source.

    • For details about how to use APIs, see API Application Scenario and OTA APIs in API Reference.

    • If the development board needs to be adapted, see the base\update\ota_lite\hals\hal_hota_board.h file.

  2. For the standard system, see the Reference Specifications for details.

API Application Scenario (Default)

The update package is generated by following the instructions provided in Generating a Public/Private Key Pair and Generating an Update Package.

How to Develop

  1. Download the update package for the current device, and then call the HotaInit function to initialize the OTA module.

  2. Call the HotaWrite function to verify, parse, and write data streams into the device.

  3. Call the HotaRestart function to restart the system for the update to take effect. Call the HotaCancel function if you want to cancel the update.

Sample Code

Perform an OTA update using the update package format and verification method provided by OpenHarmony.

int main(int argc, char **argv)
{
    printf("this is update print!\r\n");
    if (HotaInit(NULL, NULL) < 0) {
        printf("ota update init fail!\r\n");
        return -1;
    }
    int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        printf("file open failed, fd = %d\r\n", fd);
        (void)HotaCancel();
        return -1;
    }
    int offset = 0;
    int fileLen = lseek(fd, 0, SEEK_END);
    int leftLen = fileLen;
    while (leftLen > 0) {
        if (lseek(fd, offset, SEEK_SET) < 0) {
            close(fd);
            printf("lseek fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen;
        (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN);
        if (read(fd, g_readBuf, tmpLen) < 0) {
            close(fd);
            printf("read fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) {
            printf("ota write fail!\r\n");
            close(fd);
            (void)HotaCancel();
            return -1;
        }
        offset += READ_BUF_LEN;
        leftLen -= tmpLen;
    }
    close(fd);
    printf("ota write finish!\r\n");
    printf("device will reboot in 10s...\r\n");
    sleep(10);
    (void)HotaRestart();
    return 0;
}

API Application Scenario (Custom)

The update package is generated in other ways instead of following the instructions provided in Generating a Public/Private Key Pair and Generating an Update Package.

How to Develop

  1. Download the update package for the current device, and then call the HotaInit function to initialize the OTA module.

  2. Call the HotaSetPackageType function to set the package type to NOT_USE_DEFAULT_PKG.

  3. Call the HotaWrite function to write data streams into the device.

  4. Call the HotaRead function to read data. Vendors can choose whether to verify the data.

  5. (Optional) Call the HotaSetBootSettings function to set the startup tag used for entering the U-Boot mode during system restarting.

  6. Call the HotaRestart function to restart the system for the update to take effect. Call the HotaCancel function if you want to cancel the update.

Sample Code

Perform an OTA update using the update package format and verification method not provided by OpenHarmony.

int main(int argc, char **argv)
{
    printf("this is update print!\r\n");
    if (HotaInit(NULL, NULL) < 0) {
        printf("ota update init fail!\r\n");
        (void)HotaCancel();
        return -1;
    }
    (void)HotaSetPackageType(NOT_USE_DEFAULT_PKG);
    int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        printf("file open failed, fd = %d\r\n", fd);
        (void)HotaCancel();
        return -1;
    }
    int offset = 0;
    int fileLen = lseek(fd, 0, SEEK_END);
    int leftLen = fileLen;
    while (leftLen > 0) {
        if (lseek(fd, offset, SEEK_SET) < 0) {
            close(fd);
            printf("lseek fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen;
        (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN);
        if (read(fd, g_readBuf, tmpLen) < 0) {
            close(fd);
            printf("read fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) {
            printf("ota write fail!\r\n");
            close(fd);
            (void)HotaCancel();
            return -1;
        }
        offset += READ_BUF_LEN;
        leftLen -= tmpLen;
    }
    close(fd);
    printf("ota write finish!\r\n");
    leftLen = fileLen;
    while (leftLen > 0) {
        int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen;
        (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN);
        if (HotaRead(offset, READ_BUF_LEN, (unsigned char *)g_readBuf) != 0) {}
            printf("ota write fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        /* do your verify and parse */
        offset += READ_BUF_LEN;
        leftLen -= tmpLen;
    }
    /* set your boot settings */
    (void)HotaSetBootSettings();
    printf("device will reboot in 10s...\r\n");
    sleep(10);
    (void)HotaRestart();
    return 0;
}

Upgrading the System

Vendor applications call APIs of the OTA module to perform functions such as signature verification of the update package, anti-rollback, burning and data flushing-to-disk. After the update is complete, the system automatically restarts.

For the mini and small systems that use the Hi3518E V300 or Hi3516D V300 open source suite, add the value of LOCAL_VERSION to the version that needs to implement the anti-rollback function. For example, for "ohos default 1.0"->"ohos default 1.1", add the value of LOCAL_VERSION in device\hisilicon\third_party\uboot\u-boot-2020.01\product\hiupdate\ota_update\ota_local_info.c.

Example for modification of the local version:

const char *get_local_version(void)
{
#if defined(CONFIG_TARGET_HI3516EV200) || \
    defined(CONFIG_TARGET_HI3516DV300) || \
    defined(CONFIG_TARGET_HI3518EV300)
#define LOCAL_VERSION "ohos default 1.0" /* increase: default release version */
1
https://gitee.com/jungle8023/docs.git
git@gitee.com:jungle8023/docs.git
jungle8023
docs
docs
master

搜索帮助