1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <ctype.h> 18 #include <dirent.h> 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <getopt.h> 22 #include <limits.h> 23 #include <linux/input.h> 24 #include <stdarg.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <sys/stat.h> 29 #include <sys/types.h> 30 #include <time.h> 31 #include <unistd.h> 32 33 #include "bootloader.h" 34 #include "common.h" 35 #include "cutils/properties.h" 36 #include "cutils/android_reboot.h" 37 #include "install.h" 38 #include "minui/minui.h" 39 #include "minzip/DirUtil.h" 40 #include "roots.h" 41 #include "ui.h" 42 #include "screen_ui.h" 43 #include "device.h" 44 #include "adb_install.h" 45 extern "C" { 46 #include "minadbd/adb.h" 47 #include "fuse_sideload.h" 48 #include "fuse_sdcard_provider.h" 49 } 50 51 struct selabel_handle *sehandle; 52 53 static const struct option OPTIONS[] = { 54 { "send_intent", required_argument, NULL, 's' }, 55 { "update_package", required_argument, NULL, 'u' }, 56 { "wipe_data", no_argument, NULL, 'w' }, 57 { "wipe_cache", no_argument, NULL, 'c' }, 58 { "show_text", no_argument, NULL, 't' }, 59 { "just_exit", no_argument, NULL, 'x' }, 60 { "locale", required_argument, NULL, 'l' }, 61 { "stages", required_argument, NULL, 'g' }, 62 { "shutdown_after", no_argument, NULL, 'p' }, 63 { "reason", required_argument, NULL, 'r' }, 64 { NULL, 0, NULL, 0 }, 65 }; 66 67 #define LAST_LOG_FILE "/cache/recovery/last_log" 68 69 static const char *CACHE_LOG_DIR = "/cache/recovery"; 70 static const char *COMMAND_FILE = "/cache/recovery/command"; 71 static const char *INTENT_FILE = "/cache/recovery/intent"; 72 static const char *LOG_FILE = "/cache/recovery/log"; 73 static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install"; 74 static const char *LOCALE_FILE = "/cache/recovery/last_locale"; 75 static const char *CACHE_ROOT = "/cache"; 76 static const char *SDCARD_ROOT = "/sdcard"; 77 static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log"; 78 static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install"; 79 80 #define KEEP_LOG_COUNT 10 81 82 RecoveryUI* ui = NULL; 83 char* locale = NULL; 84 char recovery_version[PROPERTY_VALUE_MAX+1]; 85 char* stage = NULL; 86 char* reason = NULL; 87 88 /* 89 * The recovery tool communicates with the main system through /cache files. 90 * /cache/recovery/command - INPUT - command line for tool, one arg per line 91 * /cache/recovery/log - OUTPUT - combined log file from recovery run(s) 92 * /cache/recovery/intent - OUTPUT - intent that was passed in 93 * 94 * The arguments which may be supplied in the recovery.command file: 95 * --send_intent=anystring - write the text out to recovery.intent 96 * --update_package=path - verify install an OTA package file 97 * --wipe_data - erase user data (and cache), then reboot 98 * --wipe_cache - wipe cache (but not user data), then reboot 99 * --set_encrypted_filesystem=on|off - enables / diasables encrypted fs 100 * --just_exit - do nothing; exit and reboot 101 * 102 * After completing, we remove /cache/recovery/command and reboot. 103 * Arguments may also be supplied in the bootloader control block (BCB). 104 * These important scenarios must be safely restartable at any point: 105 * 106 * FACTORY RESET 107 * 1. user selects "factory reset" 108 * 2. main system writes "--wipe_data" to /cache/recovery/command 109 * 3. main system reboots into recovery 110 * 4. get_args() writes BCB with "boot-recovery" and "--wipe_data" 111 * -- after this, rebooting will restart the erase -- 112 * 5. erase_volume() reformats /data 113 * 6. erase_volume() reformats /cache 114 * 7. finish_recovery() erases BCB 115 * -- after this, rebooting will restart the main system -- 116 * 8. main() calls reboot() to boot main system 117 * 118 * OTA INSTALL 119 * 1. main system downloads OTA package to /cache/some-filename.zip 120 * 2. main system writes "--update_package=/cache/some-filename.zip" 121 * 3. main system reboots into recovery 122 * 4. get_args() writes BCB with "boot-recovery" and "--update_package=..." 123 * -- after this, rebooting will attempt to reinstall the update -- 124 * 5. install_package() attempts to install the update 125 * NOTE: the package install must itself be restartable from any point 126 * 6. finish_recovery() erases BCB 127 * -- after this, rebooting will (try to) restart the main system -- 128 * 7. ** if install failed ** 129 * 7a. prompt_and_wait() shows an error icon and waits for the user 130 * 7b; the user reboots (pulling the battery, etc) into the main system 131 * 8. main() calls maybe_install_firmware_update() 132 * ** if the update contained radio/hboot firmware **: 133 * 8a. m_i_f_u() writes BCB with "boot-recovery" and "--wipe_cache" 134 * -- after this, rebooting will reformat cache & restart main system -- 135 * 8b. m_i_f_u() writes firmware image into raw cache partition 136 * 8c. m_i_f_u() writes BCB with "update-radio/hboot" and "--wipe_cache" 137 * -- after this, rebooting will attempt to reinstall firmware -- 138 * 8d. bootloader tries to flash firmware 139 * 8e. bootloader writes BCB with "boot-recovery" (keeping "--wipe_cache") 140 * -- after this, rebooting will reformat cache & restart main system -- 141 * 8f. erase_volume() reformats /cache 142 * 8g. finish_recovery() erases BCB 143 * -- after this, rebooting will (try to) restart the main system -- 144 * 9. main() calls reboot() to boot main system 145 */ 146 147 static const int MAX_ARG_LENGTH = 4096; 148 static const int MAX_ARGS = 100; 149 150 // open a given path, mounting partitions as necessary 151 FILE* 152 fopen_path(const char *path, const char *mode) { 153 if (ensure_path_mounted(path) != 0) { 154 LOGE("Can't mount %s\n", path); 155 return NULL; 156 } 157 158 // When writing, try to create the containing directory, if necessary. 159 // Use generous permissions, the system (init.rc) will reset them. 160 if (strchr("wa", mode[0])) dirCreateHierarchy(path, 0777, NULL, 1, sehandle); 161 162 FILE *fp = fopen(path, mode); 163 return fp; 164 } 165 166 static void redirect_stdio(const char* filename) { 167 // If these fail, there's not really anywhere to complain... 168 freopen(filename, "a", stdout); setbuf(stdout, NULL); 169 freopen(filename, "a", stderr); setbuf(stderr, NULL); 170 } 171 172 // close a file, log an error if the error indicator is set 173 static void 174 check_and_fclose(FILE *fp, const char *name) { 175 fflush(fp); 176 if (ferror(fp)) LOGE("Error in %s\n(%s)\n", name, strerror(errno)); 177 fclose(fp); 178 } 179 180 // command line args come from, in decreasing precedence: 181 // - the actual command line 182 // - the bootloader control block (one per line, after "recovery") 183 // - the contents of COMMAND_FILE (one per line) 184 static void 185 get_args(int *argc, char ***argv) { 186 struct bootloader_message boot; 187 memset(&boot, 0, sizeof(boot)); 188 get_bootloader_message(&boot); // this may fail, leaving a zeroed structure 189 stage = strndup(boot.stage, sizeof(boot.stage)); 190 191 if (boot.command[0] != 0 && boot.command[0] != 255) { 192 LOGI("Boot command: %.*s\n", (int)sizeof(boot.command), boot.command); 193 } 194 195 if (boot.status[0] != 0 && boot.status[0] != 255) { 196 LOGI("Boot status: %.*s\n", (int)sizeof(boot.status), boot.status); 197 } 198 199 // --- if arguments weren't supplied, look in the bootloader control block 200 if (*argc <= 1) { 201 boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination 202 const char *arg = strtok(boot.recovery, "\n"); 203 if (arg != NULL && !strcmp(arg, "recovery")) { 204 *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); 205 (*argv)[0] = strdup(arg); 206 for (*argc = 1; *argc < MAX_ARGS; ++*argc) { 207 if ((arg = strtok(NULL, "\n")) == NULL) break; 208 (*argv)[*argc] = strdup(arg); 209 } 210 LOGI("Got arguments from boot message\n"); 211 } else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) { 212 LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery); 213 } 214 } 215 216 // --- if that doesn't work, try the command file 217 if (*argc <= 1) { 218 FILE *fp = fopen_path(COMMAND_FILE, "r"); 219 if (fp != NULL) { 220 char *token; 221 char *argv0 = (*argv)[0]; 222 *argv = (char **) malloc(sizeof(char *) * MAX_ARGS); 223 (*argv)[0] = argv0; // use the same program name 224 225 char buf[MAX_ARG_LENGTH]; 226 for (*argc = 1; *argc < MAX_ARGS; ++*argc) { 227 if (!fgets(buf, sizeof(buf), fp)) break; 228 token = strtok(buf, "\r\n"); 229 if (token != NULL) { 230 (*argv)[*argc] = strdup(token); // Strip newline. 231 } else { 232 --*argc; 233 } 234 } 235 236 check_and_fclose(fp, COMMAND_FILE); 237 LOGI("Got arguments from %s\n", COMMAND_FILE); 238 } 239 } 240 241 // --> write the arguments we have back into the bootloader control block 242 // always boot into recovery after this (until finish_recovery() is called) 243 strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); 244 strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); 245 int i; 246 for (i = 1; i < *argc; ++i) { 247 strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery)); 248 strlcat(boot.recovery, "\n", sizeof(boot.recovery)); 249 } 250 set_bootloader_message(&boot); 251 } 252 253 static void 254 set_sdcard_update_bootloader_message() { 255 struct bootloader_message boot; 256 memset(&boot, 0, sizeof(boot)); 257 strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); 258 strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); 259 set_bootloader_message(&boot); 260 } 261 262 // How much of the temp log we have copied to the copy in cache. 263 static long tmplog_offset = 0; 264 265 static void 266 copy_log_file(const char* source, const char* destination, int append) { 267 FILE *log = fopen_path(destination, append ? "a" : "w"); 268 if (log == NULL) { 269 LOGE("Can't open %s\n", destination); 270 } else { 271 FILE *tmplog = fopen(source, "r"); 272 if (tmplog != NULL) { 273 if (append) { 274 fseek(tmplog, tmplog_offset, SEEK_SET); // Since last write 275 } 276 char buf[4096]; 277 while (fgets(buf, sizeof(buf), tmplog)) fputs(buf, log); 278 if (append) { 279 tmplog_offset = ftell(tmplog); 280 } 281 check_and_fclose(tmplog, source); 282 } 283 check_and_fclose(log, destination); 284 } 285 } 286 287 // Rename last_log -> last_log.1 -> last_log.2 -> ... -> last_log.$max 288 // Overwrites any existing last_log.$max. 289 static void 290 rotate_last_logs(int max) { 291 char oldfn[256]; 292 char newfn[256]; 293 294 int i; 295 for (i = max-1; i >= 0; --i) { 296 snprintf(oldfn, sizeof(oldfn), (i==0) ? LAST_LOG_FILE : (LAST_LOG_FILE ".%d"), i); 297 snprintf(newfn, sizeof(newfn), LAST_LOG_FILE ".%d", i+1); 298 // ignore errors 299 rename(oldfn, newfn); 300 } 301 } 302 303 static void 304 copy_logs() { 305 // Copy logs to cache so the system can find out what happened. 306 copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true); 307 copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false); 308 copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false); 309 chmod(LOG_FILE, 0600); 310 chown(LOG_FILE, 1000, 1000); // system user 311 chmod(LAST_LOG_FILE, 0640); 312 chmod(LAST_INSTALL_FILE, 0644); 313 sync(); 314 } 315 316 // clear the recovery command and prepare to boot a (hopefully working) system, 317 // copy our log file to cache as well (for the system to read), and 318 // record any intent we were asked to communicate back to the system. 319 // this function is idempotent: call it as many times as you like. 320 static void 321 finish_recovery(const char *send_intent) { 322 // By this point, we're ready to return to the main system... 323 if (send_intent != NULL) { 324 FILE *fp = fopen_path(INTENT_FILE, "w"); 325 if (fp == NULL) { 326 LOGE("Can't open %s\n", INTENT_FILE); 327 } else { 328 fputs(send_intent, fp); 329 check_and_fclose(fp, INTENT_FILE); 330 } 331 } 332 333 // Save the locale to cache, so if recovery is next started up 334 // without a --locale argument (eg, directly from the bootloader) 335 // it will use the last-known locale. 336 if (locale != NULL) { 337 LOGI("Saving locale \"%s\"\n", locale); 338 FILE* fp = fopen_path(LOCALE_FILE, "w"); 339 fwrite(locale, 1, strlen(locale), fp); 340 fflush(fp); 341 fsync(fileno(fp)); 342 check_and_fclose(fp, LOCALE_FILE); 343 } 344 345 copy_logs(); 346 347 // Reset to normal system boot so recovery won't cycle indefinitely. 348 struct bootloader_message boot; 349 memset(&boot, 0, sizeof(boot)); 350 set_bootloader_message(&boot); 351 352 // Remove the command file, so recovery won't repeat indefinitely. 353 if (ensure_path_mounted(COMMAND_FILE) != 0 || 354 (unlink(COMMAND_FILE) && errno != ENOENT)) { 355 LOGW("Can't unlink %s\n", COMMAND_FILE); 356 } 357 358 ensure_path_unmounted(CACHE_ROOT); 359 sync(); // For good measure. 360 } 361 362 typedef struct _saved_log_file { 363 char* name; 364 struct stat st; 365 unsigned char* data; 366 struct _saved_log_file* next; 367 } saved_log_file; 368 369 static int 370 erase_volume(const char *volume) { 371 bool is_cache = (strcmp(volume, CACHE_ROOT) == 0); 372 373 ui->SetBackground(RecoveryUI::ERASING); 374 ui->SetProgressType(RecoveryUI::INDETERMINATE); 375 376 saved_log_file* head = NULL; 377 378 if (is_cache) { 379 // If we're reformatting /cache, we load any 380 // "/cache/recovery/last*" files into memory, so we can restore 381 // them after the reformat. 382 383 ensure_path_mounted(volume); 384 385 DIR* d; 386 struct dirent* de; 387 d = opendir(CACHE_LOG_DIR); 388 if (d) { 389 char path[PATH_MAX]; 390 strcpy(path, CACHE_LOG_DIR); 391 strcat(path, "/"); 392 int path_len = strlen(path); 393 while ((de = readdir(d)) != NULL) { 394 if (strncmp(de->d_name, "last", 4) == 0) { 395 saved_log_file* p = (saved_log_file*) malloc(sizeof(saved_log_file)); 396 strcpy(path+path_len, de->d_name); 397 p->name = strdup(path); 398 if (stat(path, &(p->st)) == 0) { 399 // truncate files to 512kb 400 if (p->st.st_size > (1 << 19)) { 401 p->st.st_size = 1 << 19; 402 } 403 p->data = (unsigned char*) malloc(p->st.st_size); 404 FILE* f = fopen(path, "rb"); 405 fread(p->data, 1, p->st.st_size, f); 406 fclose(f); 407 p->next = head; 408 head = p; 409 } else { 410 free(p); 411 } 412 } 413 } 414 closedir(d); 415 } else { 416 if (errno != ENOENT) { 417 printf("opendir failed: %s\n", strerror(errno)); 418 } 419 } 420 } 421 422 ui->Print("Formatting %s...\n", volume); 423 424 ensure_path_unmounted(volume); 425 int result = format_volume(volume); 426 427 if (is_cache) { 428 while (head) { 429 FILE* f = fopen_path(head->name, "wb"); 430 if (f) { 431 fwrite(head->data, 1, head->st.st_size, f); 432 fclose(f); 433 chmod(head->name, head->st.st_mode); 434 chown(head->name, head->st.st_uid, head->st.st_gid); 435 } 436 free(head->name); 437 free(head->data); 438 saved_log_file* temp = head->next; 439 free(head); 440 head = temp; 441 } 442 443 // Any part of the log we'd copied to cache is now gone. 444 // Reset the pointer so we copy from the beginning of the temp 445 // log. 446 tmplog_offset = 0; 447 copy_logs(); 448 } 449 450 return result; 451 } 452 453 static const char** 454 prepend_title(const char* const* headers) { 455 // count the number of lines in our title, plus the 456 // caller-provided headers. 457 int count = 3; // our title has 3 lines 458 const char* const* p; 459 for (p = headers; *p; ++p, ++count); 460 461 const char** new_headers = (const char**)malloc((count+1) * sizeof(char*)); 462 const char** h = new_headers; 463 *(h++) = "Android system recovery <" EXPAND(RECOVERY_API_VERSION) "e>"; 464 *(h++) = recovery_version; 465 *(h++) = ""; 466 for (p = headers; *p; ++p, ++h) *h = *p; 467 *h = NULL; 468 469 return new_headers; 470 } 471 472 static int 473 get_menu_selection(const char* const * headers, const char* const * items, 474 int menu_only, int initial_selection, Device* device) { 475 // throw away keys pressed previously, so user doesn't 476 // accidentally trigger menu items. 477 ui->FlushKeys(); 478 479 ui->StartMenu(headers, items, initial_selection); 480 int selected = initial_selection; 481 int chosen_item = -1; 482 483 while (chosen_item < 0) { 484 int key = ui->WaitKey(); 485 int visible = ui->IsTextVisible(); 486 487 if (key == -1) { // ui_wait_key() timed out 488 if (ui->WasTextEverVisible()) { 489 continue; 490 } else { 491 LOGI("timed out waiting for key input; rebooting.\n"); 492 ui->EndMenu(); 493 return 0; // XXX fixme 494 } 495 } 496 497 int action = device->HandleMenuKey(key, visible); 498 499 if (action < 0) { 500 switch (action) { 501 case Device::kHighlightUp: 502 --selected; 503 selected = ui->SelectMenu(selected); 504 break; 505 case Device::kHighlightDown: 506 ++selected; 507 selected = ui->SelectMenu(selected); 508 break; 509 case Device::kInvokeItem: 510 chosen_item = selected; 511 break; 512 case Device::kNoAction: 513 break; 514 } 515 } else if (!menu_only) { 516 chosen_item = action; 517 } 518 } 519 520 ui->EndMenu(); 521 return chosen_item; 522 } 523 524 static int compare_string(const void* a, const void* b) { 525 return strcmp(*(const char**)a, *(const char**)b); 526 } 527 528 // Returns a malloc'd path, or NULL. 529 static char* 530 browse_directory(const char* path, Device* device) { 531 ensure_path_mounted(path); 532 533 const char* MENU_HEADERS[] = { "Choose a package to install:", 534 path, 535 "", 536 NULL }; 537 DIR* d; 538 struct dirent* de; 539 d = opendir(path); 540 if (d == NULL) { 541 LOGE("error opening %s: %s\n", path, strerror(errno)); 542 return NULL; 543 } 544 545 const char** headers = prepend_title(MENU_HEADERS); 546 547 int d_size = 0; 548 int d_alloc = 10; 549 char** dirs = (char**)malloc(d_alloc * sizeof(char*)); 550 int z_size = 1; 551 int z_alloc = 10; 552 char** zips = (char**)malloc(z_alloc * sizeof(char*)); 553 zips[0] = strdup("../"); 554 555 while ((de = readdir(d)) != NULL) { 556 int name_len = strlen(de->d_name); 557 558 if (de->d_type == DT_DIR) { 559 // skip "." and ".." entries 560 if (name_len == 1 && de->d_name[0] == '.') continue; 561 if (name_len == 2 && de->d_name[0] == '.' && 562 de->d_name[1] == '.') continue; 563 564 if (d_size >= d_alloc) { 565 d_alloc *= 2; 566 dirs = (char**)realloc(dirs, d_alloc * sizeof(char*)); 567 } 568 dirs[d_size] = (char*)malloc(name_len + 2); 569 strcpy(dirs[d_size], de->d_name); 570 dirs[d_size][name_len] = '/'; 571 dirs[d_size][name_len+1] = '\0'; 572 ++d_size; 573 } else if (de->d_type == DT_REG && 574 name_len >= 4 && 575 strncasecmp(de->d_name + (name_len-4), ".zip", 4) == 0) { 576 if (z_size >= z_alloc) { 577 z_alloc *= 2; 578 zips = (char**)realloc(zips, z_alloc * sizeof(char*)); 579 } 580 zips[z_size++] = strdup(de->d_name); 581 } 582 } 583 closedir(d); 584 585 qsort(dirs, d_size, sizeof(char*), compare_string); 586 qsort(zips, z_size, sizeof(char*), compare_string); 587 588 // append dirs to the zips list 589 if (d_size + z_size + 1 > z_alloc) { 590 z_alloc = d_size + z_size + 1; 591 zips = (char**)realloc(zips, z_alloc * sizeof(char*)); 592 } 593 memcpy(zips + z_size, dirs, d_size * sizeof(char*)); 594 free(dirs); 595 z_size += d_size; 596 zips[z_size] = NULL; 597 598 char* result; 599 int chosen_item = 0; 600 while (true) { 601 chosen_item = get_menu_selection(headers, zips, 1, chosen_item, device); 602 603 char* item = zips[chosen_item]; 604 int item_len = strlen(item); 605 if (chosen_item == 0) { // item 0 is always "../" 606 // go up but continue browsing (if the caller is update_directory) 607 result = NULL; 608 break; 609 } 610 611 char new_path[PATH_MAX]; 612 strlcpy(new_path, path, PATH_MAX); 613 strlcat(new_path, "/", PATH_MAX); 614 strlcat(new_path, item, PATH_MAX); 615 616 if (item[item_len-1] == '/') { 617 // recurse down into a subdirectory 618 new_path[strlen(new_path)-1] = '\0'; // truncate the trailing '/' 619 result = browse_directory(new_path, device); 620 if (result) break; 621 } else { 622 // selected a zip file: return the malloc'd path to the caller. 623 result = strdup(new_path); 624 break; 625 } 626 } 627 628 int i; 629 for (i = 0; i < z_size; ++i) free(zips[i]); 630 free(zips); 631 free(headers); 632 633 return result; 634 } 635 636 static void 637 wipe_data(int confirm, Device* device) { 638 if (confirm) { 639 static const char** title_headers = NULL; 640 641 if (title_headers == NULL) { 642 const char* headers[] = { "Confirm wipe of all user data?", 643 " THIS CAN NOT BE UNDONE.", 644 "", 645 NULL }; 646 title_headers = prepend_title((const char**)headers); 647 } 648 649 const char* items[] = { " No", 650 " No", 651 " No", 652 " No", 653 " No", 654 " No", 655 " No", 656 " Yes -- delete all user data", // [7] 657 " No", 658 " No", 659 " No", 660 NULL }; 661 662 int chosen_item = get_menu_selection(title_headers, items, 1, 0, device); 663 if (chosen_item != 7) { 664 return; 665 } 666 } 667 668 ui->Print("\n-- Wiping data...\n"); 669 device->WipeData(); 670 erase_volume("/data"); 671 erase_volume("/cache"); 672 erase_persistent_partition(); 673 ui->Print("Data wipe complete.\n"); 674 } 675 676 static void file_to_ui(const char* fn) { 677 FILE *fp = fopen_path(fn, "re"); 678 if (fp == NULL) { 679 ui->Print(" Unable to open %s: %s\n", fn, strerror(errno)); 680 return; 681 } 682 char line[1024]; 683 int ct = 0; 684 redirect_stdio("/dev/null"); 685 while(fgets(line, sizeof(line), fp) != NULL) { 686 ui->Print("%s", line); 687 ct++; 688 if (ct % 30 == 0) { 689 // give the user time to glance at the entries 690 ui->WaitKey(); 691 } 692 } 693 redirect_stdio(TEMPORARY_LOG_FILE); 694 fclose(fp); 695 } 696 697 static void choose_recovery_file(Device* device) { 698 int i; 699 static const char** title_headers = NULL; 700 char *filename; 701 const char* headers[] = { "Select file to view", 702 "", 703 NULL }; 704 char* entries[KEEP_LOG_COUNT + 2]; 705 memset(entries, 0, sizeof(entries)); 706 707 for (i = 0; i < KEEP_LOG_COUNT; i++) { 708 char *filename; 709 if (asprintf(&filename, (i==0) ? LAST_LOG_FILE : (LAST_LOG_FILE ".%d"), i) == -1) { 710 // memory allocation failure - return early. Should never happen. 711 return; 712 } 713 if ((ensure_path_mounted(filename) != 0) || (access(filename, R_OK) == -1)) { 714 free(filename); 715 entries[i+1] = NULL; 716 break; 717 } 718 entries[i+1] = filename; 719 } 720 721 entries[0] = strdup("Go back"); 722 title_headers = prepend_title((const char**)headers); 723 724 while(1) { 725 int chosen_item = get_menu_selection(title_headers, entries, 1, 0, device); 726 if (chosen_item == 0) break; 727 file_to_ui(entries[chosen_item]); 728 } 729 730 for (i = 0; i < KEEP_LOG_COUNT + 1; i++) { 731 free(entries[i]); 732 } 733 } 734 735 // Return REBOOT, SHUTDOWN, or REBOOT_BOOTLOADER. Returning NO_ACTION 736 // means to take the default, which is to reboot or shutdown depending 737 // on if the --shutdown_after flag was passed to recovery. 738 static Device::BuiltinAction 739 prompt_and_wait(Device* device, int status) { 740 const char* const* headers = prepend_title(device->GetMenuHeaders()); 741 742 for (;;) { 743 finish_recovery(NULL); 744 switch (status) { 745 case INSTALL_SUCCESS: 746 case INSTALL_NONE: 747 ui->SetBackground(RecoveryUI::NO_COMMAND); 748 break; 749 750 case INSTALL_ERROR: 751 case INSTALL_CORRUPT: 752 ui->SetBackground(RecoveryUI::ERROR); 753 break; 754 } 755 ui->SetProgressType(RecoveryUI::EMPTY); 756 757 int chosen_item = get_menu_selection(headers, device->GetMenuItems(), 0, 0, device); 758 759 // device-specific code may take some action here. It may 760 // return one of the core actions handled in the switch 761 // statement below. 762 Device::BuiltinAction chosen_action = device->InvokeMenuItem(chosen_item); 763 764 int wipe_cache = 0; 765 switch (chosen_action) { 766 case Device::NO_ACTION: 767 break; 768 769 case Device::REBOOT: 770 case Device::SHUTDOWN: 771 case Device::REBOOT_BOOTLOADER: 772 return chosen_action; 773 774 case Device::WIPE_DATA: 775 wipe_data(ui->IsTextVisible(), device); 776 if (!ui->IsTextVisible()) return Device::NO_ACTION; 777 break; 778 779 case Device::WIPE_CACHE: 780 ui->Print("\n-- Wiping cache...\n"); 781 erase_volume("/cache"); 782 ui->Print("Cache wipe complete.\n"); 783 if (!ui->IsTextVisible()) return Device::NO_ACTION; 784 break; 785 786 case Device::APPLY_EXT: { 787 ensure_path_mounted(SDCARD_ROOT); 788 char* path = browse_directory(SDCARD_ROOT, device); 789 if (path == NULL) { 790 ui->Print("\n-- No package file selected.\n", path); 791 break; 792 } 793 794 ui->Print("\n-- Install %s ...\n", path); 795 set_sdcard_update_bootloader_message(); 796 void* token = start_sdcard_fuse(path); 797 798 int status = install_package(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache, 799 TEMPORARY_INSTALL_FILE, false); 800 801 finish_sdcard_fuse(token); 802 ensure_path_unmounted(SDCARD_ROOT); 803 804 if (status == INSTALL_SUCCESS && wipe_cache) { 805 ui->Print("\n-- Wiping cache (at package request)...\n"); 806 if (erase_volume("/cache")) { 807 ui->Print("Cache wipe failed.\n"); 808 } else { 809 ui->Print("Cache wipe complete.\n"); 810 } 811 } 812 813 if (status >= 0) { 814 if (status != INSTALL_SUCCESS) { 815 ui->SetBackground(RecoveryUI::ERROR); 816 ui->Print("Installation aborted.\n"); 817 } else if (!ui->IsTextVisible()) { 818 return Device::NO_ACTION; // reboot if logs aren't visible 819 } else { 820 ui->Print("\nInstall from sdcard complete.\n"); 821 } 822 } 823 break; 824 } 825 826 case Device::APPLY_CACHE: 827 ui->Print("\nAPPLY_CACHE is deprecated.\n"); 828 break; 829 830 case Device::READ_RECOVERY_LASTLOG: 831 choose_recovery_file(device); 832 break; 833 834 case Device::APPLY_ADB_SIDELOAD: 835 status = apply_from_adb(ui, &wipe_cache, TEMPORARY_INSTALL_FILE); 836 if (status >= 0) { 837 if (status != INSTALL_SUCCESS) { 838 ui->SetBackground(RecoveryUI::ERROR); 839 ui->Print("Installation aborted.\n"); 840 copy_logs(); 841 } else if (!ui->IsTextVisible()) { 842 return Device::NO_ACTION; // reboot if logs aren't visible 843 } else { 844 ui->Print("\nInstall from ADB complete.\n"); 845 } 846 } 847 break; 848 } 849 } 850 } 851 852 static void 853 print_property(const char *key, const char *name, void *cookie) { 854 printf("%s=%s\n", key, name); 855 } 856 857 static void 858 load_locale_from_cache() { 859 FILE* fp = fopen_path(LOCALE_FILE, "r"); 860 char buffer[80]; 861 if (fp != NULL) { 862 fgets(buffer, sizeof(buffer), fp); 863 int j = 0; 864 unsigned int i; 865 for (i = 0; i < sizeof(buffer) && buffer[i]; ++i) { 866 if (!isspace(buffer[i])) { 867 buffer[j++] = buffer[i]; 868 } 869 } 870 buffer[j] = 0; 871 locale = strdup(buffer); 872 check_and_fclose(fp, LOCALE_FILE); 873 } 874 } 875 876 static RecoveryUI* gCurrentUI = NULL; 877 878 void 879 ui_print(const char* format, ...) { 880 char buffer[256]; 881 882 va_list ap; 883 va_start(ap, format); 884 vsnprintf(buffer, sizeof(buffer), format, ap); 885 va_end(ap); 886 887 if (gCurrentUI != NULL) { 888 gCurrentUI->Print("%s", buffer); 889 } else { 890 fputs(buffer, stdout); 891 } 892 } 893 894 int 895 main(int argc, char **argv) { 896 time_t start = time(NULL); 897 898 redirect_stdio(TEMPORARY_LOG_FILE); 899 900 // If this binary is started with the single argument "--adbd", 901 // instead of being the normal recovery binary, it turns into kind 902 // of a stripped-down version of adbd that only supports the 903 // 'sideload' command. Note this must be a real argument, not 904 // anything in the command file or bootloader control block; the 905 // only way recovery should be run with this argument is when it 906 // starts a copy of itself from the apply_from_adb() function. 907 if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { 908 adb_main(); 909 return 0; 910 } 911 912 printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start)); 913 914 load_volume_table(); 915 ensure_path_mounted(LAST_LOG_FILE); 916 rotate_last_logs(KEEP_LOG_COUNT); 917 get_args(&argc, &argv); 918 919 const char *send_intent = NULL; 920 const char *update_package = NULL; 921 int wipe_data = 0, wipe_cache = 0, show_text = 0; 922 bool just_exit = false; 923 bool shutdown_after = false; 924 925 int arg; 926 while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) { 927 switch (arg) { 928 case 's': send_intent = optarg; break; 929 case 'u': update_package = optarg; break; 930 case 'w': wipe_data = wipe_cache = 1; break; 931 case 'c': wipe_cache = 1; break; 932 case 't': show_text = 1; break; 933 case 'x': just_exit = true; break; 934 case 'l': locale = optarg; break; 935 case 'g': { 936 if (stage == NULL || *stage == '\0') { 937 char buffer[20] = "1/"; 938 strncat(buffer, optarg, sizeof(buffer)-3); 939 stage = strdup(buffer); 940 } 941 break; 942 } 943 case 'p': shutdown_after = true; break; 944 case 'r': reason = optarg; break; 945 case '?': 946 LOGE("Invalid command argument\n"); 947 continue; 948 } 949 } 950 951 if (locale == NULL) { 952 load_locale_from_cache(); 953 } 954 printf("locale is [%s]\n", locale); 955 printf("stage is [%s]\n", stage); 956 printf("reason is [%s]\n", reason); 957 958 Device* device = make_device(); 959 ui = device->GetUI(); 960 gCurrentUI = ui; 961 962 ui->SetLocale(locale); 963 ui->Init(); 964 965 int st_cur, st_max; 966 if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) { 967 ui->SetStage(st_cur, st_max); 968 } 969 970 ui->SetBackground(RecoveryUI::NONE); 971 if (show_text) ui->ShowText(true); 972 973 struct selinux_opt seopts[] = { 974 { SELABEL_OPT_PATH, "/file_contexts" } 975 }; 976 977 sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); 978 979 if (!sehandle) { 980 ui->Print("Warning: No file_contexts\n"); 981 } 982 983 device->StartRecovery(); 984 985 printf("Command:"); 986 for (arg = 0; arg < argc; arg++) { 987 printf(" \"%s\"", argv[arg]); 988 } 989 printf("\n"); 990 991 if (update_package) { 992 // For backwards compatibility on the cache partition only, if 993 // we're given an old 'root' path "CACHE:foo", change it to 994 // "/cache/foo". 995 if (strncmp(update_package, "CACHE:", 6) == 0) { 996 int len = strlen(update_package) + 10; 997 char* modified_path = (char*)malloc(len); 998 strlcpy(modified_path, "/cache/", len); 999 strlcat(modified_path, update_package+6, len); 1000 printf("(replacing path \"%s\" with \"%s\")\n", 1001 update_package, modified_path); 1002 update_package = modified_path; 1003 } 1004 } 1005 printf("\n"); 1006 1007 property_list(print_property, NULL); 1008 property_get("ro.build.display.id", recovery_version, ""); 1009 printf("\n"); 1010 1011 int status = INSTALL_SUCCESS; 1012 1013 if (update_package != NULL) { 1014 status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE, true); 1015 if (status == INSTALL_SUCCESS && wipe_cache) { 1016 if (erase_volume("/cache")) { 1017 LOGE("Cache wipe (requested by package) failed."); 1018 } 1019 } 1020 if (status != INSTALL_SUCCESS) { 1021 ui->Print("Installation aborted.\n"); 1022 1023 // If this is an eng or userdebug build, then automatically 1024 // turn the text display on if the script fails so the error 1025 // message is visible. 1026 char buffer[PROPERTY_VALUE_MAX+1]; 1027 property_get("ro.build.fingerprint", buffer, ""); 1028 if (strstr(buffer, ":userdebug/") || strstr(buffer, ":eng/")) { 1029 ui->ShowText(true); 1030 } 1031 } 1032 } else if (wipe_data) { 1033 if (device->WipeData()) status = INSTALL_ERROR; 1034 if (erase_volume("/data")) status = INSTALL_ERROR; 1035 if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; 1036 if (erase_persistent_partition() == -1 ) status = INSTALL_ERROR; 1037 if (status != INSTALL_SUCCESS) ui->Print("Data wipe failed.\n"); 1038 } else if (wipe_cache) { 1039 if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; 1040 if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n"); 1041 } else if (!just_exit) { 1042 status = INSTALL_NONE; // No command specified 1043 ui->SetBackground(RecoveryUI::NO_COMMAND); 1044 } 1045 1046 if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) { 1047 copy_logs(); 1048 ui->SetBackground(RecoveryUI::ERROR); 1049 } 1050 Device::BuiltinAction after = shutdown_after ? Device::SHUTDOWN : Device::REBOOT; 1051 if (status != INSTALL_SUCCESS || ui->IsTextVisible()) { 1052 Device::BuiltinAction temp = prompt_and_wait(device, status); 1053 if (temp != Device::NO_ACTION) after = temp; 1054 } 1055 1056 // Save logs and clean up before rebooting or shutting down. 1057 finish_recovery(send_intent); 1058 1059 switch (after) { 1060 case Device::SHUTDOWN: 1061 ui->Print("Shutting down...\n"); 1062 property_set(ANDROID_RB_PROPERTY, "shutdown,"); 1063 break; 1064 1065 case Device::REBOOT_BOOTLOADER: 1066 ui->Print("Rebooting to bootloader...\n"); 1067 property_set(ANDROID_RB_PROPERTY, "reboot,bootloader"); 1068 break; 1069 1070 default: 1071 ui->Print("Rebooting...\n"); 1072 property_set(ANDROID_RB_PROPERTY, "reboot,"); 1073 break; 1074 } 1075 sleep(5); // should reboot before this finishes 1076 return EXIT_SUCCESS; 1077 } 1078