xref: /OK3568_Linux_fs/external/recovery/recovery.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <ctype.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <getopt.h>
21 #include <limits.h>
22 #include <linux/input.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/reboot.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include <dirent.h>
32 #include <sys/time.h>
33 
34 #include "bootloader.h"
35 #include "common.h"
36 //#include "cutils/properties.h"
37 #include "install.h"
38 #include "minui/minui.h"
39 #include "minzip/DirUtil.h"
40 #include "roots.h"
41 #include "recovery_ui.h"
42 #include "encryptedfs_provisioning.h"
43 #include "rktools.h"
44 #include "sdboot.h"
45 #include "usbboot.h"
46 #include "mtdutils/mtdutils.h"
47 #include "recovery_version.h"
48 
49 static const char *recovery_version = RECOVERY_VERSION_STRING;
50 
51 static const struct option OPTIONS[] = {
52     { "send_intent", required_argument, NULL, 's' },
53     { "update_package", required_argument, NULL, 'u' },
54     { "wipe_data", no_argument, NULL, 'w' },
55     { "wipe_all", no_argument, NULL, 'a' },
56     { "set_encrypted_filesystems", required_argument, NULL, 'e' },
57     { "show_text", no_argument, NULL, 't' },
58     { "factory_pcba_test", no_argument, NULL, 'f' },
59     { "rkdebug", no_argument, NULL, 'r'},
60     { "ui_rotation", required_argument, NULL, 'i'},
61     { NULL, 0, NULL, 0 },
62 };
63 
64 static const char *COMMAND_FILE = "/userdata/recovery/command";
65 static const char *INTENT_FILE = "/userdata/recovery/intent";
66 static const char *LOG_FILE = "/userdata/recovery/log";
67 static const char *LAST_LOG_FILE = "/userdata/recovery/last_log";
68 static const char *SDCARD_ROOT = "/sdcard";
69 static const char *SDCARD_ROOT2 = "/mnt/external_sd";
70 static const char *USERDATA_ROOT = "/userdata";
71 static const char *UDISK_ROOT = "/udisk";
72 static const char *UDISK_ROOT2 = "/mnt/usb_storage";
73 static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
74 static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
75 static const char *coldboot_done = "/dev/.coldboot_done";
76 
77 char systemFlag[252];
78 bool bSDBootUpdate = false;
79 bool bUdiskUpdate  = false;
80 
81 /*
82  * The recovery tool communicates with the main system through /cache files.
83  *   /cache/recovery/command - INPUT - command line for tool, one arg per line
84  *   /cache/recovery/log - OUTPUT - combined log file from recovery run(s)
85  *   /cache/recovery/intent - OUTPUT - intent that was passed in
86  *
87  * The arguments which may be supplied in the recovery.command file:
88  *   --send_intent=anystring - write the text out to recovery.intent
89  *   --update_package=path - verify install an OTA package file
90  *   --wipe_data - erase user data (and cache), then reboot
91  *   --wipe_cache - wipe cache (but not user data), then reboot
92  *   --set_encrypted_filesystem=on|off - enables / diasables encrypted fs
93  *
94  * After completing, we remove /cache/recovery/command and reboot.
95  * Arguments may also be supplied in the bootloader control block (BCB).
96  * These important scenarios must be safely restartable at any point:
97  *
98  * FACTORY RESET
99  * 1. user selects "factory reset"
100  * 2. main system writes "--wipe_data" to /cache/recovery/command
101  * 3. main system reboots into recovery
102  * 4. get_args() writes BCB with "boot-recovery" and "--wipe_data"
103  *    -- after this, rebooting will restart the erase --
104  * 5. erase_volume() reformats /userdata
105  * 6. erase_volume() reformats /cache
106  * 7. finish_recovery() erases BCB
107  *    -- after this, rebooting will restart the main system --
108  * 8. main() calls reboot() to boot main system
109  *
110  * OTA INSTALL
111  * 1. main system downloads OTA package to /cache/some-filename.zip
112  * 2. main system writes "--update_package=/cache/some-filename.zip"
113  * 3. main system reboots into recovery
114  * 4. get_args() writes BCB with "boot-recovery" and "--update_package=..."
115  *    -- after this, rebooting will attempt to reinstall the update --
116  * 5. install_package() attempts to install the update
117  *    NOTE: the package install must itself be restartable from any point
118  * 6. finish_recovery() erases BCB
119  *    -- after this, rebooting will (try to) restart the main system --
120  * 7. ** if install failed **
121  *    7a. prompt_and_wait() shows an error icon and waits for the user
122  *    7b; the user reboots (pulling the battery, etc) into the main system
123  * 8. main() calls maybe_install_firmware_update()
124  *    ** if the update contained radio/hboot firmware **:
125  *    8a. m_i_f_u() writes BCB with "boot-recovery" and "--wipe_cache"
126  *        -- after this, rebooting will reformat cache & restart main system --
127  *    8b. m_i_f_u() writes firmware image into raw cache partition
128  *    8c. m_i_f_u() writes BCB with "update-radio/hboot" and "--wipe_cache"
129  *        -- after this, rebooting will attempt to reinstall firmware --
130  *    8d. bootloader tries to flash firmware
131  *    8e. bootloader writes BCB with "boot-recovery" (keeping "--wipe_cache")
132  *        -- after this, rebooting will reformat cache & restart main system --
133  *    8f. erase_volume() reformats /cache
134  *    8g. finish_recovery() erases BCB
135  *        -- after this, rebooting will (try to) restart the main system --
136  * 9. main() calls reboot() to boot main system
137  *
138  * SECURE FILE SYSTEMS ENABLE/DISABLE
139  * 1. user selects "enable encrypted file systems"
140  * 2. main system writes "--set_encrypted_filesystems=on|off" to
141  *    /cache/recovery/command
142  * 3. main system reboots into recovery
143  * 4. get_args() writes BCB with "boot-recovery" and
144  *    "--set_encrypted_filesystems=on|off"
145  *    -- after this, rebooting will restart the transition --
146  * 5. read_encrypted_fs_info() retrieves encrypted file systems settings from /userdata
147  *    Settings include: property to specify the Encrypted FS istatus and
148  *    FS encryption key if enabled (not yet implemented)
149  * 6. erase_volume() reformats /userdata
150  * 7. erase_volume() reformats /cache
151  * 8. restore_encrypted_fs_info() writes required encrypted file systems settings to /userdata
152  *    Settings include: property to specify the Encrypted FS status and
153  *    FS encryption key if enabled (not yet implemented)
154  * 9. finish_recovery() erases BCB
155  *    -- after this, rebooting will restart the main system --
156  * 10. main() calls reboot() to boot main system
157  */
158 
159 static const int MAX_ARG_LENGTH = 4096;
160 static const int MAX_ARGS = 100;
161 extern size_t strlcpy(char *dst, const char *src, size_t dsize);
162 extern size_t strlcat(char *dst, const char *src, size_t dsize);
163 extern int do_rk_updateEngine(const char *binary, const char *path);
164 
165 
read_encrypted_fs_info(encrypted_fs_info * encrypted_fs_data)166 int read_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data)
167 {
168     return ENCRYPTED_FS_ERROR;
169 }
170 
restore_encrypted_fs_info(encrypted_fs_info * encrypted_fs_data)171 int restore_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data)
172 {
173     return ENCRYPTED_FS_ERROR;
174 }
175 // open a given path, mounting partitions as necessary
176 static FILE*
fopen_path(const char * path,const char * mode)177 fopen_path(const char *path, const char *mode)
178 {
179     if (ensure_path_mounted(path) != 0) {
180         LOGE("Can't mount %s\n", path);
181         return NULL;
182     }
183 
184     // When writing, try to create the containing directory, if necessary.
185     // Use generous permissions, the system (init.rc) will reset them.
186     if (strchr("wa", mode[0])) dirCreateHierarchy(path, 0777, NULL, 1);
187 
188     FILE *fp = fopen(path, mode);
189     return fp;
190 }
191 
192 // close a file, log an error if the error indicator is set
193 static void
check_and_fclose(FILE * fp,const char * name)194 check_and_fclose(FILE *fp, const char *name)
195 {
196     fflush(fp);
197     if (ferror(fp)) LOGE("Error in %s\n(%s)\n", name, strerror(errno));
198     fclose(fp);
199 }
200 
201 // rockchip partition check (e.g: oem/userdata....)
202 static void
rockchip_partition_check()203 rockchip_partition_check()
204 {
205     if (ensure_path_unmounted("/oem") != 0)
206         LOGE("\n === umount oem fail === \n");
207 
208     if (ensure_path_unmounted("/userdata") != 0)
209         LOGE("\n === umount userdata fail === \n");
210 
211     ui_print("check userdata/oem partition success ...\n");
212     LOGI("check userdata/oem partition success ...\n");
213 }
214 
215 // command line args come from, in decreasing precedence:
216 //   - the actual command line
217 //   - the bootloader control block (one per line, after "recovery")
218 //   - the contents of COMMAND_FILE (one per line)
219 static void
get_args(int * argc,char *** argv)220 get_args(int *argc, char ***argv)
221 {
222     struct bootloader_message boot;
223     memset(&boot, 0, sizeof(boot));
224     get_bootloader_message(&boot);  // this may fail, leaving a zeroed structure
225 
226     if (boot.command[0] != 0 && boot.command[0] != 255) {
227         LOGI("Boot command: %.*s\n", (int)sizeof(boot.command), boot.command);
228     }
229 
230     if (boot.status[0] != 0 && boot.status[0] != 255) {
231         LOGI("Boot status: %.*s\n", (int)sizeof(boot.status), boot.status);
232     }
233 
234     // --- if arguments weren't supplied, look in the bootloader control block
235     if (*argc <= 1) {
236         boot.recovery[sizeof(boot.recovery) - 1] = '\0';  // Ensure termination
237         const char *arg = strtok(boot.recovery, "\n");
238         if (arg != NULL && !strcmp(arg, "recovery")) {
239             *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
240             (*argv)[0] = strdup(arg);
241             for (*argc = 1; *argc < MAX_ARGS; ++*argc) {
242                 if ((arg = strtok(NULL, "\n")) == NULL) break;
243                 (*argv)[*argc] = strdup(arg);
244             }
245             LOGI("Got arguments from boot message\n");
246         } else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) {
247             LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery);
248         }
249     }
250 
251     // --- if that doesn't work, try the command file
252     if (*argc <= 1) {
253         FILE *fp = fopen_path(COMMAND_FILE, "r");
254         if (fp != NULL) {
255             char *argv0 = (*argv)[0];
256             *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
257             (*argv)[0] = argv0;  // use the same program name
258 
259             char buf[MAX_ARG_LENGTH];
260             for (*argc = 1; *argc < MAX_ARGS; ++*argc) {
261                 if (!fgets(buf, sizeof(buf), fp)) break;
262                 (*argv)[*argc] = strdup(strtok(buf, "\r\n"));  // Strip newline.
263             }
264 
265             check_and_fclose(fp, COMMAND_FILE);
266             LOGI("Got arguments from %s\n", COMMAND_FILE);
267         }
268     }
269 
270     // --> write the arguments we have back into the bootloader control block
271     // always boot into recovery after this (until finish_recovery() is called)
272     strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
273     strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
274     int i;
275     for (i = 1; i < *argc; ++i) {
276         strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery));
277         strlcat(boot.recovery, "\n", sizeof(boot.recovery));
278     }
279     set_bootloader_message(&boot);
280 }
281 
282 static void
set_sdcard_update_bootloader_message()283 set_sdcard_update_bootloader_message()
284 {
285     struct bootloader_message boot;
286     memset(&boot, 0, sizeof(boot));
287     strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
288     strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
289     set_bootloader_message(&boot);
290 }
291 
292 // How much of the temp log we have copied to the copy in cache.
293 static long tmplog_offset = 0;
294 
295 static void
copy_log_file(const char * destination,int append)296 copy_log_file(const char* destination, int append)
297 {
298     FILE *log = fopen_path(destination, append ? "a" : "w");
299     if (log == NULL) {
300         LOGE("Can't open %s\n", destination);
301     } else {
302         FILE *tmplog = fopen(TEMPORARY_LOG_FILE, "r");
303         if (tmplog == NULL) {
304             LOGE("Can't open %s\n", TEMPORARY_LOG_FILE);
305         } else {
306             if (append) {
307                 fseek(tmplog, tmplog_offset, SEEK_SET);  // Since last write
308             }
309             char buf[4096];
310             while (fgets(buf, sizeof(buf), tmplog)) fputs(buf, log);
311             if (append) {
312                 tmplog_offset = ftell(tmplog);
313             }
314             check_and_fclose(tmplog, TEMPORARY_LOG_FILE);
315         }
316         check_and_fclose(log, destination);
317     }
318 }
319 
320 
321 // clear the recovery command and prepare to boot a (hopefully working) system,
322 // copy our log file to cache as well (for the system to read), and
323 // record any intent we were asked to communicate back to the system.
324 // this function is idempotent: call it as many times as you like.
325 static void
finish_recovery(const char * send_intent)326 finish_recovery(const char *send_intent)
327 {
328     // By this point, we're ready to return to the main system...
329     if (send_intent != NULL) {
330         FILE *fp = fopen_path(INTENT_FILE, "w");
331         if (fp == NULL) {
332             LOGE("Can't open %s\n", INTENT_FILE);
333         } else {
334             fputs(send_intent, fp);
335             check_and_fclose(fp, INTENT_FILE);
336         }
337     }
338 
339     LOGI("finish_recovery Enter.....\n");
340 
341     // Copy logs to cache so the system can find out what happened.
342     copy_log_file(LOG_FILE, true);
343     copy_log_file(LAST_LOG_FILE, false);
344     chmod(LAST_LOG_FILE, 0640);
345 
346     // Reset to mormal system boot so recovery won't cycle indefinitely.
347     struct bootloader_message boot;
348     memset(&boot, 0, sizeof(boot));
349     strlcpy(boot.systemFlag, systemFlag, sizeof(boot.systemFlag));
350     set_bootloader_message(&boot);
351 
352     // Remove the command file, so recovery won't repeat indefinitely.
353     if (ensure_path_mounted(COMMAND_FILE) != 0 ||
354         (unlink(COMMAND_FILE) && errno != ENOENT)) {
355         LOGW("Can't unlink %s\n", COMMAND_FILE);
356     }
357 
358     sync();  // For good measure.
359 }
360 
361 static int
erase_volume(const char * volume)362 erase_volume(const char *volume)
363 {
364     ui_set_background(BACKGROUND_ICON_INSTALLING);
365     ui_show_indeterminate_progress();
366     ui_print("Formatting %s...\n", volume);
367 
368     if (strcmp(volume, "/userdata") == 0) {
369         // Any part of the log we'd copied to data is now gone.
370         // Reset the pointer so we copy from the beginning of the temp
371         // log.
372         tmplog_offset = 0;
373     }
374 
375     return format_volume(volume);
376 }
377 
378 static char*
copy_sideloaded_package(const char * original_path)379 copy_sideloaded_package(const char* original_path)
380 {
381     if (ensure_path_mounted(original_path) != 0) {
382         LOGE("Can't mount %s\n", original_path);
383         return NULL;
384     }
385 
386     if (ensure_path_mounted(SIDELOAD_TEMP_DIR) != 0) {
387         LOGE("Can't mount %s\n", SIDELOAD_TEMP_DIR);
388         return NULL;
389     }
390 
391     if (mkdir(SIDELOAD_TEMP_DIR, 0700) != 0) {
392         if (errno != EEXIST) {
393             LOGE("Can't mkdir %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno));
394             return NULL;
395         }
396     }
397 
398     // verify that SIDELOAD_TEMP_DIR is exactly what we expect: a
399     // directory, owned by root, readable and writable only by root.
400     struct stat st;
401     if (stat(SIDELOAD_TEMP_DIR, &st) != 0) {
402         LOGE("failed to stat %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno));
403         return NULL;
404     }
405     if (!S_ISDIR(st.st_mode)) {
406         LOGE("%s isn't a directory\n", SIDELOAD_TEMP_DIR);
407         return NULL;
408     }
409     if ((st.st_mode & 0777) != 0700) {
410         LOGE("%s has perms %o\n", SIDELOAD_TEMP_DIR, st.st_mode);
411         return NULL;
412     }
413     if (st.st_uid != 0) {
414         LOGE("%s owned by %u; not root\n", SIDELOAD_TEMP_DIR, st.st_uid);
415         return NULL;
416     }
417 
418     char copy_path[PATH_MAX];
419     strcpy(copy_path, SIDELOAD_TEMP_DIR);
420     strcat(copy_path, "/package.zip");
421 
422     char* buffer = malloc(BUFSIZ);
423     if (buffer == NULL) {
424         LOGE("Failed to allocate buffer\n");
425         return NULL;
426     }
427 
428     size_t read;
429     FILE* fin = fopen(original_path, "rb");
430     if (fin == NULL) {
431         LOGE("Failed to open %s (%s)\n", original_path, strerror(errno));
432         return NULL;
433     }
434     FILE* fout = fopen(copy_path, "wb");
435     if (fout == NULL) {
436         LOGE("Failed to open %s (%s)\n", copy_path, strerror(errno));
437         return NULL;
438     }
439 
440     while ((read = fread(buffer, 1, BUFSIZ, fin)) > 0) {
441         if (fwrite(buffer, 1, read, fout) != read) {
442             LOGE("Short write of %s (%s)\n", copy_path, strerror(errno));
443             return NULL;
444         }
445     }
446 
447     free(buffer);
448 
449     if (fclose(fout) != 0) {
450         LOGE("Failed to close %s (%s)\n", copy_path, strerror(errno));
451         return NULL;
452     }
453 
454     if (fclose(fin) != 0) {
455         LOGE("Failed to close %s (%s)\n", original_path, strerror(errno));
456         return NULL;
457     }
458 
459     // "adb push" is happy to overwrite read-only files when it's
460     // running as root, but we'll try anyway.
461     if (chmod(copy_path, 0400) != 0) {
462         LOGE("Failed to chmod %s (%s)\n", copy_path, strerror(errno));
463         return NULL;
464     }
465 
466     return strdup(copy_path);
467 }
468 
469 static char**
prepend_title(const char ** headers)470 prepend_title(const char** headers)
471 {
472     char* title[] = { "Linux system recovery <"
473                       EXPAND(RECOVERY_API_VERSION) "e>",
474                       "",
475                       NULL
476                     };
477 
478     // count the number of lines in our title, plus the
479     // caller-provided headers.
480     int count = 0;
481     char** p;
482     for (p = title; *p; ++p, ++count);
483     for (p = (char** )headers; *p; ++p, ++count);
484 
485     char** new_headers = malloc((count + 1) * sizeof(char*));
486     char** h = new_headers;
487     for (p = title; *p; ++p, ++h) *h = *p;
488     for (p = (char** )headers; *p; ++p, ++h) *h = *p;
489     *h = NULL;
490 
491     return new_headers;
492 }
493 
494 static int
get_menu_selection(char ** headers,char ** items,int menu_only,int initial_selection)495 get_menu_selection(char** headers, char** items, int menu_only,
496                    int initial_selection)
497 {
498     // throw away keys pressed previously, so user doesn't
499     // accidentally trigger menu items.
500     ui_clear_key_queue();
501 
502     ui_start_menu(headers, items, initial_selection);
503     int selected = initial_selection;
504     int chosen_item = -1;
505 
506     while (chosen_item < 0) {
507         int key = ui_wait_key();
508         int visible = ui_text_visible();
509 
510         int action = device_handle_key(key, visible);
511 
512         if (action < 0) {
513             switch (action) {
514             case HIGHLIGHT_UP:
515                 --selected;
516                 selected = ui_menu_select(selected);
517                 break;
518             case HIGHLIGHT_DOWN:
519                 ++selected;
520                 selected = ui_menu_select(selected);
521                 break;
522             case SELECT_ITEM:
523                 chosen_item = selected;
524                 break;
525             case NO_ACTION:
526                 break;
527             }
528         } else if (!menu_only) {
529             chosen_item = action;
530         }
531     }
532 
533     ui_end_menu();
534     return chosen_item;
535 }
536 
compare_string(const void * a,const void * b)537 static int compare_string(const void* a, const void* b)
538 {
539     return strcmp(*(const char**)a, *(const char**)b);
540 }
541 
542 static int
sdcard_directory(const char * path)543 sdcard_directory(const char* path)
544 {
545     ensure_path_mounted(SDCARD_ROOT);
546 
547     const char* MENU_HEADERS[] = { "Choose a package to install:",
548                                    path,
549                                    "",
550                                    NULL
551                                  };
552     DIR* d;
553     struct dirent* de;
554     d = opendir(path);
555     if (d == NULL) {
556         LOGE("error opening %s: %s\n", path, strerror(errno));
557         ensure_path_unmounted(SDCARD_ROOT);
558         return 0;
559     }
560 
561     char** headers = prepend_title(MENU_HEADERS);
562 
563     int d_size = 0;
564     int d_alloc = 10;
565     char** dirs = malloc(d_alloc * sizeof(char*));
566     int z_size = 1;
567     int z_alloc = 10;
568     char** zips = malloc(z_alloc * sizeof(char*));
569     zips[0] = strdup("../");
570 
571     while ((de = readdir(d)) != NULL) {
572         int name_len = strlen(de->d_name);
573 
574         if (de->d_type == DT_DIR) {
575             // skip "." and ".." entries
576             if (name_len == 1 && de->d_name[0] == '.') continue;
577             if (name_len == 2 && de->d_name[0] == '.' &&
578                 de->d_name[1] == '.') continue;
579 
580             if (d_size >= d_alloc) {
581                 d_alloc *= 2;
582                 dirs = realloc(dirs, d_alloc * sizeof(char*));
583             }
584             dirs[d_size] = malloc(name_len + 2);
585             strcpy(dirs[d_size], de->d_name);
586             dirs[d_size][name_len] = '/';
587             dirs[d_size][name_len + 1] = '\0';
588             ++d_size;
589         } else if (de->d_type == DT_REG &&
590                    name_len >= 4 &&
591                    strncasecmp(de->d_name + (name_len - 4), ".zip", 4) == 0) {
592             if (z_size >= z_alloc) {
593                 z_alloc *= 2;
594                 zips = realloc(zips, z_alloc * sizeof(char*));
595             }
596             zips[z_size++] = strdup(de->d_name);
597         }
598     }
599     closedir(d);
600 
601     qsort(dirs, d_size, sizeof(char*), compare_string);
602     qsort(zips, z_size, sizeof(char*), compare_string);
603 
604     // append dirs to the zips list
605     if (d_size + z_size + 1 > z_alloc) {
606         z_alloc = d_size + z_size + 1;
607         zips = realloc(zips, z_alloc * sizeof(char*));
608     }
609     memcpy(zips + z_size, dirs, d_size * sizeof(char*));
610     free(dirs);
611     z_size += d_size;
612     zips[z_size] = NULL;
613 
614     int result;
615     int chosen_item = 0;
616     do {
617         chosen_item = get_menu_selection(headers, zips, 1, chosen_item);
618 
619         char* item = zips[chosen_item];
620         int item_len = strlen(item);
621         if (chosen_item == 0) {          // item 0 is always "../"
622             // go up but continue browsing (if the caller is sdcard_directory)
623             result = -1;
624             break;
625         } else if (item[item_len - 1] == '/') {
626             // recurse down into a subdirectory
627             char new_path[PATH_MAX];
628             strlcpy(new_path, path, PATH_MAX);
629             strlcat(new_path, "/", PATH_MAX);
630             strlcat(new_path, item, PATH_MAX);
631             new_path[strlen(new_path) - 1] = '\0'; // truncate the trailing '/'
632             result = sdcard_directory(new_path);
633             if (result >= 0) break;
634         } else {
635             // selected a zip file:  attempt to install it, and return
636             // the status to the caller.
637             char new_path[PATH_MAX];
638             strlcpy(new_path, path, PATH_MAX);
639             strlcat(new_path, "/", PATH_MAX);
640             strlcat(new_path, item, PATH_MAX);
641 
642             ui_print("\n-- Install %s ...\n", path);
643             set_sdcard_update_bootloader_message();
644             char* copy = copy_sideloaded_package(new_path);
645             ensure_path_unmounted(SDCARD_ROOT);
646             if (copy) {
647                 //result = install_package(copy);
648                 free(copy);
649             } else {
650                 result = INSTALL_ERROR;
651             }
652             break;
653         }
654     } while (true);
655 
656     int i;
657     for (i = 0; i < z_size; ++i) free(zips[i]);
658     free(zips);
659     free(headers);
660 
661     ensure_path_unmounted(SDCARD_ROOT);
662     return result;
663 }
664 
665 static void
wipe_data(int confirm)666 wipe_data(int confirm)
667 {
668     if (confirm) {
669         static char** title_headers = NULL;
670 
671         if (title_headers == NULL) {
672             char* headers[] = { "Confirm wipe of all user data?",
673                                 "  THIS CAN NOT BE UNDONE.",
674                                 "",
675                                 NULL
676                               };
677             title_headers = prepend_title((const char**)headers);
678         }
679 
680         char* items[] = { " No",
681                           " No",
682                           " No",
683                           " No",
684                           " No",
685                           " No",
686                           " No",
687                           " Yes -- delete all user data",   // [7]
688                           " No",
689                           " No",
690                           " No",
691                           NULL
692                         };
693 
694         int chosen_item = get_menu_selection(title_headers, items, 1, 0);
695         if (chosen_item != 7) {
696             return;
697         }
698     }
699 
700     ui_print("\n-- Wiping data...\n");
701     device_wipe_data();
702     erase_volume("/userdata");
703     ui_print("Data wipe complete.\n");
704 }
705 
ui_update(const char * fw_package)706 static int ui_update(const char * fw_package)
707 {
708     const char* binary = "/usr/bin/rkupdate";
709     int i, ret = 0;
710     int status = INSTALL_SUCCESS;
711 
712     for (i = 0; i < 5; i++) {
713         ret = ensure_path_mounted(fw_package);
714         if (ret == 0)
715             break;
716         sleep(1);
717         LOGD("mounted %s failed.\n", fw_package);
718     }
719 
720     if (ret == 0 && access(fw_package, F_OK) == 0) {
721         LOGD(">>>rkflash will update from %s\n", fw_package);
722 #ifdef USE_RKUPDATE
723         status = do_rk_update(binary, fw_package);
724 #endif
725 
726 #ifdef USE_UPDATEENGINE
727         const char* updateEnginebin = "/usr/bin/updateEngine";
728         status = do_rk_updateEngine(updateEnginebin, fw_package);
729 #endif
730         if (status == INSTALL_SUCCESS) {
731             strcpy(systemFlag, fw_package);
732             /* update success, delete update.img */
733             if (access(fw_package, F_OK) == 0)
734                 remove(fw_package);
735         }
736     } else {
737         status = INSTALL_ERROR;
738     }
739 
740     if (status != INSTALL_SUCCESS) {
741         ui_print("Installation aborted.\n");
742         while (1) {
743             /* code */
744         }
745 
746         return -1;
747     }
748     ui_print("update.img Installation done.\n");
749     ui_show_text(0);
750 
751     return 0;
752 }
753 
754 static void
prompt_and_wait()755 prompt_and_wait()
756 {
757     char** headers = prepend_title((const char**)MENU_HEADERS);
758 
759     for (;;) {
760         finish_recovery(NULL);
761         ui_reset_progress();
762 
763         int chosen_item = get_menu_selection(headers, MENU_ITEMS, 0, 0);
764 
765         // device-specific code may take some action here.  It may
766         // return one of the core actions handled in the switch
767         // statement below.
768         chosen_item = device_perform_action(chosen_item);
769 
770         switch (chosen_item) {
771         case ITEM_REBOOT:
772             return;
773 
774         case ITEM_WIPE_DATA:
775             wipe_data(ui_text_visible());
776             if (!ui_text_visible()) return;
777             break;
778 
779         case ITEM_APPLY_SDCARD: {
780             int status = sdcard_directory(SDCARD_ROOT);
781             if (status >= 0) {
782                 if (status != INSTALL_SUCCESS) {
783                     ui_set_background(BACKGROUND_ICON_ERROR);
784                     ui_print("Installation aborted.\n");
785                 } else if (!ui_text_visible()) {
786                     return;  // reboot if logs aren't visible
787                 } else {
788                     ui_print("\nInstall from sdcard complete.\n");
789                 }
790             }
791         }
792         break;
793 
794         case ITEM_APPLY_USERDATA: {
795             //update firmware from local userdata;
796             const char* fw_package = "/userdata/update.img";
797             // LOGD("%s:%d:-------->>>>> USERDATA update\n",__func__, __LINE__);
798             int status = ui_update(fw_package);
799             if (status < 0) {
800                 ui_set_background(BACKGROUND_ICON_ERROR);
801             } else if (!ui_text_visible()) {
802                 return;  // reboot if logs aren't visible
803             } else {
804                 ui_print("\nInstall from sdcard complete.\n");
805             }
806         }
807         break;
808 
809         case ITEM_APPLY_UDISK: {
810             //update firmware from udisk;
811             const char* fw_package = "/udisk/update.img";
812             // LOGD("%s:%d:-------->>>> UDISK update\n",__func__, __LINE__);
813             int status = ui_update(fw_package);
814             if (status < 0) {
815                 ui_set_background(BACKGROUND_ICON_ERROR);
816             } else if (!ui_text_visible()) {
817                 ui_print("\nInstall from sdcard complete.\n");
818                 return;  // reboot if logs aren't visible
819             } else {
820                 ui_print("\nInstall from sdcard complete.\n");
821             }
822         }
823         break;
824         }
825     }
826 }
827 
828 static void
print_property(const char * key,const char * name,void * cookie)829 print_property(const char *key, const char *name, void *cookie)
830 {
831     printf("%s=%s\n", key, name);
832 }
833 
834 
835 int
main(int argc,char ** argv)836 main(int argc, char **argv)
837 {
838     bool bSDBoot    = false;
839     bool bUDiskBoot = false;
840     const char *sdupdate_package = NULL;
841     const char *usbupdate_package = NULL;
842     int previous_runs = 0;
843     const char *send_intent = NULL;
844     const char *update_package = NULL;
845     const char *encrypted_fs_mode = NULL;
846     int wipe_data = 0;
847     int wipe_all = 0;
848     int pcba_test = 0;  // add for pcba test
849     int toggle_secure_fs = 0;
850     int arg;
851     bool isrkdebug = false;
852     int log_level = LOG_DEBUG;
853     encrypted_fs_info encrypted_fs_data;
854     struct timeval start_time, end_time;
855     long long elapsed_time;
856 
857     gettimeofday(&start_time, NULL);
858 
859     get_args(&argc, &argv);
860     strcpy(systemFlag, "false");
861     while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
862         switch (arg) {
863         case 'p':
864             previous_runs = atoi(optarg);
865             break;
866         case 's':
867             send_intent = optarg;
868             break;
869         case 'u':
870             update_package = optarg;
871             break;
872         case 'w':
873             wipe_data = 1;
874             break;
875         case 'a':
876             wipe_all = 1;
877             break;
878         case 'e':
879             encrypted_fs_mode = optarg;
880             toggle_secure_fs = 1;
881             break;
882         case 't':
883             ui_show_text(1);
884             break;
885         case 'f':
886             pcba_test = 1;
887             break;  // add for pcba test
888         case 'r':
889             isrkdebug = true;
890             break;
891         case 'i':
892             gr_set_rotate(atoi(optarg));
893             break;
894         case '?':
895             LOGE("Invalid command argument\n");
896             continue;
897         }
898     }
899 
900     time_t start = time(NULL);
901     if ((access("/.rkdebug", F_OK) != 0) && (isrkdebug != true)) {
902         // If these fail, there's not really anywhere to complain...
903         if (freopen(TEMPORARY_LOG_FILE, "a", stdout) == NULL) {
904             LOGW("freopen stdout error");
905         }
906         setbuf(stdout, NULL);
907         if (freopen(TEMPORARY_LOG_FILE, "a", stderr) == NULL) {
908             LOGE("freopen stderr error");
909         }
910         setbuf(stderr, NULL);
911     }
912 
913     printf("\n");
914     printf("*********************************************************\n");
915     printf("            ROCKCHIP recovery system                     \n");
916     printf("*********************************************************\n");
917     printf("**** version : %s ****\n", recovery_version);
918 
919     LOGI("Starting recovery on %s\n", ctime(&start));
920     while (access(coldboot_done, F_OK) != 0) {
921         LOGI("coldboot not done, wait...\n");
922         sleep(1);
923     }
924 
925 #ifndef RecoveryNoUi
926     LOGI("Recovery System have UI defined.\n");
927 #endif
928 
929     ui_init();
930     ui_set_background(BACKGROUND_ICON_INSTALLING);
931     load_volume_table();
932     setFlashPoint();
933 
934     bSDBoot = is_boot_from_SD();
935     bUDiskBoot = is_boot_from_udisk();
936 
937     if (bSDBoot || bUDiskBoot) {
938         char imageFile[64] = {0};
939         if (bSDBoot) {
940             if (is_sdcard_update()) {
941                 strlcpy(imageFile, EX_SDCARD_ROOT, sizeof(imageFile));
942                 strlcat(imageFile, "/sdupdate.img", sizeof(imageFile));
943                 if (access(imageFile, F_OK) == 0) {
944                     sdupdate_package = strdup(imageFile);
945                     bSDBootUpdate = true;
946                     ui_show_text(1);
947                     LOGI("sdupdate_package = %s\n", sdupdate_package);
948                 }
949             }
950         }
951 
952         if (bUDiskBoot) {
953             if (is_udisk_update()) {
954                 strlcpy(imageFile, EX_UDISK_ROOT, sizeof(imageFile));
955                 strlcat(imageFile, "/sdupdate.img", sizeof(imageFile));
956                 if (access(imageFile, F_OK) == 0) {
957                     usbupdate_package = strdup(imageFile);
958                     bUdiskUpdate = true;
959                     ui_show_text(1);
960                     LOGI("usbupdate_package = %s\n", usbupdate_package);
961                 }
962             }
963         }
964     }
965 
966     device_recovery_start();
967 	system("echo default-on > /sys/class/leds/work/trigger");
968 
969     LOGI("Command:");
970     for (arg = 0; arg < argc; arg++) {
971         printf(" \"%s\"", argv[arg]);
972     }
973     printf("\n");
974 
975     if (update_package) {
976         // For backwards compatibility on the cache partition only, if
977         // we're given an old 'root' path "CACHE:foo", change it to
978         // "/cache/foo".
979         if (strncmp(update_package, "CACHE:", 6) == 0) {
980             int len = strlen(update_package) + 10;
981             char* modified_path = malloc(len);
982             strlcpy(modified_path, "/cache/", len);
983             strlcat(modified_path, update_package + 6, len);
984             LOGI("(replacing path \"%s\" with \"%s\")\n",
985                  update_package, modified_path);
986             update_package = modified_path;
987         }
988     }
989     printf("\n");
990 
991     int status = INSTALL_SUCCESS;
992 
993     if (toggle_secure_fs) {
994         if (strcmp(encrypted_fs_mode, "on") == 0) {
995             encrypted_fs_data.mode = MODE_ENCRYPTED_FS_ENABLED;
996             ui_print("Enabling Encrypted FS.\n");
997         } else if (strcmp(encrypted_fs_mode, "off") == 0) {
998             encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;
999             ui_print("Disabling Encrypted FS.\n");
1000         } else {
1001             ui_print("Error: invalid Encrypted FS setting.\n");
1002             status = INSTALL_ERROR;
1003         }
1004 
1005         // Recovery strategy: if the data partition is damaged, disable encrypted file systems.
1006         // This preventsthe device recycling endlessly in recovery mode.
1007         if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&
1008             (read_encrypted_fs_info(&encrypted_fs_data))) {
1009             ui_print("Encrypted FS change aborted, resetting to disabled state.\n");
1010             encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;
1011         }
1012 
1013         if (status != INSTALL_ERROR) {
1014             if (erase_volume("/userdata")) {
1015                 ui_print("Data wipe failed.\n");
1016                 status = INSTALL_ERROR;
1017 #if 0
1018             } else if (erase_volume("/cache")) {
1019                 ui_print("Cache wipe failed.\n");
1020                 status = INSTALL_ERROR;
1021 #endif
1022             } else if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&
1023                        (restore_encrypted_fs_info(&encrypted_fs_data))) {
1024                 ui_print("Encrypted FS change aborted.\n");
1025                 status = INSTALL_ERROR;
1026             } else {
1027                 ui_print("Successfully updated Encrypted FS.\n");
1028                 status = INSTALL_SUCCESS;
1029             }
1030         }
1031     } else if (update_package != NULL) {
1032         int i, ret = 0;
1033         const char* binary = "/usr/bin/rkupdate";
1034 
1035         rockchip_partition_check();
1036 
1037         for (i = 0; i < 5; i++) {
1038             if (!ensure_path_mounted(update_package)) {
1039                 LOGI("mounted %s Success.\n", update_package);
1040                 break;
1041             }
1042             LOGW("mounted %s Failed. retry %d\n", update_package, i + 1);
1043             sleep(1);
1044         }
1045         if (i != 5) {
1046             LOGI(">>>rkflash will update from %s\n", update_package);
1047 #ifdef USE_RKUPDATE
1048             status = do_rk_update(binary, update_package);
1049 #endif
1050 #ifdef USE_UPDATEENGINE
1051             const char* updateEnginebin = "/usr/bin/updateEngine";
1052             status = do_rk_updateEngine(updateEnginebin, update_package);
1053 #endif
1054             if (status == INSTALL_SUCCESS) {
1055                 strcpy(systemFlag, update_package);
1056                 /* update success, delete update.img. */
1057                 if (access(update_package, F_OK) == 0)
1058                     remove(update_package);
1059                 ui_print("update.img images success!\n");
1060             } else {
1061                 ui_print("update.img images failed!\n");
1062             }
1063         } else {
1064             LOGE("mounted %s Failed.\n", update_package);
1065             ui_print("mounted %s Failed.\n", update_package);
1066         }
1067 
1068         if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n");
1069         ui_print("update.img Installation done.\n");
1070         //ui_show_text(0);
1071     } else if (sdupdate_package != NULL) {
1072         rockchip_partition_check();
1073 
1074         // update image from sdcard
1075 #ifdef USE_RKUPDATE
1076         const char* binary = "/usr/bin/rkupdate";
1077         LOGI(">>>sdboot update will update from %s\n", sdupdate_package);
1078         status = do_rk_update(binary, sdupdate_package);
1079 #endif
1080 
1081 #ifdef USE_UPDATEENGINE
1082 #undef FACTORY_FIRMWARE_IMAGE
1083 #undef CMD4RECOVERY_FILENAME
1084 #define FACTORY_FIRMWARE_IMAGE "/mnt/sdcard/out_image.img"
1085 #define CMD4RECOVERY_FILENAME "/mnt/sdcard/cmd4recovery"
1086         if ((access(FACTORY_FIRMWARE_IMAGE, F_OK)) && access(CMD4RECOVERY_FILENAME, F_OK)) {
1087             int tmp_fd = creat(CMD4RECOVERY_FILENAME, 0777);
1088             if (tmp_fd < 0) {
1089                 LOGE("creat %s error.\n", CMD4RECOVERY_FILENAME);
1090                 status = INSTALL_ERROR;
1091             } else {
1092                 close(tmp_fd);
1093                 const char* updateEnginebin = "/usr/bin/updateEngine";
1094                 status = do_rk_updateEngine(updateEnginebin, sdupdate_package);
1095             }
1096         }
1097 
1098         if (isMtdDevice()) {
1099             LOGI("start flash write to /dev/mtd0.\n");
1100             size_t total_size;
1101             size_t erase_size;
1102             mtd_scan_partitions();
1103             const MtdPartition *part = mtd_find_partition_by_name("rk-nand");
1104             if ( part == NULL ) {
1105                 part = mtd_find_partition_by_name("spi-nand0");
1106             }
1107             if (part == NULL || mtd_partition_info(part, &total_size, &erase_size, NULL)) {
1108                 if ((!access(FACTORY_FIRMWARE_IMAGE, F_OK)) && mtd_find_partition_by_name("sfc_nor") != NULL) {
1109                     LOGI("Info: start flash out_image.img to spi nor.\n");
1110                     system("flashcp -v " FACTORY_FIRMWARE_IMAGE " /dev/mtd0");
1111                 } else
1112                     LOGE("Error: Can't find rk-nand or spi-nand0.\n");
1113             } else {
1114                 system("flash_erase /dev/mtd0 0x0 0");
1115                 system("sh "CMD4RECOVERY_FILENAME);
1116             }
1117         } else {
1118             LOGI("Start to dd data to emmc partition.\n");
1119             system("sh "CMD4RECOVERY_FILENAME);
1120             LOGI("sdcard upgrade done\n");
1121         }
1122 
1123 #endif
1124 
1125         if (status == INSTALL_SUCCESS) {
1126             LOGI("update.img Installation success.\n");
1127             ui_print("update.img Installation success.\n");
1128             //ui_show_text(0);
1129         }
1130 
1131     } else if (usbupdate_package != NULL) {
1132         rockchip_partition_check();
1133         // update image from udisk
1134 #ifdef USE_RKUPDATE
1135         const char* binary = "/usr/bin/rkupdate";
1136         LOGI(">>>sdboot update will update from %s\n", usbupdate_package);
1137         status = do_rk_update(binary, usbupdate_package);
1138 #endif
1139 
1140 #ifdef USE_UPDATEENGINE
1141 #undef FACTORY_FIRMWARE_IMAGE
1142 #undef CMD4RECOVERY_FILENAME
1143 #define FACTORY_FIRMWARE_IMAGE "/mnt/usb_storage/out_image.img"
1144 #define CMD4RECOVERY_FILENAME "/mnt/usb_storage/cmd4recovery"
1145         if ((access(FACTORY_FIRMWARE_IMAGE, F_OK)) && access(CMD4RECOVERY_FILENAME, F_OK)) {
1146             int tmp_fd = creat(CMD4RECOVERY_FILENAME, 0777);
1147             if (tmp_fd < 0) {
1148                 LOGE("creat %s error.\n", CMD4RECOVERY_FILENAME);
1149                 status = INSTALL_ERROR;
1150             } else {
1151                 close(tmp_fd);
1152                 const char* updateEnginebin = "/usr/bin/updateEngine";
1153                 status = do_rk_updateEngine(updateEnginebin, usbupdate_package);
1154             }
1155         }
1156 
1157         if (isMtdDevice()) {
1158             LOGI("start flash write to /dev/mtd0.\n");
1159             size_t total_size;
1160             size_t erase_size;
1161             mtd_scan_partitions();
1162             const MtdPartition *part = mtd_find_partition_by_name("rk-nand");
1163             if ( part == NULL ) {
1164                 part = mtd_find_partition_by_name("spi-nand0");
1165             }
1166             if (part == NULL || mtd_partition_info(part, &total_size, &erase_size, NULL)) {
1167                 if ((!access(FACTORY_FIRMWARE_IMAGE, F_OK)) && mtd_find_partition_by_name("sfc_nor") != NULL) {
1168                     LOGI("Info: start flash out_image.img to spi nor.\n");
1169                     system("flashcp -v " FACTORY_FIRMWARE_IMAGE " /dev/mtd0");
1170                 } else
1171                     LOGE("Error: Can't find rk-nand or spi-nand0.\n");
1172             } else {
1173                 system("flash_erase /dev/mtd0 0x0 0");
1174                 system("sh "CMD4RECOVERY_FILENAME);
1175             }
1176         } else {
1177             LOGI("Start to dd data to emmc partition.\n");
1178             system("sh "CMD4RECOVERY_FILENAME);
1179             LOGI("usb upgrade done\n");
1180         }
1181 #endif
1182 
1183         if (status == INSTALL_SUCCESS) {
1184             LOGI("update.img Installation success.\n");
1185             ui_print("update.img Installation success.\n");
1186             //ui_show_text(0);
1187         }
1188     } else if (wipe_data) {
1189         if (device_wipe_data()) status = INSTALL_ERROR;
1190 //        if (erase_volume("/userdata")) status = INSTALL_ERROR;
1191         if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n");
1192     } else if (wipe_all) {
1193         if (device_wipe_data()) status = INSTALL_ERROR;
1194 //        if (erase_volume("/userdata")) status = INSTALL_ERROR;
1195         if (status != INSTALL_SUCCESS) {
1196             ui_print("Data wipe failed.\n");
1197             LOGE("userdata wipe failed.\n");
1198         } else {
1199             ui_print("Data wipe done.\n");
1200             LOGI("userdata wipe done.\n");
1201         }
1202 
1203         //ui_show_text(0);
1204     } else if (pcba_test) {
1205         //pcba test todo...
1206         printf("------------------ pcba test start -------------\n");
1207         exit(EXIT_SUCCESS); //exit recovery bin directly, not start pcba here, in rkLanuch.sh
1208         return 0;
1209     } else {
1210         if (argc == 1) { // No command specified
1211             if (!bSDBootUpdate && !bUdiskUpdate && ui_text_visible())
1212                 prompt_and_wait();
1213             finish_recovery(NULL);
1214             reboot(RB_AUTOBOOT);
1215             return 0;
1216         }
1217         status = INSTALL_ERROR;  // No command specified
1218     }
1219 
1220     if (status != INSTALL_SUCCESS) ui_set_background(BACKGROUND_ICON_ERROR);
1221     if (status != INSTALL_SUCCESS) {
1222         LOGE("\n Install fail! \n");
1223         if (!bSDBootUpdate && !bUdiskUpdate && ui_text_visible())
1224             prompt_and_wait();
1225     }
1226 
1227     if (sdupdate_package != NULL && bSDBootUpdate) {
1228         if (status == INSTALL_SUCCESS) {
1229             char *SDDdevice =
1230                 strdup(get_mounted_device_from_path(EX_SDCARD_ROOT));
1231 
1232             ensure_ex_path_unmounted(EX_SDCARD_ROOT);
1233             /* Updating is finished here, we must print this message
1234              * in console, it shows user a specific message that
1235              * updating is completely, remove SD CARD and reboot */
1236             fflush(stdout);
1237             freopen("/dev/console", "w", stdout);
1238             LOGI("\nPlease remove SD CARD!!!, wait for reboot.\n");
1239             ui_print("Please remove SD CARD!!!, wait for reboot.");
1240 
1241 	    	if (access(SDDdevice, F_OK) == 0){
1242                                system("echo heartbeat >  /sys/class/leds/work/trigger");
1243             		 printf("{ \"PROGRAM\":\"OK\"} \n");
1244 
1245 		}
1246 
1247             while (access(SDDdevice, F_OK) == 0) { sleep(1); }
1248             free(SDDdevice);
1249         }
1250     } else if (usbupdate_package && bUdiskUpdate) {
1251         if (status == INSTALL_SUCCESS) {
1252             char *udiskDev = strdup(get_mounted_device_from_path(EX_SDCARD_ROOT));
1253             ensure_path_unmounted(EX_UDISK_ROOT);
1254             /* Updating is finished here, we must print this message
1255              * in console, it shows user a specific message that
1256              * updating is completely, remove U-disk and reboot */
1257             fflush(stdout);
1258             freopen("/dev/console", "w", stdout);
1259             LOGI("\nPlease remove U DISK!!!, wait for reboot.\n");
1260             ui_print("Please remove U DISK!!!, wait for reboot.");
1261 
1262             while (access(udiskDev, F_OK) == 0) { sleep(1); }
1263             free(udiskDev);
1264         }
1265     }
1266 
1267     // Otherwise, get ready to boot the main system...
1268     finish_recovery(send_intent);
1269     gettimeofday(&end_time, NULL);
1270 
1271     elapsed_time = (end_time.tv_sec - start_time.tv_sec) * 1000LL +
1272                    (end_time.tv_usec - start_time.tv_usec) / 1000LL;
1273     LOGI("recovery usage time:%lld ms\n", elapsed_time);
1274     ui_print("Rebooting...\n");
1275     LOGI("Reboot...\n");
1276     ui_show_text(0);
1277     fflush(stdout);
1278     sync();
1279     reboot(RB_AUTOBOOT);
1280     return EXIT_SUCCESS;
1281 }
1282