diff options
author | David Pursell <dpursell@google.com> | 2015-10-30 11:22:01 -0700 |
---|---|---|
committer | David Pursell <dpursell@google.com> | 2015-11-16 09:31:07 -0800 |
commit | 0b156638307db890e5539b52521fd24beb3440cb (patch) | |
tree | 42feda4e66833b368f6c6b7c6a63562baa0db084 /fastboot/fastboot.cpp | |
parent | 942f8ea84f3f96c2e2556fe90ebba0ec76730553 (diff) |
fastboot: create Transport object (take 2).
(Second upload of this CL; original upload had the wrong version of
usb_windows.cpp that caused a compilation error. Fixed error and
re-tested.)
This CL creates a Transport object to provide a generic interface for
various transports. Specifically this is designed to be able to add UDP
support to fastboot in an upcoming CL without changing the main program
logic.
Also includes some minor code style fixes and replaces malloc/free
in the USB implementation files with smart pointers and std::string.
Bug: http://b/22029765
Change-Id: I1175bbce08690fbd15f51e68166be9b3e9973ea0
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; } |