int install_zip(const char* packagefilepath) { ui_print("\n-- Installing: %s\n", packagefilepath); set_sdcard_update_bootloader_message(); // will ensure_path_mounted(packagefilepath) // will also set background icon to installing and indeterminate progress bar int wipe_cache = 0; int status = install_package(packagefilepath, &wipe_cache, TEMPORARY_INSTALL_FILE); ui_reset_progress(); if (status != INSTALL_SUCCESS) { copy_logs(); ui_set_background(BACKGROUND_ICON_ERROR); LOGE("Installation aborted.\n"); return 1; } else if (wipe_cache && erase_volume("/cache")) { LOGE("Cache wipe (requested by package) failed.\n"); } #ifdef PHILZ_TOUCH_RECOVERY if (show_background_icon.value) ui_set_background(BACKGROUND_ICON_CLOCKWORK); else #endif ui_set_background(BACKGROUND_ICON_NONE); ui_print("\nInstall from sdcard complete.\n"); return 0; }
// 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(); // 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 read_logs(char **argv){ void *logs; int i,j; uint8_t temp; copy_logs(); memcpy(&table_dest, &table, sizeof(struct copy_table)); return 0; }
// 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(); // 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) { time_t start = time(NULL); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); // If this binary is started with the single argument "--adbd", // instead of being the normal recovery binary, it turns into kind // of a stripped-down version of adbd that only supports the // 'sideload' command. Note this must be a real argument, not // anything in the command file or bootloader control block; the // only way recovery should be run with this argument is when it // starts a copy of itself from the apply_from_adb() function. if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { adb_main(); return 0; } printf("Starting recovery on %s", ctime(&start)); load_volume_table(); ensure_path_mounted(LAST_LOG_FILE); rotate_last_logs(10); get_args(&argc, &argv); const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0, show_text = 0; bool just_exit = false; bool shutdown_after = false; int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { 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': show_text = 1; break; case 'x': just_exit = true; break; case 'l': locale = optarg; break; case 'g': { if (stage == NULL || *stage == '\0') { char buffer[20] = "1/"; strncat(buffer, optarg, sizeof(buffer)-3); stage = strdup(buffer); } break; } case 'p': shutdown_after = true; break; case '?': LOGE("Invalid command argument\n"); continue; } } if (locale == NULL) { load_locale_from_cache(); } printf("locale is [%s]\n", locale); printf("stage is [%s]\n", stage, stage); Device* device = make_device(); ui = device->GetUI(); gCurrentUI = ui; ui->SetLocale(locale); ui->Init(); int st_cur, st_max; if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) { ui->SetStage(st_cur, st_max); } ui->SetBackground(RecoveryUI::NONE); if (show_text) ui->ShowText(true); struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { ui->Print("Warning: No file_contexts\n"); } device->StartRecovery(); 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 = (char*)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); property_get("ro.build.display.id", recovery_version, ""); printf("\n"); int status = INSTALL_SUCCESS; if (update_package != NULL) { status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE); if (status == INSTALL_SUCCESS && wipe_cache) { if (erase_volume("/cache")) { LOGE("Cache wipe (requested by package) failed."); } } if (status != INSTALL_SUCCESS) { ui->Print("Installation aborted.\n"); // If this is an eng or userdebug build, then automatically // turn the text display on if the script fails so the error // message is visible. char buffer[PROPERTY_VALUE_MAX+1]; property_get("ro.build.fingerprint", buffer, ""); if (strstr(buffer, ":userdebug/") || strstr(buffer, ":eng/")) { ui->ShowText(true); } } } else if (wipe_data) { if (device->WipeData()) 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 if (!just_exit) { status = INSTALL_NONE; // No command specified ui->SetBackground(RecoveryUI::NO_COMMAND); } if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) { copy_logs(); ui->SetBackground(RecoveryUI::ERROR); } if (status != INSTALL_SUCCESS || ui->IsTextVisible()) { prompt_and_wait(device, status); } // Otherwise, get ready to boot the main system... finish_recovery(send_intent); if (shutdown_after) { ui->Print("Shutting down...\n"); property_set(ANDROID_RB_PROPERTY, "shutdown,"); } else { ui->Print("Rebooting...\n"); property_set(ANDROID_RB_PROPERTY, "reboot,"); } return EXIT_SUCCESS; }
static void prompt_and_wait(Device* device, int status) { const char* const* headers = prepend_title(device->GetMenuHeaders()); for (;;) { finish_recovery(NULL); switch (status) { case INSTALL_SUCCESS: case INSTALL_NONE: ui->SetBackground(RecoveryUI::NO_COMMAND); break; case INSTALL_ERROR: case INSTALL_CORRUPT: ui->SetBackground(RecoveryUI::ERROR); break; } ui->SetProgressType(RecoveryUI::EMPTY); int chosen_item = get_menu_selection(headers, device->GetMenuItems(), 0, 0, device); // device-specific code may take some action here. It may // return one of the core actions handled in the switch // statement below. chosen_item = device->InvokeMenuItem(chosen_item); int wipe_cache; switch (chosen_item) { case Device::REBOOT: return; case Device::WIPE_DATA: wipe_data(ui->IsTextVisible(), device); if (!ui->IsTextVisible()) return; break; case Device::WIPE_CACHE: ui->Print("\n-- Wiping cache...\n"); erase_volume("/cache"); ui->Print("Cache wipe complete.\n"); if (!ui->IsTextVisible()) return; break; case Device::APPLY_EXT: status = update_directory(SDCARD_ROOT, SDCARD_ROOT, &wipe_cache, device); if (status == INSTALL_SUCCESS && wipe_cache) { ui->Print("\n-- Wiping cache (at package request)...\n"); if (erase_volume("/cache")) { ui->Print("Cache wipe failed.\n"); } else { ui->Print("Cache wipe complete.\n"); } } if (status >= 0) { if (status != INSTALL_SUCCESS) { ui->SetBackground(RecoveryUI::ERROR); ui->Print("Installation aborted.\n"); } else if (!ui->IsTextVisible()) { return; // reboot if logs aren't visible } else { ui->Print("\nInstall from sdcard complete.\n"); } } break; case Device::APPLY_CACHE: // Don't unmount cache at the end of this. status = update_directory(CACHE_ROOT, NULL, &wipe_cache, device); if (status == INSTALL_SUCCESS && wipe_cache) { ui->Print("\n-- Wiping cache (at package request)...\n"); if (erase_volume("/cache")) { ui->Print("Cache wipe failed.\n"); } else { ui->Print("Cache wipe complete.\n"); } } if (status >= 0) { if (status != INSTALL_SUCCESS) { ui->SetBackground(RecoveryUI::ERROR); ui->Print("Installation aborted.\n"); } else if (!ui->IsTextVisible()) { return; // reboot if logs aren't visible } else { ui->Print("\nInstall from cache complete.\n"); } } break; case Device::APPLY_ADB_SIDELOAD: status = apply_from_adb(ui, &wipe_cache, TEMPORARY_INSTALL_FILE); if (status >= 0) { if (status != INSTALL_SUCCESS) { ui->SetBackground(RecoveryUI::ERROR); ui->Print("Installation aborted.\n"); copy_logs(); } else if (!ui->IsTextVisible()) { return; // reboot if logs aren't visible } else { ui->Print("\nInstall from ADB complete.\n"); } } break; } } }
static int erase_volume(const char *volume) { bool is_cache = (strcmp(volume, CACHE_ROOT) == 0); ui->SetBackground(RecoveryUI::ERASING); ui->SetProgressType(RecoveryUI::INDETERMINATE); saved_log_file* head = NULL; if (is_cache) { // If we're reformatting /cache, we load any // "/cache/recovery/last*" files into memory, so we can restore // them after the reformat. ensure_path_mounted(volume); DIR* d; struct dirent* de; d = opendir(CACHE_LOG_DIR); if (d) { char path[PATH_MAX]; strcpy(path, CACHE_LOG_DIR); strcat(path, "/"); int path_len = strlen(path); while ((de = readdir(d)) != NULL) { if (strncmp(de->d_name, "last", 4) == 0) { saved_log_file* p = (saved_log_file*) malloc(sizeof(saved_log_file)); strcpy(path+path_len, de->d_name); p->name = strdup(path); if (stat(path, &(p->st)) == 0) { // truncate files to 512kb if (p->st.st_size > (1 << 19)) { p->st.st_size = 1 << 19; } p->data = (unsigned char*) malloc(p->st.st_size); FILE* f = fopen(path, "rb"); fread(p->data, 1, p->st.st_size, f); fclose(f); p->next = head; head = p; } else { free(p); } } } closedir(d); } else { if (errno != ENOENT) { printf("opendir failed: %s\n", strerror(errno)); } } } ui->Print("Formatting %s...\n", volume); ensure_path_unmounted(volume); int result = format_volume(volume); if (is_cache) { while (head) { FILE* f = fopen_path(head->name, "wb"); if (f) { fwrite(head->data, 1, head->st.st_size, f); fclose(f); chmod(head->name, head->st.st_mode); chown(head->name, head->st.st_uid, head->st.st_gid); } free(head->name); free(head->data); saved_log_file* temp = head->next; free(head); head = temp; } // Any part of the log we'd copied to cache is now gone. // Reset the pointer so we copy from the beginning of the temp // log. tmplog_offset = 0; copy_logs(); } return result; }
// Return REBOOT, SHUTDOWN, or REBOOT_BOOTLOADER. Returning NO_ACTION // means to take the default, which is to reboot or shutdown depending // on if the --shutdown_after flag was passed to recovery. static Device::BuiltinAction prompt_and_wait(Device* device, int status) { const char* const* headers = prepend_title(device->GetMenuHeaders()); for (;;) { finish_recovery(NULL); switch (status) { case INSTALL_SUCCESS: case INSTALL_NONE: ui->SetBackground(RecoveryUI::NO_COMMAND); break; case INSTALL_ERROR: case INSTALL_CORRUPT: ui->SetBackground(RecoveryUI::ERROR); break; } ui->SetProgressType(RecoveryUI::EMPTY); int chosen_item = get_menu_selection(headers, device->GetMenuItems(), 0, 0, device); // device-specific code may take some action here. It may // return one of the core actions handled in the switch // statement below. Device::BuiltinAction chosen_action = device->InvokeMenuItem(chosen_item); int wipe_cache = 0; switch (chosen_action) { case Device::NO_ACTION: break; case Device::REBOOT: case Device::SHUTDOWN: case Device::REBOOT_BOOTLOADER: return chosen_action; case Device::WIPE_DATA: wipe_data(ui->IsTextVisible(), device); if (!ui->IsTextVisible()) return Device::NO_ACTION; break; case Device::WIPE_CACHE: ui->Print("\n-- Wiping cache...\n"); erase_volume("/cache"); ui->Print("Cache wipe complete.\n"); if (!ui->IsTextVisible()) return Device::NO_ACTION; break; case Device::APPLY_EXT: { ensure_path_mounted(SDCARD_ROOT); char* path = browse_directory(SDCARD_ROOT, device); if (path == NULL) { ui->Print("\n-- No package file selected.\n", path); break; } ui->Print("\n-- Install %s ...\n", path); set_sdcard_update_bootloader_message(); void* token = start_sdcard_fuse(path); int status = install_package(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache, TEMPORARY_INSTALL_FILE, false); finish_sdcard_fuse(token); ensure_path_unmounted(SDCARD_ROOT); if (status == INSTALL_SUCCESS && wipe_cache) { ui->Print("\n-- Wiping cache (at package request)...\n"); if (erase_volume("/cache")) { ui->Print("Cache wipe failed.\n"); } else { ui->Print("Cache wipe complete.\n"); } } if (status >= 0) { if (status != INSTALL_SUCCESS) { ui->SetBackground(RecoveryUI::ERROR); ui->Print("Installation aborted.\n"); } else if (!ui->IsTextVisible()) { return Device::NO_ACTION; // reboot if logs aren't visible } else { ui->Print("\nInstall from sdcard complete.\n"); } } break; } case Device::APPLY_CACHE: ui->Print("\nAPPLY_CACHE is deprecated.\n"); break; case Device::READ_RECOVERY_LASTLOG: choose_recovery_file(device); break; case Device::APPLY_ADB_SIDELOAD: status = apply_from_adb(ui, &wipe_cache, TEMPORARY_INSTALL_FILE); if (status >= 0) { if (status != INSTALL_SUCCESS) { ui->SetBackground(RecoveryUI::ERROR); ui->Print("Installation aborted.\n"); copy_logs(); } else if (!ui->IsTextVisible()) { return Device::NO_ACTION; // reboot if logs aren't visible } else { ui->Print("\nInstall from ADB complete.\n"); } } break; } } }
int main(int argc, char **argv) { time_t start = time(NULL); // If this binary is started with the single argument "--adbd", // instead of being the normal recovery binary, it turns into kind // of a stripped-down version of adbd that only supports the // 'sideload' command. Note this must be a real argument, not // anything in the command file or bootloader control block; the // only way recovery should be run with this argument is when it // starts a copy of itself from the apply_from_adb() function. if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { adb_main(); return 0; } // Handle alternative invocations char* command = argv[0]; char* stripped = strrchr(argv[0], '/'); if (stripped) command = stripped + 1; if (strcmp(command, "recovery") != 0) { struct recovery_cmd cmd = get_command(command); if (cmd.name) return cmd.main_func(argc, argv); #ifdef BOARD_RECOVERY_HANDLES_MOUNT if (!strcmp(command, "mount") && argc == 2) { load_volume_table(); return ensure_path_mounted(argv[1]); } #endif if (!strcmp(command, "setup_adbd")) { load_volume_table(); setup_adbd(); return 0; } if (strstr(argv[0], "start")) { property_set("ctl.start", argv[1]); return 0; } if (strstr(argv[0], "stop")) { property_set("ctl.stop", argv[1]); return 0; } return busybox_driver(argc, argv); } // devices can run specific tasks on recovery start __system("/sbin/postrecoveryboot.sh"); // Clear umask for packages that copy files out to /tmp and then over // to /system without properly setting all permissions (eg. gapps). umask(0); // If these fail, there's not really anywhere to complain... 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)); load_volume_table(); setup_data_media(1); vold_client_start(&v_callbacks, 0); vold_set_automount(1); setup_legacy_storage_paths(); ensure_path_mounted(LAST_LOG_FILE); rotate_last_logs(10); get_args(&argc, &argv); const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0, wipe_media = 0, show_text = 0, sideload = 0; bool just_exit = false; bool shutdown_after = false; printf("Checking arguments.\n"); int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 's': send_intent = optarg; break; case 'u': update_package = optarg; break; case 'w': wipe_data = wipe_cache = 1; break; case 'm': wipe_media = 1; break; case 'c': wipe_cache = 1; break; case 't': show_text = 1; break; case 'x': just_exit = true; break; case 'a': sideload = 1; break; case 'p': shutdown_after = true; break; case 'g': { if (stage == NULL || *stage == '\0') { char buffer[20] = "1/"; strncat(buffer, optarg, sizeof(buffer)-3); stage = strdup(buffer); } break; } case '?': LOGE("Invalid command argument\n"); continue; } } printf("stage is [%s]\n", stage); device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_MOD_VERSION_BUILD) "\n"); ui_print("ClockworkMod " EXPAND(CWM_BASE_VERSION) "\n"); LOGI("Device target: " EXPAND(TARGET_COMMON_NAME) "\n"); #ifdef PHILZ_TOUCH_RECOVERY print_libtouch_version(0); #endif int st_cur, st_max; if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) { ui_SetStage(st_cur, st_max); } // ui_SetStage(5, 8); // debug if (show_text) ui_ShowText(true); struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { ui_print("Warning: No file_contexts\n"); } LOGI("device_recovery_start()\n"); 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 = (char*)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) { status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE); if (status == INSTALL_SUCCESS && wipe_cache) { if (erase_volume("/cache")) { LOGE("Cache wipe (requested by package) failed.\n"); } } if (status != INSTALL_SUCCESS) { ui_print("Installation aborted.\n"); // If this is an eng or userdebug build, then automatically // turn the text display on if the script fails so the error // message is visible. char buffer[PROPERTY_VALUE_MAX+1]; property_get("ro.build.fingerprint", buffer, ""); if (strstr(buffer, ":userdebug/") || strstr(buffer, ":eng/")) { ui_ShowText(true); } } } else if (wipe_data) { if (device_wipe_data()) status = INSTALL_ERROR; if (erase_volume("/data")) status = INSTALL_ERROR; if (has_datadata() && erase_volume("/datadata")) 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 if (wipe_media) { if (is_data_media() && erase_volume("/data/media")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("Media wipe failed.\n"); } else if (sideload) { status = enter_sideload_mode(status); } else if (!just_exit) { // let's check recovery start up scripts (openrecoveryscript and ROM Manager extendedcommands) status = INSTALL_NONE; // No command specified, it is a normal recovery boot unless we find a boot script to run LOGI("Checking for extendedcommand & OpenRecoveryScript...\n"); // we need show_text to show boot scripts log bool text_visible = ui_IsTextVisible(); ui_SetShowText(true); if (0 == check_boot_script_file(EXTENDEDCOMMAND_SCRIPT)) { LOGI("Running extendedcommand...\n"); status = INSTALL_ERROR; if (0 == run_and_remove_extendedcommand()) status = INSTALL_SUCCESS; } if (0 == check_boot_script_file(ORS_BOOT_SCRIPT_FILE)) { LOGI("Running openrecoveryscript....\n"); status = INSTALL_ERROR; if (0 == run_ors_boot_script()) status = INSTALL_SUCCESS; } ui_SetShowText(text_visible); } if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) { copy_logs(); // ui_set_background(BACKGROUND_ICON_ERROR); // will be set in prompt_and_wait() after recovery lock check handle_failure(); } if (status != INSTALL_SUCCESS || ui_IsTextVisible()) { ui_SetShowText(true); #ifdef PHILZ_TOUCH_RECOVERY check_recovery_lock(); #endif prompt_and_wait(status); } // We reach here when in main menu we choose reboot main system or on success install of boot scripts and recovery commands finish_recovery(send_intent); if (shutdown_after) { ui_print("Shutting down...\n"); reboot_main_system(ANDROID_RB_POWEROFF, 0, 0); } else { ui_print("Rebooting...\n"); reboot_main_system(ANDROID_RB_RESTART, 0, 0); } return EXIT_SUCCESS; }
int main(int argc, char **argv) { if (argc == 2 && strcmp(argv[1], "adbd") == 0) { adb_main(); return 0; } // Recovery needs to install world-readable files, so clear umask // set by init umask(0); char* command = argv[0]; char* stripped = strrchr(argv[0], '/'); if (stripped) command = stripped + 1; if (strcmp(command, "recovery") != 0) { struct recovery_cmd cmd = get_command(command); if (cmd.name) return cmd.main_func(argc, argv); #ifdef BOARD_RECOVERY_HANDLES_MOUNT if (!strcmp(command, "mount") && argc == 2) { load_volume_table(); return ensure_path_mounted(argv[1]); } #endif if (!strcmp(command, "setup_adbd")) { load_volume_table(); setup_adbd(); return 0; } if (!strcmp(command, "start")) { property_set("ctl.start", argv[1]); return 0; } if (!strcmp(command, "stop")) { property_set("ctl.stop", argv[1]); return 0; } return busybox_driver(argc, argv); } //__system("/sbin/postrecoveryboot.sh"); int is_user_initiated_recovery = 0; time_t start = time(NULL); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); printf("Starting recovery on %s\n", ctime(&start)); device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_VERSION)"\n"); ui_print("Builder: "EXPAND(RECOVERY_BUILDER)"\n"); ui_print("Date: "EXPAND(RECOVERY_BUILD_TIME)"\n"); ui_print("weibo:@nx-baby\n"); __system("/sbin/postrecoveryboot.sh"); //#ifdef BOARD_RECOVERY_SWIPE //#ifndef BOARD_TOUCH_RECOVERY //display directions for swipe controls ui_print("Swipe up/down to change selections.\n"); ui_print("Swipe to the right for enter.\n"); ui_print("Swipe to the left for back.\n"); //#endif //#endif load_volume_table(); process_volumes(); vold_init(); setup_legacy_storage_paths(); #ifdef QCOM_HARDWARE parse_t_daemon_data_files(); apply_time_zone(); #endif LOGI("Processing arguments.\n"); ensure_path_mounted(LAST_LOG_FILE); rotate_last_logs(10); get_args(&argc, &argv); const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0; int sideload = 0; int headless = 0; int shutdown_after = 0; LOGI("Checking arguments.\n"); int arg; while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { switch (arg) { case 's': send_intent = optarg; break; case 'u': if (update_package == NULL) update_package = optarg; break; case 'w': #ifndef BOARD_RECOVERY_ALWAYS_WIPES wipe_data = wipe_cache = 1; #endif break; case 'h': ui_set_background(BACKGROUND_ICON_CID); ui_show_text(0); headless = 1; break; case 'c': wipe_cache = 1; break; case 't': ui_show_text(1); break; case 'l': sideload = 1; break; case 'p': shutdown_after = 1; break; case '?': LOGE("Invalid command argument\n"); continue; } } struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { fprintf(stderr, "Warning: No file_contexts\n"); //ui_print("Warning: No file_contexts\n"); } LOGI("device_recovery_start()\n"); 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) { status = install_package(update_package); if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Installation aborted.\n"); } else if (!strcmp(TARGET_DEVICE, "A0001")) { //hack for a0001 ota if (strstr(update_package, "/.OTA/")) send_intent = "0"; } } else if (wipe_data) { if (device_wipe_data()) status = INSTALL_ERROR; preserve_data_media(0); if (erase_volume("/data")) status = INSTALL_ERROR; preserve_data_media(1); if (has_datadata() && erase_volume("/datadata")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Data wipe failed.\n"); } } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Cache wipe failed.\n"); } } else { LOGI("Checking for extendedcommand...\n"); status = INSTALL_ERROR; // No command specified // we are starting up in user initiated recovery here // let's set up some default options signature_check_enabled = 0; is_user_initiated_recovery = 1; if (!headless) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_CLOCKWORK); } if (extendedcommand_file_exists()) { LOGI("Running extendedcommand...\n"); int ret; if (0 == (ret = run_and_remove_extendedcommand())) { status = INSTALL_SUCCESS; ui_set_show_text(0); } else { handle_failure(ret); } } else { LOGI("Skipping execution of extendedcommand, file not found...\n"); } } if (sideload) { signature_check_enabled = 0; if (!headless) ui_set_show_text(1); if (0 == apply_from_adb()) { status = INSTALL_SUCCESS; ui_set_show_text(0); } } if (headless) { headless_wait(); } if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_ERROR); } else if (status != INSTALL_SUCCESS || ui_text_visible()) { prompt_and_wait(); } // We reach here when in main menu we choose reboot main system or for some wipe commands on start // If there is a radio image pending, reboot now to install it. maybe_install_firmware_update(send_intent); // Otherwise, get ready to boot the main system... finish_recovery(send_intent); if (shutdown_after) { ui_print("Shutting down...\n"); reboot_main_system(ANDROID_RB_POWEROFF, 0, 0); } else { ui_print("Rebooting...\n"); reboot_main_system(ANDROID_RB_RESTART, 0, 0); } return EXIT_SUCCESS; }
int main(int argc, char **argv) { if (argc == 2 && strcmp(argv[1], "adbd") == 0) { adb_main(); return 0; } // Recovery needs to install world-readable files, so clear umask // set by init umask(0); char* command = argv[0]; char* stripped = strrchr(argv[0], '/'); if (stripped) command = stripped + 1; if (strcmp(command, "recovery") != 0) { struct recovery_cmd cmd = get_command(command); if (cmd.name) return cmd.main_func(argc, argv); #ifdef BOARD_RECOVERY_HANDLES_MOUNT if (!strcmp(command, "mount") && argc == 2) { load_volume_table(); return ensure_path_mounted(argv[1]); } #endif if (!strcmp(command, "setup_adbd")) { load_volume_table(); setup_adbd(); return 0; } if (!strcmp(command, "start")) { property_set("ctl.start", argv[1]); return 0; } if (!strcmp(command, "stop")) { property_set("ctl.stop", argv[1]); return 0; } /* Make sure stdout is not fully buffered, we don't want to * have issues when calling busybox commands */ setlinebuf(stdout); return busybox_driver(argc, argv); } __system("/sbin/postrecoveryboot.sh"); int is_user_initiated_recovery = 0; time_t start = time(NULL); // If these fail, there's not really anywhere to complain... freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL); freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL); printf("Starting recovery on %s\n", ctime(&start)); device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_VERSION)"\n"); #ifdef BOARD_RECOVERY_SWIPE #ifndef BOARD_TOUCH_RECOVERY //display directions for swipe controls ui_print("Swipe up/down to change selections.\n"); ui_print("Swipe to the right for enter.\n"); ui_print("Swipe to the left for back.\n"); #endif #endif load_volume_table(); process_volumes(); vold_client_start(&v_callbacks, 0); vold_set_automount(1); setup_legacy_storage_paths(); LOGI("Processing arguments.\n"); ensure_path_mounted(LAST_LOG_FILE); rotate_last_logs(10); get_args(&argc, &argv); int previous_runs = 0; const char *send_intent = NULL; const char *update_package = NULL; const char *update_ubuntu_package = NULL; const char *user_data_update_package = NULL; int wipe_data = 0, wipe_cache = 0; int sideload = 0; int headless = 0; try_autodeploy(AUTODEPLOY_PACKAGE_FILE); try_autodeploy(AUTODEPLOY_PACKAGE_FILE_MULTI); LOGI("Checking arguments.\n"); 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 'd': user_data_update_package = optarg; break; case 'w': #ifndef BOARD_RECOVERY_ALWAYS_WIPES wipe_data = wipe_cache = 1; #endif break; case 'h': ui_set_background(BACKGROUND_ICON_CID); ui_show_text(0); headless = 1; break; case 'c': wipe_cache = 1; break; case 't': ui_show_text(1); break; case 'l': sideload = 1; break; case 'v': update_ubuntu_package = UBUNTU_UPDATE_SCRIPT; break; case '?': LOGE("Invalid command argument\n"); continue; } } struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "/file_contexts" } }; sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { fprintf(stderr, "Warning: No file_contexts\n"); ui_print("Warning: No file_contexts\n"); } LOGI("device_recovery_start()\n"); 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) { status = install_package(update_package); if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Installation aborted.\n"); } } else if (update_ubuntu_package != NULL) { LOGI("Performing Ubuntu update"); ui_set_background(BACKGROUND_ICON_INSTALLING); ui_show_indeterminate_progress(); ui_print("Installing Ubuntu update.\n"); char tmp[PATH_MAX]; sprintf(tmp, "%s %s", UBUNTU_UPDATE_SCRIPT, UBUNTU_COMMAND_FILE ); __system(tmp); LOGI("Ubuntu update complete"); ui_print("Ubuntu update complete.\n"); } else if (wipe_data) { if (device_wipe_data()) status = INSTALL_ERROR; ignore_data_media_workaround(1); if (erase_volume("/data")) status = INSTALL_ERROR; ignore_data_media_workaround(0); if (has_datadata() && erase_volume("/datadata")) status = INSTALL_ERROR; if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Data wipe failed.\n"); } } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) { copy_logs(); ui_print("Cache wipe failed.\n"); } } else { LOGI("Checking for extendedcommand...\n"); status = INSTALL_ERROR; // No command specified // we are starting up in user initiated recovery here // let's set up some default options signature_check_enabled = 0; script_assert_enabled = 0; is_user_initiated_recovery = 1; if (!headless) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_UBUNTU); } if (extendedcommand_file_exists()) { LOGI("Running extendedcommand...\n"); int ret; if (0 == (ret = run_and_remove_extendedcommand())) { status = INSTALL_SUCCESS; ui_set_show_text(0); } else { handle_failure(ret); } } else { LOGI("Skipping execution of extendedcommand, file not found...\n"); } } if (sideload) { signature_check_enabled = 0; if (!headless) ui_set_show_text(1); if (0 == apply_from_adb()) { status = INSTALL_SUCCESS; ui_set_show_text(0); } } if (headless) { headless_wait(); } if (user_data_update_package != NULL) { status = install_package(user_data_update_package); if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n"); } if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_ERROR); } else if (status != INSTALL_SUCCESS || ui_text_visible()) { prompt_and_wait(); } // We reach here when in main menu we choose reboot main system or for some wipe commands on start // If there is a radio image pending, reboot now to install it. maybe_install_firmware_update(send_intent); // Otherwise, get ready to boot the main system... finish_recovery(send_intent); ui_print("Rebooting...\n"); reboot_main_system(ANDROID_RB_RESTART, 0, 0); return EXIT_SUCCESS; }