int maybe_install_firmware_update(const char *send_intent) { if (update_data == NULL || update_length == 0) return 0; /* We destroy the cache partition to pass the update image to the * bootloader, so all we can really do afterwards is wipe cache and reboot. * Set up this instruction now, in case we're interrupted while writing. */ struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n--wipe_cache\n", sizeof(boot.command)); if (send_intent != NULL) { strlcat(boot.recovery, "--send_intent=", sizeof(boot.recovery)); strlcat(boot.recovery, send_intent, sizeof(boot.recovery)); strlcat(boot.recovery, "\n", sizeof(boot.recovery)); } if (set_bootloader_message(&boot)) return -1; int width = 0, height = 0, bpp = 0; char *busy_image = ui_copy_image( BACKGROUND_ICON_FIRMWARE_INSTALLING, &width, &height, &bpp); char *fail_image = ui_copy_image( BACKGROUND_ICON_FIRMWARE_ERROR, &width, &height, &bpp); ui_print("Writing %s image...\n", update_type); if (write_update_for_bootloader( update_data, update_length, width, height, bpp, busy_image, fail_image)) { LOGE("Can't write %s image\n(%s)\n", update_type, strerror(errno)); format_volume("/cache"); // Attempt to clean cache up, at least. return -1; } free(busy_image); free(fail_image); /* The update image is fully written, so now we can instruct the bootloader * to install it. (After doing so, it will come back here, and we will * wipe the cache and reboot into the system.) */ snprintf(boot.command, sizeof(boot.command), "update-%s", update_type); if (set_bootloader_message(&boot)) { format_volume("/cache"); return -1; } reboot(RB_AUTOBOOT); // Can't reboot? WTF? LOGE("Can't reboot\n"); return -1; }
void TWFunc::Update_Log_File(void) { // Copy logs to cache so the system can find out what happened. if (PartitionManager.Mount_By_Path("/cache", false)) { if (!TWFunc::Path_Exists("/cache/recovery/.")) { LOGINFO("Recreating /cache/recovery folder.\n"); if (mkdir("/cache/recovery", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0) LOGINFO("Unable to create /cache/recovery folder.\n"); } Copy_Log(TMP_LOG_FILE, "/cache/recovery/log"); copy_file("/cache/recovery/log", "/cache/recovery/last_log", 600); chown("/cache/recovery/log", 1000, 1000); chmod("/cache/recovery/log", 0600); chmod("/cache/recovery/last_log", 0640); } else { LOGINFO("Failed to mount /cache for TWFunc::Update_Log_File\n"); } // Reset bootloader message TWPartition* Part = PartitionManager.Find_Partition_By_Path("/misc"); if (Part != NULL) { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); if (set_bootloader_message(&boot) != 0) LOGERR("Unable to set bootloader message.\n"); } if (PartitionManager.Mount_By_Path("/cache", true)) { if (unlink("/cache/recovery/command") && errno != ENOENT) { LOGINFO("Can't unlink %s\n", "/cache/recovery/command"); } } sync(); }
STATUS wipe_item_show(menuUnit *p) { /* OPPO 2013-01-17 jizhengkang azx Add begin for reason */ struct bootloader_message boot; /* OPPO 2013-01-17 jizhengkang Add end */ int wipe_result; oppo_debug("start .....\n"); if (RET_YES == oppo_confirm(3, p->name, p->desc, p->icon)) { wipe_result = oppo_wipe_items(p->result); /* OPPO 2013-01-17 jizhengkang azx Add begin for reason */ if (!(wipe_result%2)) { memset(&boot, 0, sizeof(boot)); set_bootloader_message(&boot); strncpy(p->title_name, "<~wipe.result.success.title>", MENU_LEN); } else { strncpy(p->title_name, "<~wipe.result.failed.title>", MENU_LEN); } /* OPPO 2013-01-17 jizhengkang Add end */ wipe_result_confirm(p, wipe_result); wipe_item_show_end = 1; selectedCount--; } /* OPPO 2013-02-18 jizhengkang azx Add begin for reason */ selectedCount--; /* OPPO 2013-02-18 jizhengkang azx Add end */ oppo_debug("end...\n"); return MENU_BACK; }
/* Write bootloader paramenter block */ int mt_set_bootloader_message(const char *command, const char *status, const char *stage, const char *fmt, ...) { int ret; int i; struct bootloader_message boot; va_list vl; memset(&boot, 0, sizeof(boot)); if (command) strlcpy(boot.command, command, sizeof(boot.command)); if (status) strlcpy(boot.status, status, sizeof(boot.status)); if (stage) strlcpy(boot.stage, stage, sizeof(boot.stage)); if (fmt) { va_start(vl, fmt); ret = vsprintf(boot.recovery, fmt, vl); va_end(vl); } ret = set_bootloader_message(&boot); sync(); return ret; }
// clear the recovery command and prepare to boot a (hopefully working) system, // copy our log file to cache as well (for the system to read), and // record any intent we were asked to communicate back to the system. // this function is idempotent: call it as many times as you like. static void finish_recovery(const char *send_intent) { // By this point, we're ready to return to the main system... if (send_intent != NULL) { FILE *fp = fopen_path(INTENT_FILE, "w"); if (fp == NULL) { LOGE("Can't open %s\n", INTENT_FILE); } else { fputs(send_intent, fp); check_and_fclose(fp, INTENT_FILE); } } // Copy logs to cache so the system can find out what happened. copy_log_file(LOG_FILE, true); copy_log_file(LAST_LOG_FILE, false); chmod(LAST_LOG_FILE, 0640); // Reset to normal system boot so recovery won't cycle indefinitely. struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); set_bootloader_message(&boot); // Remove the command file, so recovery won't repeat indefinitely. if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) { LOGW("Can't unlink %s\n", COMMAND_FILE); } sync(); // For good measure. }
static void reset_mark_block(void) { // Reset the bootloader message to revert to a normal main system boot. struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); set_bootloader_message(&boot); sync(); }
static void set_sdcard_update_bootloader_message() { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); set_bootloader_message(&boot); }
int install_firmware_update(const char *update_type, const char *update_data, size_t update_length, int width, int height, int bpp, const char* busy_image, const char* fail_image, const char *log_filename) { if (update_data == NULL || update_length == 0) return 0; mtd_scan_partitions(); /* We destroy the cache partition to pass the update image to the * bootloader, so all we can really do afterwards is wipe cache and reboot. * Set up this instruction now, in case we're interrupted while writing. */ struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n--wipe_cache\n", sizeof(boot.command)); if (set_bootloader_message(&boot)) return -1; if (write_update_for_bootloader( update_data, update_length, width, height, bpp, busy_image, fail_image, log_filename)) { LOGE("Can't write %s image\n(%s)\n", update_type, strerror(errno)); return -1; } /* The update image is fully written, so now we can instruct the bootloader * to install it. (After doing so, it will come back here, and we will * wipe the cache and reboot into the system.) */ snprintf(boot.command, sizeof(boot.command), "update-%s", update_type); if (set_bootloader_message(&boot)) { return -1; } reboot(RB_AUTOBOOT); // Can't reboot? WTF? LOGE("Can't reboot\n"); return -1; }
static void get_args(int *argc, char ***argv) { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); get_bootloader_message(&boot); // this may fail, leaving a zeroed structure if (boot.command[0] != 0 && boot.command[0] != 255) LOGI("Boot command: %.*s\n", sizeof(boot.command), boot.command); if (boot.status[0] != 0 && boot.status[0] != 255) LOGI("Boot status: %.*s\n", sizeof(boot.status), boot.status); // --- if arguments weren't supplied, look in the bootloader control block if (*argc <= 1) { boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination const char *arg = strtok(boot.recovery, "\n"); if (arg != NULL && !strcmp(arg, "recovery")) { *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = strdup(arg); for (*argc = 1; *argc < MAX_ARGS; ++*argc) { if ((arg = strtok(NULL, "\n")) == NULL) break; (*argv)[*argc] = strdup(arg); } LOGI("Got arguments from boot message\n"); } else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery); } // --- if that doesn't work, try the command file if (*argc <= 1) get_cmd_file_args(argc, argv); // --> write the arguments we have back into the bootloader control block // always boot into recovery after this (until finish_recovery() is called) strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); int i; for (i = 1; i < *argc; ++i) { strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery)); strlcat(boot.recovery, "\n", sizeof(boot.recovery)); } set_bootloader_message(&boot); }
static void reset_deltaupdate_recovery_bootmessage(void) { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); LOGI("Resetting recovery boot...\n"); set_bootloader_message(&boot); LOGI("boot.command=%s\n",boot.command); LOGI("boot.recovery=%s\n",boot.recovery); }
// command line args come from, in decreasing precedence: // - the actual command line // - the bootloader control block (one per line, after "recovery") // - the contents of COMMAND_FILE (one per line) static void get_args(int *argc, char ***argv) { if (*argc > 1) return; // actual command line arguments take priority char *argv0 = (*argv)[0]; struct bootloader_message boot; if (!get_bootloader_message(&boot)) { if (boot.command[0] != 0 && boot.command[0] != 255) { LOGI("Boot command: %.*s\n", sizeof(boot.command), boot.command); } if (boot.status[0] != 0 && boot.status[0] != 255) { LOGI("Boot status: %.*s\n", sizeof(boot.status), boot.status); } // Ensure that from here on, a reboot goes back into recovery strcpy(boot.command, "boot-recovery"); set_bootloader_message(&boot); boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination const char *arg = strtok(boot.recovery, "\n"); if (arg != NULL && !strcmp(arg, "recovery")) { *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; for (*argc = 1; *argc < MAX_ARGS; ++*argc) { if ((arg = strtok(NULL, "\n")) == NULL) break; (*argv)[*argc] = strdup(arg); } LOGI("Got arguments from boot message\n"); return; } else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) { LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery); } } FILE *fp = fopen_root_path(COMMAND_FILE, "r"); if (fp == NULL) return; *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; // use the same program name char buf[MAX_ARG_LENGTH]; for (*argc = 1; *argc < MAX_ARGS && fgets(buf, sizeof(buf), fp); ++*argc) { (*argv)[*argc] = strdup(strtok(buf, "\r\n")); // Strip newline. } check_and_fclose(fp, COMMAND_FILE); LOGI("Got arguments from %s\n", COMMAND_FILE); }
// clear the recovery command and prepare to boot a (hopefully working) system, // copy our log file to cache as well (for the system to read), and // record any intent we were asked to communicate back to the system. // this function is idempotent: call it as many times as you like. static void finish_recovery(const char *send_intent) { // By this point, we're ready to return to the main system... if (send_intent != NULL) { FILE *fp = fopen_root_path(INTENT_FILE, "w"); if (fp == NULL) { LOGE("Can't open %s\n", INTENT_FILE); } else { fputs(send_intent, fp); check_and_fclose(fp, INTENT_FILE); } } // Copy logs to cache so the system can find out what happened. FILE *log = fopen_root_path(LOG_FILE, "a"); if (log == NULL) { LOGE("Can't open %s\n", LOG_FILE); } else { FILE *tmplog = fopen(TEMPORARY_LOG_FILE, "r"); if (tmplog == NULL) { LOGE("Can't open %s\n", TEMPORARY_LOG_FILE); } else { static long tmplog_offset = 0; fseek(tmplog, tmplog_offset, SEEK_SET); // Since last write char buf[4096]; while (fgets(buf, sizeof(buf), tmplog)) fputs(buf, log); tmplog_offset = ftell(tmplog); check_and_fclose(tmplog, TEMPORARY_LOG_FILE); } check_and_fclose(log, LOG_FILE); } #ifndef BOARD_HAS_NO_MISC_PARTITION // Reset to mormal system boot so recovery won't cycle indefinitely. struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); set_bootloader_message(&boot); #endif // Remove the command file, so recovery won't repeat indefinitely. char path[PATH_MAX] = ""; if (ensure_root_path_mounted(COMMAND_FILE) != 0 || translate_root_path(COMMAND_FILE, path, sizeof(path)) == NULL || (unlink(path) && errno != ENOENT)) { LOGW("Can't unlink %s\n", COMMAND_FILE); } sync(); // For good measure. }
// clear the recovery command and prepare to boot a (hopefully working) system, // copy our log file to cache as well (for the system to read), and // record any intent we were asked to communicate back to the system. // this function is idempotent: call it as many times as you like. static void finish_recovery(const char *send_intent) { // By this point, we're ready to return to the main system... if (send_intent != NULL) { FILE *fp = fopen_path(INTENT_FILE, "w"); if (fp == NULL) { LOGE("Can't open %s\n", INTENT_FILE); } else { fputs(send_intent, fp); check_and_fclose(fp, INTENT_FILE); } } // Save the locale to cache, so if recovery is next started up // without a --locale argument (eg, directly from the bootloader) // it will use the last-known locale. if (locale != NULL) { LOGI("Saving locale \"%s\"\n", locale); FILE* fp = fopen_path(LOCALE_FILE, "w"); fwrite(locale, 1, strlen(locale), fp); fflush(fp); fsync(fileno(fp)); check_and_fclose(fp, LOCALE_FILE); } // Copy logs to cache so the system can find out what happened. copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true); copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false); copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false); chmod(LOG_FILE, 0600); chown(LOG_FILE, 1000, 1000); // system user chmod(LAST_LOG_FILE, 0640); chmod(LAST_INSTALL_FILE, 0644); // Reset to normal system boot so recovery won't cycle indefinitely. struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); set_bootloader_message(&boot); // Remove the command file, so recovery won't repeat indefinitely. if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) { LOGW("Can't unlink %s\n", COMMAND_FILE); } ensure_path_unmounted(CACHE_ROOT); sync(); // For good measure. }
int main(int argc, char *argv[]) { struct bootloader_message boot; const char *command = 0, *status = 0, *recovery = 0; int opt, write = 0; while ((opt = getopt(argc, argv, "c:s:r:wh")) != -1) { switch (opt) { case 'c': command = strdup(optarg); break; case 's': status = strdup(optarg); break; case 'r': recovery = strdup(optarg); break; case 'w': write = 1; break; case 'h': usage(); return 0; default: usage(); return -1; } } memset(&boot, 0, sizeof(boot)); get_bootloader_message(&boot); if (write) { if (command) strncpy(boot.command, command, sizeof(boot.command)); if (status) strncpy(boot.status, status, sizeof(boot.status)); if (recovery) strncpy(boot.recovery, recovery, sizeof(boot.recovery)); set_bootloader_message(&boot); } else { fprintf(stdout, "command=%s\nstatus=%s\nrecovery=%s\n", boot.command, boot.status, boot.recovery); } return 0; }
static void set_deltaupdate_recovery_bootmessage(void) { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); LOGI("Setting recovery boot...\n"); if(MAX_NUM_UPDATE_RECOVERY > get_deltaupdate_recoverycount()) { strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); } else { LOGI("Recovery mode reached maximum retry. Clear boot message.\n"); } set_bootloader_message(&boot); LOGI("boot.command=%s\n",boot.command); LOGI("boot.recovery=%s\n",boot.recovery); }
MOTOBOX_CONFIG_ERR_T set_recovery() { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); if(get_bootloader_message(&boot)) { return MOTOBOX_CONFIG_ERR_SET_RECOVERY; } if (boot.command[0] != 0 && boot.command[0] != 255) { LOGI("Boot command: %.*s\n", sizeof(boot.command), boot.command); if( !strcmp(boot.command,"boot-recovery")){ /* already been set to boot-recovery to the command file */ if(set_cache_command() != MOTOBOX_CONFIG_ERR_NONE) { return MOTOBOX_CONFIG_ERR_SET_RECOVERY; } } else { /* not boot-recovery command, we quit it */ LOGE("Busy, try setconfig later"); return MOTOBOX_CONFIG_ERR_SET_RECOVERY; } } else { /* misc is clean , set the boot-recovery command */ char command_buf[255]; memset(command_buf, 0, sizeof(command_buf)); strncpy(command_buf, RECOVERY_COMMAND, sizeof(command_buf)-1); memset(&boot, 0, sizeof(boot)); strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, command_buf, sizeof(boot.recovery)); if (set_bootloader_message(&boot)) { return MOTOBOX_CONFIG_ERR_SET_RECOVERY; } } return MOTOBOX_CONFIG_ERR_NONE; }
int start_firmware_update(char *update_type, char *part_type) { int result; struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); if(!strcmp(part_type, "mtd")) { mtd_scan_partitions(); strlcpy(boot.recovery, "recovery\n--radio_status\n", sizeof(boot.command)); snprintf(boot.command, sizeof(boot.command), "update-%s", update_type); if (set_bootloader_message(&boot)) { return -1; } } else if(!strcmp(part_type, "emmc")) { Volume *v = NULL; load_volume_table(); v = volume_for_path("/sys_boot"); if (strcmp(v->fs_type, "vfat")) { LOGE("Error in fs_type for sys_boot partition\n"); return -1; } mkdir("/sys_boot", 777); /* Try mounting device first */ result = mount(v->device, v->mount_point, v->fs_type, MS_NOATIME | MS_NODEV | MS_NODIRATIME, ""); if(result) { /* Try mounting device2 next */ result = mount(v->device2, v->mount_point, v->fs_type, MS_NOATIME | MS_NODEV | MS_NODIRATIME, ""); } if(result == 0) { /* Creating cookie file for radio update */ FILE *fp = fopen("/sys_boot/upcookie.txt", "w"); fclose(fp); /* Unmount the sdcard now */ if(umount(v->mount_point)) { LOGE("Error in unmounting %s\n",v->mount_point); return -1; } else LOGI("Created cookie file for eMMC radio update\n"); } else { LOGE("Error in mounting %s\n",v->mount_point); return -1; } memset(&boot, 0, sizeof(boot)); v = volume_for_path("/misc"); if (set_bootloader_message_emmc(&boot, v)) { return -1; } } else { LOGE("Error in part_type %s\n",part_type); return -1; } sync(); reboot(RB_AUTOBOOT); // Can't reboot? WTF? LOGE("Can't reboot\n"); return -1; }
// command line args come from, in decreasing precedence: // - the actual command line // - the bootloader control block (one per line, after "recovery") // - the contents of COMMAND_FILE (one per line) static void get_args(int *argc, char ***argv) { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); get_bootloader_message(&boot); // this may fail, leaving a zeroed structure stage = strndup(boot.stage, sizeof(boot.stage)); if (boot.command[0] != 0 && boot.command[0] != 255) { LOGI("Boot command: %.*s\n", (int)sizeof(boot.command), boot.command); } if (boot.status[0] != 0 && boot.status[0] != 255) { LOGI("Boot status: %.*s\n", (int)sizeof(boot.status), boot.status); } // --- if arguments weren't supplied, look in the bootloader control block if (*argc <= 1) { boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination const char *arg = strtok(boot.recovery, "\n"); if (arg != NULL && !strcmp(arg, "recovery")) { *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = strdup(arg); for (*argc = 1; *argc < MAX_ARGS; ++*argc) { if ((arg = strtok(NULL, "\n")) == NULL) break; (*argv)[*argc] = strdup(arg); } LOGI("Got arguments from boot message\n"); } else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) { LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery); } } // --- if that doesn't work, try the command file if (*argc <= 1) { FILE *fp = fopen_path(COMMAND_FILE, "r"); if (fp != NULL) { char *token; char *argv0 = (*argv)[0]; *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; // use the same program name char buf[MAX_ARG_LENGTH]; for (*argc = 1; *argc < MAX_ARGS; ++*argc) { if (!fgets(buf, sizeof(buf), fp)) break; token = strtok(buf, "\r\n"); if (token != NULL) { (*argv)[*argc] = strdup(token); // Strip newline. } else { --*argc; } } check_and_fclose(fp, COMMAND_FILE); LOGI("Got arguments from %s\n", COMMAND_FILE); } } // --> write the arguments we have back into the bootloader control block // always boot into recovery after this (until finish_recovery() is called) strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); int i; for (i = 1; i < *argc; ++i) { strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery)); strlcat(boot.recovery, "\n", sizeof(boot.recovery)); } set_bootloader_message(&boot); }
// command line args come from, in decreasing precedence: // - the actual command line // - the bootloader control block (one per line, after "recovery") // - the contents of COMMAND_FILE (one per line) static void get_args(int *argc, char ***argv) { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); get_bootloader_message(&boot); // this may fail, leaving a zeroed structure if (boot.command[0] != 0 && boot.command[0] != 255) { LOGI("Boot command: %.*s\n", sizeof(boot.command), boot.command); } if (boot.status[0] != 0 && boot.status[0] != 255) { LOGI("Boot status: %.*s\n", sizeof(boot.status), boot.status); } // --- if arguments weren't supplied, look in the bootloader control block if (*argc <= 1) { boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination const char *arg = strtok(boot.recovery, "\n"); if (arg != NULL && !strcmp(arg, "recovery")) { *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = strdup(arg); for (*argc = 1; *argc < MAX_ARGS; ++*argc) { if ((arg = strtok(NULL, "\n")) == NULL) break; (*argv)[*argc] = strdup(arg); } LOGI("Got arguments from boot message\n"); } else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) { LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery); } } // --- if that doesn't work, try the command file form bootloader:recovery_command if (*argc <= 1) { char *parg = NULL; char *recovery_command = fw_getenv ("recovery_command"); if (recovery_command != NULL && strcmp(recovery_command, "")) { char *argv0 = (*argv)[0]; *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; // use the same program name char buf[MAX_ARG_LENGTH]; strcpy(buf, recovery_command); if((parg = strtok(buf, "#")) == NULL){ LOGE("Bad bootloader arguments\n\"%.20s\"\n", recovery_command); }else{ (*argv)[1] = strdup(parg); // Strip newline. for (*argc = 2; *argc < MAX_ARGS; ++*argc) { if((parg = strtok(NULL, "#")) == NULL){ break; }else{ (*argv)[*argc] = strdup(parg); // Strip newline. } } LOGI("Got arguments from bootloader\n"); } } else { LOGE("Bad bootloader arguments\n\"%.20s\"\n", recovery_command); } } // --- if that doesn't work, try the command file char * temp_args =NULL; if (*argc <= 1) { FILE *fp = fopen_path(COMMAND_FILE, "r"); if (fp != NULL) { char *argv0 = (*argv)[0]; *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; // use the same program name char buf[MAX_ARG_LENGTH]; for (*argc = 1; *argc < MAX_ARGS; ) { if (!fgets(buf, sizeof(buf), fp)) break; temp_args = strtok(buf, "\r\n"); if(temp_args == NULL) continue; (*argv)[*argc] = strdup(temp_args); // Strip newline. ++*argc; } check_and_fclose(fp, COMMAND_FILE); LOGI("Got arguments from %s\n", COMMAND_FILE); } } // -- sleep 1 second to ensure SD card initialization complete usleep(1000000); // --- if that doesn't work, try the sdcard command file if (*argc <= 1) { FILE *fp = fopen_path(SDCARD_COMMAND_FILE, "r"); if (fp != NULL) { char *argv0 = (*argv)[0]; *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; // use the same program name char buf[MAX_ARG_LENGTH]; for (*argc = 1; *argc < MAX_ARGS; ) { if (!fgets(buf, sizeof(buf), fp)) break; temp_args = strtok(buf, "\r\n"); if(temp_args == NULL) continue; (*argv)[*argc] = strdup(temp_args); // Strip newline. ++*argc; } check_and_fclose(fp, SDCARD_COMMAND_FILE); LOGI("Got arguments from %s\n", SDCARD_COMMAND_FILE); } } // --- if that doesn't work, try the udisk command file if (*argc <= 1) { FILE *fp = fopen_path(UDISK_COMMAND_FILE, "r"); if (fp != NULL) { char *argv0 = (*argv)[0]; *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; // use the same program name char buf[MAX_ARG_LENGTH]; for (*argc = 1; *argc < MAX_ARGS; ) { if (!fgets(buf, sizeof(buf), fp)) break; temp_args = strtok(buf, "\r\n"); if(temp_args == NULL) continue; (*argv)[*argc] = strdup(temp_args); // Strip newline. ++*argc; } check_and_fclose(fp, UDISK_COMMAND_FILE); LOGI("Got arguments from %s\n", UDISK_COMMAND_FILE); } } // --- if no argument, then force show_text if (*argc <= 1) { char *argv0 = (*argv)[0]; *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; // use the same program name (*argv)[1] = "--show_text"; *argc = 2; } // --> write the arguments we have back into the bootloader control block // always boot into recovery after this (until finish_recovery() is called) strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); int i; for (i = 1; i < *argc; ++i) { strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery)); strlcat(boot.recovery, "\n", sizeof(boot.recovery)); } set_bootloader_message(&boot); }
int main(int argc, char **argv) { if (strcmp(basename(argv[0]), "recovery") != 0) { if (strstr(argv[0], "flash_image") != NULL) return flash_image_main(argc, argv); if (strstr(argv[0], "dump_image") != NULL) return dump_image_main(argc, argv); if (strstr(argv[0], "erase_image") != NULL) return erase_image_main(argc, argv); if (strstr(argv[0], "mkyaffs2image") != NULL) return mkyaffs2image_main(argc, argv); if (strstr(argv[0], "unyaffs") != NULL) return unyaffs_main(argc, argv); if (strstr(argv[0], "nandroid")) return nandroid_main(argc, argv); if (strstr(argv[0], "reboot")) return reboot_main(argc, argv); #ifdef BOARD_RECOVERY_HANDLES_MOUNT if (strstr(argv[0], "mount") && argc == 2 && !strstr(argv[0], "umount")) { load_volume_table(); return ensure_path_mounted(argv[1]); } #endif if (strstr(argv[0], "poweroff")){ return reboot_main(argc, argv); } } __system("/sbin/postrecoveryboot.sh"); time_t start = time(NULL); // If these fail, there's not really anywhere to complain... #ifndef DEBUG unlink(TEMPORARY_LOG_FILE); #endif freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); printf("Starting recovery on %s", ctime(&start)); //miuiIntent init miuiIntent_init(10); miuiIntent_register(INTENT_MOUNT, &intent_mount); miuiIntent_register(INTENT_ISMOUNT, &intent_ismount); miuiIntent_register(INTENT_UNMOUNT, &intent_unmount); miuiIntent_register(INTENT_REBOOT, &intent_reboot); miuiIntent_register(INTENT_INSTALL, &intent_install); miuiIntent_register(INTENT_WIPE, &intent_wipe); miuiIntent_register(INTENT_TOGGLE, &intent_toggle); miuiIntent_register(INTENT_FORMAT, &intent_format); miuiIntent_register(INTENT_RESTORE, &intent_restore); miuiIntent_register(INTENT_BACKUP, &intent_backup); miuiIntent_register(INTENT_ADVANCED_BACKUP, &intent_advanced_backup); miuiIntent_register(INTENT_SYSTEM, &intent_system); miuiIntent_register(INTENT_COPY, &intent_copy); device_ui_init(); load_volume_table(); get_args(&argc, &argv); struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); set_bootloader_message(&boot); create_fstab(); int previous_runs = 0; const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0; int arg; 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 = wipe_cache = 1; break; case 'c': wipe_cache = 1; break; //case 't': ui_show_text(1); break; case '?': LOGE("Invalid command argument\n"); continue; } } device_recovery_start(); printf("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); printf("(replacing path \"%s\" with \"%s\")\n", update_package, modified_path); update_package = modified_path; } } printf("\n"); property_list(print_property, NULL); printf("\n"); int status = INSTALL_SUCCESS; if (update_package != NULL) { if (wipe_cache) erase_volume("/cache"); miuiIntent_send(INTENT_INSTALL, 3, update_package,"0", "0"); //if echo 0 ,don't print success dialog status = miuiIntent_result_get_int(); if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n"); } else if (wipe_data) { if (device_wipe_data()) status = INSTALL_ERROR; if (erase_volume("/data")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n"); } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Cache wipe failed.\n"); } else { status = INSTALL_ERROR; // No command specified } if (status != INSTALL_SUCCESS) device_main_ui_show();//show menu device_main_ui_release(); // Otherwise, get ready to boot the main system... finish_recovery(send_intent); ui_print("Rebooting...\n"); android_reboot(ANDROID_RB_RESTART, 0, 0); return EXIT_SUCCESS; }