• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
die(const char * fmt,...)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 
find_item(const char * item,const char * product)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 
file_size(const char * fn)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 
load_file(const char * fn,unsigned * _sz)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 
match_fastboot(usb_ifc_info * info)189 int match_fastboot(usb_ifc_info *info)
190 {
191     return match_fastboot_with_serial(info, serial);
192 }
193 
match_fastboot_with_serial(usb_ifc_info * info,const char * local_serial)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 
list_devices_callback(usb_ifc_info * info)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 
open_device(void)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 
list_devices(void)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 
usage(void)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 
load_bootable_image(unsigned page_size,const char * kernel,const char * ramdisk,unsigned * sz,const char * cmdline)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 
unzip_file(zipfile_t zip,const char * name,unsigned * sz)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 
strip(char * s)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
setup_requirement_line(char * name)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 
setup_requirements(char * data,unsigned sz)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 
queue_info_dump(void)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 
load_sparse_files(const char * fname,int max_size)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 
get_target_sparse_limit(struct usb_handle * usb)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 
get_sparse_limit(struct usb_handle * usb,int64_t size)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  */
needs_erase(const char * part)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 
do_flash(usb_handle * usb,const char * pname,const char * fname)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 
do_update_signature(zipfile_t zip,char * fn)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 
do_update(char * fn,int erase_first)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 
do_send_signature(char * fn)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 
do_flashall(int erase_first)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 
do_oem_command(int argc,char ** argv)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 
parse_num(const char * arg)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 
main(int argc,char ** argv)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