----------------------------------------------------------------------------------------------------------------------------
開發板 :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.o
ifdef 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
endif
CFLAGS += -I$(PROJECT_DIR) -I/usr/include -I/usr/include/libdrm/ -lc -DUSE_UPDATEENGINE=ON
ifdef 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 test
int 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 test
case '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 RecoveryNoUi
LOGI("Recovery System have UI defined.\n");
#endif
ui_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_RKUPDATE
status = do_rk_update(binary, update_package);
#endif
#ifdef USE_UPDATEENGINE
const char* updateEnginebin = "/usr/bin/updateEngine";
status = do_rk_updateEngine(updateEnginebin, update_package);
#endif
if (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_RKUPDATE
const 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");
} else
LOGE("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");
}
#endif
if (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_RKUPDATE
const 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");
} else
LOGE("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");
}
#endif
if (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.sh
return 0;
} else {
if (argc == 1) { // No command specified
if (!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
測試