----------------------------------------------------------------------------------------------------------------------------
开发板 :ArmSoM-Sige7
开发板
eMMC
:64GB
LPDDR4
:8GB
显示屏 :15.6
英寸HDMI
接口显示屏
u-boot
:2017.09
linux
:5.10
----------------------------------------------------------------------------------------------------------------------------
在《Rockchip RK3588 - Rockchip Linux Recovery updateEngine
源码分析》中我们对updateEngine
源码进行了深入分析,并提到updateEngine
升级命令由两部分组成;
normal
系统下的升级:升级recovery
分区,并修改misc
分区,重启系统;recovery
系统下的升级:系统重启之后,会根据misc
分区存放的字段来判断将要引导的系统是normal
系统还是recovery
系统,这里会进入到recovery
系统,进行剩余分区的升级;
其中normal
系统下的升级是通过updateEngine
可执行程序完成的;
// 1. 在normal系统,updateEngine升级recovery分区;升级完函数就返回了,并不会升级其它分区
main(argc, argv)MiscUpdate(image_url, partition, save_path) // 对需要执行的升级命令打标记(这里标记了parameter、recovery升级命令)RK_ota_set_partition(0x040000) // 进行parameter、recovery分区升级RK_ota_start(handle_upgrade_callback, handle_print_callback)// 往misc偏移16k位置写入recovery信息,这样系统重启后会进入recovery系统执行剩余分区的升级set_bootloader_message(&msg)// 2. 触发系统重启system(" echo b > /proc/sysrq-trigger ")
而recovery
系统下的升级,是通过recovery
可执行程序实现,recovery
二进制bin
程序部会根据编译配置调用updateEngine
或者rkupdate
进行升级,本章的目标就是对recovery
源码进行分析。
一、recovery
目标分析
1.1 目标recovery
定位到<Rockchip Linux SDK>/external/recovery
目录下的Makefile
文件,找到目标recovery
;
OBJ = recovery.o \default_recovery_ui.o \rktools.o \roots.o \bootloader.o \safe_iop.o \strlcpy.o \strlcat.o \rkupdate.o \sdboot.o \usbboot.o \mtdutils/mounts.o \mtdutils/mtdutils.o \mtdutils/rk29.o \minzip/DirUtil.o \update_engine/log.oifdef RecoveryNoUi
OBJ += noui.o # 不走这里
else
OBJ += ui.o\ # 走这里 minzip/Hash.o \minzip/SysUtil.o \minzip/Zip.o \minui/events.o \minui/graphics.o \minui/resources.o \minui/graphics_drm.o
endifCFLAGS += -I$(PROJECT_DIR) -I/usr/include -I/usr/include/libdrm/ -lc -DUSE_UPDATEENGINE=ONifdef RecoveryNoUi
CFLAGS += -lpthread -lbz2 # 不走这里
else
CFLAGS += -lz -lpng -ldrm -lpthread -lcurl -lcrypto -lbz2 # 走这里
endif$(PROM): $(OBJ)$(CC) -o $(PROM) $(OBJ) $(CFLAGS)
可以看到目标recovery
是由若干个.o
文件通过aarch64-buildroot-linux-gnu-gcc
编译器链接生成的可执行文件。
而.o
文件实际上是由.c
文件通过aarch64-buildroot-linux-gnu-gcc
编译器编译生成的。
# build in buildroot, it need change work directory
recovery_version:cd $(PROJECT_DIR)/../../../../../external/recovery && \COMMIT_HASH=$$(git rev-parse --verify --short HEAD) && \GIT_COMMIT_TIME=$$(git log -1 --format=%cd --date=format:%y%m%d) && \GIT_DIRTY=$$(git diff-index --quiet HEAD -- || echo "-dirty") && \commit_info=-g$${COMMIT_HASH}-$${GIT_COMMIT_TIME}$${GIT_DIRTY} && \cd $(PROJECT_DIR) && \echo "#define GIT_COMMIT_INFO $${commit_info}" > recovery_autogenerate.h%.o: %.cpp$(CC) -c $< -o $@ $(CFLAGS)%.o: %.c recovery_version$(CC) -c $< -o $@ $(CFLAGS)
其中:%.o
表示所有以.o
结尾的文件作为目标文件,%.cpp
表示所有以.c
结尾的文件作为依赖文件。
程序的入口为update_engine/main.cpp
文件。
1.2 编译
在《Rockchip RK3588 - Rockchip Linux SDK Buildroot
文件系统构建》中介绍过buildroot
编译命令;
root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot$ sudo make -j8
或者使用如下命令单独编译recovery
软件包:
root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot$ sudo make recovery-dirclean
root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot$ sudo make recovery
其中recovery
编译日志如下:
>>> recovery develop Syncing from source dir /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/../external/recovery
rsync -au --chmod=u=rwX,go=rX --exclude .svn --exclude .git --exclude .hg --exclude .bzr --exclude CVS /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/../external/recovery/ /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop
>>> recovery develop Configuring
>>> recovery develop Building
PATH="/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/bin:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin" /usr/bin/make -C /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop CC="/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/bin/aarch64-buildroot-linux-gnu-gcc" CFLAGS="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0 -D_FORTIFY_SOURCE=1 -I. -fPIC -lpthread -lcurl -lssl -lcrypto -lbz2 -lpng -ldrm -lz -lm -I/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/libdrm -DUSE_UPDATEENGINE=ON -DSUCCESSFUL_BOOT=ON"
make[1]: 进入目录“/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop”
cd /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop/../../../../../external/recovery && \
COMMIT_HASH=$(git rev-parse --verify --short HEAD) && \
GIT_COMMIT_TIME=$(git log -1 --format=%cd --date=format:%y%m%d) && \
GIT_DIRTY=$(git diff-index --quiet HEAD -- || echo "-dirty") && \
commit_info=-g${COMMIT_HASH}-${GIT_COMMIT_TIME}${GIT_DIRTY} && \
cd /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop && \
echo "#define GIT_COMMIT_INFO ${commit_info}" > recovery_autogenerate.h
/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/bin/aarch64-buildroot-linux-gnu-gcc -c recovery.c -o recovery.o -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0 -D_FORTIFY_SOURCE=1 -I. -fPIC -lpthread -lcurl -lssl -lcrypto -lbz2 -lpng -ldrm -lz -lm -I/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/libdrm -DUSE_UPDATEENGINE=ON -DSUCCESSFUL_BOOT=ON
......
/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/bin/aarch64-buildroot-linux-gnu-gcc -o updateEngine mtdutils/mounts.o mtdutils/mtdutils.o mtdutils/rk29.o update_engine/rkbootloader.o update_engine/download.o update_engine/flash_image.o update_engine/log.o update_engine/main.o update_engine/md5sum.o update_engine/rkimage.o update_engine/rktools.o update_engine/rkboot.o update_engine/crc.o update_engine/update.o update_engine/do_patch.o -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0 -D_FORTIFY_SOURCE=1 -I. -fPIC -lpthread -lcurl -lssl -lcrypto -lbz2 -lpng -ldrm -lz -lm -I/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/libdrm -DUSE_UPDATEENGINE=ON -DSUCCESSFUL_BOOT=ON
make[1]: 离开目录“/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop”
>>> recovery develop Installing to target
/usr/bin/install -D -m 755 /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop/recovery /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/target/usr/bin/
mkdir -p /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/target/res/images
cp /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop/res/images/* /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/target/res/images/
/usr/bin/install -D -m 755 /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/build/recovery-develop/updateEngine /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/target/usr/bin/
/usr/bin/install -D -m 755 package/rockchip/recovery//S40recovery /work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/target/etc/init.d/S40recovery
二、recovery
源码分析
recovery
程序的入口为recovery.c
文件。recovery.c
代码比较长,如下所示:
点开查看详情
int
main(int argc, char **argv)
{bool bSDBoot = false;bool bUDiskBoot = false;const char *sdupdate_package = NULL;const char *usbupdate_package = NULL;int previous_runs = 0;const char *send_intent = NULL;const char *update_package = NULL;const char *encrypted_fs_mode = NULL;int wipe_data = 0;int wipe_all = 0;int pcba_test = 0; // add for pcba testint toggle_secure_fs = 0;int arg;bool isrkdebug = false;int log_level = LOG_DEBUG;encrypted_fs_info encrypted_fs_data;struct timeval start_time, end_time;long long elapsed_time;gettimeofday(&start_time, NULL);get_args(&argc, &argv);strcpy(systemFlag, "false");while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {switch (arg) {case 'p':previous_runs = atoi(optarg);break;case 's':send_intent = optarg;break;case 'u':update_package = optarg;break;case 'w':wipe_data = 1;break;case 'a':wipe_all = 1;break;case 'e':encrypted_fs_mode = optarg;toggle_secure_fs = 1;break;case 't':ui_show_text(1);break;case 'f':pcba_test = 1;break; // add for pcba testcase 'r':isrkdebug = true;break;case 'i':gr_set_rotate(atoi(optarg));break;case '?':LOGE("Invalid command argument\n");continue;}}time_t start = time(NULL);if ((access("/.rkdebug", F_OK) != 0) && (isrkdebug != true)) {// If these fail, there's not really anywhere to complain...if (freopen(TEMPORARY_LOG_FILE, "a", stdout) == NULL) {LOGW("freopen stdout error");}setbuf(stdout, NULL);if (freopen(TEMPORARY_LOG_FILE, "a", stderr) == NULL) {LOGE("freopen stderr error");}setbuf(stderr, NULL);}printf("\n");printf("*********************************************************\n");printf(" ROCKCHIP recovery system \n");printf("*********************************************************\n");printf("**** version : %s ****\n", recovery_version);LOGI("Starting recovery on %s\n", ctime(&start));while (access(coldboot_done, F_OK) != 0) {LOGI("coldboot not done, wait...\n");sleep(1);}#ifndef RecoveryNoUiLOGI("Recovery System have UI defined.\n");
#endifui_init();ui_set_background(BACKGROUND_ICON_INSTALLING);load_volume_table();setFlashPoint();bSDBoot = is_boot_from_SD();bUDiskBoot = is_boot_from_udisk();if (bSDBoot || bUDiskBoot) {char imageFile[64] = {0};if (bSDBoot) {if (is_sdcard_update()) {strlcpy(imageFile, EX_SDCARD_ROOT, sizeof(imageFile));strlcat(imageFile, "/sdupdate.img", sizeof(imageFile));if (access(imageFile, F_OK) == 0) {sdupdate_package = strdup(imageFile);bSDBootUpdate = true;ui_show_text(1);LOGI("sdupdate_package = %s\n", sdupdate_package);}}}if (bUDiskBoot) {if (is_udisk_update()) {strlcpy(imageFile, EX_UDISK_ROOT, sizeof(imageFile));strlcat(imageFile, "/sdupdate.img", sizeof(imageFile));if (access(imageFile, F_OK) == 0) {usbupdate_package = strdup(imageFile);bUdiskUpdate = true;ui_show_text(1);LOGI("usbupdate_package = %s\n", usbupdate_package);}}}}device_recovery_start();LOGI("Command:");for (arg = 0; arg < argc; arg++) {printf(" \"%s\"", argv[arg]);}printf("\n");if (update_package) {// For backwards compatibility on the cache partition only, if// we're given an old 'root' path "CACHE:foo", change it to// "/cache/foo".if (strncmp(update_package, "CACHE:", 6) == 0) {int len = strlen(update_package) + 10;char* modified_path = malloc(len);strlcpy(modified_path, "/cache/", len);strlcat(modified_path, update_package + 6, len);LOGI("(replacing path \"%s\" with \"%s\")\n",update_package, modified_path);update_package = modified_path;}}printf("\n");int status = INSTALL_SUCCESS;if (toggle_secure_fs) {if (strcmp(encrypted_fs_mode, "on") == 0) {encrypted_fs_data.mode = MODE_ENCRYPTED_FS_ENABLED;ui_print("Enabling Encrypted FS.\n");} else if (strcmp(encrypted_fs_mode, "off") == 0) {encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;ui_print("Disabling Encrypted FS.\n");} else {ui_print("Error: invalid Encrypted FS setting.\n");status = INSTALL_ERROR;}// Recovery strategy: if the data partition is damaged, disable encrypted file systems.// This preventsthe device recycling endlessly in recovery mode.if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&(read_encrypted_fs_info(&encrypted_fs_data))) {ui_print("Encrypted FS change aborted, resetting to disabled state.\n");encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;}if (status != INSTALL_ERROR) {if (erase_volume("/userdata")) {ui_print("Data wipe failed.\n");status = INSTALL_ERROR;
#if 0} else if (erase_volume("/cache")) {ui_print("Cache wipe failed.\n");status = INSTALL_ERROR;
#endif} else if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&(restore_encrypted_fs_info(&encrypted_fs_data))) {ui_print("Encrypted FS change aborted.\n");status = INSTALL_ERROR;} else {ui_print("Successfully updated Encrypted FS.\n");status = INSTALL_SUCCESS;}}} else if (update_package != NULL) {int i, ret = 0;const char* binary = "/usr/bin/rkupdate";rockchip_partition_check();for (i = 0; i < 5; i++) {if (!ensure_path_mounted(update_package)) {LOGI("mounted %s Success.\n", update_package);break;}LOGW("mounted %s Failed. retry %d\n", update_package, i + 1);sleep(1);}if (i != 5) {LOGI(">>>rkflash will update from %s\n", update_package);
#ifdef USE_RKUPDATEstatus = do_rk_update(binary, update_package);
#endif
#ifdef USE_UPDATEENGINEconst char* updateEnginebin = "/usr/bin/updateEngine";status = do_rk_updateEngine(updateEnginebin, update_package);
#endifif (status == INSTALL_SUCCESS) {strcpy(systemFlag, update_package);/* update success, delete update.img. */if (access(update_package, F_OK) == 0)remove(update_package);ui_print("update.img images success!\n");} else {ui_print("update.img images failed!\n");}} else {LOGE("mounted %s Failed.\n", update_package);ui_print("mounted %s Failed.\n", update_package);}if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n");ui_print("update.img Installation done.\n");//ui_show_text(0);} else if (sdupdate_package != NULL) {rockchip_partition_check();// update image from sdcard
#ifdef USE_RKUPDATEconst char* binary = "/usr/bin/rkupdate";LOGI(">>>sdboot update will update from %s\n", sdupdate_package);status = do_rk_update(binary, sdupdate_package);
#endif#ifdef USE_UPDATEENGINE
#undef FACTORY_FIRMWARE_IMAGE
#undef CMD4RECOVERY_FILENAME
#define FACTORY_FIRMWARE_IMAGE "/mnt/sdcard/out_image.img"
#define CMD4RECOVERY_FILENAME "/mnt/sdcard/cmd4recovery"if ((access(FACTORY_FIRMWARE_IMAGE, F_OK)) && access(CMD4RECOVERY_FILENAME, F_OK)) {int tmp_fd = creat(CMD4RECOVERY_FILENAME, 0777);if (tmp_fd < 0) {LOGE("creat %s error.\n", CMD4RECOVERY_FILENAME);status = INSTALL_ERROR;} else {close(tmp_fd);const char* updateEnginebin = "/usr/bin/updateEngine";status = do_rk_updateEngine(updateEnginebin, sdupdate_package);}}if (isMtdDevice()) {LOGI("start flash write to /dev/mtd0.\n");size_t total_size;size_t erase_size;mtd_scan_partitions();const MtdPartition *part = mtd_find_partition_by_name("rk-nand");if ( part == NULL ) {part = mtd_find_partition_by_name("spi-nand0");}if (part == NULL || mtd_partition_info(part, &total_size, &erase_size, NULL)) {if ((!access(FACTORY_FIRMWARE_IMAGE, F_OK)) && mtd_find_partition_by_name("sfc_nor") != NULL) {LOGI("Info: start flash out_image.img to spi nor.\n");system("flashcp -v " FACTORY_FIRMWARE_IMAGE " /dev/mtd0");} elseLOGE("Error: Can't find rk-nand or spi-nand0.\n");} else {system("flash_erase /dev/mtd0 0x0 0");system("sh "CMD4RECOVERY_FILENAME);}} else {LOGI("Start to dd data to emmc partition.\n");system("sh "CMD4RECOVERY_FILENAME);LOGI("sdcard upgrade done\n");}#endifif (status == INSTALL_SUCCESS) {LOGI("update.img Installation success.\n");ui_print("update.img Installation success.\n");//ui_show_text(0);}} else if (usbupdate_package != NULL) {rockchip_partition_check();// update image from udisk
#ifdef USE_RKUPDATEconst char* binary = "/usr/bin/rkupdate";LOGI(">>>sdboot update will update from %s\n", usbupdate_package);status = do_rk_update(binary, usbupdate_package);
#endif#ifdef USE_UPDATEENGINE
#undef FACTORY_FIRMWARE_IMAGE
#undef CMD4RECOVERY_FILENAME
#define FACTORY_FIRMWARE_IMAGE "/mnt/usb_storage/out_image.img"
#define CMD4RECOVERY_FILENAME "/mnt/usb_storage/cmd4recovery"if ((access(FACTORY_FIRMWARE_IMAGE, F_OK)) && access(CMD4RECOVERY_FILENAME, F_OK)) {int tmp_fd = creat(CMD4RECOVERY_FILENAME, 0777);if (tmp_fd < 0) {LOGE("creat %s error.\n", CMD4RECOVERY_FILENAME);status = INSTALL_ERROR;} else {close(tmp_fd);const char* updateEnginebin = "/usr/bin/updateEngine";status = do_rk_updateEngine(updateEnginebin, usbupdate_package);}}if (isMtdDevice()) {LOGI("start flash write to /dev/mtd0.\n");size_t total_size;size_t erase_size;mtd_scan_partitions();const MtdPartition *part = mtd_find_partition_by_name("rk-nand");if ( part == NULL ) {part = mtd_find_partition_by_name("spi-nand0");}if (part == NULL || mtd_partition_info(part, &total_size, &erase_size, NULL)) {if ((!access(FACTORY_FIRMWARE_IMAGE, F_OK)) && mtd_find_partition_by_name("sfc_nor") != NULL) {LOGI("Info: start flash out_image.img to spi nor.\n");system("flashcp -v " FACTORY_FIRMWARE_IMAGE " /dev/mtd0");} elseLOGE("Error: Can't find rk-nand or spi-nand0.\n");} else {system("flash_erase /dev/mtd0 0x0 0");system("sh "CMD4RECOVERY_FILENAME);}} else {LOGI("Start to dd data to emmc partition.\n");system("sh "CMD4RECOVERY_FILENAME);LOGI("usb upgrade done\n");}
#endifif (status == INSTALL_SUCCESS) {LOGI("update.img Installation success.\n");ui_print("update.img Installation success.\n");//ui_show_text(0);}} else if (wipe_data) {if (device_wipe_data()) status = INSTALL_ERROR;if (erase_volume("/userdata")) status = INSTALL_ERROR;if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n");} else if (wipe_all) {if (device_wipe_data()) status = INSTALL_ERROR;if (erase_volume("/userdata")) status = INSTALL_ERROR;if (status != INSTALL_SUCCESS) {ui_print("Data wipe failed.\n");LOGE("userdata wipe failed.\n");} else {ui_print("Data wipe done.\n");LOGI("userdata wipe done.\n");}//ui_show_text(0);} else if (pcba_test) {//pcba test todo...printf("------------------ pcba test start -------------\n");exit(EXIT_SUCCESS); //exit recovery bin directly, not start pcba here, in rkLanuch.shreturn 0;} else {if (argc == 1) { // No command specifiedif (!bSDBootUpdate && !bUdiskUpdate && ui_text_visible())prompt_and_wait();finish_recovery(NULL);reboot(RB_AUTOBOOT);return 0;}status = INSTALL_ERROR; // No command specified}if (status != INSTALL_SUCCESS) ui_set_background(BACKGROUND_ICON_ERROR);if (status != INSTALL_SUCCESS) {LOGE("\n Install fail! \n");if (!bSDBootUpdate && !bUdiskUpdate && ui_text_visible())prompt_and_wait();}if (sdupdate_package != NULL && bSDBootUpdate) {if (status == INSTALL_SUCCESS) {char *SDDdevice =strdup(get_mounted_device_from_path(EX_SDCARD_ROOT));ensure_ex_path_unmounted(EX_SDCARD_ROOT);/* Updating is finished here, we must print this message* in console, it shows user a specific message that* updating is completely, remove SD CARD and reboot */fflush(stdout);freopen("/dev/console", "w", stdout);LOGI("\nPlease remove SD CARD!!!, wait for reboot.\n");ui_print("Please remove SD CARD!!!, wait for reboot.");while (access(SDDdevice, F_OK) == 0) { sleep(1); }free(SDDdevice);}} else if (usbupdate_package && bUdiskUpdate) {if (status == INSTALL_SUCCESS) {char *udiskDev = strdup(get_mounted_device_from_path(EX_SDCARD_ROOT));ensure_path_unmounted(EX_UDISK_ROOT);/* Updating is finished here, we must print this message* in console, it shows user a specific message that* updating is completely, remove U-disk and reboot */fflush(stdout);freopen("/dev/console", "w", stdout);LOGI("\nPlease remove U DISK!!!, wait for reboot.\n");ui_print("Please remove U DISK!!!, wait for reboot.");while (access(udiskDev, F_OK) == 0) { sleep(1); }free(udiskDev);}}// Otherwise, get ready to boot the main system...finish_recovery(send_intent);gettimeofday(&end_time, NULL);elapsed_time = (end_time.tv_sec - start_time.tv_sec) * 1000LL +(end_time.tv_usec - start_time.tv_usec) / 1000LL;LOGI("recovery usage time:%lld ms\n", elapsed_time);ui_print("Rebooting...\n");LOGI("Reboot...\n");ui_show_text(0);fflush(stdout);sync();reboot(RB_AUTOBOOT);return EXIT_SUCCESS;
}
参考文章:
[1] Rockchip RK3588 - Rockchip Linux Recovery updateEngine
源码分析
[2] Rockchip RK3588 - Rockchip Linux Recovery updateEngine
测试