Home | History | Annotate | Download | only in fastboot
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #define _LARGEFILE64_SOURCE
     30 
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <stdarg.h>
     34 #include <stdbool.h>
     35 #include <stdint.h>
     36 #include <string.h>
     37 #include <errno.h>
     38 #include <fcntl.h>
     39 #include <unistd.h>
     40 #include <limits.h>
     41 #include <ctype.h>
     42 #include <getopt.h>
     43 
     44 #include <sys/time.h>
     45 #include <sys/types.h>
     46 
     47 #include <bootimg.h>
     48 #include <sparse/sparse.h>
     49 #include <zipfile/zipfile.h>
     50 
     51 #include "fastboot.h"
     52 
     53 #ifndef O_BINARY
     54 #define O_BINARY 0
     55 #endif
     56 
     57 char cur_product[FB_RESPONSE_SZ + 1];
     58 
     59 void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
     60 
     61 boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
     62                         void *ramdisk, unsigned ramdisk_size,
     63                         void *second, unsigned second_size,
     64                         unsigned page_size, unsigned base,
     65                         unsigned *bootimg_size);
     66 
     67 static usb_handle *usb = 0;
     68 static const char *serial = 0;
     69 static const char *product = 0;
     70 static const char *cmdline = 0;
     71 static int wipe_data = 0;
     72 static unsigned short vendor_id = 0;
     73 static int long_listing = 0;
     74 static int64_t sparse_limit = -1;
     75 static int64_t target_sparse_limit = -1;
     76 
     77 static unsigned base_addr = 0x10000000;
     78 
     79 void die(const char *fmt, ...)
     80 {
     81     va_list ap;
     82     va_start(ap, fmt);
     83     fprintf(stderr,"error: ");
     84     vfprintf(stderr, fmt, ap);
     85     fprintf(stderr,"\n");
     86     va_end(ap);
     87     exit(1);
     88 }
     89 
     90 void get_my_path(char *path);
     91 
     92 char *find_item(const char *item, const char *product)
     93 {
     94     char *dir;
     95     char *fn;
     96     char path[PATH_MAX + 128];
     97 
     98     if(!strcmp(item,"boot")) {
     99         fn = "boot.img";
    100     } else if(!strcmp(item,"recovery")) {
    101         fn = "recovery.img";
    102     } else if(!strcmp(item,"system")) {
    103         fn = "system.img";
    104     } else if(!strcmp(item,"userdata")) {
    105         fn = "userdata.img";
    106     } else if(!strcmp(item,"cache")) {
    107         fn = "cache.img";
    108     } else if(!strcmp(item,"info")) {
    109         fn = "android-info.txt";
    110     } else {
    111         fprintf(stderr,"unknown partition '%s'\n", item);
    112         return 0;
    113     }
    114 
    115     if(product) {
    116         get_my_path(path);
    117         sprintf(path + strlen(path),
    118                 "../../../target/product/%s/%s", product, fn);
    119         return strdup(path);
    120     }
    121 
    122     dir = getenv("ANDROID_PRODUCT_OUT");
    123     if((dir == 0) || (dir[0] == 0)) {
    124         die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
    125         return 0;
    126     }
    127 
    128     sprintf(path, "%s/%s", dir, fn);
    129     return strdup(path);
    130 }
    131 
    132 #ifdef _WIN32
    133 void *load_file(const char *fn, unsigned *_sz);
    134 int64_t file_size(const char *fn);
    135 #else
    136 #if defined(__APPLE__) && defined(__MACH__)
    137 #define lseek64 lseek
    138 #define off64_t off_t
    139 #endif
    140 
    141 int64_t file_size(const char *fn)
    142 {
    143     off64_t off;
    144     int fd;
    145 
    146     fd = open(fn, O_RDONLY);
    147     if (fd < 0) return -1;
    148 
    149     off = lseek64(fd, 0, SEEK_END);
    150     close(fd);
    151 
    152     return off;
    153 }
    154 
    155 void *load_file(const char *fn, unsigned *_sz)
    156 {
    157     char *data;
    158     int sz;
    159     int fd;
    160     int errno_tmp;
    161 
    162     data = 0;
    163     fd = open(fn, O_RDONLY);
    164     if(fd < 0) return 0;
    165 
    166     sz = lseek(fd, 0, SEEK_END);
    167     if(sz < 0) goto oops;
    168 
    169     if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
    170 
    171     data = (char*) malloc(sz);
    172     if(data == 0) goto oops;
    173 
    174     if(read(fd, data, sz) != sz) goto oops;
    175     close(fd);
    176 
    177     if(_sz) *_sz = sz;
    178     return data;
    179 
    180 oops:
    181     errno_tmp = errno;
    182     close(fd);
    183     if(data != 0) free(data);
    184     errno = errno_tmp;
    185     return 0;
    186 }
    187 #endif
    188 
    189 int match_fastboot(usb_ifc_info *info)
    190 {
    191     return match_fastboot_with_serial(info, serial);
    192 }
    193 
    194 int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial)
    195 {
    196     if(!(vendor_id && (info->dev_vendor == vendor_id)) &&
    197        (info->dev_vendor != 0x18d1) &&  // Google
    198        (info->dev_vendor != 0x8087) &&  // Intel
    199        (info->dev_vendor != 0x0451) &&
    200        (info->dev_vendor != 0x0502) &&
    201        (info->dev_vendor != 0x0fce) &&  // Sony Ericsson
    202        (info->dev_vendor != 0x05c6) &&  // Qualcomm
    203        (info->dev_vendor != 0x22b8) &&  // Motorola
    204        (info->dev_vendor != 0x0955) &&  // Nvidia
    205        (info->dev_vendor != 0x413c) &&  // DELL
    206        (info->dev_vendor != 0x2314) &&  // INQ Mobile
    207        (info->dev_vendor != 0x0b05) &&  // Asus
    208        (info->dev_vendor != 0x0bb4))    // HTC
    209             return -1;
    210     if(info->ifc_class != 0xff) return -1;
    211     if(info->ifc_subclass != 0x42) return -1;
    212     if(info->ifc_protocol != 0x03) return -1;
    213     // require matching serial number or device path if requested
    214     // at the command line with the -s option.
    215     if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
    216                    strcmp(local_serial, info->device_path) != 0)) return -1;
    217     return 0;
    218 }
    219 
    220 int list_devices_callback(usb_ifc_info *info)
    221 {
    222     if (match_fastboot_with_serial(info, NULL) == 0) {
    223         char* serial = info->serial_number;
    224         if (!info->writable) {
    225             serial = "no permissions"; // like "adb devices"
    226         }
    227         if (!serial[0]) {
    228             serial = "????????????";
    229         }
    230         // output compatible with "adb devices"
    231         if (!long_listing) {
    232             printf("%s\tfastboot\n", serial);
    233         } else if (!info->device_path) {
    234             printf("%-22s fastboot\n", serial);
    235         } else {
    236             printf("%-22s fastboot %s\n", serial, info->device_path);
    237         }
    238     }
    239 
    240     return -1;
    241 }
    242 
    243 usb_handle *open_device(void)
    244 {
    245     static usb_handle *usb = 0;
    246     int announce = 1;
    247 
    248     if(usb) return usb;
    249 
    250     for(;;) {
    251         usb = usb_open(match_fastboot);
    252         if(usb) return usb;
    253         if(announce) {
    254             announce = 0;
    255             fprintf(stderr,"< waiting for device >\n");
    256         }
    257         sleep(1);
    258     }
    259 }
    260 
    261 void list_devices(void) {
    262     // We don't actually open a USB device here,
    263     // just getting our callback called so we can
    264     // list all the connected devices.
    265     usb_open(list_devices_callback);
    266 }
    267 
    268 void usage(void)
    269 {
    270     fprintf(stderr,
    271 /*           1234567890123456789012345678901234567890123456789012345678901234567890123456 */
    272             "usage: fastboot [ <option> ] <command>\n"
    273             "\n"
    274             "commands:\n"
    275             "  update <filename>                        reflash device from update.zip\n"
    276             "  flashall                                 flash boot + recovery + system\n"
    277             "  flash <partition> [ <filename> ]         write a file to a flash partition\n"
    278             "  erase <partition>                        erase a flash partition\n"
    279             "  format <partition>                       format a flash partition \n"
    280             "  getvar <variable>                        display a bootloader variable\n"
    281             "  boot <kernel> [ <ramdisk> ]              download and boot kernel\n"
    282             "  flash:raw boot <kernel> [ <ramdisk> ]    create bootimage and flash it\n"
    283             "  devices                                  list all connected devices\n"
    284             "  continue                                 continue with autoboot\n"
    285             "  reboot                                   reboot device normally\n"
    286             "  reboot-bootloader                        reboot device into bootloader\n"
    287             "  help                                     show this help message\n"
    288             "\n"
    289             "options:\n"
    290             "  -w                                       erase userdata and cache (and format\n"
    291             "                                           if supported by partition type)\n"
    292             "  -u                                       do not first erase partition before\n"
    293             "                                           formatting\n"
    294             "  -s <specific device>                     specify device serial number\n"
    295             "                                           or path to device port\n"
    296             "  -l                                       with \"devices\", lists device paths\n"
    297             "  -p <product>                             specify product name\n"
    298             "  -c <cmdline>                             override kernel commandline\n"
    299             "  -i <vendor id>                           specify a custom USB vendor id\n"
    300             "  -b <base_addr>                           specify a custom kernel base address\n"
    301             "  -n <page size>                           specify the nand page size. default: 2048\n"
    302             "  -S <size>[K|M|G]                         automatically sparse files greater than\n"
    303             "                                           size.  0 to disable\n"
    304         );
    305 }
    306 
    307 void *load_bootable_image(unsigned page_size, const char *kernel, const char *ramdisk,
    308                           unsigned *sz, const char *cmdline)
    309 {
    310     void *kdata = 0, *rdata = 0;
    311     unsigned ksize = 0, rsize = 0;
    312     void *bdata;
    313     unsigned bsize;
    314 
    315     if(kernel == 0) {
    316         fprintf(stderr, "no image specified\n");
    317         return 0;
    318     }
    319 
    320     kdata = load_file(kernel, &ksize);
    321     if(kdata == 0) {
    322         fprintf(stderr, "cannot load '%s': %s\n", kernel, strerror(errno));
    323         return 0;
    324     }
    325 
    326         /* is this actually a boot image? */
    327     if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
    328         if(cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
    329 
    330         if(ramdisk) {
    331             fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n");
    332             return 0;
    333         }
    334 
    335         *sz = ksize;
    336         return kdata;
    337     }
    338 
    339     if(ramdisk) {
    340         rdata = load_file(ramdisk, &rsize);
    341         if(rdata == 0) {
    342             fprintf(stderr,"cannot load '%s': %s\n", ramdisk, strerror(errno));
    343             return  0;
    344         }
    345     }
    346 
    347     fprintf(stderr,"creating boot image...\n");
    348     bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, page_size, base_addr, &bsize);
    349     if(bdata == 0) {
    350         fprintf(stderr,"failed to create boot.img\n");
    351         return 0;
    352     }
    353     if(cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
    354     fprintf(stderr,"creating boot image - %d bytes\n", bsize);
    355     *sz = bsize;
    356 
    357     return bdata;
    358 }
    359 
    360 void *unzip_file(zipfile_t zip, const char *name, unsigned *sz)
    361 {
    362     void *data;
    363     zipentry_t entry;
    364     unsigned datasz;
    365 
    366     entry = lookup_zipentry(zip, name);
    367     if (entry == NULL) {
    368         fprintf(stderr, "archive does not contain '%s'\n", name);
    369         return 0;
    370     }
    371 
    372     *sz = get_zipentry_size(entry);
    373 
    374     datasz = *sz * 1.001;
    375     data = malloc(datasz);
    376 
    377     if(data == 0) {
    378         fprintf(stderr, "failed to allocate %d bytes\n", *sz);
    379         return 0;
    380     }
    381 
    382     if (decompress_zipentry(entry, data, datasz)) {
    383         fprintf(stderr, "failed to unzip '%s' from archive\n", name);
    384         free(data);
    385         return 0;
    386     }
    387 
    388     return data;
    389 }
    390 
    391 static char *strip(char *s)
    392 {
    393     int n;
    394     while(*s && isspace(*s)) s++;
    395     n = strlen(s);
    396     while(n-- > 0) {
    397         if(!isspace(s[n])) break;
    398         s[n] = 0;
    399     }
    400     return s;
    401 }
    402 
    403 #define MAX_OPTIONS 32
    404 static int setup_requirement_line(char *name)
    405 {
    406     char *val[MAX_OPTIONS];
    407     const char **out;
    408     char *prod = NULL;
    409     unsigned n, count;
    410     char *x;
    411     int invert = 0;
    412 
    413     if (!strncmp(name, "reject ", 7)) {
    414         name += 7;
    415         invert = 1;
    416     } else if (!strncmp(name, "require ", 8)) {
    417         name += 8;
    418         invert = 0;
    419     } else if (!strncmp(name, "require-for-product:", 20)) {
    420         // Get the product and point name past it
    421         prod = name + 20;
    422         name = strchr(name, ' ');
    423         if (!name) return -1;
    424         *name = 0;
    425         name += 1;
    426         invert = 0;
    427     }
    428 
    429     x = strchr(name, '=');
    430     if (x == 0) return 0;
    431     *x = 0;
    432     val[0] = x + 1;
    433 
    434     for(count = 1; count < MAX_OPTIONS; count++) {
    435         x = strchr(val[count - 1],'|');
    436         if (x == 0) break;
    437         *x = 0;
    438         val[count] = x + 1;
    439     }
    440 
    441     name = strip(name);
    442     for(n = 0; n < count; n++) val[n] = strip(val[n]);
    443 
    444     name = strip(name);
    445     if (name == 0) return -1;
    446 
    447         /* work around an unfortunate name mismatch */
    448     if (!strcmp(name,"board")) name = "product";
    449 
    450     out = malloc(sizeof(char*) * count);
    451     if (out == 0) return -1;
    452 
    453     for(n = 0; n < count; n++) {
    454         out[n] = strdup(strip(val[n]));
    455         if (out[n] == 0) return -1;
    456     }
    457 
    458     fb_queue_require(prod, name, invert, n, out);
    459     return 0;
    460 }
    461 
    462 static void setup_requirements(char *data, unsigned sz)
    463 {
    464     char *s;
    465 
    466     s = data;
    467     while (sz-- > 0) {
    468         if(*s == '\n') {
    469             *s++ = 0;
    470             if (setup_requirement_line(data)) {
    471                 die("out of memory");
    472             }
    473             data = s;
    474         } else {
    475             s++;
    476         }
    477     }
    478 }
    479 
    480 void queue_info_dump(void)
    481 {
    482     fb_queue_notice("--------------------------------------------");
    483     fb_queue_display("version-bootloader", "Bootloader Version...");
    484     fb_queue_display("version-baseband",   "Baseband Version.....");
    485     fb_queue_display("serialno",           "Serial Number........");
    486     fb_queue_notice("--------------------------------------------");
    487 }
    488 
    489 
    490 struct sparse_file **load_sparse_files(const char *fname, int max_size)
    491 {
    492     int fd;
    493     struct sparse_file *s;
    494     int files;
    495     struct sparse_file **out_s;
    496 
    497     fd = open(fname, O_RDONLY | O_BINARY);
    498     if (fd < 0) {
    499         die("cannot open '%s'\n", fname);
    500     }
    501 
    502     s = sparse_file_import_auto(fd, false);
    503     if (!s) {
    504         die("cannot sparse read file '%s'\n", fname);
    505     }
    506 
    507     files = sparse_file_resparse(s, max_size, NULL, 0);
    508     if (files < 0) {
    509         die("Failed to resparse '%s'\n", fname);
    510     }
    511 
    512     out_s = calloc(sizeof(struct sparse_file *), files + 1);
    513     if (!out_s) {
    514         die("Failed to allocate sparse file array\n");
    515     }
    516 
    517     files = sparse_file_resparse(s, max_size, out_s, files);
    518     if (files < 0) {
    519         die("Failed to resparse '%s'\n", fname);
    520     }
    521 
    522     return out_s;
    523 }
    524 
    525 static int64_t get_target_sparse_limit(struct usb_handle *usb)
    526 {
    527     int64_t limit = 0;
    528     char response[FB_RESPONSE_SZ + 1];
    529     int status = fb_getvar(usb, response, "max-download-size");
    530 
    531     if (!status) {
    532         limit = strtoul(response, NULL, 0);
    533         if (limit > 0) {
    534             fprintf(stderr, "target reported max download size of %lld bytes\n",
    535                     limit);
    536         }
    537     }
    538 
    539     return limit;
    540 }
    541 
    542 static int64_t get_sparse_limit(struct usb_handle *usb, int64_t size)
    543 {
    544     int64_t limit;
    545 
    546     if (sparse_limit == 0) {
    547         return 0;
    548     } else if (sparse_limit > 0) {
    549         limit = sparse_limit;
    550     } else {
    551         if (target_sparse_limit == -1) {
    552             target_sparse_limit = get_target_sparse_limit(usb);
    553         }
    554         if (target_sparse_limit > 0) {
    555             limit = target_sparse_limit;
    556         } else {
    557             return 0;
    558         }
    559     }
    560 
    561     if (size > limit) {
    562         return limit;
    563     }
    564 
    565     return 0;
    566 }
    567 
    568 /* Until we get lazy inode table init working in make_ext4fs, we need to
    569  * erase partitions of type ext4 before flashing a filesystem so no stale
    570  * inodes are left lying around.  Otherwise, e2fsck gets very upset.
    571  */
    572 static int needs_erase(const char *part)
    573 {
    574     /* The function fb_format_supported() currently returns the value
    575      * we want, so just call it.
    576      */
    577      return fb_format_supported(usb, part);
    578 }
    579 
    580 void do_flash(usb_handle *usb, const char *pname, const char *fname)
    581 {
    582     int64_t sz64;
    583     void *data;
    584     int64_t limit;
    585 
    586     sz64 = file_size(fname);
    587     limit = get_sparse_limit(usb, sz64);
    588     if (limit) {
    589         struct sparse_file **s = load_sparse_files(fname, limit);
    590         if (s == NULL) {
    591             die("cannot sparse load '%s'\n", fname);
    592         }
    593         while (*s) {
    594             sz64 = sparse_file_len(*s, true, false);
    595             fb_queue_flash_sparse(pname, *s++, sz64);
    596         }
    597     } else {
    598         unsigned int sz;
    599         data = load_file(fname, &sz);
    600         if (data == 0) die("cannot load '%s': %s\n", fname, strerror(errno));
    601         fb_queue_flash(pname, data, sz);
    602     }
    603 }
    604 
    605 void do_update_signature(zipfile_t zip, char *fn)
    606 {
    607     void *data;
    608     unsigned sz;
    609     data = unzip_file(zip, fn, &sz);
    610     if (data == 0) return;
    611     fb_queue_download("signature", data, sz);
    612     fb_queue_command("signature", "installing signature");
    613 }
    614 
    615 void do_update(char *fn, int erase_first)
    616 {
    617     void *zdata;
    618     unsigned zsize;
    619     void *data;
    620     unsigned sz;
    621     zipfile_t zip;
    622 
    623     queue_info_dump();
    624 
    625     fb_queue_query_save("product", cur_product, sizeof(cur_product));
    626 
    627     zdata = load_file(fn, &zsize);
    628     if (zdata == 0) die("failed to load '%s': %s", fn, strerror(errno));
    629 
    630     zip = init_zipfile(zdata, zsize);
    631     if(zip == 0) die("failed to access zipdata in '%s'");
    632 
    633     data = unzip_file(zip, "android-info.txt", &sz);
    634     if (data == 0) {
    635         char *tmp;
    636             /* fallback for older zipfiles */
    637         data = unzip_file(zip, "android-product.txt", &sz);
    638         if ((data == 0) || (sz < 1)) {
    639             die("update package has no android-info.txt or android-product.txt");
    640         }
    641         tmp = malloc(sz + 128);
    642         if (tmp == 0) die("out of memory");
    643         sprintf(tmp,"board=%sversion-baseband=0.66.04.19\n",(char*)data);
    644         data = tmp;
    645         sz = strlen(tmp);
    646     }
    647 
    648     setup_requirements(data, sz);
    649 
    650     data = unzip_file(zip, "boot.img", &sz);
    651     if (data == 0) die("update package missing boot.img");
    652     do_update_signature(zip, "boot.sig");
    653     if (erase_first && needs_erase("boot")) {
    654         fb_queue_erase("boot");
    655     }
    656     fb_queue_flash("boot", data, sz);
    657 
    658     data = unzip_file(zip, "recovery.img", &sz);
    659     if (data != 0) {
    660         do_update_signature(zip, "recovery.sig");
    661         if (erase_first && needs_erase("recovery")) {
    662             fb_queue_erase("recovery");
    663         }
    664         fb_queue_flash("recovery", data, sz);
    665     }
    666 
    667     data = unzip_file(zip, "system.img", &sz);
    668     if (data == 0) die("update package missing system.img");
    669     do_update_signature(zip, "system.sig");
    670     if (erase_first && needs_erase("system")) {
    671         fb_queue_erase("system");
    672     }
    673     fb_queue_flash("system", data, sz);
    674 }
    675 
    676 void do_send_signature(char *fn)
    677 {
    678     void *data;
    679     unsigned sz;
    680     char *xtn;
    681 
    682     xtn = strrchr(fn, '.');
    683     if (!xtn) return;
    684     if (strcmp(xtn, ".img")) return;
    685 
    686     strcpy(xtn,".sig");
    687     data = load_file(fn, &sz);
    688     strcpy(xtn,".img");
    689     if (data == 0) return;
    690     fb_queue_download("signature", data, sz);
    691     fb_queue_command("signature", "installing signature");
    692 }
    693 
    694 void do_flashall(int erase_first)
    695 {
    696     char *fname;
    697     void *data;
    698     unsigned sz;
    699 
    700     queue_info_dump();
    701 
    702     fb_queue_query_save("product", cur_product, sizeof(cur_product));
    703 
    704     fname = find_item("info", product);
    705     if (fname == 0) die("cannot find android-info.txt");
    706     data = load_file(fname, &sz);
    707     if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
    708     setup_requirements(data, sz);
    709 
    710     fname = find_item("boot", product);
    711     data = load_file(fname, &sz);
    712     if (data == 0) die("could not load boot.img: %s", strerror(errno));
    713     do_send_signature(fname);
    714     if (erase_first && needs_erase("boot")) {
    715         fb_queue_erase("boot");
    716     }
    717     fb_queue_flash("boot", data, sz);
    718 
    719     fname = find_item("recovery", product);
    720     data = load_file(fname, &sz);
    721     if (data != 0) {
    722         do_send_signature(fname);
    723         if (erase_first && needs_erase("recovery")) {
    724             fb_queue_erase("recovery");
    725         }
    726         fb_queue_flash("recovery", data, sz);
    727     }
    728 
    729     fname = find_item("system", product);
    730     data = load_file(fname, &sz);
    731     if (data == 0) die("could not load system.img: %s", strerror(errno));
    732     do_send_signature(fname);
    733     if (erase_first && needs_erase("system")) {
    734         fb_queue_erase("system");
    735     }
    736     fb_queue_flash("system", data, sz);
    737 }
    738 
    739 #define skip(n) do { argc -= (n); argv += (n); } while (0)
    740 #define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0)
    741 
    742 int do_oem_command(int argc, char **argv)
    743 {
    744     int i;
    745     char command[256];
    746     if (argc <= 1) return 0;
    747 
    748     command[0] = 0;
    749     while(1) {
    750         strcat(command,*argv);
    751         skip(1);
    752         if(argc == 0) break;
    753         strcat(command," ");
    754     }
    755 
    756     fb_queue_command(command,"");
    757     return 0;
    758 }
    759 
    760 static int64_t parse_num(const char *arg)
    761 {
    762     char *endptr;
    763     unsigned long long num;
    764 
    765     num = strtoull(arg, &endptr, 0);
    766     if (endptr == arg) {
    767         return -1;
    768     }
    769 
    770     if (*endptr == 'k' || *endptr == 'K') {
    771         if (num >= (-1ULL) / 1024) {
    772             return -1;
    773         }
    774         num *= 1024LL;
    775         endptr++;
    776     } else if (*endptr == 'm' || *endptr == 'M') {
    777         if (num >= (-1ULL) / (1024 * 1024)) {
    778             return -1;
    779         }
    780         num *= 1024LL * 1024LL;
    781         endptr++;
    782     } else if (*endptr == 'g' || *endptr == 'G') {
    783         if (num >= (-1ULL) / (1024 * 1024 * 1024)) {
    784             return -1;
    785         }
    786         num *= 1024LL * 1024LL * 1024LL;
    787         endptr++;
    788     }
    789 
    790     if (*endptr != '\0') {
    791         return -1;
    792     }
    793 
    794     if (num > INT64_MAX) {
    795         return -1;
    796     }
    797 
    798     return num;
    799 }
    800 
    801 int main(int argc, char **argv)
    802 {
    803     int wants_wipe = 0;
    804     int wants_reboot = 0;
    805     int wants_reboot_bootloader = 0;
    806     int erase_first = 1;
    807     void *data;
    808     unsigned sz;
    809     unsigned page_size = 2048;
    810     int status;
    811     int c;
    812     int r;
    813 
    814     const struct option longopts = { 0, 0, 0, 0 };
    815 
    816     serial = getenv("ANDROID_SERIAL");
    817 
    818     while (1) {
    819         c = getopt_long(argc, argv, "wub:n:s:S:lp:c:i:m:h", &longopts, NULL);
    820         if (c < 0) {
    821             break;
    822         }
    823 
    824         switch (c) {
    825         case 'w':
    826             wants_wipe = 1;
    827             break;
    828         case 'u':
    829             erase_first = 0;
    830             break;
    831         case 'b':
    832             base_addr = strtoul(optarg, 0, 16);
    833             break;
    834         case 'n':
    835             page_size = (unsigned)strtoul(optarg, NULL, 0);
    836             if (!page_size) die("invalid page size");
    837             break;
    838         case 's':
    839             serial = optarg;
    840             break;
    841         case 'S':
    842             sparse_limit = parse_num(optarg);
    843             if (sparse_limit < 0) {
    844                     die("invalid sparse limit");
    845             }
    846             break;
    847         case 'l':
    848             long_listing = 1;
    849             break;
    850         case 'p':
    851             product = optarg;
    852             break;
    853         case 'c':
    854             cmdline = optarg;
    855             break;
    856         case 'i': {
    857                 char *endptr = NULL;
    858                 unsigned long val;
    859 
    860                 val = strtoul(optarg, &endptr, 0);
    861                 if (!endptr || *endptr != '\0' || (val & ~0xffff))
    862                     die("invalid vendor id '%s'", optarg);
    863                 vendor_id = (unsigned short)val;
    864                 break;
    865             }
    866         case 'h':
    867             usage();
    868             return 1;
    869         case '?':
    870             return 1;
    871         default:
    872             abort();
    873         }
    874     }
    875 
    876     argc -= optind;
    877     argv += optind;
    878 
    879     if (argc == 0 && !wants_wipe) {
    880         usage();
    881         return 1;
    882     }
    883 
    884     if (argc > 0 && !strcmp(*argv, "devices")) {
    885         skip(1);
    886         list_devices();
    887         return 0;
    888     }
    889 
    890     if (argc > 0 && !strcmp(*argv, "help")) {
    891         usage();
    892         return 0;
    893     }
    894 
    895     usb = open_device();
    896 
    897     while (argc > 0) {
    898         if(!strcmp(*argv, "getvar")) {
    899             require(2);
    900             fb_queue_display(argv[1], argv[1]);
    901             skip(2);
    902         } else if(!strcmp(*argv, "erase")) {
    903             require(2);
    904 
    905             if (fb_format_supported(usb, argv[1])) {
    906                 fprintf(stderr, "******** Did you mean to fastboot format this partition?\n");
    907             }
    908 
    909             fb_queue_erase(argv[1]);
    910             skip(2);
    911         } else if(!strcmp(*argv, "format")) {
    912             require(2);
    913             if (erase_first && needs_erase(argv[1])) {
    914                 fb_queue_erase(argv[1]);
    915             }
    916             fb_queue_format(argv[1], 0);
    917             skip(2);
    918         } else if(!strcmp(*argv, "signature")) {
    919             require(2);
    920             data = load_file(argv[1], &sz);
    921             if (data == 0) die("could not load '%s': %s", argv[1], strerror(errno));
    922             if (sz != 256) die("signature must be 256 bytes");
    923             fb_queue_download("signature", data, sz);
    924             fb_queue_command("signature", "installing signature");
    925             skip(2);
    926         } else if(!strcmp(*argv, "reboot")) {
    927             wants_reboot = 1;
    928             skip(1);
    929         } else if(!strcmp(*argv, "reboot-bootloader")) {
    930             wants_reboot_bootloader = 1;
    931             skip(1);
    932         } else if (!strcmp(*argv, "continue")) {
    933             fb_queue_command("continue", "resuming boot");
    934             skip(1);
    935         } else if(!strcmp(*argv, "boot")) {
    936             char *kname = 0;
    937             char *rname = 0;
    938             skip(1);
    939             if (argc > 0) {
    940                 kname = argv[0];
    941                 skip(1);
    942             }
    943             if (argc > 0) {
    944                 rname = argv[0];
    945                 skip(1);
    946             }
    947             data = load_bootable_image(page_size, kname, rname, &sz, cmdline);
    948             if (data == 0) return 1;
    949             fb_queue_download("boot.img", data, sz);
    950             fb_queue_command("boot", "booting");
    951         } else if(!strcmp(*argv, "flash")) {
    952             char *pname = argv[1];
    953             char *fname = 0;
    954             require(2);
    955             if (argc > 2) {
    956                 fname = argv[2];
    957                 skip(3);
    958             } else {
    959                 fname = find_item(pname, product);
    960                 skip(2);
    961             }
    962             if (fname == 0) die("cannot determine image filename for '%s'", pname);
    963             if (erase_first && needs_erase(pname)) {
    964                 fb_queue_erase(pname);
    965             }
    966             do_flash(usb, pname, fname);
    967         } else if(!strcmp(*argv, "flash:raw")) {
    968             char *pname = argv[1];
    969             char *kname = argv[2];
    970             char *rname = 0;
    971             require(3);
    972             if(argc > 3) {
    973                 rname = argv[3];
    974                 skip(4);
    975             } else {
    976                 skip(3);
    977             }
    978             data = load_bootable_image(page_size, kname, rname, &sz, cmdline);
    979             if (data == 0) die("cannot load bootable image");
    980             fb_queue_flash(pname, data, sz);
    981         } else if(!strcmp(*argv, "flashall")) {
    982             skip(1);
    983             do_flashall(erase_first);
    984             wants_reboot = 1;
    985         } else if(!strcmp(*argv, "update")) {
    986             if (argc > 1) {
    987                 do_update(argv[1], erase_first);
    988                 skip(2);
    989             } else {
    990                 do_update("update.zip", erase_first);
    991                 skip(1);
    992             }
    993             wants_reboot = 1;
    994         } else if(!strcmp(*argv, "oem")) {
    995             argc = do_oem_command(argc, argv);
    996         } else {
    997             usage();
    998             return 1;
    999         }
   1000     }
   1001 
   1002     if (wants_wipe) {
   1003         fb_queue_erase("userdata");
   1004         fb_queue_format("userdata", 1);
   1005         fb_queue_erase("cache");
   1006         fb_queue_format("cache", 1);
   1007     }
   1008     if (wants_reboot) {
   1009         fb_queue_reboot();
   1010     } else if (wants_reboot_bootloader) {
   1011         fb_queue_command("reboot-bootloader", "rebooting into bootloader");
   1012     }
   1013 
   1014     if (fb_queue_is_empty())
   1015         return 0;
   1016 
   1017     status = fb_execute_queue(usb);
   1018     return (status) ? 1 : 0;
   1019 }
   1020