diff options
Diffstat (limited to 'fastboot/fastboot.c')
-rw-r--r-- | fastboot/fastboot.c | 101 |
1 files changed, 86 insertions, 15 deletions
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c index b6eab8c..3de6d7d 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -70,6 +70,7 @@ static const char *product = 0; static const char *cmdline = 0; static int wipe_data = 0; static unsigned short vendor_id = 0; +static int long_listing = 0; static int64_t sparse_limit = -1; static int64_t target_sparse_limit = -1; @@ -187,6 +188,11 @@ oops: int match_fastboot(usb_ifc_info *info) { + return match_fastboot_with_serial(info, serial); +} + +int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) +{ if(!(vendor_id && (info->dev_vendor == vendor_id)) && (info->dev_vendor != 0x18d1) && // Google (info->dev_vendor != 0x8087) && // Intel @@ -204,15 +210,16 @@ int match_fastboot(usb_ifc_info *info) if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; if(info->ifc_protocol != 0x03) return -1; - // require matching serial number if a serial number is specified + // require matching serial number or device path if requested // at the command line with the -s option. - if (serial && strcmp(serial, info->serial_number) != 0) return -1; + if (local_serial && (strcmp(local_serial, info->serial_number) != 0 && + strcmp(local_serial, info->device_path) != 0)) return -1; return 0; } int list_devices_callback(usb_ifc_info *info) { - if (match_fastboot(info) == 0) { + if (match_fastboot_with_serial(info, NULL) == 0) { char* serial = info->serial_number; if (!info->writable) { serial = "no permissions"; // like "adb devices" @@ -221,7 +228,13 @@ int list_devices_callback(usb_ifc_info *info) serial = "????????????"; } // output compatible with "adb devices" - printf("%s\tfastboot\n", serial); + if (!long_listing) { + printf("%s\tfastboot\n", serial); + } else if (!info->device_path) { + printf("%-22s fastboot\n", serial); + } else { + printf("%-22s fastboot %s\n", serial, info->device_path); + } } return -1; @@ -274,8 +287,13 @@ void usage(void) " help show this help message\n" "\n" "options:\n" - " -w erase userdata and cache\n" - " -s <serial number> specify device serial number\n" + " -w erase userdata and cache (and format\n" + " if supported by partition type)\n" + " -u do not first erase partition before\n" + " formatting\n" + " -s <specific device> specify device serial number\n" + " or path to device port\n" + " -l with \"devices\", lists device paths\n" " -p <product> specify product name\n" " -c <cmdline> override kernel commandline\n" " -i <vendor id> specify a custom USB vendor id\n" @@ -547,6 +565,18 @@ static int64_t get_sparse_limit(struct usb_handle *usb, int64_t size) return 0; } +/* Until we get lazy inode table init working in make_ext4fs, we need to + * erase partitions of type ext4 before flashing a filesystem so no stale + * inodes are left lying around. Otherwise, e2fsck gets very upset. + */ +static int needs_erase(const char *part) +{ + /* The function fb_format_supported() currently returns the value + * we want, so just call it. + */ + return fb_format_supported(usb, part); +} + void do_flash(usb_handle *usb, const char *pname, const char *fname) { int64_t sz64; @@ -582,7 +612,7 @@ void do_update_signature(zipfile_t zip, char *fn) fb_queue_command("signature", "installing signature"); } -void do_update(char *fn) +void do_update(char *fn, int erase_first) { void *zdata; unsigned zsize; @@ -620,17 +650,26 @@ void do_update(char *fn) data = unzip_file(zip, "boot.img", &sz); if (data == 0) die("update package missing boot.img"); do_update_signature(zip, "boot.sig"); + if (erase_first && needs_erase("boot")) { + fb_queue_erase("boot"); + } fb_queue_flash("boot", data, sz); data = unzip_file(zip, "recovery.img", &sz); if (data != 0) { do_update_signature(zip, "recovery.sig"); + if (erase_first && needs_erase("recovery")) { + fb_queue_erase("recovery"); + } fb_queue_flash("recovery", data, sz); } data = unzip_file(zip, "system.img", &sz); if (data == 0) die("update package missing system.img"); do_update_signature(zip, "system.sig"); + if (erase_first && needs_erase("system")) { + fb_queue_erase("system"); + } fb_queue_flash("system", data, sz); } @@ -652,7 +691,7 @@ void do_send_signature(char *fn) fb_queue_command("signature", "installing signature"); } -void do_flashall(void) +void do_flashall(int erase_first) { char *fname; void *data; @@ -672,12 +711,18 @@ void do_flashall(void) data = load_file(fname, &sz); if (data == 0) die("could not load boot.img: %s", strerror(errno)); do_send_signature(fname); + if (erase_first && needs_erase("boot")) { + fb_queue_erase("boot"); + } fb_queue_flash("boot", data, sz); fname = find_item("recovery", product); data = load_file(fname, &sz); if (data != 0) { do_send_signature(fname); + if (erase_first && needs_erase("recovery")) { + fb_queue_erase("recovery"); + } fb_queue_flash("recovery", data, sz); } @@ -685,6 +730,9 @@ void do_flashall(void) data = load_file(fname, &sz); if (data == 0) die("could not load system.img: %s", strerror(errno)); do_send_signature(fname); + if (erase_first && needs_erase("system")) { + fb_queue_erase("system"); + } fb_queue_flash("system", data, sz); } @@ -755,6 +803,7 @@ int main(int argc, char **argv) int wants_wipe = 0; int wants_reboot = 0; int wants_reboot_bootloader = 0; + int erase_first = 1; void *data; unsigned sz; unsigned page_size = 2048; @@ -767,7 +816,7 @@ int main(int argc, char **argv) serial = getenv("ANDROID_SERIAL"); while (1) { - c = getopt_long(argc, argv, "wb:n:s:S:p:c:i:m:h", &longopts, NULL); + c = getopt_long(argc, argv, "wub:n:s:S:lp:c:i:m:h", &longopts, NULL); if (c < 0) { break; } @@ -776,6 +825,9 @@ int main(int argc, char **argv) case 'w': wants_wipe = 1; break; + case 'u': + erase_first = 0; + break; case 'b': base_addr = strtoul(optarg, 0, 16); break; @@ -792,6 +844,9 @@ int main(int argc, char **argv) die("invalid sparse limit"); } break; + case 'l': + long_listing = 1; + break; case 'p': product = optarg; break; @@ -832,6 +887,11 @@ int main(int argc, char **argv) return 0; } + if (argc > 0 && !strcmp(*argv, "help")) { + usage(); + return 0; + } + usb = open_device(); while (argc > 0) { @@ -841,10 +901,18 @@ int main(int argc, char **argv) skip(2); } else if(!strcmp(*argv, "erase")) { require(2); + + if (fb_format_supported(usb, argv[1])) { + fprintf(stderr, "******** Did you mean to fastboot format this partition?\n"); + } + fb_queue_erase(argv[1]); skip(2); } else if(!strcmp(*argv, "format")) { require(2); + if (erase_first && needs_erase(argv[1])) { + fb_queue_erase(argv[1]); + } fb_queue_format(argv[1], 0); skip(2); } else if(!strcmp(*argv, "signature")) { @@ -892,6 +960,9 @@ int main(int argc, char **argv) skip(2); } if (fname == 0) die("cannot determine image filename for '%s'", pname); + if (erase_first && needs_erase(pname)) { + fb_queue_erase(pname); + } do_flash(usb, pname, fname); } else if(!strcmp(*argv, "flash:raw")) { char *pname = argv[1]; @@ -909,22 +980,19 @@ int main(int argc, char **argv) fb_queue_flash(pname, data, sz); } else if(!strcmp(*argv, "flashall")) { skip(1); - do_flashall(); + do_flashall(erase_first); wants_reboot = 1; } else if(!strcmp(*argv, "update")) { if (argc > 1) { - do_update(argv[1]); + do_update(argv[1], erase_first); skip(2); } else { - do_update("update.zip"); + do_update("update.zip", erase_first); skip(1); } wants_reboot = 1; } else if(!strcmp(*argv, "oem")) { argc = do_oem_command(argc, argv); - } else if (!strcmp(*argv, "help")) { - usage(); - return 0; } else { usage(); return 1; @@ -943,6 +1011,9 @@ int main(int argc, char **argv) fb_queue_command("reboot-bootloader", "rebooting into bootloader"); } + if (fb_queue_is_empty()) + return 0; + status = fb_execute_queue(usb); return (status) ? 1 : 0; } |