void show_install_update_menu() { static char* headers[] = { "Install update from zip file", "", NULL }; char* install_menu_items[] = { "choose zip from sdcard", "install zip from sideload", "apply /sdcard/update.zip", "toggle signature verification", NULL, NULL }; char *other_sd = NULL; if (volume_for_path("/emmc") != NULL) { other_sd = "/emmc/"; install_menu_items[4] = "choose zip from internal sdcard"; } else if (volume_for_path("/external_sd") != NULL) { other_sd = "/external_sd/"; install_menu_items[4] = "choose zip from external sdcard"; } for (;;) { int chosen_item = get_menu_selection(headers, install_menu_items, 0, 0); switch (chosen_item) { case ITEM_SIG_CHECK: toggle_signature_check(); break; case ITEM_APPLY_UPDATE: { if (confirm_selection("Confirm install?", "Yes - Install /sdcard/update.zip")) install_zip(SDCARD_UPDATE_FILE); break; } case ITEM_CHOOSE_ZIP: show_choose_zip_menu("/sdcard/"); write_recovery_version(); break; case ITEM_APPLY_SIDELOAD: apply_from_adb(); break; case ITEM_CHOOSE_ZIP_INT: if (other_sd != NULL) show_choose_zip_menu(other_sd); break; default: return; } } }
void show_install_update_menu() { static char* headers[] = { "从SD卡选择ZIP格式文件进行刷机", "", NULL }; char* install_menu_items[] = { "从SD卡中选择一个ZIP格式刷机包", "从电脑用ADB载入刷机包", "直接应用/sdcard/update.zip刷机", "启用/禁用签名校验", NULL, NULL }; char *other_sd = NULL; if (volume_for_path("/emmc") != NULL) { other_sd = "/emmc/"; install_menu_items[4] = "从内置SD卡选择ZIP文件"; } else if (volume_for_path("/external_sd") != NULL) { other_sd = "/external_sd/"; install_menu_items[4] = "从外置SD卡选择ZIP文件"; } for (;;) { int chosen_item = get_menu_selection(headers, install_menu_items, 0, 0); switch (chosen_item) { case ITEM_SIG_CHECK: toggle_signature_check(); break; case ITEM_APPLY_UPDATE: { if (confirm_selection("确认安装?", "是-直接刷入/sdcard/update.zip")) install_zip(SDCARD_UPDATE_FILE); break; } case ITEM_CHOOSE_ZIP: show_choose_zip_menu("/sdcard/"); write_recovery_version(); break; case ITEM_APPLY_SIDELOAD: apply_from_adb(); break; case ITEM_CHOOSE_ZIP_INT: if (other_sd != NULL) show_choose_zip_menu(other_sd); break; default: return; } } }
int GUIAction::adbsideload(std::string arg) { operation_start("Sideload"); if (simulate) { simulate_progress_bar(); operation_end(0); } else { gui_print("Starting ADB sideload feature...\n"); bool mtp_was_enabled = TWFunc::Toggle_MTP(false); // wait for the adb connection int ret = apply_from_adb("/", &sideload_child_pid); DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui now that the zip install is going to start if (ret != 0) { if (ret == -2) gui_print("You need adb 1.0.32 or newer to sideload to this device.\n"); ret = 1; // failure } else { int wipe_cache = 0; int wipe_dalvik = 0; DataManager::GetValue("tw_wipe_dalvik", wipe_dalvik); if (TWinstall_zip(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache) == 0) { if (wipe_cache || DataManager::GetIntValue("tw_wipe_cache")) PartitionManager.Wipe_By_Path("/cache"); if (wipe_dalvik) PartitionManager.Wipe_Dalvik_Cache(); } else { ret = 1; // failure } } if (sideload_child_pid) { LOGINFO("Signaling child sideload process to exit.\n"); struct stat st; // Calling stat() on this magic filename signals the minadbd // subprocess to shut down. stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st); int status; LOGINFO("Waiting for child sideload process to exit.\n"); waitpid(sideload_child_pid, &status, 0); } property_set("ctl.start", "adbd"); TWFunc::Toggle_MTP(mtp_was_enabled); reinject_after_flash(); operation_end(ret); } return 0; }
int enter_sideload_mode(int status) { ensure_path_mounted(CACHE_ROOT); start_sideload(); static const char* headers[] = { "ADB Sideload", "", NULL }; static char* list[] = { "Cancel sideload", NULL }; int icon = ui_get_background_icon(); int wipe_cache = 0; // we need show_text to show adb sideload cancel menu (get_menu_selection()) bool text_visible = ui_IsTextVisible(); ui_SetShowText(true); get_menu_selection(headers, list, 0, 0); ui_SetShowText(text_visible); int ret = apply_from_adb(&wipe_cache, TEMPORARY_INSTALL_FILE); // if item < 0 (cancel), apply_from_adb() will return INSTALL_NONE with appropriate log message if (ret != INSTALL_NONE) { status = ret; if (status != INSTALL_SUCCESS) { ui_set_background(BACKGROUND_ICON_ERROR); ui_print("Installation aborted.\n"); } else { if (wipe_cache && erase_volume("/cache")) { LOGE("Cache wipe (requested by package) failed.\n"); } if (ui_IsTextVisible()) { ui_set_background(icon); ui_print("\nInstall from ADB complete.\n"); } } } return status; }
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; } } }
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); if (strcmp(basename(argv[0]), "recovery") != 0) { if (strstr(argv[0], "minizip") != NULL) return minizip_main(argc, argv); if (strstr(argv[0], "dedupe") != NULL) return dedupe_main(argc, argv); if (strstr(argv[0], "flash_image") != NULL) return flash_image_main(argc, argv); if (strstr(argv[0], "volume") != NULL) return volume_main(argc, argv); if (strstr(argv[0], "edify") != NULL) return edify_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], "make_ext4fs") != NULL) return make_ext4fs_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], "bu") == argv[0] + strlen(argv[0]) - 2) return bu_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); } if (strstr(argv[0], "setprop")) return setprop_main(argc, argv); if (strstr(argv[0], "getprop")) return getprop_main(argc, argv); 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", ctime(&start)); device_ui_init(&ui_parameters); ui_init(); ui_print(EXPAND(RECOVERY_VERSION)"\n"); load_volume_table(); process_volumes(); LOGI("Processing arguments.\n"); get_args(&argc, &argv); int previous_runs = 0; const char *send_intent = NULL; const char *update_package = NULL; int wipe_data = 0, wipe_cache = 0; int sideload = 0; 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 'w': #ifndef BOARD_RECOVERY_ALWAYS_WIPES wipe_data = wipe_cache = 1; #endif break; case 'c': wipe_cache = 1; break; case 't': ui_show_text(1); break; case 'l': sideload = 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("命令:"); 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) ui_print("安装失败.\n"); } 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失败.\n"); } else if (wipe_cache) { if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; if (status != INSTALL_SUCCESS) ui_print("清空cache失败.\n"); } else if (sideload) { signature_check_enabled = 0; ui_set_show_text(1); if (0 == apply_from_adb()) { status = INSTALL_SUCCESS; ui_set_show_text(0); } } 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; 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"); } } setup_adbd(); if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) { ui_set_show_text(1); ui_set_background(BACKGROUND_ICON_ERROR); } if (status != INSTALL_SUCCESS || ui_text_visible()) { prompt_and_wait(); } verify_root_and_recovery(); // 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); sync(); if(!poweroff) { ui_print("正在重启...\n"); android_reboot(ANDROID_RB_RESTART, 0, 0); } else { ui_print("正在关机...\n"); android_reboot(ANDROID_RB_POWEROFF, 0, 0); } return EXIT_SUCCESS; }
// 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; } } }
static void prompt_and_wait() { char** headers = prepend_title((const char**)MENU_HEADERS); for (;;) { finish_recovery(NULL); ui_reset_progress(); ui_root_menu = 1; // ui_menu_level is a legacy variable that i am keeping around to prevent build breakage. ui_menu_level = 0; // allow_display_toggle = 1; int chosen_item = get_menu_selection(headers, MENU_ITEMS, 0, 0); ui_menu_level = 1; ui_root_menu = 0; // allow_display_toggle = 0; // 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_perform_action(chosen_item); int status; switch (chosen_item) { case ITEM_REBOOT: poweroff=0; return; case ITEM_WIPE_DATA: wipe_data(ui_text_visible()); if (!ui_text_visible()) return; break; case ITEM_WIPE_CACHE: if (confirm_selection("Confirm wipe?", "Yes - Wipe Cache")) { ui_print("\n-- Wiping cache...\n"); erase_volume("/cache"); ui_print("Cache wipe complete.\n"); if (!ui_text_visible()) return; } break; case ITEM_APPLY_SDCARD: show_install_update_menu(); break; case ITEM_APPLY_SIDELOAD: apply_from_adb(); break; case ITEM_NANDROID: show_nandroid_menu(); break; case ITEM_PARTITION: show_partition_menu(); break; case ITEM_ADVANCED: show_advanced_menu(); break; case ITEM_POWEROFF: poweroff = 1; return; } } }
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; }
static void prompt_and_wait(Device* device, int status) { const char* const* headers = prepend_title(device->GetMenuHeaders()); int chosen_item = 6; // add by cjcheng for (;;) { finish_recovery(NULL); switch (status) { case INSTALL_SUCCESS: case INSTALL_NONE: ui->SetBackground(RecoveryUI::INSTALLING_UPDATE); // modify by cjcheng break; } ui->SetProgressType(RecoveryUI::EMPTY); // int chosen_item = get_menu_selection(headers, device->GetMenuItems(), 0, 0, device); // modify by cjcheng // 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); // modify by cjcheng 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->ShowText(false); ui->Print("\n-- Wiping cache...\n"); erase_volume("/cache"); ui->Print("Cache wipe complete.\n"); if (!ui->IsTextVisible()) return; 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: ensure_path_mounted(CACHE_ROOT); 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"); } else if (!ui->IsTextVisible()) { return; // reboot if logs aren't visible } else { ui->Print("\nInstall from ADB complete.\n"); } } break; /* add by cjcheng start... */ case Device::APPLY_SDCARD: // Some packages expect /cache to be mounted (eg, // standard incremental packages expect to use /cache // as scratch space). ensure_path_mounted(CACHE_ROOT); status = smdt_update_directory(SDCARD_ROOT, SDCARD_ROOT, &wipe_cache); install_flag = status; 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"); chosen_item = 1; } } break; case Device::APPLY_EXT: // Some packages expect /cache to be mounted (eg, // standard incremental packages expect to use /cache // as scratch space). ensure_path_mounted(CACHE_ROOT); status = smdt_update_directory(EXTSD_ROOT, EXTSD_ROOT, &wipe_cache); install_flag = status; 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"); chosen_item = 1; } } break; case Device::APPLY_USB1: // Some packages expect /cache to be mounted (eg, // standard incremental packages expect to use /cache // as scratch space). ensure_path_mounted(CACHE_ROOT); status = smdt_update_directory(USB1_ROOT, USB1_ROOT, &wipe_cache); install_flag = status; 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"); chosen_item = 1; } } break; case Device::APPLY_USB0: // Some packages expect /cache to be mounted (eg, // standard incremental packages expect to use /cache // as scratch space). ensure_path_mounted(CACHE_ROOT); status = smdt_update_directory(USB0_ROOT, USB0_ROOT, &wipe_cache); install_flag = status; 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"); chosen_item = 1; } } break; case Device::APPLY_SATA: // Some packages expect /cache to be mounted (eg, // standard incremental packages expect to use /cache // as scratch space). ensure_path_mounted(CACHE_ROOT); status = smdt_update_directory(SATA_ROOT, SATA_ROOT, &wipe_cache); install_flag = status; 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"); chosen_item = 1; } } break; /* add by cjcheng end... */ } /* add by cjcheng start... */ if (chosen_item < 11 && chosen_item != 1) chosen_item++; else chosen_item = 1; /* add by cjcheng end... */ } }