高可靠OTA升级

platform:RK3399
OS:Android 7.1

概述

​ OTA(空中下载技术)是一项在线升级技术,它允许终端设备通过网络从服务器下载系统固件并进行升级。高可靠OTA是RK在OTA的基础上增加了两个备份分区实现的一套高可靠的OTA升级机制,其高可靠表现在由于意外情况(断电、固件问题、机器故障)导致升级失败的情况下,仍然可以使用备份分区开机,再次进行升级,避免了升级变砖的情况。

​ 先简要介绍普通OTA,然后介绍高可靠OTA

普通OTA

步骤1.配置版本号及更新服务器

device/rockchip/rk3399/rk3399_mid_pi.mk
diff --git a/rk3399_mid_pi.mk b/rk3399_mid_pi.mk
index 2c7f0f0..d19b131 100755
--- a/rk3399_mid_pi.mk
+++ b/rk3399_mid_pi.mk
@@ -49,11 +49,13 @@ BUILD_WITH_WIDEVINE := true
 ifeq ($(TARGET_BUILD_VARIANT),user)
 PRODUCT_PROPERTY_OVERRIDES += \
     ro.adb.secure=1 \
-    persist.sys.usb.config=mtp
+    persist.sys.usb.config=mtp \
+    ro.product.version = 1.0.0 \
+   ro.product.ota.host =14.29.134.165:2300
 else
 PRODUCT_PROPERTY_OVERRIDES += \
     ro.adb.secure=0 \
-    persist.sys.usb.config=mtp,adb
+    persist.sys.usb.config=mtp,adb \
+    ro.product.version = 1.0.0 \
+   ro.product.ota.host =14.29.134.165:2300
 endif

步骤2. 编译ota固件

//仅编译android固件
source build/envsetup.sh
lunch 9
make
make otapackage
./mkimage.sh ota

//全编译
//uboot
cd u-boot
make rk3399_defconfig
make ARCHV=aarch
//kernel
cd kernel
make ARCH=arm64 qxzn_onfig
make ARCH=arm64 rk3399-mid-pi.img 
//android 
 source build/envsetup.sh
 lunch 9
 make
 //ota
make otapackage
./mkimage.sh ota

步骤3. 修改版本,编译差异包

差异包生成脚本:

./build/tools/releasetools/ota_from_target_files --block -v -i rockdev/ota_package/orignal/rk3399-target_files-v1.0.0.zip -p out/host/linux-x86 -k build/target/product/security/testkey rockdev/ota_package/orignal/rk3399-target_files-v1.0.1.zip rockdev/ota_package/diff/rk3399-v100-v101.zip

原始包路径(用于生成差异包的素材包):

out/target/product/rk3399_mid_pi/obj/PACKAGING/target_files_intermediates

ota升级整包路径(用于整包升级):

out/target/product/rk3399_mid_pi

注意:

  • 重新编译时要修改版本号
  • 重新编译时要删除out/target/product/rk3399_mid_pi/system/build.prop 文件
  • 重新编译时要删除out/target/product/rk3399_mid_pi/obj/PACKAGING 目录

步骤4. 烧录烧录基准ota包

使用RK提供的烧录工具即可.注意:不要单独烧kernel.img,否则无法进行差分升级。

步骤5. 固件升级(本地测试)

将固件(整包或差分包)改名为update.zip,放到机器用户根目录,即可自动检测升级(插拔typec或重启)。

高可靠OTA

步骤1.打开高可靠功能配置

diff --git a/BoardConfig.mk b/BoardConfig.mk
index c7ac4d3..e048b70 100755
--- a/BoardConfig.mk
+++ b/BoardConfig.mk
@@ -368,5 +368,5 @@ BOARD_USE_FIX_WALLPAPER ?= false
 # SDBoot: Format data.
 RECOVERY_SDBOOT_FORMATE_DATA ?= false
 
-HIGH_RELIABLE_RECOVERY_OTA := false
+HIGH_RELIABLE_RECOVERY_OTA := true
 BOARD_USES_FULL_RECOVERY_IMAGE := false

注意:不建议打开BOARD_USES_FULL_RECOVERY_IMAGE;该宏可能会导致高可靠OTA差分包制作失败。

步骤2.制作parameter_hrr.txt高可靠分区文件

FIRMWARE_VER: 7.1
MACHINE_MODEL: RK3399
MACHINE_ID: 007
MANUFACTURER: RK3399
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 3399
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
#KERNEL_IMG: 0x00280000
#FDT_NAME: rk-kernel.dtb
#RECOVER_KEY: 1,1,0,20,0
#in section; per section 512(0x200) bytes
CMDLINE: console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(trust),0x00002000@0x00006000(uboot_ro),0x00002000@0x00008000(trust_ro),0x00002000@0x0000A000(misc),0x00008000@0x0000C000(resource),0x0000C000@0x00014000(kernel),0x00010000@0x00020000(boot),0x00020000@0x00030000(recovery),0x00038000@0x00050000(backup),0x00040000@0x00088000(cache),0x00600000@0x000C8000(system),0x00008000@0x006C8000(metadata),0x00000040@0x006D0000(verity_mode),0x00002000@0x006D0040(reserved),0x00000400@0x006D2040(frp),-@0x006D2440(userdata)

相较于普通parameter.txt文件,增加了uboot_ro和trust_ro分区.后面分区的起始地址都要做相应的增加.

步骤3.生成uboot_ro.img

合入补丁

diff --git a/board/rockchip/common/rkboot/fastboot.c b/board/rockchip/common/rkboot/fastboot.c
index ce6a0a1..80bbd98 100755
--- a/board/rockchip/common/rkboot/fastboot.c
+++ b/board/rockchip/common/rkboot/fastboot.c
@@ -628,27 +628,32 @@ void board_fbt_preboot(void)
#endif
if (frt == FASTBOOT_REBOOT_RECOVERY) {
- FBTDBG("\n%s: starting recovery img because of reboot flag\n", __func__);
+ printf("\nUBOOT_RO %s: starting recovery img because of reboot flag\n", __func__);
board_fbt_run_recovery();
} else if (frt == FASTBOOT_REBOOT_RECOVERY_WIPE_DATA) {
- FBTDBG("\n%s: starting recovery img to wipe data "
+ printf("\nnUBOOT_RO %s: starting recovery img to wipe data "
"because of reboot flag\n", __func__);
/* we've not initialized most of our state so don't
* save env in this case
*/
board_fbt_run_recovery_wipe_data();
}
-#ifdef CONFIG_CMD_FASTBOOT
+#if 0//def CONFIG_CMD_FASTBOOT
else if (frt == FASTBOOT_REBOOT_FASTBOOT) {
FBTDBG("\n%s: starting fastboot because of reboot flag\n", __func__);
board_fbt_request_start_fastboot();
}
#endif
else {
+ #if 0
FBTDBG("\n%s: check misc command.\n", __func__);
/* unknown reboot cause (typically because of a cold boot).
* check if we had misc command to boot recovery.
*/
rkloader_run_misc_cmd();
+ #else
+ printf("\nUBOOT_RO %s: Boot to recovery anyway\n", __func__);
+ board_fbt_run_recovery();
+ #endif
}
}

然后编译,编译成功后将 uboot.img 修改为 uboot_ro.img

注意:移植完成高可靠OTA之后,每次在u-boot目录进行提交都需要重新生成uboot_ro.img。这样才能保证备份分区和主分区代码一致。

步骤4. 去掉前面生成 uboot_ro 的补丁修改;将高可靠升级的 miniloader放置在 u-boot/ tools/rk_tools/bin/rk33/目录下(miniloader需要向RK申请)

打上loader的patch

diff --git a/board/rockchip/common/rkboot/fastboot.c b/board/rockchip/common/rkboot/fastboot.c
index ce6a0a1..e630dda 100755
--- a/board/rockchip/common/rkboot/fastboot.c
+++ b/board/rockchip/common/rkboot/fastboot.c
@@ -62,6 +62,7 @@ int low_power_level = 0;
 int exit_uboot_charge_level = 0;
 int exit_uboot_charge_voltage = 0;
 int uboot_brightness = 1;
+extern void board_fbt_run_recovery(void);
 
 #ifdef CONFIG_UBOOT_CHARGE
 /**
@@ -256,8 +257,12 @@ void board_fbt_boot_failed(const char* boot)
 #ifdef CONFIG_CMD_BOOTRK
    if (!memcmp(BOOT_NAME, boot, sizeof(BOOT_NAME))) {
        printf("try to start recovery\n");
+       #if 0
        char *const boot_cmd[] = {"bootrk", RECOVERY_NAME};
        do_bootrk(NULL, 0, ARRAY_SIZE(boot_cmd), boot_cmd);
+       #else
+       board_fbt_run_recovery();
+       #endif
    } else if (!memcmp(RECOVERY_NAME, boot, sizeof(RECOVERY_NAME))) {
        printf("try to start backup\n");
        char *const boot_cmd[] = {"bootrk", BACKUP_NAME};
@@ -326,19 +331,72 @@ const disk_partition_t* board_fbt_get_partition(const char* name)
    return get_disk_partition(name);
 }
 
+void board_fbt_set_recovery_for_hrr_0(void)
+{
+   struct bootloader_message bmsg;
+
+   printf("board_fbt_set_recovery_for_hrr_0\n");
+
+   memset((char *)&bmsg, 0, sizeof(struct bootloader_message));
+   strcpy(bmsg.command, "boot-recovery");
+   bmsg.status[0] = 0;
+   rkloader_set_bootloader_msg_for_hrr(&bmsg);
+}
+
+void board_fbt_set_recovery_for_hrr_32(void)
+{
+   struct bootloader_message bmsg;
+
+   printf("board_fbt_set_recovery_for_hrr_32\n");
+
+
+   memset((char *)&bmsg, 0, sizeof(struct bootloader_message));
+   strcpy(bmsg.command, "boot-recovery");
+   bmsg.status[0] = 0;
+   if(is_bootloader_msg_has_content())
+   {
+       printf("board_fbt_set_recovery_for_hrr_32 bcb has content\n");
+   }
+   else
+   {
+       rkloader_set_bootloader_msg(&bmsg);
+   }
+}
 
-static void board_fbt_run_recovery(void)
+void board_fbt_set_recovery_for_hrr_reset(void)
 {
+   printf("board_fbt_set_recovery_for_hrr_reset reset to miniloader\n");
+#if 0
 #ifdef CONFIG_CMD_BOOTRK
    char *const boot_recovery_cmd[] = {"bootrk", "recovery"};
    do_bootrk(NULL, 0, ARRAY_SIZE(boot_recovery_cmd), boot_recovery_cmd);
 #endif
+#else
+   do_reset(NULL,0,0,NULL);
+#endif
+}
+
+void board_fbt_set_recovery_for_hrr(void)
+{
+   board_fbt_set_recovery_for_hrr_0();
+   check_misc_info_offset_0_and_32();
+   board_fbt_set_recovery_for_hrr_reset();
+}
 
+void board_fbt_run_recovery(void)
+{
+#if 0
+#ifdef CONFIG_CMD_BOOTRK
+   char *const boot_recovery_cmd[] = {"bootrk", "recovery"};
+   do_bootrk(NULL, 0, ARRAY_SIZE(boot_recovery_cmd), boot_recovery_cmd);
+#endif
+#else
+   board_fbt_set_recovery_for_hrr();
+#endif
    /* returns if recovery.img is bad */
    FBTERR("\nfastboot: Error: Invalid recovery img\n");
 }
 
-
 void board_fbt_run_recovery_wipe_data(void)
 {
    struct bootloader_message bmsg;
@@ -346,7 +404,7 @@ void board_fbt_run_recovery_wipe_data(void)
    FBTDBG("Rebooting into recovery to do wipe_data\n");
 
    if (!board_fbt_get_partition("misc")) {
-       FBTERR("not found misc partition, just run recovery.\n");
+       printf("not found misc partition, just run recovery.\n");
        board_fbt_run_recovery();
    }
 
@@ -359,7 +417,6 @@ void board_fbt_run_recovery_wipe_data(void)
    board_fbt_run_recovery();
 }
 
-
 #ifdef CONFIG_RK_POWER
 static void board_fbt_low_power_check(void)
 {
@@ -628,10 +685,13 @@ void board_fbt_preboot(void)
 #endif
 
    if (frt == FASTBOOT_REBOOT_RECOVERY) {
-       FBTDBG("\n%s: starting recovery img because of reboot flag\n", __func__);
+       printf("\n%s: starting recovery img because of reboot flag\n", __func__);
+       #if 1
+       board_fbt_set_recovery_for_hrr_32();
+       #endif
        board_fbt_run_recovery();
    } else if (frt == FASTBOOT_REBOOT_RECOVERY_WIPE_DATA) {
-       FBTDBG("\n%s: starting recovery img to wipe data "
+       printf("\n%s: starting recovery img to wipe data "
                "because of reboot flag\n", __func__);
        /* we've not initialized most of our state so don't
         * save env in this case
diff --git a/board/rockchip/common/rkloader/rkloader.c b/board/rockchip/common/rkloader/rkloader.c
index 3afe20c..ddcc51f 100755
--- a/board/rockchip/common/rkloader/rkloader.c
+++ b/board/rockchip/common/rkloader/rkloader.c
@@ -141,7 +141,7 @@ static int dispose_bootloader_cmd(struct bootloader_message *msg,
    int ret = 0;
 
    if (0 == strcmp(msg->command, "bootloader")
-           || 0 == strcmp(msg->command, "loader")) // ÐÂLoader²ÅÄÜÖ§³Ö"loader"ÃüÁî
+           || 0 == strcmp(msg->command, "loader"))
    {
        bool reboot;
 
@@ -151,7 +151,7 @@ static int dispose_bootloader_cmd(struct bootloader_message *msg,
            ret = -1;
        }
 
-       {// ²»¹Ü³É¹¦Óë·ñ£¬½«miscÇå0
+       {
            int i=0;
            memset(g_32secbuf, 0, 32*528);
            for(i=0; i<3; i++)
@@ -204,6 +204,7 @@ void rkloader_change_cmd_for_recovery(PBootInfo boot_info, char * rec_cmd)
 #define PAGE_SIZE           (16 * 1024)//16K
 #define MISC_SIZE           (MISC_PAGES * PAGE_SIZE)//48K
 #define MISC_COMMAND_OFFSET (MISC_COMMAND_PAGE * PAGE_SIZE / RK_BLK_SIZE)//32
+extern void board_fbt_run_recovery(void);
 
 int rkloader_run_misc_cmd(void)
 {
@@ -234,8 +235,12 @@ int rkloader_run_misc_cmd(void)
 #endif
        printf("got recovery cmd from misc.\n");
 #ifdef CONFIG_CMD_BOOTRK
+       #if 0
        char *const boot_cmd[] = {"bootrk", "recovery"};
        do_bootrk(NULL, 0, ARRAY_SIZE(boot_cmd), boot_cmd);
+       #else
+       board_fbt_run_recovery();
+       #endif
 #endif
        return false;
    } else if (!strcmp(bmsg->command, "boot-factory")) {
@@ -259,6 +264,96 @@ int rkloader_run_misc_cmd(void)
    return false;
 }
 
+int is_bootloader_msg_has_content(void)
+{
+   struct bootloader_message *bmsg = NULL;
+#ifdef CONFIG_RK_NVME_BOOT_EN
+   ALLOC_ALIGN_BUFFER(u8, buf, DIV_ROUND_UP(sizeof(struct bootloader_message),
+       RK_BLK_SIZE) * RK_BLK_SIZE, SZ_4K);
+#else
+   ALLOC_CACHE_ALIGN_BUFFER(u8, buf, DIV_ROUND_UP(sizeof(struct bootloader_message),
+       RK_BLK_SIZE) * RK_BLK_SIZE);
+#endif
+   const disk_partition_t *ptn = get_disk_partition(MISC_NAME);
+
+   if (!ptn) {
+       printf("misc partition not found!\n");
+       return 1;
+   }
+
+   bmsg = (struct bootloader_message *)buf;
+   if (StorageReadLba(ptn->start + MISC_COMMAND_OFFSET, buf, DIV_ROUND_UP(
+       sizeof(struct bootloader_message), RK_BLK_SIZE)) != 0) {
+           printf("failed to read misc\n");
+           return 1;
+       }
+   
+   if(strlen(bmsg->command) > 0)
+   {
+       printf("is_bootloader_msg_has_content bmsg->command=%s bmsg->recovery=%s\n", 
+           bmsg->command, bmsg->recovery);
+           return 1;
+   }
+   else
+   {
+       return 0;
+   }
+}
+
+void check_misc_info_offset_0_and_32(void)
+{
+   struct bootloader_message *bmsg = NULL;
+#ifdef CONFIG_RK_NVME_BOOT_EN
+   ALLOC_ALIGN_BUFFER(u8, buf, DIV_ROUND_UP(sizeof(struct bootloader_message),
+       RK_BLK_SIZE) * RK_BLK_SIZE, SZ_4K);
+#else
+   ALLOC_CACHE_ALIGN_BUFFER(u8, buf, DIV_ROUND_UP(sizeof(struct bootloader_message),
+       RK_BLK_SIZE) * RK_BLK_SIZE);
+#endif
+   const disk_partition_t *ptn = get_disk_partition(MISC_NAME);
+
+   if (!ptn) {
+       printf("misc partition not found!\n");
+       return;
+   }
+
+   memset(buf, 0x0, DIV_ROUND_UP(sizeof(struct bootloader_message), RK_BLK_SIZE));
+   bmsg = (struct bootloader_message *)buf;
+   if (StorageReadLba(ptn->start, buf, DIV_ROUND_UP(
+       sizeof(struct bootloader_message), RK_BLK_SIZE)) != 0) {
+           printf("failed to read misc\n");
+           return;
+       }
+
+   if(strlen(bmsg->command) > 0)
+   {
+       printf("check_misc_info_offset_0 bmsg->command=%s \n", bmsg->command);
+   }
+   else
+   {
+       printf("check_misc_info_offset_0 bmsg->command is NULL \n");
+   }
+   
+   memset(buf, 0x0, DIV_ROUND_UP(sizeof(struct bootloader_message), RK_BLK_SIZE));
+   bmsg = (struct bootloader_message *)buf;
+   if (StorageReadLba(ptn->start + MISC_COMMAND_OFFSET, buf, DIV_ROUND_UP(
+       sizeof(struct bootloader_message), RK_BLK_SIZE)) != 0) {
+           printf("failed to read misc\n");
+           return;
+       }
+
+   if(strlen(bmsg->command) > 0)
+   {
+       printf("check_misc_info_offset_32 bmsg->command=%s \n", bmsg->command);
+       return;
+   }
+   else
+   {
+       printf("check_misc_info_offset_32 bmsg->command is NULL \n");
+       return;
+   }
+}
+   
 
 void rkloader_fixInitrd(PBootInfo pboot_info, int ramdisk_addr, int ramdisk_sz)
 {
@@ -317,4 +412,22 @@ int rkloader_set_bootloader_msg(struct bootloader_message* bmsg)
            DIV_ROUND_UP(sizeof(struct bootloader_message), RK_BLK_SIZE));
 }
 
+int rkloader_set_bootloader_msg_for_hrr(struct bootloader_message* bmsg)
+{
+#ifdef CONFIG_RK_NVME_BOOT_EN
+   ALLOC_ALIGN_BUFFER(u8, buf, DIV_ROUND_UP(sizeof(struct bootloader_message),
+       RK_BLK_SIZE) * RK_BLK_SIZE, SZ_4K);
+#else
+   ALLOC_CACHE_ALIGN_BUFFER(u8, buf, DIV_ROUND_UP(sizeof(struct bootloader_message),
+       RK_BLK_SIZE) * RK_BLK_SIZE);
+#endif
+   memcpy(buf, bmsg, sizeof(struct bootloader_message));
+   const disk_partition_t *ptn = get_disk_partition(MISC_NAME);
+   if (!ptn) {
+       printf("misc partition not found!\n");
+       return -1;
+   }
 
+   return rkloader_CopyMemory2Flash((uint32)(unsigned long)buf, ptn->start/* + 
+MISC_COMMAND_OFFSET*/,DIV_ROUND_UP(sizeof(struct bootloader_message), RK_BLK_SIZE));
+}
diff --git a/board/rockchip/common/rkloader/rkloader.h b/board/rockchip/common/rkloader/rkloader.h
index 202a4c8..5a57093 100755
--- a/board/rockchip/common/rkloader/rkloader.h
+++ b/board/rockchip/common/rkloader/rkloader.h
@@ -22,5 +22,8 @@ void rkloader_change_cmd_for_recovery(PBootInfo boot_info, char * rec_cmd);
 int rkloader_run_misc_cmd(void);
 void rkloader_fixInitrd(PBootInfo pboot_info, int ramdisk_addr, int ramdisk_sz);
 int rkloader_set_bootloader_msg(struct bootloader_message* bmsg);
+int rkloader_set_bootloader_msg_for_hrr(struct bootloader_message* bmsg);
+int is_bootloader_msg_has_content(void);
+void check_misc_info_offset_0_and_32(void);
 
 #endif /* __RK_LOADER_H__ */
diff --git a/tools/rk_tools/RKBOOT/RK3399MINIALL.ini b/tools/rk_tools/RKBOOT/RK3399MINIALL.ini
index ef79b35..3b9352b 100644
--- a/tools/rk_tools/RKBOOT/RK3399MINIALL.ini
+++ b/tools/rk_tools/RKBOOT/RK3399MINIALL.ini
@@ -15,6 +15,6 @@ NUM=2
 LOADER1=FlashData
 LOADER2=FlashBoot
 FlashData=tools/rk_tools/bin/rk33/rk3399_ddr_800MHz_v1.22.bin
-FlashBoot=tools/rk_tools/bin/rk33/rk3399_miniloader_v1.15.bin
+FlashBoot=tools/rk_tools/bin/rk33/rk3399miniloaderall.bin
 [OUTPUT]
 PATH=rk3399_loader_v1.22.115.bin

打上build_tools的补丁

commit 85b475cebca65830889269552b51e99c5d8041b7
Author: letcos 
Date:   Sun Oct 20 23:01:13 2019 -0400

    hrr_ota

diff --git a/core/Makefile b/core/Makefile
old mode 100644
new mode 100755
index 2cc1588..6bdf3be
--- a/core/Makefile
+++ b/core/Makefile
@@ -1997,11 +1997,9 @@ ifeq ($(HIGH_RELIABLE_RECOVERY_OTA),true)
 endif
    $(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
-ifneq ($(HIGH_RELIABLE_RECOVERY_OTA),true)
    $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
        ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
 endif
-endif
 ifeq ($(AB_OTA_UPDATER),true)
    @# When using the A/B updater, include the updater config files in the zip.
    $(hide) $(ACP) $(TOPDIR)system/update_engine/update_engine.conf $(zip_root)/META/update_engine_config.txt
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index af4db33..133ab98 100755
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1654,6 +1654,7 @@ def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img,
 
   full_recovery_image = info_dict.get("full_recovery_image", None) == "true"
   system_root_image = info_dict.get("system_root_image", None) == "true"
+  hrr_omit_recovery = info_dict.get("hrr_omit_recovery_image", None) == "true"
 
   if full_recovery_image:
     output_sink("etc/recovery.img", recovery_img.data)
@@ -1708,6 +1709,37 @@ fi
        'recovery_device': recovery_device,
        'bonus_args': bonus_args}
 
+
+  if hrr_omit_recovery:
+    if full_recovery_image:
+      sh_hrr = """#!/system/bin/sh
+if ! applypatch -c %(type)s:%(device)s:%(size)d:%(sha1)s; then
+  log -t recovery "Recovery image skip"
+else
+  log -t recovery "Recovery image already installed"
+fi
+""" % {'type': recovery_type,
+       'device': recovery_device,
+       'sha1': recovery_img.sha1,
+       'size': recovery_img.size}
+    else:
+      sh_hrr = """#!/system/bin/sh
+if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then
+  log -t recovery "Recovery image skip"
+else
+  log -t recovery "Recovery image already installed"
+fi
+""" % {'boot_size': boot_img.size,
+       'boot_sha1': boot_img.sha1,
+       'recovery_size': recovery_img.size,
+       'recovery_sha1': recovery_img.sha1,
+       'boot_type': boot_type,
+       'boot_device': boot_device,
+       'recovery_type': recovery_type,
+       'recovery_device': recovery_device,
+       'bonus_args': bonus_args}
+
+
   # The install script location moved from /system/etc to /system/bin
   # in the L release.  Parse init.*.rc files to find out where the
   # target-files expects it to be, and put it there.
@@ -1736,4 +1768,7 @@ fi
 
   print "putting script in", sh_location
 
-  output_sink(sh_location, sh)
+  if hrr_omit_recovery:
+    output_sink(sh_location, sh_hrr)
+  else:
+    output_sink(sh_location, sh)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index e88fa7d..b58a24d 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -834,6 +834,7 @@ def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip):
   source_version = OPTIONS.source_info_dict["recovery_api_version"]
   target_version = OPTIONS.target_info_dict["recovery_api_version"]
 
+  hrr_omit_recovery = OPTIONS.info_dict.get("hrr_omit_recovery_image")
   if source_version == 0:
     print ("WARNING: generating edify script for a source that "
            "can't install it.")
@@ -1022,10 +1023,11 @@ else if get_stage("%(bcb_dev)s") != "3/3" then
     # patching on a device that's already on the target build will damage the
     # system. Because operations like move don't check the block state, they
     # always apply the changes unconditionally.
-    if blockimgdiff_version <= 2:
-      script.AssertSomeFingerprint(source_fp)
-    else:
-      script.AssertSomeFingerprint(source_fp, target_fp)
+    if not hrr_omit_recovery:
+      if blockimgdiff_version <= 2:
+        script.AssertSomeFingerprint(source_fp)
+      else:
+        script.AssertSomeFingerprint(source_fp, target_fp)
   else:
     if blockimgdiff_version <= 2:
       script.AssertSomeThumbprint(
@@ -1534,6 +1536,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
 
   source_version = OPTIONS.source_info_dict["recovery_api_version"]
   target_version = OPTIONS.target_info_dict["recovery_api_version"]
+  hrr_omit_recovery = OPTIONS.info_dict.get("hrr_omit_recovery_image")
 
   if source_version == 0:
     print ("WARNING: generating edify script for a source that "
@@ -1605,7 +1608,8 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
                                    OPTIONS.source_info_dict)
 
   if oem_props is None:
-    script.AssertSomeFingerprint(source_fp, target_fp)
+    if not hrr_omit_recovery:
+      script.AssertSomeFingerprint(source_fp, target_fp)
   else:
     script.AssertSomeThumbprint(
         GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict),

步骤五:重新编译uboot即可生成支持高可靠OTA的uboot.img

注意:

  1. 不同SDK和主板miniloader可能不同,在源码路径的放置也可能不同。具体可以参考SDK中的《高可靠OTA使用说明文档.pdf》

  2. 步骤四不是必须的,如果不打build_tools的patch 也可以正常生成OTA整包和差分包,那么就不需要执行步骤四。

其余步骤同普通OTA.

固件无法单独烧录Kernel

实现了高可靠OTA之后,测试时单独编译kernel并烧录可能出现问题,可以采用如下补丁规避.

diff --git a/make_mid_pi.sh b/make_mid_pi.sh
index 1da24f5..0d0f92d 100755
--- a/make_mid_pi.sh
+++ b/make_mid_pi.sh
@@ -2,6 +2,30 @@
 
 set -e
 
+. build/envsetup.sh >/dev/null && setpaths
+
+export PATH=$ANDROID_BUILD_PATHS:$PATH
+TARGET_PRODUCT=`get_build_var TARGET_PRODUCT`
+TARGET_HARDWARE=`get_build_var TARGET_BOARD_HARDWARE`
+TARGET_BOARD_PLATFORM=`get_build_var TARGET_BOARD_PLATFORM`
+TARGET_DEVICE_DIR=`get_build_var TARGET_DEVICE_DIR`
+PLATFORM_VERSION=`get_build_var PLATFORM_VERSION`
+PLATFORM_SECURITY_PATCH=`get_build_var PLATFORM_SECURITY_PATCH`
+TARGET_BUILD_VARIANT=`get_build_var TARGET_BUILD_VARIANT`
+BOARD_SYSTEMIMAGE_PARTITION_SIZE=`get_build_var BOARD_SYSTEMIMAGE_PARTITION_SIZE`
+BOARD_USE_SPARSE_SYSTEM_IMAGE=`get_build_var BOARD_USE_SPARSE_SYSTEM_IMAGE`
+HIGH_RELIABLE_RECOVERY_OTA=`get_build_var HIGH_RELIABLE_RECOVERY_OTA`
+TARGET_BASE_PARAMETER_IMAGE=`get_build_var TARGET_BASE_PARAMETER_IMAGE`
+echo TARGET_BOARD_PLATFORM=$TARGET_BOARD_PLATFORM
+echo TARGET_PRODUCT=$TARGET_PRODUCT
+echo TARGET_HARDWARE=$TARGET_HARDWARE
+echo TARGET_BUILD_VARIANT=$TARGET_BUILD_VARIANT
+echo BOARD_SYSTEMIMAGE_PARTITION_SIZE=$BOARD_SYSTEMIMAGE_PARTITION_SIZE
+echo BOARD_USE_SPARSE_SYSTEM_IMAGE=$BOARD_USE_SPARSE_SYSTEM_IMAGE
+echo HIGH_RELIABLE_RECOVERY_OTA=$HIGH_RELIABLE_RECOVERY_OTA
+echo TARGET_BASE_PARAMETER_IMAGE==$TARGET_BASE_PARAMETER_IMAGE
+TARGET="withoutkernel"

 usage()
 {
 cat << EOF
@@ -67,6 +91,10 @@ if  $MAKE_ALL || [ $MAKE_MODULES = 'k' ]; then
     make  ARCH=arm64 "${KERNEL_DTS}.img" -j $MAKE_THEARD | tee build_kernel.log
     popd
 fi

+    mkbootfs $OUT/root | minigzip > $OUT/ramdisk.img
+    truncate -s "%4" $OUT/ramdisk.img
+    cp kernel/arch/arm64/boot/Image kernel/kernel_Image
+    mkbootimg --kernel kernel/kernel_Image --ramdisk $OUT/ramdisk.img --second kernel/resource.img --os_version $PLATFORM_VERSION --os_patch_level $PLATFORM_SECURITY_PATCH --cmdline buildvariant=$TARGET_BUILD_VARIANT --output kernel/boot_nokernel.img

 if $MAKE_ALL || [ $MAKE_MODULES = 'a' ]; then
     source ${QXZNTOOLS_PATH}/build.sh

你可能感兴趣的:(高可靠OTA升级)