diff options
author | Alex Light <allight@google.com> | 2016-06-29 09:26:44 -0700 |
---|---|---|
committer | Daniel Rosenberg <drosen@google.com> | 2016-08-19 16:52:26 -0700 |
commit | bb9b8a5abf08eed123ccf3311af290ca84ed9168 (patch) | |
tree | 200956eff39c142f7278c2d8fd9c53d93471a5ff /fastboot | |
parent | ad3d3c184e1f548051e24a1a78ae4dddf5ab34fd (diff) | |
download | core-bb9b8a5abf08eed123ccf3311af290ca84ed9168.tar.gz core-bb9b8a5abf08eed123ccf3311af290ca84ed9168.tar.bz2 core-bb9b8a5abf08eed123ccf3311af290ca84ed9168.zip |
Add Fastboot support for flashing secondary images
Fastboot update and flashall will now flash secondary
images if provided, and if the --slot flag is not set
to 'all'. Also added flash-primary to preserve the
previous behavior, and flash-secondary to just flash
the secondary images.
Fixes from: I5bd2de1c1e0e6224a195b566f7dcbe383555a80a
Bug: 29278988
Change-Id: Ia870e4be55617c0eefa4e1381287f8cd14affe7e
(cherry-picked from commit 6c98509c34d152007cf953c2cacb5750745dd464)
Diffstat (limited to 'fastboot')
-rw-r--r-- | fastboot/fastboot.cpp | 189 |
1 files changed, 136 insertions, 53 deletions
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 3c699646d..8714471e1 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -97,19 +97,40 @@ struct fastboot_buffer { }; static struct { - char img_name[13]; - char sig_name[13]; + char img_name[17]; + char sig_name[17]; char part_name[9]; bool is_optional; + bool is_secondary; } images[] = { - {"boot.img", "boot.sig", "boot", false}, - {"recovery.img", "recovery.sig", "recovery", true}, - {"system.img", "system.sig", "system", false}, - {"vendor.img", "vendor.sig", "vendor", true}, + {"boot.img", "boot.sig", "boot", false, false}, + {"boot_other.img", "boot.sig", "boot", true, true}, + {"recovery.img", "recovery.sig", "recovery", true, false}, + {"system.img", "system.sig", "system", false, false}, + {"system_other.img", "system.sig", "system", true, true}, + {"vendor.img", "vendor.sig", "vendor", true, false}, + {"vendor_other.img", "vendor.sig", "vendor", true, true}, }; -static std::string find_item(const char* item, const char* product) { +static std::string find_item_given_name(const char* img_name, const char* product) { + if(product) { + std::string path = get_my_path(); + path.erase(path.find_last_of('/')); + return android::base::StringPrintf("%s/../../../target/product/%s/%s", + path.c_str(), product, img_name); + } + + char *dir = getenv("ANDROID_PRODUCT_OUT"); + if (dir == nullptr || dir[0] == '\0') { + die("neither -p product specified nor ANDROID_PRODUCT_OUT set"); + } + + return android::base::StringPrintf("%s/%s", dir, img_name); +} + +std::string find_item(const char* item, const char* product) { const char *fn; + if (!strcmp(item,"boot")) { fn = "boot.img"; } else if(!strcmp(item,"recovery")) { @@ -127,21 +148,10 @@ static std::string find_item(const char* item, const char* product) { } else { fprintf(stderr,"unknown partition '%s'\n", item); return ""; - } - - if (product) { - std::string path = get_my_path(); - path.erase(path.find_last_of('/')); - return android::base::StringPrintf("%s/../../../target/product/%s/%s", - path.c_str(), product, fn); - } - char* dir = getenv("ANDROID_PRODUCT_OUT"); - if (dir == nullptr || dir[0] == '\0') { - die("neither -p product specified nor ANDROID_PRODUCT_OUT set"); } - return android::base::StringPrintf("%s/%s", dir, fn); + return find_item_given_name(fn, product); } static int64_t get_file_size(int fd) { @@ -312,6 +322,11 @@ static void usage() { " if found -- recovery. If the device\n" " supports slots, the slot that has\n" " been flashed to is set as active.\n" + " Secondary images may be flashed to\n" + " an inactive slot.\n" + " flash-primary Same as flashall, but do not flash\n" + " secondary images.\n" + " flash-secondary Only flashes the secondary images.\n" " flash <partition> [ <filename> ] Write a file to a flash partition.\n" " flashing lock Locks the device. Prevents flashing.\n" " flashing unlock Unlocks the device. Allows flashing\n" @@ -801,8 +816,12 @@ static std::vector<std::string> get_suffixes(Transport* transport) { return suffixes; } +static bool supports_AB(Transport* transport) { + return !get_suffixes(transport).empty(); +} + // Given a current slot, this returns what the 'other' slot is. -static std::string get_other_slot(Transport* transport, std::string& current_slot) { +static std::string get_other_slot(Transport* transport, const std::string& current_slot) { std::vector<std::string> suffixes = get_suffixes(transport); if (!suffixes.empty()) { @@ -815,6 +834,12 @@ static std::string get_other_slot(Transport* transport, std::string& current_slo return ""; } +static std::string get_other_slot(Transport* transport) { + std::string current_slot; + fb_getvar(transport, "current-slot", ¤t_slot); + return get_other_slot(transport, current_slot); +} + static std::string verify_slot(Transport* transport, const char *slot, bool allow_all) { if (strcmp(slot, "all") == 0) { if (allow_all) { @@ -937,9 +962,11 @@ static void do_update_signature(ZipArchiveHandle zip, char* fn) { // Sets slot_override as the active slot. If slot_override is blank, // set current slot as active instead. This clears slot-unbootable. -static void set_active(Transport* transport, const char* slot_override) { - if (slot_override && slot_override[0]) { - fb_set_active(slot_override); +static void set_active(Transport* transport, const std::string& slot_override) { + if (!supports_AB(transport)) { + return; + } else if (slot_override != "") { + fb_set_active(slot_override.c_str()); } else { std::string current_slot; if (fb_getvar(transport, "current-slot", ¤t_slot)) { @@ -949,7 +976,7 @@ static void set_active(Transport* transport, const char* slot_override) { } } -static void do_update(Transport* transport, const char* filename, const char* slot_override, bool erase_first) { +static void do_update(Transport* transport, const char* filename, const std::string& slot_override, bool erase_first) { queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); @@ -970,7 +997,31 @@ static void do_update(Transport* transport, const char* filename, const char* sl setup_requirements(reinterpret_cast<char*>(data), sz); + std::string secondary; + bool update_secondary = slot_override != "all"; + if (update_secondary) { + if (slot_override != "") { + secondary = get_other_slot(transport, slot_override); + } else { + secondary = get_other_slot(transport); + } + if (secondary == "") { + if (supports_AB(transport)) { + fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n"); + } + update_secondary = false; + } + } for (size_t i = 0; i < arraysize(images); ++i) { + const char* slot = slot_override.c_str(); + if (images[i].is_secondary) { + if (update_secondary) { + slot = secondary.c_str(); + } else { + continue; + } + } + int fd = unzip_to_file(zip, images[i].img_name); if (fd == -1) { if (images[i].is_optional) { @@ -995,50 +1046,71 @@ static void do_update(Transport* transport, const char* filename, const char* sl * program exits. */ }; - do_for_partitions(transport, images[i].part_name, slot_override, update, false); + do_for_partitions(transport, images[i].part_name, slot, update, false); } CloseArchive(zip); set_active(transport, slot_override); } -static void do_send_signature(const char* filename) { - if (android::base::EndsWith(filename, ".img") == false) { - return; - } +static void do_send_signature(const std::string& fn) { + std::size_t extension_loc = fn.find(".img"); + if (extension_loc == std::string::npos) return; - std::string sig_path = filename; - sig_path.erase(sig_path.size() - 4); - sig_path += ".sig"; + std::string fs_sig = fn.substr(0, extension_loc) + ".sig"; int64_t sz; - void* data = load_file(sig_path, &sz); + void* data = load_file(fs_sig.c_str(), &sz); if (data == nullptr) return; fb_queue_download("signature", data, sz); fb_queue_command("signature", "installing signature"); } -static void do_flashall(Transport* transport, const char* slot_override, int erase_first) { - queue_info_dump(); +static void do_flashall(Transport* transport, const std::string& slot_override, int erase_first, bool flash_primary, bool flash_secondary) { + std::string fname; + if (flash_primary) { + queue_info_dump(); - fb_queue_query_save("product", cur_product, sizeof(cur_product)); + fb_queue_query_save("product", cur_product, sizeof(cur_product)); - std::string fname = find_item("info", product); - if (fname.empty()) die("cannot find android-info.txt"); + fname = find_item("info", product); + if (fname.empty()) die("cannot find android-info.txt"); - int64_t sz; - void* data = load_file(fname, &sz); - if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno)); + int64_t sz; + void* data = load_file(fname.c_str(), &sz); + if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno)); - setup_requirements(reinterpret_cast<char*>(data), sz); + setup_requirements(reinterpret_cast<char*>(data), sz); + } + std::string secondary; + if (flash_secondary) { + if (slot_override != "") { + secondary = get_other_slot(transport, slot_override); + } else { + secondary = get_other_slot(transport); + } + if (secondary == "") { + if (supports_AB(transport)) { + fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n"); + } + flash_secondary = false; + } + } for (size_t i = 0; i < arraysize(images); i++) { - fname = find_item(images[i].part_name, product); + const char* slot = NULL; + if (images[i].is_secondary) { + if (flash_secondary) slot = secondary.c_str(); + } else { + if (flash_primary) slot = slot_override.c_str(); + } + if (!slot) continue; + fname = find_item_given_name(images[i].img_name, product); fastboot_buffer buf; if (!load_buf(transport, fname.c_str(), &buf)) { if (images[i].is_optional) continue; - die("could not load '%s': %s", images[i].img_name, strerror(errno)); + die("could not load '%s': %s\n", images[i].img_name, strerror(errno)); } auto flashall = [&](const std::string &partition) { @@ -1048,10 +1120,10 @@ static void do_flashall(Transport* transport, const char* slot_override, int era } flash_buf(partition.c_str(), &buf); }; - do_for_partitions(transport, images[i].part_name, slot_override, flashall, false); + do_for_partitions(transport, images[i].part_name, slot, flashall, false); } - set_active(transport, slot_override); + if (flash_primary) set_active(transport, slot_override); } #define skip(n) do { argc -= (n); argv += (n); } while (0) @@ -1364,10 +1436,8 @@ int main(int argc, char **argv) return 1; } - if (slot_override != "") - slot_override = verify_slot(transport, slot_override.c_str()); - if (next_active != "") - next_active = verify_slot(transport, next_active.c_str(), false); + if (slot_override != "") slot_override = verify_slot(transport, slot_override.c_str()); + if (next_active != "") next_active = verify_slot(transport, next_active.c_str(), false); if (wants_set_active) { if (next_active == "") { @@ -1527,14 +1597,27 @@ int main(int argc, char **argv) do_for_partitions(transport, argv[1], slot_override.c_str(), flashraw, true); } else if(!strcmp(*argv, "flashall")) { skip(1); - do_flashall(transport, slot_override.c_str(), erase_first); + if (slot_override == "all") { + fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed."); + do_flashall(transport, slot_override, erase_first, true, false); + } else { + do_flashall(transport, slot_override, erase_first, true, true); + } + wants_reboot = true; + } else if(!strcmp(*argv, "flash-primary")) { + skip(1); + do_flashall(transport, slot_override, erase_first, true, false); + wants_reboot = true; + } else if(!strcmp(*argv, "flash-secondary")) { + skip(1); + do_flashall(transport, slot_override, erase_first, false, true); wants_reboot = true; } else if(!strcmp(*argv, "update")) { if (argc > 1) { - do_update(transport, argv[1], slot_override.c_str(), erase_first); + do_update(transport, argv[1], slot_override, erase_first); skip(2); } else { - do_update(transport, "update.zip", slot_override.c_str(), erase_first); + do_update(transport, "update.zip", slot_override, erase_first); skip(1); } wants_reboot = 1; |