blob: f1b675f4acd953225ceb8208c78d37252e45bda9 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
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
Tsu Chiang Chuangee520552011-02-25 18:38:53 -080012 * the documentation and/or other materials provided with the
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080013 * 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
Tsu Chiang Chuangee520552011-02-25 18:38:53 -080022 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023 * 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#include <stdio.h>
30#include <stdlib.h>
31#include <stdarg.h>
32#include <string.h>
33#include <errno.h>
34#include <fcntl.h>
35#include <unistd.h>
36#include <limits.h>
37#include <ctype.h>
38
39#include <sys/time.h>
40#include <bootimg.h>
41#include <zipfile/zipfile.h>
42
43#include "fastboot.h"
44
Wink Savilleb98762f2011-04-04 17:54:59 -070045char cur_product[FB_RESPONSE_SZ + 1];
46
Brian Swetland2a63bb72009-04-28 16:05:07 -070047void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
48
49boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
50 void *ramdisk, unsigned ramdisk_size,
51 void *second, unsigned second_size,
52 unsigned page_size, unsigned base,
53 unsigned *bootimg_size);
54
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080055static usb_handle *usb = 0;
56static const char *serial = 0;
57static const char *product = 0;
58static const char *cmdline = 0;
59static int wipe_data = 0;
60static unsigned short vendor_id = 0;
Scott Anderson13081c62012-04-06 12:39:30 -070061static int long_listing = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080062
Brian Swetland2a63bb72009-04-28 16:05:07 -070063static unsigned base_addr = 0x10000000;
64
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080065void die(const char *fmt, ...)
66{
67 va_list ap;
68 va_start(ap, fmt);
69 fprintf(stderr,"error: ");
70 vfprintf(stderr, fmt, ap);
71 fprintf(stderr,"\n");
72 va_end(ap);
73 exit(1);
Tsu Chiang Chuangee520552011-02-25 18:38:53 -080074}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080075
76void get_my_path(char *path);
77
78char *find_item(const char *item, const char *product)
79{
80 char *dir;
81 char *fn;
82 char path[PATH_MAX + 128];
83
84 if(!strcmp(item,"boot")) {
85 fn = "boot.img";
86 } else if(!strcmp(item,"recovery")) {
87 fn = "recovery.img";
88 } else if(!strcmp(item,"system")) {
89 fn = "system.img";
90 } else if(!strcmp(item,"userdata")) {
91 fn = "userdata.img";
92 } else if(!strcmp(item,"info")) {
93 fn = "android-info.txt";
94 } else {
95 fprintf(stderr,"unknown partition '%s'\n", item);
96 return 0;
97 }
98
99 if(product) {
100 get_my_path(path);
101 sprintf(path + strlen(path),
102 "../../../target/product/%s/%s", product, fn);
103 return strdup(path);
104 }
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800105
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800106 dir = getenv("ANDROID_PRODUCT_OUT");
107 if((dir == 0) || (dir[0] == 0)) {
108 die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
109 return 0;
110 }
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800111
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800112 sprintf(path, "%s/%s", dir, fn);
113 return strdup(path);
114}
115
116#ifdef _WIN32
117void *load_file(const char *fn, unsigned *_sz);
118#else
119void *load_file(const char *fn, unsigned *_sz)
120{
121 char *data;
122 int sz;
123 int fd;
124
125 data = 0;
126 fd = open(fn, O_RDONLY);
127 if(fd < 0) return 0;
128
129 sz = lseek(fd, 0, SEEK_END);
130 if(sz < 0) goto oops;
131
132 if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
133
134 data = (char*) malloc(sz);
135 if(data == 0) goto oops;
136
137 if(read(fd, data, sz) != sz) goto oops;
138 close(fd);
139
140 if(_sz) *_sz = sz;
141 return data;
142
143oops:
144 close(fd);
145 if(data != 0) free(data);
146 return 0;
147}
148#endif
149
150int match_fastboot(usb_ifc_info *info)
151{
152 if(!(vendor_id && (info->dev_vendor == vendor_id)) &&
Mike Lockwood09070d92009-08-05 17:04:36 -0400153 (info->dev_vendor != 0x18d1) && // Google
The Android Open Source Projectf614d642009-03-18 17:39:49 -0700154 (info->dev_vendor != 0x0451) &&
Robert CH Choue25ff1c2009-09-21 09:51:35 +0800155 (info->dev_vendor != 0x0502) &&
Dima Zavin509f7392010-05-14 14:48:30 -0700156 (info->dev_vendor != 0x0fce) && // Sony Ericsson
157 (info->dev_vendor != 0x05c6) && // Qualcomm
Mike Lockwood09070d92009-08-05 17:04:36 -0400158 (info->dev_vendor != 0x22b8) && // Motorola
Erik Gilling37e9e902010-01-20 17:40:05 -0800159 (info->dev_vendor != 0x0955) && // Nvidia
Xavier Ducrohetaf82f212010-01-21 17:39:25 -0800160 (info->dev_vendor != 0x413c) && // DELL
Xavier Ducrohet746f3242012-01-13 16:03:37 -0800161 (info->dev_vendor != 0x2314) && // INQ Mobile
Mike Lockwood09070d92009-08-05 17:04:36 -0400162 (info->dev_vendor != 0x0bb4)) // HTC
163 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800164 if(info->ifc_class != 0xff) return -1;
165 if(info->ifc_subclass != 0x42) return -1;
166 if(info->ifc_protocol != 0x03) return -1;
Scott Anderson13081c62012-04-06 12:39:30 -0700167 // require matching serial number or device path if requested
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800168 // at the command line with the -s option.
Scott Anderson13081c62012-04-06 12:39:30 -0700169 if (serial && (strcmp(serial, info->serial_number) != 0 &&
170 strcmp(serial, info->device_path) != 0)) return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800171 return 0;
172}
173
174int list_devices_callback(usb_ifc_info *info)
175{
176 if (match_fastboot(info) == 0) {
177 char* serial = info->serial_number;
Elliott Hughesb4add9b2009-10-06 18:07:49 -0700178 if (!info->writable) {
179 serial = "no permissions"; // like "adb devices"
180 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800181 if (!serial[0]) {
182 serial = "????????????";
183 }
Scott Anderson13081c62012-04-06 12:39:30 -0700184 if (!long_listing) {
185 // output compatible with "adb devices"
186 printf("%s\tfastboot\n", serial);
187 } else {
188 char* device_path = info->device_path;
189 if (!device_path[0]) {
190 device_path = "????????????";
191 }
192 printf("%s\t%s\tfastboot\n", serial, device_path);
193 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800194 }
195
196 return -1;
197}
198
199usb_handle *open_device(void)
200{
201 static usb_handle *usb = 0;
202 int announce = 1;
203
204 if(usb) return usb;
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800205
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800206 for(;;) {
207 usb = usb_open(match_fastboot);
208 if(usb) return usb;
209 if(announce) {
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800210 announce = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800211 fprintf(stderr,"< waiting for device >\n");
212 }
213 sleep(1);
214 }
215}
216
217void list_devices(void) {
218 // We don't actually open a USB device here,
219 // just getting our callback called so we can
220 // list all the connected devices.
221 usb_open(list_devices_callback);
222}
223
224void usage(void)
225{
226 fprintf(stderr,
227/* 1234567890123456789012345678901234567890123456789012345678901234567890123456 */
228 "usage: fastboot [ <option> ] <command>\n"
229 "\n"
230 "commands:\n"
231 " update <filename> reflash device from update.zip\n"
232 " flashall flash boot + recovery + system\n"
233 " flash <partition> [ <filename> ] write a file to a flash partition\n"
234 " erase <partition> erase a flash partition\n"
Anatol Pomazau65cf84f2011-12-15 17:50:18 -0800235 " format <partition> format a flash partition \n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800236 " getvar <variable> display a bootloader variable\n"
237 " boot <kernel> [ <ramdisk> ] download and boot kernel\n"
238 " flash:raw boot <kernel> [ <ramdisk> ] create bootimage and flash it\n"
239 " devices list all connected devices\n"
Bruce Beare24ce4bc2010-10-14 09:43:26 -0700240 " continue continue with autoboot\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 " reboot reboot device normally\n"
242 " reboot-bootloader reboot device into bootloader\n"
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800243 " help show this help message\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800244 "\n"
245 "options:\n"
246 " -w erase userdata and cache\n"
Scott Anderson13081c62012-04-06 12:39:30 -0700247 " -s <specific device> specify device serial number\n"
248 " or path to device port\n"
249 " -l with \"devices\", lists device paths\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800250 " -p <product> specify product name\n"
251 " -c <cmdline> override kernel commandline\n"
252 " -i <vendor id> specify a custom USB vendor id\n"
Dima Zavin95ec9832009-04-30 15:03:05 -0700253 " -b <base_addr> specify a custom kernel base address\n"
Dima Zavin931175a2010-02-12 20:26:33 -0800254 " -n <page size> specify the nand page size. default: 2048\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800255 );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256}
257
Dima Zavin931175a2010-02-12 20:26:33 -0800258void *load_bootable_image(unsigned page_size, const char *kernel, const char *ramdisk,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259 unsigned *sz, const char *cmdline)
260{
261 void *kdata = 0, *rdata = 0;
262 unsigned ksize = 0, rsize = 0;
263 void *bdata;
264 unsigned bsize;
265
266 if(kernel == 0) {
267 fprintf(stderr, "no image specified\n");
268 return 0;
269 }
270
271 kdata = load_file(kernel, &ksize);
272 if(kdata == 0) {
273 fprintf(stderr, "cannot load '%s'\n", kernel);
274 return 0;
275 }
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800276
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277 /* is this actually a boot image? */
278 if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
279 if(cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800280
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 if(ramdisk) {
282 fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n");
283 return 0;
284 }
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800285
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800286 *sz = ksize;
287 return kdata;
288 }
289
290 if(ramdisk) {
291 rdata = load_file(ramdisk, &rsize);
292 if(rdata == 0) {
293 fprintf(stderr,"cannot load '%s'\n", ramdisk);
294 return 0;
295 }
296 }
297
298 fprintf(stderr,"creating boot image...\n");
Dima Zavin931175a2010-02-12 20:26:33 -0800299 bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, page_size, base_addr, &bsize);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300 if(bdata == 0) {
301 fprintf(stderr,"failed to create boot.img\n");
302 return 0;
303 }
304 if(cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
305 fprintf(stderr,"creating boot image - %d bytes\n", bsize);
306 *sz = bsize;
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800307
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800308 return bdata;
309}
310
311void *unzip_file(zipfile_t zip, const char *name, unsigned *sz)
312{
313 void *data;
314 zipentry_t entry;
315 unsigned datasz;
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800316
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800317 entry = lookup_zipentry(zip, name);
318 if (entry == NULL) {
319 fprintf(stderr, "archive does not contain '%s'\n", name);
320 return 0;
321 }
322
323 *sz = get_zipentry_size(entry);
324
325 datasz = *sz * 1.001;
326 data = malloc(datasz);
327
328 if(data == 0) {
329 fprintf(stderr, "failed to allocate %d bytes\n", *sz);
330 return 0;
331 }
332
333 if (decompress_zipentry(entry, data, datasz)) {
334 fprintf(stderr, "failed to unzip '%s' from archive\n", name);
335 free(data);
336 return 0;
337 }
338
339 return data;
340}
341
342static char *strip(char *s)
343{
344 int n;
345 while(*s && isspace(*s)) s++;
346 n = strlen(s);
347 while(n-- > 0) {
348 if(!isspace(s[n])) break;
349 s[n] = 0;
350 }
351 return s;
352}
353
354#define MAX_OPTIONS 32
355static int setup_requirement_line(char *name)
356{
357 char *val[MAX_OPTIONS];
358 const char **out;
Wink Savilleb98762f2011-04-04 17:54:59 -0700359 char *prod = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800360 unsigned n, count;
361 char *x;
362 int invert = 0;
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800363
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800364 if (!strncmp(name, "reject ", 7)) {
365 name += 7;
366 invert = 1;
367 } else if (!strncmp(name, "require ", 8)) {
368 name += 8;
369 invert = 0;
Wink Savilleb98762f2011-04-04 17:54:59 -0700370 } else if (!strncmp(name, "require-for-product:", 20)) {
371 // Get the product and point name past it
372 prod = name + 20;
373 name = strchr(name, ' ');
374 if (!name) return -1;
375 *name = 0;
376 name += 1;
377 invert = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800378 }
379
380 x = strchr(name, '=');
381 if (x == 0) return 0;
382 *x = 0;
383 val[0] = x + 1;
384
385 for(count = 1; count < MAX_OPTIONS; count++) {
386 x = strchr(val[count - 1],'|');
387 if (x == 0) break;
388 *x = 0;
389 val[count] = x + 1;
390 }
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800391
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800392 name = strip(name);
393 for(n = 0; n < count; n++) val[n] = strip(val[n]);
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800394
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800395 name = strip(name);
396 if (name == 0) return -1;
397
398 /* work around an unfortunate name mismatch */
399 if (!strcmp(name,"board")) name = "product";
400
401 out = malloc(sizeof(char*) * count);
402 if (out == 0) return -1;
403
404 for(n = 0; n < count; n++) {
405 out[n] = strdup(strip(val[n]));
406 if (out[n] == 0) return -1;
407 }
408
Wink Savilleb98762f2011-04-04 17:54:59 -0700409 fb_queue_require(prod, name, invert, n, out);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 return 0;
411}
412
413static void setup_requirements(char *data, unsigned sz)
414{
415 char *s;
416
417 s = data;
418 while (sz-- > 0) {
419 if(*s == '\n') {
420 *s++ = 0;
421 if (setup_requirement_line(data)) {
422 die("out of memory");
423 }
424 data = s;
425 } else {
426 s++;
427 }
428 }
429}
430
431void queue_info_dump(void)
432{
433 fb_queue_notice("--------------------------------------------");
434 fb_queue_display("version-bootloader", "Bootloader Version...");
435 fb_queue_display("version-baseband", "Baseband Version.....");
436 fb_queue_display("serialno", "Serial Number........");
437 fb_queue_notice("--------------------------------------------");
438}
439
440void do_update_signature(zipfile_t zip, char *fn)
441{
442 void *data;
443 unsigned sz;
444 data = unzip_file(zip, fn, &sz);
445 if (data == 0) return;
446 fb_queue_download("signature", data, sz);
447 fb_queue_command("signature", "installing signature");
448}
449
450void do_update(char *fn)
451{
452 void *zdata;
453 unsigned zsize;
454 void *data;
455 unsigned sz;
456 zipfile_t zip;
457
458 queue_info_dump();
459
Wink Savilleb98762f2011-04-04 17:54:59 -0700460 fb_queue_query_save("product", cur_product, sizeof(cur_product));
461
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800462 zdata = load_file(fn, &zsize);
463 if (zdata == 0) die("failed to load '%s'", fn);
464
465 zip = init_zipfile(zdata, zsize);
466 if(zip == 0) die("failed to access zipdata in '%s'");
467
468 data = unzip_file(zip, "android-info.txt", &sz);
469 if (data == 0) {
470 char *tmp;
471 /* fallback for older zipfiles */
472 data = unzip_file(zip, "android-product.txt", &sz);
473 if ((data == 0) || (sz < 1)) {
474 die("update package has no android-info.txt or android-product.txt");
475 }
476 tmp = malloc(sz + 128);
477 if (tmp == 0) die("out of memory");
478 sprintf(tmp,"board=%sversion-baseband=0.66.04.19\n",(char*)data);
479 data = tmp;
480 sz = strlen(tmp);
481 }
482
483 setup_requirements(data, sz);
484
485 data = unzip_file(zip, "boot.img", &sz);
486 if (data == 0) die("update package missing boot.img");
487 do_update_signature(zip, "boot.sig");
488 fb_queue_flash("boot", data, sz);
489
490 data = unzip_file(zip, "recovery.img", &sz);
491 if (data != 0) {
492 do_update_signature(zip, "recovery.sig");
493 fb_queue_flash("recovery", data, sz);
494 }
495
496 data = unzip_file(zip, "system.img", &sz);
497 if (data == 0) die("update package missing system.img");
498 do_update_signature(zip, "system.sig");
499 fb_queue_flash("system", data, sz);
500}
501
502void do_send_signature(char *fn)
503{
504 void *data;
505 unsigned sz;
506 char *xtn;
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800507
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800508 xtn = strrchr(fn, '.');
509 if (!xtn) return;
510 if (strcmp(xtn, ".img")) return;
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800511
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800512 strcpy(xtn,".sig");
513 data = load_file(fn, &sz);
514 strcpy(xtn,".img");
515 if (data == 0) return;
516 fb_queue_download("signature", data, sz);
517 fb_queue_command("signature", "installing signature");
518}
519
520void do_flashall(void)
521{
522 char *fname;
523 void *data;
524 unsigned sz;
525
526 queue_info_dump();
527
Wink Savilleb98762f2011-04-04 17:54:59 -0700528 fb_queue_query_save("product", cur_product, sizeof(cur_product));
529
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800530 fname = find_item("info", product);
531 if (fname == 0) die("cannot find android-info.txt");
532 data = load_file(fname, &sz);
533 if (data == 0) die("could not load android-info.txt");
534 setup_requirements(data, sz);
535
536 fname = find_item("boot", product);
537 data = load_file(fname, &sz);
538 if (data == 0) die("could not load boot.img");
539 do_send_signature(fname);
540 fb_queue_flash("boot", data, sz);
541
542 fname = find_item("recovery", product);
543 data = load_file(fname, &sz);
544 if (data != 0) {
545 do_send_signature(fname);
546 fb_queue_flash("recovery", data, sz);
547 }
548
549 fname = find_item("system", product);
550 data = load_file(fname, &sz);
551 if (data == 0) die("could not load system.img");
552 do_send_signature(fname);
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800553 fb_queue_flash("system", data, sz);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800554}
555
556#define skip(n) do { argc -= (n); argv += (n); } while (0)
JP Abgrall2d13d142011-03-01 23:35:07 -0800557#define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800558
559int do_oem_command(int argc, char **argv)
560{
561 int i;
562 char command[256];
563 if (argc <= 1) return 0;
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800564
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565 command[0] = 0;
566 while(1) {
567 strcat(command,*argv);
568 skip(1);
569 if(argc == 0) break;
570 strcat(command," ");
571 }
572
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800573 fb_queue_command(command,"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800574 return 0;
575}
576
577int main(int argc, char **argv)
578{
579 int wants_wipe = 0;
580 int wants_reboot = 0;
581 int wants_reboot_bootloader = 0;
Scott Anderson13081c62012-04-06 12:39:30 -0700582 int wants_device_list = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800583 void *data;
584 unsigned sz;
Dima Zavin931175a2010-02-12 20:26:33 -0800585 unsigned page_size = 2048;
Brian Carlstromeb31c0b2010-04-23 12:38:51 -0700586 int status;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800587
588 skip(1);
589 if (argc == 0) {
590 usage();
Brian Carlstromeb31c0b2010-04-23 12:38:51 -0700591 return 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800592 }
593
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800594 if (!strcmp(*argv, "help")) {
595 usage();
596 return 0;
597 }
598
599
Elliott Hughes31dbed72009-10-07 15:38:53 -0700600 serial = getenv("ANDROID_SERIAL");
601
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800602 while (argc > 0) {
603 if(!strcmp(*argv, "-w")) {
604 wants_wipe = 1;
605 skip(1);
Brian Swetland2a63bb72009-04-28 16:05:07 -0700606 } else if(!strcmp(*argv, "-b")) {
607 require(2);
608 base_addr = strtoul(argv[1], 0, 16);
609 skip(2);
Dima Zavin931175a2010-02-12 20:26:33 -0800610 } else if(!strcmp(*argv, "-n")) {
611 require(2);
612 page_size = (unsigned)strtoul(argv[1], NULL, 0);
613 if (!page_size) die("invalid page size");
614 skip(2);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800615 } else if(!strcmp(*argv, "-s")) {
616 require(2);
617 serial = argv[1];
618 skip(2);
Scott Anderson13081c62012-04-06 12:39:30 -0700619 } else if(!strcmp(*argv, "-l")) {
620 long_listing = 1;
621 skip(1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800622 } else if(!strcmp(*argv, "-p")) {
623 require(2);
624 product = argv[1];
625 skip(2);
626 } else if(!strcmp(*argv, "-c")) {
627 require(2);
628 cmdline = argv[1];
629 skip(2);
630 } else if(!strcmp(*argv, "-i")) {
631 char *endptr = NULL;
632 unsigned long val;
633
634 require(2);
635 val = strtoul(argv[1], &endptr, 0);
636 if (!endptr || *endptr != '\0' || (val & ~0xffff))
637 die("invalid vendor id '%s'", argv[1]);
638 vendor_id = (unsigned short)val;
639 skip(2);
Scott Anderson13081c62012-04-06 12:39:30 -0700640 } else if (!strcmp(*argv, "devices")) {
641 skip(1);
642 wants_device_list = 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800643 } else if(!strcmp(*argv, "getvar")) {
644 require(2);
645 fb_queue_display(argv[1], argv[1]);
646 skip(2);
647 } else if(!strcmp(*argv, "erase")) {
648 require(2);
649 fb_queue_erase(argv[1]);
650 skip(2);
Anatol Pomazau65cf84f2011-12-15 17:50:18 -0800651 } else if(!strcmp(*argv, "format")) {
652 require(2);
Mike J. Chen714052b2012-02-04 16:22:22 -0800653 fb_queue_format(argv[1], 0);
Anatol Pomazau65cf84f2011-12-15 17:50:18 -0800654 skip(2);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800655 } else if(!strcmp(*argv, "signature")) {
656 require(2);
657 data = load_file(argv[1], &sz);
658 if (data == 0) die("could not load '%s'", argv[1]);
659 if (sz != 256) die("signature must be 256 bytes");
660 fb_queue_download("signature", data, sz);
661 fb_queue_command("signature", "installing signature");
662 skip(2);
663 } else if(!strcmp(*argv, "reboot")) {
664 wants_reboot = 1;
665 skip(1);
666 } else if(!strcmp(*argv, "reboot-bootloader")) {
667 wants_reboot_bootloader = 1;
668 skip(1);
669 } else if (!strcmp(*argv, "continue")) {
670 fb_queue_command("continue", "resuming boot");
671 skip(1);
672 } else if(!strcmp(*argv, "boot")) {
673 char *kname = 0;
674 char *rname = 0;
675 skip(1);
676 if (argc > 0) {
677 kname = argv[0];
678 skip(1);
679 }
680 if (argc > 0) {
681 rname = argv[0];
682 skip(1);
683 }
Dima Zavin931175a2010-02-12 20:26:33 -0800684 data = load_bootable_image(page_size, kname, rname, &sz, cmdline);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800685 if (data == 0) return 1;
686 fb_queue_download("boot.img", data, sz);
687 fb_queue_command("boot", "booting");
688 } else if(!strcmp(*argv, "flash")) {
689 char *pname = argv[1];
690 char *fname = 0;
691 require(2);
692 if (argc > 2) {
693 fname = argv[2];
694 skip(3);
695 } else {
696 fname = find_item(pname, product);
697 skip(2);
698 }
699 if (fname == 0) die("cannot determine image filename for '%s'", pname);
700 data = load_file(fname, &sz);
701 if (data == 0) die("cannot load '%s'\n", fname);
702 fb_queue_flash(pname, data, sz);
703 } else if(!strcmp(*argv, "flash:raw")) {
704 char *pname = argv[1];
705 char *kname = argv[2];
706 char *rname = 0;
707 require(3);
708 if(argc > 3) {
709 rname = argv[3];
710 skip(4);
711 } else {
712 skip(3);
713 }
Dima Zavin931175a2010-02-12 20:26:33 -0800714 data = load_bootable_image(page_size, kname, rname, &sz, cmdline);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800715 if (data == 0) die("cannot load bootable image");
716 fb_queue_flash(pname, data, sz);
717 } else if(!strcmp(*argv, "flashall")) {
718 skip(1);
719 do_flashall();
720 wants_reboot = 1;
721 } else if(!strcmp(*argv, "update")) {
722 if (argc > 1) {
723 do_update(argv[1]);
724 skip(2);
725 } else {
726 do_update("update.zip");
727 skip(1);
728 }
729 wants_reboot = 1;
730 } else if(!strcmp(*argv, "oem")) {
731 argc = do_oem_command(argc, argv);
732 } else {
733 usage();
Tsu Chiang Chuangee520552011-02-25 18:38:53 -0800734 return 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800735 }
736 }
737
Scott Anderson13081c62012-04-06 12:39:30 -0700738 if (wants_device_list)
739 list_devices();
740
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800741 if (wants_wipe) {
742 fb_queue_erase("userdata");
Mike J. Chen714052b2012-02-04 16:22:22 -0800743 fb_queue_format("userdata", 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800744 fb_queue_erase("cache");
Mike J. Chen714052b2012-02-04 16:22:22 -0800745 fb_queue_format("cache", 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800746 }
747 if (wants_reboot) {
748 fb_queue_reboot();
749 } else if (wants_reboot_bootloader) {
750 fb_queue_command("reboot-bootloader", "rebooting into bootloader");
751 }
752
Scott Anderson13081c62012-04-06 12:39:30 -0700753 if (fb_queue_is_empty())
754 return 0;
755
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800756 usb = open_device();
757
Brian Carlstromeb31c0b2010-04-23 12:38:51 -0700758 status = fb_execute_queue(usb);
759 return (status) ? 1 : 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800760}