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"
46extern "C" {
47#include "minadbd/adb.h"
48#include "fuse_sideload.h"
49#include "fuse_sdcard_provider.h"
50}
51
52struct selabel_handle *sehandle;
53
54static 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
70static const char *CACHE_LOG_DIR = "/cache/recovery";
71static const char *COMMAND_FILE = "/cache/recovery/command";
72static const char *INTENT_FILE = "/cache/recovery/intent";
73static const char *LOG_FILE = "/cache/recovery/log";
74static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
75static const char *LOCALE_FILE = "/cache/recovery/last_locale";
76static const char *CACHE_ROOT = "/cache";
77static const char *SDCARD_ROOT = "/sdcard";
78static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
79static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install";
80static 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
88RecoveryUI* ui = NULL;
89char* locale = NULL;
90char recovery_version[PROPERTY_VALUE_MAX+1];
91char* stage = NULL;
92char* 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
153static const int MAX_ARG_LENGTH = 4096;
154static const int MAX_ARGS = 100;
155
156// open a given path, mounting partitions as necessary
157FILE*
158fopen_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
172static 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
179static void
180check_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)
190static void
191get_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
259static void
260set_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
269static void
270save_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.
307static long tmplog_offset = 0;
308
309static void
310copy_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.
333static void
334rotate_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
347static void
348copy_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.
367static void
368finish_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
409typedef 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
416static int
417erase_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
500static const char**
501prepend_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
519static int
520get_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
571static 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.
576static char*
577browse_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
683static void
684wipe_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    ui->Print("Data wipe complete.\n");
720}
721
722static void file_to_ui(const char* fn) {
723    FILE *fp = fopen_path(fn, "re");
724    if (fp == NULL) {
725        ui->Print("  Unable to open %s: %s\n", fn, strerror(errno));
726        return;
727    }
728    char line[1024];
729    int ct = 0;
730    int key = 0;
731    redirect_stdio("/dev/null");
732    while(fgets(line, sizeof(line), fp) != NULL) {
733        ui->Print("%s", line);
734        ct++;
735        if (ct % LINES_PER_PAGE == 0) {
736            // give the user time to glance at the entries
737            key = ui->WaitKey();
738
739            if (key == KEY_POWER) {
740                break;
741            }
742
743            if (key == KEY_VOLUMEUP) {
744                // Go back by seeking to the beginning and dumping ct - n
745                // lines.  It's ugly, but this way we don't need to store
746                // the previous offsets.  The files we're dumping here aren't
747                // expected to be very large.
748                int i;
749
750                ct -= 2 * LINES_PER_PAGE;
751                if (ct < 0) {
752                    ct = 0;
753                }
754                fseek(fp, 0, SEEK_SET);
755                for (i = 0; i < ct; i++) {
756                    fgets(line, sizeof(line), fp);
757                }
758                ui->Print("^^^^^^^^^^\n");
759            }
760        }
761    }
762
763    // If the user didn't abort, then give the user time to glance at
764    // the end of the log, sorry, no rewind here
765    if (key != KEY_POWER) {
766        ui->Print("\n--END-- (press any key)\n");
767        ui->WaitKey();
768    }
769
770    redirect_stdio(TEMPORARY_LOG_FILE);
771    fclose(fp);
772}
773
774static void choose_recovery_file(Device* device) {
775    unsigned int i;
776    unsigned int n;
777    static const char** title_headers = NULL;
778    char *filename;
779    const char* headers[] = { "Select file to view",
780                              "",
781                              NULL };
782    // "Go back" + LAST_KMSG_FILE + KEEP_LOG_COUNT + terminating NULL entry
783    char* entries[KEEP_LOG_COUNT + 3];
784    memset(entries, 0, sizeof(entries));
785
786    n = 0;
787    entries[n++] = strdup("Go back");
788
789    // Add kernel kmsg file if available
790    if ((ensure_path_mounted(LAST_KMSG_FILE) == 0) && (access(LAST_KMSG_FILE, R_OK) == 0)) {
791        entries[n++] = strdup(LAST_KMSG_FILE);
792    }
793
794    // Add LAST_LOG_FILE + LAST_LOG_FILE.x
795    for (i = 0; i < KEEP_LOG_COUNT; i++) {
796        char *filename;
797        if (asprintf(&filename, (i==0) ? LAST_LOG_FILE : (LAST_LOG_FILE ".%d"), i) == -1) {
798            // memory allocation failure - return early. Should never happen.
799            return;
800        }
801        if ((ensure_path_mounted(filename) != 0) || (access(filename, R_OK) == -1)) {
802            free(filename);
803            entries[n++] = NULL;
804            break;
805        }
806        entries[n++] = filename;
807    }
808
809    title_headers = prepend_title((const char**)headers);
810
811    while(1) {
812        int chosen_item = get_menu_selection(title_headers, entries, 1, 0, device);
813        if (chosen_item == 0) break;
814        file_to_ui(entries[chosen_item]);
815    }
816
817    for (i = 0; i < (sizeof(entries) / sizeof(*entries)); i++) {
818        free(entries[i]);
819    }
820}
821
822// Return REBOOT, SHUTDOWN, or REBOOT_BOOTLOADER.  Returning NO_ACTION
823// means to take the default, which is to reboot or shutdown depending
824// on if the --shutdown_after flag was passed to recovery.
825static Device::BuiltinAction
826prompt_and_wait(Device* device, int status) {
827    const char* const* headers = prepend_title(device->GetMenuHeaders());
828
829    for (;;) {
830        finish_recovery(NULL);
831        switch (status) {
832            case INSTALL_SUCCESS:
833            case INSTALL_NONE:
834                ui->SetBackground(RecoveryUI::NO_COMMAND);
835                break;
836
837            case INSTALL_ERROR:
838            case INSTALL_CORRUPT:
839                ui->SetBackground(RecoveryUI::ERROR);
840                break;
841        }
842        ui->SetProgressType(RecoveryUI::EMPTY);
843
844        int chosen_item = get_menu_selection(headers, device->GetMenuItems(), 0, 0, device);
845
846        // device-specific code may take some action here.  It may
847        // return one of the core actions handled in the switch
848        // statement below.
849        Device::BuiltinAction chosen_action = device->InvokeMenuItem(chosen_item);
850
851        int wipe_cache = 0;
852        switch (chosen_action) {
853            case Device::NO_ACTION:
854                break;
855
856            case Device::REBOOT:
857            case Device::SHUTDOWN:
858            case Device::REBOOT_BOOTLOADER:
859                return chosen_action;
860
861            case Device::WIPE_DATA:
862                wipe_data(ui->IsTextVisible(), device);
863                if (!ui->IsTextVisible()) return Device::NO_ACTION;
864                break;
865
866            case Device::WIPE_CACHE:
867                ui->Print("\n-- Wiping cache...\n");
868                erase_volume("/cache");
869                ui->Print("Cache wipe complete.\n");
870                if (!ui->IsTextVisible()) return Device::NO_ACTION;
871                break;
872
873            case Device::APPLY_EXT: {
874                ensure_path_mounted(SDCARD_ROOT);
875                char* path = browse_directory(SDCARD_ROOT, device);
876                if (path == NULL) {
877                    ui->Print("\n-- No package file selected.\n", path);
878                    break;
879                }
880
881                ui->Print("\n-- Install %s ...\n", path);
882                set_sdcard_update_bootloader_message();
883                void* token = start_sdcard_fuse(path);
884
885                int status = install_package(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache,
886                                             TEMPORARY_INSTALL_FILE, false);
887
888                finish_sdcard_fuse(token);
889                ensure_path_unmounted(SDCARD_ROOT);
890
891                if (status == INSTALL_SUCCESS && wipe_cache) {
892                    ui->Print("\n-- Wiping cache (at package request)...\n");
893                    if (erase_volume("/cache")) {
894                        ui->Print("Cache wipe failed.\n");
895                    } else {
896                        ui->Print("Cache wipe complete.\n");
897                    }
898                }
899
900                if (status >= 0) {
901                    if (status != INSTALL_SUCCESS) {
902                        ui->SetBackground(RecoveryUI::ERROR);
903                        ui->Print("Installation aborted.\n");
904                    } else if (!ui->IsTextVisible()) {
905                        return Device::NO_ACTION;  // reboot if logs aren't visible
906                    } else {
907                        ui->Print("\nInstall from sdcard complete.\n");
908                    }
909                }
910                break;
911            }
912
913            case Device::APPLY_CACHE:
914                ui->Print("\nAPPLY_CACHE is deprecated.\n");
915                break;
916
917            case Device::READ_RECOVERY_LASTLOG:
918                choose_recovery_file(device);
919                break;
920
921            case Device::APPLY_ADB_SIDELOAD:
922                status = apply_from_adb(ui, &wipe_cache, TEMPORARY_INSTALL_FILE);
923                if (status >= 0) {
924                    if (status != INSTALL_SUCCESS) {
925                        ui->SetBackground(RecoveryUI::ERROR);
926                        ui->Print("Installation aborted.\n");
927                        copy_logs();
928                    } else if (!ui->IsTextVisible()) {
929                        return Device::NO_ACTION;  // reboot if logs aren't visible
930                    } else {
931                        ui->Print("\nInstall from ADB complete.\n");
932                    }
933                }
934                break;
935        }
936    }
937}
938
939static void
940print_property(const char *key, const char *name, void *cookie) {
941    printf("%s=%s\n", key, name);
942}
943
944static void
945load_locale_from_cache() {
946    FILE* fp = fopen_path(LOCALE_FILE, "r");
947    char buffer[80];
948    if (fp != NULL) {
949        fgets(buffer, sizeof(buffer), fp);
950        int j = 0;
951        unsigned int i;
952        for (i = 0; i < sizeof(buffer) && buffer[i]; ++i) {
953            if (!isspace(buffer[i])) {
954                buffer[j++] = buffer[i];
955            }
956        }
957        buffer[j] = 0;
958        locale = strdup(buffer);
959        check_and_fclose(fp, LOCALE_FILE);
960    }
961}
962
963static RecoveryUI* gCurrentUI = NULL;
964
965void
966ui_print(const char* format, ...) {
967    char buffer[256];
968
969    va_list ap;
970    va_start(ap, format);
971    vsnprintf(buffer, sizeof(buffer), format, ap);
972    va_end(ap);
973
974    if (gCurrentUI != NULL) {
975        gCurrentUI->Print("%s", buffer);
976    } else {
977        fputs(buffer, stdout);
978    }
979}
980
981int
982main(int argc, char **argv) {
983    time_t start = time(NULL);
984
985    redirect_stdio(TEMPORARY_LOG_FILE);
986
987    // If this binary is started with the single argument "--adbd",
988    // instead of being the normal recovery binary, it turns into kind
989    // of a stripped-down version of adbd that only supports the
990    // 'sideload' command.  Note this must be a real argument, not
991    // anything in the command file or bootloader control block; the
992    // only way recovery should be run with this argument is when it
993    // starts a copy of itself from the apply_from_adb() function.
994    if (argc == 2 && strcmp(argv[1], "--adbd") == 0) {
995        adb_main();
996        return 0;
997    }
998
999    printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
1000
1001    load_volume_table();
1002    ensure_path_mounted(LAST_LOG_FILE);
1003    rotate_last_logs(KEEP_LOG_COUNT);
1004    get_args(&argc, &argv);
1005
1006    const char *send_intent = NULL;
1007    const char *update_package = NULL;
1008    int wipe_data = 0, wipe_cache = 0, show_text = 0;
1009    bool just_exit = false;
1010    bool shutdown_after = false;
1011
1012    int arg;
1013    while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
1014        switch (arg) {
1015        case 's': send_intent = optarg; break;
1016        case 'u': update_package = optarg; break;
1017        case 'w': wipe_data = wipe_cache = 1; break;
1018        case 'c': wipe_cache = 1; break;
1019        case 't': show_text = 1; break;
1020        case 'x': just_exit = true; break;
1021        case 'l': locale = optarg; break;
1022        case 'g': {
1023            if (stage == NULL || *stage == '\0') {
1024                char buffer[20] = "1/";
1025                strncat(buffer, optarg, sizeof(buffer)-3);
1026                stage = strdup(buffer);
1027            }
1028            break;
1029        }
1030        case 'p': shutdown_after = true; break;
1031        case 'r': reason = optarg; break;
1032        case '?':
1033            LOGE("Invalid command argument\n");
1034            continue;
1035        }
1036    }
1037
1038    if (locale == NULL) {
1039        load_locale_from_cache();
1040    }
1041    printf("locale is [%s]\n", locale);
1042    printf("stage is [%s]\n", stage);
1043    printf("reason is [%s]\n", reason);
1044
1045    Device* device = make_device();
1046    ui = device->GetUI();
1047    gCurrentUI = ui;
1048
1049    ui->SetLocale(locale);
1050    ui->Init();
1051
1052    int st_cur, st_max;
1053    if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) {
1054        ui->SetStage(st_cur, st_max);
1055    }
1056
1057    ui->SetBackground(RecoveryUI::NONE);
1058    if (show_text) ui->ShowText(true);
1059
1060    struct selinux_opt seopts[] = {
1061      { SELABEL_OPT_PATH, "/file_contexts" }
1062    };
1063
1064    sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
1065
1066    if (!sehandle) {
1067        ui->Print("Warning: No file_contexts\n");
1068    }
1069
1070    device->StartRecovery();
1071
1072    printf("Command:");
1073    for (arg = 0; arg < argc; arg++) {
1074        printf(" \"%s\"", argv[arg]);
1075    }
1076    printf("\n");
1077
1078    if (update_package) {
1079        // For backwards compatibility on the cache partition only, if
1080        // we're given an old 'root' path "CACHE:foo", change it to
1081        // "/cache/foo".
1082        if (strncmp(update_package, "CACHE:", 6) == 0) {
1083            int len = strlen(update_package) + 10;
1084            char* modified_path = (char*)malloc(len);
1085            strlcpy(modified_path, "/cache/", len);
1086            strlcat(modified_path, update_package+6, len);
1087            printf("(replacing path \"%s\" with \"%s\")\n",
1088                   update_package, modified_path);
1089            update_package = modified_path;
1090        }
1091    }
1092    printf("\n");
1093
1094    property_list(print_property, NULL);
1095    property_get("ro.build.display.id", recovery_version, "");
1096    printf("\n");
1097
1098    int status = INSTALL_SUCCESS;
1099
1100    if (update_package != NULL) {
1101        status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE, true);
1102        if (status == INSTALL_SUCCESS && wipe_cache) {
1103            if (erase_volume("/cache")) {
1104                LOGE("Cache wipe (requested by package) failed.");
1105            }
1106        }
1107        if (status != INSTALL_SUCCESS) {
1108            ui->Print("Installation aborted.\n");
1109            ui->Print("OTA failed! Please power off the device to keep it in this state and file a bug report!\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 (status != INSTALL_SUCCESS) ui->Print("Data wipe failed.\n");
1125    } else if (wipe_cache) {
1126        if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
1127        if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n");
1128    } else if (!just_exit) {
1129        status = INSTALL_NONE;  // No command specified
1130        ui->SetBackground(RecoveryUI::NO_COMMAND);
1131    }
1132
1133    if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) {
1134        copy_logs();
1135        ui->SetBackground(RecoveryUI::ERROR);
1136    }
1137    Device::BuiltinAction after = shutdown_after ? Device::SHUTDOWN : Device::REBOOT;
1138    if (status != INSTALL_SUCCESS || ui->IsTextVisible()) {
1139        Device::BuiltinAction temp = prompt_and_wait(device, status);
1140        if (temp != Device::NO_ACTION) after = temp;
1141    }
1142
1143    // Save logs and clean up before rebooting or shutting down.
1144    finish_recovery(send_intent);
1145
1146    switch (after) {
1147        case Device::SHUTDOWN:
1148            ui->Print("Shutting down...\n");
1149            property_set(ANDROID_RB_PROPERTY, "shutdown,");
1150            break;
1151
1152        case Device::REBOOT_BOOTLOADER:
1153            ui->Print("Rebooting to bootloader...\n");
1154            property_set(ANDROID_RB_PROPERTY, "reboot,bootloader");
1155            break;
1156
1157        default:
1158            ui->Print("Rebooting...\n");
1159            property_set(ANDROID_RB_PROPERTY, "reboot,");
1160            break;
1161    }
1162    sleep(5); // should reboot before this finishes
1163    return EXIT_SUCCESS;
1164}
1165