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); }
// 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); }
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; }
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 recovery_preboot(void) { int ret = 0, i = 0; char *str = "boot-recovery"; int len = sizeof(struct bootloader_message); struct bootloader_message *bm = (struct bootloader_message *)malloc(len); printf("checking mode for recovery ...\n"); memset((void *)bm, 0, len); ret = get_bootloader_message((void *)bm, len); if(ret != 0) { printf("[Lenovo] Fail to read recovery flag\n"); return -1; } #ifdef DEBUG_RECOVERY char *p = (char *)bm; printf("bootloader_message len : %d\n", len); printf("bootloader_message:"); printf("\n command:"); for (i = 0; i < 32; i++) printf("%c", *(p+i)); printf("\n status:"); for (i = 32; i < 32 + 32; i++) printf("%c", *(p+i)); printf("\n recovery:"); for (i = 32 + 32; i < 32 + 32 + 1024; i++) printf("%c", *(p+i)); printf("\n"); #endif if (!memcmp((void *)bm, (void *)str, strlen(str))) return 0; if(0xABABABAA == get_inform4()) return 0; 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); }