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