system/corennnnn
修訂 | 6c98509c34d152007cf953c2cacb5750745dd464 (tree) |
---|---|
時間 | 2016-06-29 09:41:46 |
作者 | Daniel Rosenberg <drosen@goog...> |
Commiter | Daniel Rosenberg |
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.
Bug: 29278988
Change-Id: Ia870e4be55617c0eefa4e1381287f8cd14affe7e
@@ -49,6 +49,7 @@ | ||
49 | 49 | |
50 | 50 | #include <android-base/parseint.h> |
51 | 51 | #include <android-base/parsenetaddress.h> |
52 | +#include <android-base/stringprintf.h> | |
52 | 53 | #include <android-base/strings.h> |
53 | 54 | #include <sparse/sparse.h> |
54 | 55 | #include <ziparchive/zip_archive.h> |
@@ -99,22 +100,41 @@ struct fastboot_buffer { | ||
99 | 100 | }; |
100 | 101 | |
101 | 102 | static struct { |
102 | - char img_name[13]; | |
103 | - char sig_name[13]; | |
103 | + char img_name[17]; | |
104 | + char sig_name[17]; | |
104 | 105 | char part_name[9]; |
105 | 106 | bool is_optional; |
107 | + bool is_secondary; | |
106 | 108 | } images[] = { |
107 | - {"boot.img", "boot.sig", "boot", false}, | |
108 | - {"recovery.img", "recovery.sig", "recovery", true}, | |
109 | - {"system.img", "system.sig", "system", false}, | |
110 | - {"vendor.img", "vendor.sig", "vendor", true}, | |
109 | + {"boot.img", "boot.sig", "boot", false, false}, | |
110 | + {"boot_other.img", "boot.sig", "boot", true, true}, | |
111 | + {"recovery.img", "recovery.sig", "recovery", true, false}, | |
112 | + {"system.img", "system.sig", "system", false, false}, | |
113 | + {"system_other.img", "system.sig", "system", true, true}, | |
114 | + {"vendor.img", "vendor.sig", "vendor", true, false}, | |
115 | + {"vendor_other.img", "vendor.sig", "vendor", true, true}, | |
111 | 116 | }; |
112 | 117 | |
113 | -static char* find_item(const char* item, const char* product) { | |
118 | +static std::string find_item_given_name(const char* img_name, const char* product) { | |
114 | 119 | char *dir; |
115 | - const char *fn; | |
116 | 120 | char path[PATH_MAX + 128]; |
117 | 121 | |
122 | + if(product) { | |
123 | + get_my_path(path); | |
124 | + return android::base::StringPrintf("../../../target/product/%s/%s", product, img_name); | |
125 | + } | |
126 | + | |
127 | + dir = getenv("ANDROID_PRODUCT_OUT"); | |
128 | + if((dir == 0) || (dir[0] == 0)) { | |
129 | + die("neither -p product specified nor ANDROID_PRODUCT_OUT set"); | |
130 | + } | |
131 | + | |
132 | + return android::base::StringPrintf("%s/%s", dir, img_name); | |
133 | +} | |
134 | + | |
135 | +std::string find_item(const char* item, const char* product) { | |
136 | + const char *fn; | |
137 | + | |
118 | 138 | if(!strcmp(item,"boot")) { |
119 | 139 | fn = "boot.img"; |
120 | 140 | } else if(!strcmp(item,"recovery")) { |
@@ -131,24 +151,10 @@ static char* find_item(const char* item, const char* product) { | ||
131 | 151 | fn = "android-info.txt"; |
132 | 152 | } else { |
133 | 153 | fprintf(stderr,"unknown partition '%s'\n", item); |
134 | - return 0; | |
135 | - } | |
136 | - | |
137 | - if(product) { | |
138 | - get_my_path(path); | |
139 | - sprintf(path + strlen(path), | |
140 | - "../../../target/product/%s/%s", product, fn); | |
141 | - return strdup(path); | |
142 | - } | |
143 | - | |
144 | - dir = getenv("ANDROID_PRODUCT_OUT"); | |
145 | - if((dir == 0) || (dir[0] == 0)) { | |
146 | - die("neither -p product specified nor ANDROID_PRODUCT_OUT set"); | |
147 | - return 0; | |
154 | + return ""; | |
148 | 155 | } |
149 | 156 | |
150 | - sprintf(path, "%s/%s", dir, fn); | |
151 | - return strdup(path); | |
157 | + return find_item_given_name(fn, product); | |
152 | 158 | } |
153 | 159 | |
154 | 160 | static int64_t get_file_size(int fd) { |
@@ -319,6 +325,11 @@ static void usage() { | ||
319 | 325 | " if found -- recovery. If the device\n" |
320 | 326 | " supports slots, the slot that has\n" |
321 | 327 | " been flashed to is set as active.\n" |
328 | + " Secondary images may be flashed to\n" | |
329 | + " an inactive slot.\n" | |
330 | + " flash-primary Same as flashall, but do not flash\n" | |
331 | + " secondary images.\n" | |
332 | + " flash-secondary Only flashes the secondary images.\n" | |
322 | 333 | " flash <partition> [ <filename> ] Write a file to a flash partition.\n" |
323 | 334 | " flashing lock Locks the device. Prevents flashing.\n" |
324 | 335 | " flashing unlock Unlocks the device. Allows flashing\n" |
@@ -867,8 +878,12 @@ static std::vector<std::string> get_suffixes(Transport* transport) { | ||
867 | 878 | return suffixes; |
868 | 879 | } |
869 | 880 | |
881 | +static bool supports_AB(Transport* transport) { | |
882 | + return !get_suffixes(transport).empty(); | |
883 | +} | |
884 | + | |
870 | 885 | // Given a current slot, this returns what the 'other' slot is. |
871 | -static std::string get_other_slot(Transport* transport, std::string& current_slot) { | |
886 | +static std::string get_other_slot(Transport* transport, const std::string& current_slot) { | |
872 | 887 | std::vector<std::string> suffixes = get_suffixes(transport); |
873 | 888 | |
874 | 889 | if (!suffixes.empty()) { |
@@ -881,6 +896,12 @@ static std::string get_other_slot(Transport* transport, std::string& current_slo | ||
881 | 896 | return ""; |
882 | 897 | } |
883 | 898 | |
899 | +static std::string get_other_slot(Transport* transport) { | |
900 | + std::string current_slot; | |
901 | + fb_getvar(transport, "current-slot", ¤t_slot); | |
902 | + return get_other_slot(transport, current_slot); | |
903 | +} | |
904 | + | |
884 | 905 | static std::string verify_slot(Transport* transport, const char *slot, bool allow_all) { |
885 | 906 | if (strcmp(slot, "all") == 0) { |
886 | 907 | if (allow_all) { |
@@ -1003,9 +1024,9 @@ static void do_update_signature(ZipArchiveHandle zip, char* fn) { | ||
1003 | 1024 | |
1004 | 1025 | // Sets slot_override as the active slot. If slot_override is blank, |
1005 | 1026 | // set current slot as active instead. This clears slot-unbootable. |
1006 | -static void set_active(Transport* transport, const char* slot_override) { | |
1007 | - if (slot_override && slot_override[0]) { | |
1008 | - fb_set_active(slot_override); | |
1027 | +static void set_active(Transport* transport, const std::string& slot_override) { | |
1028 | + if (slot_override != "") { | |
1029 | + fb_set_active(slot_override.c_str()); | |
1009 | 1030 | } else { |
1010 | 1031 | std::string current_slot; |
1011 | 1032 | if (fb_getvar(transport, "current-slot", ¤t_slot)) { |
@@ -1015,7 +1036,7 @@ static void set_active(Transport* transport, const char* slot_override) { | ||
1015 | 1036 | } |
1016 | 1037 | } |
1017 | 1038 | |
1018 | -static void do_update(Transport* transport, const char* filename, const char* slot_override, bool erase_first) { | |
1039 | +static void do_update(Transport* transport, const char* filename, const std::string& slot_override, bool erase_first) { | |
1019 | 1040 | queue_info_dump(); |
1020 | 1041 | |
1021 | 1042 | fb_queue_query_save("product", cur_product, sizeof(cur_product)); |
@@ -1036,7 +1057,31 @@ static void do_update(Transport* transport, const char* filename, const char* sl | ||
1036 | 1057 | |
1037 | 1058 | setup_requirements(reinterpret_cast<char*>(data), sz); |
1038 | 1059 | |
1060 | + std::string secondary; | |
1061 | + bool update_secondary = slot_override != "all"; | |
1062 | + if (update_secondary) { | |
1063 | + if (slot_override != "") { | |
1064 | + secondary = get_other_slot(transport, slot_override); | |
1065 | + } else { | |
1066 | + secondary = get_other_slot(transport); | |
1067 | + } | |
1068 | + if (secondary == "") { | |
1069 | + if (supports_AB(transport)) { | |
1070 | + fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n"); | |
1071 | + } | |
1072 | + update_secondary = false; | |
1073 | + } | |
1074 | + } | |
1039 | 1075 | for (size_t i = 0; i < ARRAY_SIZE(images); ++i) { |
1076 | + const char* slot = slot_override.c_str(); | |
1077 | + if (images[i].is_secondary) { | |
1078 | + if (update_secondary) { | |
1079 | + slot = secondary.c_str(); | |
1080 | + } else { | |
1081 | + continue; | |
1082 | + } | |
1083 | + } | |
1084 | + | |
1040 | 1085 | int fd = unzip_to_file(zip, images[i].img_name); |
1041 | 1086 | if (fd == -1) { |
1042 | 1087 | if (images[i].is_optional) { |
@@ -1060,49 +1105,69 @@ static void do_update(Transport* transport, const char* filename, const char* sl | ||
1060 | 1105 | * program exits. |
1061 | 1106 | */ |
1062 | 1107 | }; |
1063 | - do_for_partitions(transport, images[i].part_name, slot_override, update, false); | |
1108 | + do_for_partitions(transport, images[i].part_name, slot, update, false); | |
1064 | 1109 | } |
1065 | 1110 | |
1066 | 1111 | CloseArchive(zip); |
1067 | 1112 | set_active(transport, slot_override); |
1068 | 1113 | } |
1069 | 1114 | |
1070 | -static void do_send_signature(char* fn) { | |
1071 | - char* xtn = strrchr(fn, '.'); | |
1072 | - if (!xtn) return; | |
1115 | +static void do_send_signature(const std::string& fn) { | |
1116 | + std::size_t extension_loc = fn.find(".img"); | |
1117 | + if (extension_loc == std::string::npos) return; | |
1073 | 1118 | |
1074 | - if (strcmp(xtn, ".img")) return; | |
1075 | - | |
1076 | - strcpy(xtn, ".sig"); | |
1119 | + std::string fs_sig = fn.substr(0, extension_loc) + ".sig"; | |
1077 | 1120 | |
1078 | 1121 | int64_t sz; |
1079 | - void* data = load_file(fn, &sz); | |
1080 | - strcpy(xtn, ".img"); | |
1122 | + void* data = load_file(fs_sig.c_str(), &sz); | |
1081 | 1123 | if (data == nullptr) return; |
1082 | 1124 | fb_queue_download("signature", data, sz); |
1083 | 1125 | fb_queue_command("signature", "installing signature"); |
1084 | 1126 | } |
1085 | 1127 | |
1086 | -static void do_flashall(Transport* transport, const char* slot_override, int erase_first) { | |
1087 | - queue_info_dump(); | |
1128 | +static void do_flashall(Transport* transport, const std::string& slot_override, int erase_first, bool flash_primary, bool flash_secondary) { | |
1129 | + std::string fname; | |
1130 | + if (flash_primary) { | |
1131 | + queue_info_dump(); | |
1088 | 1132 | |
1089 | - fb_queue_query_save("product", cur_product, sizeof(cur_product)); | |
1133 | + fb_queue_query_save("product", cur_product, sizeof(cur_product)); | |
1090 | 1134 | |
1091 | - char* fname = find_item("info", product); | |
1092 | - if (fname == nullptr) die("cannot find android-info.txt"); | |
1135 | + fname = find_item("info", product); | |
1136 | + if (fname == "") die("cannot find android-info.txt"); | |
1093 | 1137 | |
1094 | - int64_t sz; | |
1095 | - void* data = load_file(fname, &sz); | |
1096 | - if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno)); | |
1138 | + int64_t sz; | |
1139 | + void* data = load_file(fname.c_str(), &sz); | |
1140 | + if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno)); | |
1097 | 1141 | |
1098 | - setup_requirements(reinterpret_cast<char*>(data), sz); | |
1142 | + setup_requirements(reinterpret_cast<char*>(data), sz); | |
1143 | + } | |
1144 | + std::string secondary; | |
1145 | + if (flash_secondary) { | |
1146 | + if (slot_override != "") { | |
1147 | + secondary = get_other_slot(transport, slot_override); | |
1148 | + } else { | |
1149 | + secondary = get_other_slot(transport); | |
1150 | + } | |
1151 | + if (secondary == "") { | |
1152 | + if (supports_AB(transport)) { | |
1153 | + fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n"); | |
1154 | + } | |
1155 | + flash_secondary = false; | |
1156 | + } | |
1157 | + } | |
1099 | 1158 | |
1100 | 1159 | for (size_t i = 0; i < ARRAY_SIZE(images); i++) { |
1101 | - fname = find_item(images[i].part_name, product); | |
1160 | + const char* slot = NULL; | |
1161 | + if (images[i].is_secondary) { | |
1162 | + if (flash_secondary) slot = secondary.c_str(); | |
1163 | + } else { | |
1164 | + if (flash_primary) slot = slot_override.c_str(); | |
1165 | + } | |
1166 | + if (!slot) continue; | |
1167 | + fname = find_item_given_name(images[i].img_name, product); | |
1102 | 1168 | fastboot_buffer buf; |
1103 | - if (load_buf(transport, fname, &buf)) { | |
1104 | - if (images[i].is_optional) | |
1105 | - continue; | |
1169 | + if (load_buf(transport, fname.c_str(), &buf)) { | |
1170 | + if (images[i].is_optional) continue; | |
1106 | 1171 | die("could not load %s\n", images[i].img_name); |
1107 | 1172 | } |
1108 | 1173 |
@@ -1113,10 +1178,10 @@ static void do_flashall(Transport* transport, const char* slot_override, int era | ||
1113 | 1178 | } |
1114 | 1179 | flash_buf(partition.c_str(), &buf); |
1115 | 1180 | }; |
1116 | - do_for_partitions(transport, images[i].part_name, slot_override, flashall, false); | |
1181 | + do_for_partitions(transport, images[i].part_name, slot, flashall, false); | |
1117 | 1182 | } |
1118 | 1183 | |
1119 | - set_active(transport, slot_override); | |
1184 | + if (flash_primary) set_active(transport, slot_override); | |
1120 | 1185 | } |
1121 | 1186 | |
1122 | 1187 | #define skip(n) do { argc -= (n); argv += (n); } while (0) |
@@ -1443,10 +1508,8 @@ int main(int argc, char **argv) | ||
1443 | 1508 | return 1; |
1444 | 1509 | } |
1445 | 1510 | |
1446 | - if (slot_override != "") | |
1447 | - slot_override = verify_slot(transport, slot_override.c_str()); | |
1448 | - if (next_active != "") | |
1449 | - next_active = verify_slot(transport, next_active.c_str(), false); | |
1511 | + if (slot_override != "") slot_override = verify_slot(transport, slot_override.c_str()); | |
1512 | + if (next_active != "") next_active = verify_slot(transport, next_active.c_str(), false); | |
1450 | 1513 | |
1451 | 1514 | if (wants_set_active) { |
1452 | 1515 | if (next_active == "") { |
@@ -1567,7 +1630,7 @@ int main(int argc, char **argv) | ||
1567 | 1630 | fb_queue_command("boot", "booting"); |
1568 | 1631 | } else if(!strcmp(*argv, "flash")) { |
1569 | 1632 | char *pname = argv[1]; |
1570 | - char *fname = 0; | |
1633 | + std::string fname; | |
1571 | 1634 | require(2); |
1572 | 1635 | if (argc > 2) { |
1573 | 1636 | fname = argv[2]; |
@@ -1576,13 +1639,13 @@ int main(int argc, char **argv) | ||
1576 | 1639 | fname = find_item(pname, product); |
1577 | 1640 | skip(2); |
1578 | 1641 | } |
1579 | - if (fname == 0) die("cannot determine image filename for '%s'", pname); | |
1642 | + if (fname == "") die("cannot determine image filename for '%s'", pname); | |
1580 | 1643 | |
1581 | 1644 | auto flash = [&](const std::string &partition) { |
1582 | 1645 | if (erase_first && needs_erase(transport, partition.c_str())) { |
1583 | 1646 | fb_queue_erase(partition.c_str()); |
1584 | 1647 | } |
1585 | - do_flash(transport, partition.c_str(), fname); | |
1648 | + do_flash(transport, partition.c_str(), fname.c_str()); | |
1586 | 1649 | }; |
1587 | 1650 | do_for_partitions(transport, pname, slot_override.c_str(), flash, true); |
1588 | 1651 | } else if(!strcmp(*argv, "flash:raw")) { |
@@ -1607,14 +1670,27 @@ int main(int argc, char **argv) | ||
1607 | 1670 | do_for_partitions(transport, argv[1], slot_override.c_str(), flashraw, true); |
1608 | 1671 | } else if(!strcmp(*argv, "flashall")) { |
1609 | 1672 | skip(1); |
1610 | - do_flashall(transport, slot_override.c_str(), erase_first); | |
1673 | + if (slot_override == "all") { | |
1674 | + fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed."); | |
1675 | + do_flashall(transport, slot_override, erase_first, true, false); | |
1676 | + } else { | |
1677 | + do_flashall(transport, slot_override, erase_first, true, true); | |
1678 | + } | |
1679 | + wants_reboot = true; | |
1680 | + } else if(!strcmp(*argv, "flash-primary")) { | |
1681 | + skip(1); | |
1682 | + do_flashall(transport, slot_override, erase_first, true, false); | |
1683 | + wants_reboot = true; | |
1684 | + } else if(!strcmp(*argv, "flash-secondary")) { | |
1685 | + skip(1); | |
1686 | + do_flashall(transport, slot_override, erase_first, false, true); | |
1611 | 1687 | wants_reboot = true; |
1612 | 1688 | } else if(!strcmp(*argv, "update")) { |
1613 | 1689 | if (argc > 1) { |
1614 | - do_update(transport, argv[1], slot_override.c_str(), erase_first); | |
1690 | + do_update(transport, argv[1], slot_override, erase_first); | |
1615 | 1691 | skip(2); |
1616 | 1692 | } else { |
1617 | - do_update(transport, "update.zip", slot_override.c_str(), erase_first); | |
1693 | + do_update(transport, "update.zip", slot_override, erase_first); | |
1618 | 1694 | skip(1); |
1619 | 1695 | } |
1620 | 1696 | wants_reboot = 1; |