Loading fastboot/engine.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,13 @@ static Action *queue_action(unsigned op, const char *fmt, ...) return a; } void fb_set_active(const char *slot) { Action *a; a = queue_action(OP_COMMAND, "set_active:%s", slot); a->msg = mkmsg("Setting current slot to '%s'", slot); } void fb_queue_erase(const char *ptn) { Action *a; Loading fastboot/fastboot.cpp +153 −35 Original line number Diff line number Diff line Loading @@ -42,12 +42,16 @@ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <functional> #include <base/parseint.h> #include <base/strings.h> #include <sparse/sparse.h> #include <ziparchive/zip_archive.h> #include <base/strings.h> #include <base/parseint.h> #include "bootimg_utils.h" #include "fastboot.h" #include "fs.h" Loading Loading @@ -273,6 +277,8 @@ static void usage() { " override the fs type and/or size\n" " the bootloader reports.\n" " getvar <variable> Display a bootloader variable.\n" " set_active <suffix> Sets the active slot. If slots are\n" " not supported, this does nothing.\n" " boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n" " flash:raw boot <kernel> [ <ramdisk> [ <second> ] ]\n" " Create bootimage and flash it.\n" Loading @@ -299,6 +305,13 @@ static void usage() { " (default: 2048).\n" " -S <size>[K|M|G] Automatically sparse files greater\n" " than 'size'. 0 to disable.\n" " --slot <suffix> Specify slot suffix to be used if the\n" " device supports slots. This will be\n" " added to all partition names that use\n" " slots. 'all' can be given to refer\n" " to all slots. If this is not given,\n" " slotted partitions will default to\n" " the current active slot.\n" ); } Loading Loading @@ -690,6 +703,80 @@ static void flash_buf(const char *pname, struct fastboot_buffer *buf) } } static std::vector<std::string> get_suffixes(usb_handle* usb) { std::vector<std::string> suffixes; std::string suffix_list; if (!fb_getvar(usb, "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) { if (strcmp(slot, "all") == 0) { return "all"; } std::vector<std::string> suffixes = get_suffixes(usb); for (const std::string &suffix : suffixes) { if (suffix == slot) return slot; } fprintf(stderr, "Slot %s does not exist. supported slots are:", slot); for (const std::string &suffix : suffixes) { fprintf(stderr, "%s\n", suffix.c_str()); } 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) { std::string partition_slot; std::string current_slot; if (!fb_getvar(usb, std::string("partition-slot:")+part, &partition_slot)) { /* If partition-slot is not supported, the answer is no. */ partition_slot = ""; } if (partition_slot == "1") { if (!slot || slot[0] == 0) { if (!fb_getvar(usb, "current-slot", ¤t_slot)) { die("Failed to identify current slot.\n"); } func(std::string(part) + '-' + current_slot); } else { func(std::string(part) + '-' + slot); } } else { if (force_slot && slot && slot[0]) { 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. */ static void do_for_partitions(usb_handle* usb, const char *part, const char *slot, std::function<void(const std::string&)> func, bool force_slot) { std::string partition_slot; if (slot && strcmp(slot, "all") == 0) { if (!fb_getvar(usb, std::string("partition-slot:") + part, &partition_slot)) { die("Could not check if partition %s has slot.", part); } if (partition_slot == "1") { std::vector<std::string> suffixes = get_suffixes(usb); for (std::string &suffix : suffixes) { do_for_partition(usb, part, suffix.c_str(), func, force_slot); } } else { do_for_partition(usb, part, "", func, force_slot); } } else { do_for_partition(usb, part, slot, func, force_slot); } } static void do_flash(usb_handle* usb, const char* pname, const char* fname) { struct fastboot_buffer buf; Loading @@ -707,7 +794,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, bool erase_first) { static void do_update(usb_handle* usb, const char* filename, const char* slot_override, bool erase_first) { queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); Loading Loading @@ -740,15 +827,19 @@ static void do_update(usb_handle* usb, const char* filename, bool erase_first) { fastboot_buffer buf; int rc = load_buf_fd(usb, 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, images[i].part_name)) { fb_queue_erase(images[i].part_name); if (erase_first && needs_erase(usb, partition.c_str())) { fb_queue_erase(partition.c_str()); } flash_buf(images[i].part_name, &buf); flash_buf(partition.c_str(), &buf); /* not closing the fd here since the sparse code keeps the fd around * but hasn't mmaped data yet. The tmpfile will get cleaned up when the * program exits. */ }; do_for_partitions(usb, images[i].part_name, slot_override, update, false); } CloseArchive(zip); Loading @@ -770,7 +861,7 @@ static void do_send_signature(char* fn) { fb_queue_command("signature", "installing signature"); } static void do_flashall(usb_handle* usb, int erase_first) { static void do_flashall(usb_handle* usb, const char *slot_override, int erase_first) { queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); Loading @@ -792,11 +883,15 @@ static void do_flashall(usb_handle* usb, int erase_first) { continue; die("could not load %s\n", images[i].img_name); } auto flashall = [&](const std::string &partition) { do_send_signature(fname); if (erase_first && needs_erase(usb, images[i].part_name)) { fb_queue_erase(images[i].part_name); if (erase_first && needs_erase(usb, partition.c_str())) { fb_queue_erase(partition.c_str()); } flash_buf(images[i].part_name, &buf); flash_buf(partition.c_str(), &buf); }; do_for_partitions(usb, images[i].part_name, slot_override, flashall, false); } } Loading Loading @@ -977,6 +1072,7 @@ int main(int argc, char **argv) void *data; int64_t sz; int longindex; std::string slot_override; const struct option longopts[] = { {"base", required_argument, 0, 'b'}, Loading @@ -987,6 +1083,7 @@ int main(int argc, char **argv) {"help", no_argument, 0, 'h'}, {"unbuffered", no_argument, 0, 0}, {"version", no_argument, 0, 0}, {"slot", required_argument, 0, 0}, {0, 0, 0, 0} }; Loading Loading @@ -1061,6 +1158,8 @@ int main(int argc, char **argv) } else if (strcmp("version", longopts[longindex].name) == 0) { fprintf(stdout, "fastboot version %s\n", FASTBOOT_REVISION); return 0; } else if (strcmp("slot", longopts[longindex].name) == 0) { slot_override = std::string(optarg); } break; default: Loading Loading @@ -1088,6 +1187,8 @@ int main(int argc, char **argv) } usb_handle* usb = open_device(); if (slot_override != "") slot_override = verify_slot(usb, slot_override.c_str()); while (argc > 0) { if (!strcmp(*argv, "getvar")) { Loading @@ -1097,6 +1198,7 @@ int main(int argc, char **argv) } else if(!strcmp(*argv, "erase")) { require(2); auto erase = [&](const std::string &partition) { std::string partition_type; if (fb_getvar(usb, std::string("partition-type:") + argv[1], &partition_type) && fs_get_generator(partition_type) != nullptr) { Loading @@ -1104,7 +1206,9 @@ int main(int argc, char **argv) partition_type.c_str()); } fb_queue_erase(argv[1]); fb_queue_erase(partition.c_str()); }; do_for_partitions(usb, argv[1], slot_override.c_str(), erase, true); skip(2); } else if(!strncmp(*argv, "format", strlen("format"))) { char *overrides; Loading Loading @@ -1132,10 +1236,14 @@ int main(int argc, char **argv) } if (type_override && !type_override[0]) type_override = nullptr; if (size_override && !size_override[0]) size_override = nullptr; if (erase_first && needs_erase(usb, argv[1])) { fb_queue_erase(argv[1]); auto format = [&](const std::string &partition) { if (erase_first && needs_erase(usb, partition.c_str())) { fb_queue_erase(partition.c_str()); } fb_perform_format(usb, argv[1], 0, type_override, size_override); fb_perform_format(usb, partition.c_str(), 0, type_override, size_override); }; do_for_partitions(usb, argv[1], slot_override.c_str(), format, true); skip(2); } else if(!strcmp(*argv, "signature")) { require(2); Loading Loading @@ -1195,12 +1303,15 @@ int main(int argc, char **argv) skip(2); } if (fname == 0) die("cannot determine image filename for '%s'", pname); if (erase_first && needs_erase(usb, pname)) { fb_queue_erase(pname); auto flash = [&](const std::string &partition) { if (erase_first && needs_erase(usb, partition.c_str())) { fb_queue_erase(partition.c_str()); } do_flash(usb, pname, fname); do_flash(usb, partition.c_str(), fname); }; do_for_partitions(usb, pname, slot_override.c_str(), flash, true); } else if(!strcmp(*argv, "flash:raw")) { char *pname = argv[1]; char *kname = argv[2]; char *rname = 0; char *sname = 0; Loading @@ -1216,20 +1327,27 @@ int main(int argc, char **argv) } data = load_bootable_image(kname, rname, sname, &sz, cmdline); if (data == 0) die("cannot load bootable image"); fb_queue_flash(pname, data, sz); 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); } else if(!strcmp(*argv, "flashall")) { skip(1); do_flashall(usb, erase_first); do_flashall(usb, slot_override.c_str(), erase_first); wants_reboot = 1; } else if(!strcmp(*argv, "update")) { if (argc > 1) { do_update(usb, argv[1], erase_first); do_update(usb, argv[1], slot_override.c_str(), erase_first); skip(2); } else { do_update(usb, "update.zip", erase_first); do_update(usb, "update.zip", slot_override.c_str(), erase_first); skip(1); } wants_reboot = 1; } else if(!strcmp(*argv, "set_active")) { require(2); fb_set_active(argv[1]); skip(2); } else if(!strcmp(*argv, "oem")) { argc = do_oem_command(argc, argv); } else if(!strcmp(*argv, "flashing")) { Loading fastboot/fastboot.h +1 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ void fb_queue_download(const char *name, void *data, uint32_t size); void fb_queue_notice(const char *notice); void fb_queue_wait_for_disconnect(void); int fb_execute_queue(usb_handle *usb); void fb_set_active(const char *slot); /* util stuff */ double now(); Loading Loading
fastboot/engine.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,13 @@ static Action *queue_action(unsigned op, const char *fmt, ...) return a; } void fb_set_active(const char *slot) { Action *a; a = queue_action(OP_COMMAND, "set_active:%s", slot); a->msg = mkmsg("Setting current slot to '%s'", slot); } void fb_queue_erase(const char *ptn) { Action *a; Loading
fastboot/fastboot.cpp +153 −35 Original line number Diff line number Diff line Loading @@ -42,12 +42,16 @@ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <functional> #include <base/parseint.h> #include <base/strings.h> #include <sparse/sparse.h> #include <ziparchive/zip_archive.h> #include <base/strings.h> #include <base/parseint.h> #include "bootimg_utils.h" #include "fastboot.h" #include "fs.h" Loading Loading @@ -273,6 +277,8 @@ static void usage() { " override the fs type and/or size\n" " the bootloader reports.\n" " getvar <variable> Display a bootloader variable.\n" " set_active <suffix> Sets the active slot. If slots are\n" " not supported, this does nothing.\n" " boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n" " flash:raw boot <kernel> [ <ramdisk> [ <second> ] ]\n" " Create bootimage and flash it.\n" Loading @@ -299,6 +305,13 @@ static void usage() { " (default: 2048).\n" " -S <size>[K|M|G] Automatically sparse files greater\n" " than 'size'. 0 to disable.\n" " --slot <suffix> Specify slot suffix to be used if the\n" " device supports slots. This will be\n" " added to all partition names that use\n" " slots. 'all' can be given to refer\n" " to all slots. If this is not given,\n" " slotted partitions will default to\n" " the current active slot.\n" ); } Loading Loading @@ -690,6 +703,80 @@ static void flash_buf(const char *pname, struct fastboot_buffer *buf) } } static std::vector<std::string> get_suffixes(usb_handle* usb) { std::vector<std::string> suffixes; std::string suffix_list; if (!fb_getvar(usb, "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) { if (strcmp(slot, "all") == 0) { return "all"; } std::vector<std::string> suffixes = get_suffixes(usb); for (const std::string &suffix : suffixes) { if (suffix == slot) return slot; } fprintf(stderr, "Slot %s does not exist. supported slots are:", slot); for (const std::string &suffix : suffixes) { fprintf(stderr, "%s\n", suffix.c_str()); } 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) { std::string partition_slot; std::string current_slot; if (!fb_getvar(usb, std::string("partition-slot:")+part, &partition_slot)) { /* If partition-slot is not supported, the answer is no. */ partition_slot = ""; } if (partition_slot == "1") { if (!slot || slot[0] == 0) { if (!fb_getvar(usb, "current-slot", ¤t_slot)) { die("Failed to identify current slot.\n"); } func(std::string(part) + '-' + current_slot); } else { func(std::string(part) + '-' + slot); } } else { if (force_slot && slot && slot[0]) { 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. */ static void do_for_partitions(usb_handle* usb, const char *part, const char *slot, std::function<void(const std::string&)> func, bool force_slot) { std::string partition_slot; if (slot && strcmp(slot, "all") == 0) { if (!fb_getvar(usb, std::string("partition-slot:") + part, &partition_slot)) { die("Could not check if partition %s has slot.", part); } if (partition_slot == "1") { std::vector<std::string> suffixes = get_suffixes(usb); for (std::string &suffix : suffixes) { do_for_partition(usb, part, suffix.c_str(), func, force_slot); } } else { do_for_partition(usb, part, "", func, force_slot); } } else { do_for_partition(usb, part, slot, func, force_slot); } } static void do_flash(usb_handle* usb, const char* pname, const char* fname) { struct fastboot_buffer buf; Loading @@ -707,7 +794,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, bool erase_first) { static void do_update(usb_handle* usb, const char* filename, const char* slot_override, bool erase_first) { queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); Loading Loading @@ -740,15 +827,19 @@ static void do_update(usb_handle* usb, const char* filename, bool erase_first) { fastboot_buffer buf; int rc = load_buf_fd(usb, 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, images[i].part_name)) { fb_queue_erase(images[i].part_name); if (erase_first && needs_erase(usb, partition.c_str())) { fb_queue_erase(partition.c_str()); } flash_buf(images[i].part_name, &buf); flash_buf(partition.c_str(), &buf); /* not closing the fd here since the sparse code keeps the fd around * but hasn't mmaped data yet. The tmpfile will get cleaned up when the * program exits. */ }; do_for_partitions(usb, images[i].part_name, slot_override, update, false); } CloseArchive(zip); Loading @@ -770,7 +861,7 @@ static void do_send_signature(char* fn) { fb_queue_command("signature", "installing signature"); } static void do_flashall(usb_handle* usb, int erase_first) { static void do_flashall(usb_handle* usb, const char *slot_override, int erase_first) { queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); Loading @@ -792,11 +883,15 @@ static void do_flashall(usb_handle* usb, int erase_first) { continue; die("could not load %s\n", images[i].img_name); } auto flashall = [&](const std::string &partition) { do_send_signature(fname); if (erase_first && needs_erase(usb, images[i].part_name)) { fb_queue_erase(images[i].part_name); if (erase_first && needs_erase(usb, partition.c_str())) { fb_queue_erase(partition.c_str()); } flash_buf(images[i].part_name, &buf); flash_buf(partition.c_str(), &buf); }; do_for_partitions(usb, images[i].part_name, slot_override, flashall, false); } } Loading Loading @@ -977,6 +1072,7 @@ int main(int argc, char **argv) void *data; int64_t sz; int longindex; std::string slot_override; const struct option longopts[] = { {"base", required_argument, 0, 'b'}, Loading @@ -987,6 +1083,7 @@ int main(int argc, char **argv) {"help", no_argument, 0, 'h'}, {"unbuffered", no_argument, 0, 0}, {"version", no_argument, 0, 0}, {"slot", required_argument, 0, 0}, {0, 0, 0, 0} }; Loading Loading @@ -1061,6 +1158,8 @@ int main(int argc, char **argv) } else if (strcmp("version", longopts[longindex].name) == 0) { fprintf(stdout, "fastboot version %s\n", FASTBOOT_REVISION); return 0; } else if (strcmp("slot", longopts[longindex].name) == 0) { slot_override = std::string(optarg); } break; default: Loading Loading @@ -1088,6 +1187,8 @@ int main(int argc, char **argv) } usb_handle* usb = open_device(); if (slot_override != "") slot_override = verify_slot(usb, slot_override.c_str()); while (argc > 0) { if (!strcmp(*argv, "getvar")) { Loading @@ -1097,6 +1198,7 @@ int main(int argc, char **argv) } else if(!strcmp(*argv, "erase")) { require(2); auto erase = [&](const std::string &partition) { std::string partition_type; if (fb_getvar(usb, std::string("partition-type:") + argv[1], &partition_type) && fs_get_generator(partition_type) != nullptr) { Loading @@ -1104,7 +1206,9 @@ int main(int argc, char **argv) partition_type.c_str()); } fb_queue_erase(argv[1]); fb_queue_erase(partition.c_str()); }; do_for_partitions(usb, argv[1], slot_override.c_str(), erase, true); skip(2); } else if(!strncmp(*argv, "format", strlen("format"))) { char *overrides; Loading Loading @@ -1132,10 +1236,14 @@ int main(int argc, char **argv) } if (type_override && !type_override[0]) type_override = nullptr; if (size_override && !size_override[0]) size_override = nullptr; if (erase_first && needs_erase(usb, argv[1])) { fb_queue_erase(argv[1]); auto format = [&](const std::string &partition) { if (erase_first && needs_erase(usb, partition.c_str())) { fb_queue_erase(partition.c_str()); } fb_perform_format(usb, argv[1], 0, type_override, size_override); fb_perform_format(usb, partition.c_str(), 0, type_override, size_override); }; do_for_partitions(usb, argv[1], slot_override.c_str(), format, true); skip(2); } else if(!strcmp(*argv, "signature")) { require(2); Loading Loading @@ -1195,12 +1303,15 @@ int main(int argc, char **argv) skip(2); } if (fname == 0) die("cannot determine image filename for '%s'", pname); if (erase_first && needs_erase(usb, pname)) { fb_queue_erase(pname); auto flash = [&](const std::string &partition) { if (erase_first && needs_erase(usb, partition.c_str())) { fb_queue_erase(partition.c_str()); } do_flash(usb, pname, fname); do_flash(usb, partition.c_str(), fname); }; do_for_partitions(usb, pname, slot_override.c_str(), flash, true); } else if(!strcmp(*argv, "flash:raw")) { char *pname = argv[1]; char *kname = argv[2]; char *rname = 0; char *sname = 0; Loading @@ -1216,20 +1327,27 @@ int main(int argc, char **argv) } data = load_bootable_image(kname, rname, sname, &sz, cmdline); if (data == 0) die("cannot load bootable image"); fb_queue_flash(pname, data, sz); 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); } else if(!strcmp(*argv, "flashall")) { skip(1); do_flashall(usb, erase_first); do_flashall(usb, slot_override.c_str(), erase_first); wants_reboot = 1; } else if(!strcmp(*argv, "update")) { if (argc > 1) { do_update(usb, argv[1], erase_first); do_update(usb, argv[1], slot_override.c_str(), erase_first); skip(2); } else { do_update(usb, "update.zip", erase_first); do_update(usb, "update.zip", slot_override.c_str(), erase_first); skip(1); } wants_reboot = 1; } else if(!strcmp(*argv, "set_active")) { require(2); fb_set_active(argv[1]); skip(2); } else if(!strcmp(*argv, "oem")) { argc = do_oem_command(argc, argv); } else if(!strcmp(*argv, "flashing")) { Loading
fastboot/fastboot.h +1 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ void fb_queue_download(const char *name, void *data, uint32_t size); void fb_queue_notice(const char *notice); void fb_queue_wait_for_disconnect(void); int fb_execute_queue(usb_handle *usb); void fb_set_active(const char *slot); /* util stuff */ double now(); Loading