diff options
Diffstat (limited to 'fastboot/fastboot.cpp')
-rw-r--r-- | fastboot/fastboot.cpp | 144 |
1 files changed, 75 insertions, 69 deletions
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 9f72c8336..a16d7dd23 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -55,6 +55,8 @@ #include "bootimg_utils.h" #include "fastboot.h" #include "fs.h" +#include "transport.h" +#include "usb.h" #ifndef O_BINARY #define O_BINARY 0 @@ -222,16 +224,16 @@ static int list_devices_callback(usb_ifc_info* info) { return -1; } -static usb_handle* open_device() { - static usb_handle *usb = 0; +static Transport* open_device() { + static Transport* transport = nullptr; int announce = 1; - if(usb) return usb; + if (transport) return transport; - for(;;) { - usb = usb_open(match_fastboot); - if(usb) return usb; - if(announce) { + for (;;) { + transport = usb_open(match_fastboot); + if (transport) return transport; + if (announce) { announce = 0; fprintf(stderr, "< waiting for %s >\n", serial ? serial : "any device"); } @@ -597,9 +599,10 @@ static struct sparse_file **load_sparse_files(int fd, int max_size) return out_s; } -static int64_t get_target_sparse_limit(usb_handle* usb) { +static int64_t get_target_sparse_limit(Transport* transport) { std::string max_download_size; - if (!fb_getvar(usb, "max-download-size", &max_download_size) || max_download_size.empty()) { + if (!fb_getvar(transport, "max-download-size", &max_download_size) || + max_download_size.empty()) { fprintf(stderr, "target didn't report max-download-size\n"); return 0; } @@ -618,7 +621,7 @@ static int64_t get_target_sparse_limit(usb_handle* usb) { return limit; } -static int64_t get_sparse_limit(usb_handle* usb, int64_t size) { +static int64_t get_sparse_limit(Transport* transport, int64_t size) { int64_t limit; if (sparse_limit == 0) { @@ -627,7 +630,7 @@ static int64_t get_sparse_limit(usb_handle* usb, int64_t size) { limit = sparse_limit; } else { if (target_sparse_limit == -1) { - target_sparse_limit = get_target_sparse_limit(usb); + target_sparse_limit = get_target_sparse_limit(transport); } if (target_sparse_limit > 0) { limit = target_sparse_limit; @@ -646,22 +649,22 @@ static int64_t get_sparse_limit(usb_handle* usb, int64_t size) { // 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 bool needs_erase(usb_handle* usb, const char* partition) { +static bool needs_erase(Transport* transport, const char* partition) { std::string partition_type; - if (!fb_getvar(usb, std::string("partition-type:") + partition, &partition_type)) { + if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) { return false; } return partition_type == "ext4"; } -static int load_buf_fd(usb_handle* usb, int fd, struct fastboot_buffer* buf) { +static int load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* buf) { int64_t sz = get_file_size(fd); if (sz == -1) { return -1; } lseek64(fd, 0, SEEK_SET); - int64_t limit = get_sparse_limit(usb, sz); + int64_t limit = get_sparse_limit(transport, sz); if (limit) { sparse_file** s = load_sparse_files(fd, limit); if (s == nullptr) { @@ -680,8 +683,7 @@ static int load_buf_fd(usb_handle* usb, int fd, struct fastboot_buffer* buf) { return 0; } -static int load_buf(usb_handle *usb, const char *fname, - struct fastboot_buffer *buf) +static int load_buf(Transport* transport, const char *fname, struct fastboot_buffer *buf) { int fd; @@ -690,7 +692,7 @@ static int load_buf(usb_handle *usb, const char *fname, return -1; } - return load_buf_fd(usb, fd, buf); + return load_buf_fd(transport, fd, buf); } static void flash_buf(const char *pname, struct fastboot_buffer *buf) @@ -713,20 +715,20 @@ static void flash_buf(const char *pname, struct fastboot_buffer *buf) } } -static std::vector<std::string> get_suffixes(usb_handle* usb) { +static std::vector<std::string> get_suffixes(Transport* transport) { std::vector<std::string> suffixes; std::string suffix_list; - if (!fb_getvar(usb, "slot-suffixes", &suffix_list)) { + if (!fb_getvar(transport, "slot-suffixes", &suffix_list)) { die("Could not get suffixes.\n"); } return android::base::Split(suffix_list, ","); } -static std::string verify_slot(usb_handle* usb, const char *slot) { +static std::string verify_slot(Transport* transport, const char *slot) { if (strcmp(slot, "all") == 0) { return "all"; } - std::vector<std::string> suffixes = get_suffixes(usb); + std::vector<std::string> suffixes = get_suffixes(transport); for (const std::string &suffix : suffixes) { if (suffix == slot) return slot; @@ -738,17 +740,18 @@ static std::string verify_slot(usb_handle* usb, const char *slot) { exit(1); } -static void do_for_partition(usb_handle* usb, const char *part, const char *slot, std::function<void(const std::string&)> func, bool force_slot) { +static void do_for_partition(Transport* transport, const char *part, const char *slot, + std::function<void(const std::string&)> func, bool force_slot) { std::string has_slot; std::string current_slot; - if (!fb_getvar(usb, std::string("has-slot:")+part, &has_slot)) { + if (!fb_getvar(transport, std::string("has-slot:")+part, &has_slot)) { /* If has-slot is not supported, the answer is no. */ has_slot = "no"; } if (has_slot == "yes") { if (!slot || slot[0] == 0) { - if (!fb_getvar(usb, "current-slot", ¤t_slot)) { + if (!fb_getvar(transport, "current-slot", ¤t_slot)) { die("Failed to identify current slot.\n"); } func(std::string(part) + current_slot); @@ -757,40 +760,43 @@ static void do_for_partition(usb_handle* usb, const char *part, const char *slot } } else { if (force_slot && slot && slot[0]) { - fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n", part, slot); + fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n", + part, slot); } func(part); } } -/* This function will find the real partition name given a base name, and a slot. If slot is NULL or empty, - * it will use the current slot. If slot is "all", it will return a list of all possible partition names. - * If force_slot is true, it will fail if a slot is specified, and the given partition does not support slots. +/* This function will find the real partition name given a base name, and a slot. If slot is NULL or + * empty, it will use the current slot. If slot is "all", it will return a list of all possible + * partition names. If force_slot is true, it will fail if a slot is specified, and the given + * partition does not support slots. */ -static void do_for_partitions(usb_handle* usb, const char *part, const char *slot, std::function<void(const std::string&)> func, bool force_slot) { +static void do_for_partitions(Transport* transport, const char *part, const char *slot, + std::function<void(const std::string&)> func, bool force_slot) { std::string has_slot; if (slot && strcmp(slot, "all") == 0) { - if (!fb_getvar(usb, std::string("has-slot:") + part, &has_slot)) { + if (!fb_getvar(transport, std::string("has-slot:") + part, &has_slot)) { die("Could not check if partition %s has slot.", part); } if (has_slot == "yes") { - std::vector<std::string> suffixes = get_suffixes(usb); + std::vector<std::string> suffixes = get_suffixes(transport); for (std::string &suffix : suffixes) { - do_for_partition(usb, part, suffix.c_str(), func, force_slot); + do_for_partition(transport, part, suffix.c_str(), func, force_slot); } } else { - do_for_partition(usb, part, "", func, force_slot); + do_for_partition(transport, part, "", func, force_slot); } } else { - do_for_partition(usb, part, slot, func, force_slot); + do_for_partition(transport, part, slot, func, force_slot); } } -static void do_flash(usb_handle* usb, const char* pname, const char* fname) { +static void do_flash(Transport* transport, const char* pname, const char* fname) { struct fastboot_buffer buf; - if (load_buf(usb, fname, &buf)) { + if (load_buf(transport, fname, &buf)) { die("cannot load '%s'", fname); } flash_buf(pname, &buf); @@ -804,7 +810,7 @@ static void do_update_signature(ZipArchiveHandle zip, char* fn) { fb_queue_command("signature", "installing signature"); } -static void do_update(usb_handle* usb, const char* filename, const char* slot_override, bool erase_first) { +static void do_update(Transport* transport, const char* filename, const char* slot_override, bool erase_first) { queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); @@ -835,12 +841,12 @@ static void do_update(usb_handle* usb, const char* filename, const char* slot_ov exit(1); // unzip_to_file already explained why. } fastboot_buffer buf; - int rc = load_buf_fd(usb, fd, &buf); + int rc = load_buf_fd(transport, fd, &buf); if (rc) die("cannot load %s from flash", images[i].img_name); auto update = [&](const std::string &partition) { do_update_signature(zip, images[i].sig_name); - if (erase_first && needs_erase(usb, partition.c_str())) { + if (erase_first && needs_erase(transport, partition.c_str())) { fb_queue_erase(partition.c_str()); } flash_buf(partition.c_str(), &buf); @@ -849,7 +855,7 @@ static void do_update(usb_handle* usb, const char* filename, const char* slot_ov * program exits. */ }; - do_for_partitions(usb, images[i].part_name, slot_override, update, false); + do_for_partitions(transport, images[i].part_name, slot_override, update, false); } CloseArchive(zip); @@ -871,7 +877,7 @@ static void do_send_signature(char* fn) { fb_queue_command("signature", "installing signature"); } -static void do_flashall(usb_handle* usb, const char *slot_override, int erase_first) { +static void do_flashall(Transport* transport, const char* slot_override, int erase_first) { queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); @@ -888,7 +894,7 @@ static void do_flashall(usb_handle* usb, const char *slot_override, int erase_fi for (size_t i = 0; i < ARRAY_SIZE(images); i++) { fname = find_item(images[i].part_name, product); fastboot_buffer buf; - if (load_buf(usb, fname, &buf)) { + if (load_buf(transport, fname, &buf)) { if (images[i].is_optional) continue; die("could not load %s\n", images[i].img_name); @@ -896,12 +902,12 @@ static void do_flashall(usb_handle* usb, const char *slot_override, int erase_fi auto flashall = [&](const std::string &partition) { do_send_signature(fname); - if (erase_first && needs_erase(usb, partition.c_str())) { + if (erase_first && needs_erase(transport, partition.c_str())) { fb_queue_erase(partition.c_str()); } flash_buf(partition.c_str(), &buf); }; - do_for_partitions(usb, images[i].part_name, slot_override, flashall, false); + do_for_partitions(transport, images[i].part_name, slot_override, flashall, false); } } @@ -986,7 +992,7 @@ static int64_t parse_num(const char *arg) return num; } -static void fb_perform_format(usb_handle* usb, +static void fb_perform_format(Transport* transport, const char* partition, int skip_if_not_supported, const char* type_override, const char* size_override) { std::string partition_type, partition_size; @@ -1004,7 +1010,7 @@ static void fb_perform_format(usb_handle* usb, limit = sparse_limit; } - if (!fb_getvar(usb, std::string("partition-type:") + partition, &partition_type)) { + if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) { errMsg = "Can't determine partition type.\n"; goto failed; } @@ -1016,7 +1022,7 @@ static void fb_perform_format(usb_handle* usb, partition_type = type_override; } - if (!fb_getvar(usb, std::string("partition-size:") + partition, &partition_size)) { + if (!fb_getvar(transport, std::string("partition-size:") + partition, &partition_size)) { errMsg = "Unable to get partition size\n"; goto failed; } @@ -1058,7 +1064,7 @@ static void fb_perform_format(usb_handle* usb, return; } - if (load_buf_fd(usb, fd, &buf)) { + if (load_buf_fd(transport, fd, &buf)) { fprintf(stderr, "Cannot read image: %s\n", strerror(errno)); close(fd); return; @@ -1210,11 +1216,11 @@ int main(int argc, char **argv) return 0; } - usb_handle* usb = open_device(); + Transport* transport = open_device(); if (slot_override != "") - slot_override = verify_slot(usb, slot_override.c_str()); + slot_override = verify_slot(transport, slot_override.c_str()); if (next_active != "") - next_active = verify_slot(usb, next_active.c_str()); + next_active = verify_slot(transport, next_active.c_str()); if (wants_set_active) { if (next_active == "") { @@ -1235,8 +1241,8 @@ int main(int argc, char **argv) require(2); auto erase = [&](const std::string &partition) { - std::string partition_type; - if (fb_getvar(usb, std::string("partition-type:") + argv[1], &partition_type) && + std::string partition_type; + if (fb_getvar(transport, std::string("partition-type:") + argv[1], &partition_type) && fs_get_generator(partition_type) != nullptr) { fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n", partition_type.c_str()); @@ -1244,7 +1250,7 @@ int main(int argc, char **argv) fb_queue_erase(partition.c_str()); }; - do_for_partitions(usb, argv[1], slot_override.c_str(), erase, true); + do_for_partitions(transport, argv[1], slot_override.c_str(), erase, true); skip(2); } else if(!strncmp(*argv, "format", strlen("format"))) { char *overrides; @@ -1274,12 +1280,12 @@ int main(int argc, char **argv) if (size_override && !size_override[0]) size_override = nullptr; auto format = [&](const std::string &partition) { - if (erase_first && needs_erase(usb, partition.c_str())) { + if (erase_first && needs_erase(transport, partition.c_str())) { fb_queue_erase(partition.c_str()); } - fb_perform_format(usb, partition.c_str(), 0, type_override, size_override); + fb_perform_format(transport, partition.c_str(), 0, type_override, size_override); }; - do_for_partitions(usb, argv[1], slot_override.c_str(), format, true); + do_for_partitions(transport, argv[1], slot_override.c_str(), format, true); skip(2); } else if(!strcmp(*argv, "signature")) { require(2); @@ -1341,12 +1347,12 @@ int main(int argc, char **argv) if (fname == 0) die("cannot determine image filename for '%s'", pname); auto flash = [&](const std::string &partition) { - if (erase_first && needs_erase(usb, partition.c_str())) { + if (erase_first && needs_erase(transport, partition.c_str())) { fb_queue_erase(partition.c_str()); } - do_flash(usb, partition.c_str(), fname); + do_flash(transport, partition.c_str(), fname); }; - do_for_partitions(usb, pname, slot_override.c_str(), flash, true); + do_for_partitions(transport, pname, slot_override.c_str(), flash, true); } else if(!strcmp(*argv, "flash:raw")) { char *kname = argv[2]; char *rname = 0; @@ -1366,17 +1372,17 @@ int main(int argc, char **argv) auto flashraw = [&](const std::string &partition) { fb_queue_flash(partition.c_str(), data, sz); }; - do_for_partitions(usb, argv[1], slot_override.c_str(), flashraw, true); + do_for_partitions(transport, argv[1], slot_override.c_str(), flashraw, true); } else if(!strcmp(*argv, "flashall")) { skip(1); - do_flashall(usb, slot_override.c_str(), erase_first); + do_flashall(transport, slot_override.c_str(), erase_first); wants_reboot = true; } else if(!strcmp(*argv, "update")) { if (argc > 1) { - do_update(usb, argv[1], slot_override.c_str(), erase_first); + do_update(transport, argv[1], slot_override.c_str(), erase_first); skip(2); } else { - do_update(usb, "update.zip", slot_override.c_str(), erase_first); + do_update(transport, "update.zip", slot_override.c_str(), erase_first); skip(1); } wants_reboot = true; @@ -1407,13 +1413,13 @@ int main(int argc, char **argv) if (wants_wipe) { fprintf(stderr, "wiping userdata...\n"); fb_queue_erase("userdata"); - fb_perform_format(usb, "userdata", 1, nullptr, nullptr); + fb_perform_format(transport, "userdata", 1, nullptr, nullptr); std::string cache_type; - if (fb_getvar(usb, "partition-type:cache", &cache_type) && !cache_type.empty()) { + if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) { fprintf(stderr, "wiping cache...\n"); fb_queue_erase("cache"); - fb_perform_format(usb, "cache", 1, nullptr, nullptr); + fb_perform_format(transport, "cache", 1, nullptr, nullptr); } } if (wants_set_active) { @@ -1427,5 +1433,5 @@ int main(int argc, char **argv) fb_queue_wait_for_disconnect(); } - return fb_execute_queue(usb) ? EXIT_FAILURE : EXIT_SUCCESS; + return fb_execute_queue(transport) ? EXIT_FAILURE : EXIT_SUCCESS; } |