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