1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include "fastboot.h"
30
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <getopt.h>
34 #include <inttypes.h>
35 #include <limits.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
42 #include <sys/types.h>
43 #include <unistd.h>
44
45 #include <chrono>
46 #include <functional>
47 #include <iostream>
48 #include <memory>
49 #include <regex>
50 #include <string>
51 #include <thread>
52 #include <utility>
53 #include <vector>
54
55 #include <android-base/endian.h>
56 #include <android-base/file.h>
57 #include <android-base/logging.h>
58 #include <android-base/macros.h>
59 #include <android-base/parseint.h>
60 #include <android-base/parsenetaddress.h>
61 #include <android-base/stringprintf.h>
62 #include <android-base/strings.h>
63 #include <android-base/unique_fd.h>
64 #include <build/version.h>
65 #include <libavb/libavb.h>
66 #include <liblp/liblp.h>
67 #include <liblp/super_layout_builder.h>
68 #include <platform_tools_version.h>
69 #include <sparse/sparse.h>
70 #include <ziparchive/zip_archive.h>
71
72 #include "bootimg_utils.h"
73 #include "constants.h"
74 #include "diagnose_usb.h"
75 #include "fastboot_driver.h"
76 #include "fastboot_driver_interface.h"
77 #include "fs.h"
78 #include "storage.h"
79 #include "task.h"
80 #include "tcp.h"
81 #include "transport.h"
82 #include "udp.h"
83 #include "usb.h"
84 #include "util.h"
85 #include "vendor_boot_img_utils.h"
86
87 using android::base::borrowed_fd;
88 using android::base::ReadFully;
89 using android::base::Split;
90 using android::base::Trim;
91 using android::base::unique_fd;
92 using namespace std::placeholders;
93
94 #define FASTBOOT_INFO_VERSION 1
95
96 static const char* serial = nullptr;
97
98 static bool g_long_listing = false;
99 // Don't resparse files in too-big chunks.
100 // libsparse will support INT_MAX, but this results in large allocations, so
101 // let's keep it at 1GB to avoid memory pressure on the host.
102 static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024;
103 static int64_t target_sparse_limit = -1;
104
105 static unsigned g_base_addr = 0x10000000;
106 static boot_img_hdr_v2 g_boot_img_hdr = {};
107 static std::string g_cmdline;
108 static std::string g_dtb_path;
109
110 static bool g_disable_verity = false;
111 static bool g_disable_verification = false;
112
113 fastboot::FastBootDriver* fb = nullptr;
114
115 static std::vector<Image> images = {
116 // clang-format off
117 { "boot", "boot.img", "boot.sig", "boot", false, ImageType::BootCritical },
118 { "bootloader",
119 "bootloader.img", "", "bootloader",
120 true, ImageType::Extra },
121 { "init_boot",
122 "init_boot.img", "init_boot.sig",
123 "init_boot",
124 true, ImageType::BootCritical },
125 { "", "boot_other.img", "boot.sig", "boot", true, ImageType::Normal },
126 { "cache", "cache.img", "cache.sig", "cache", true, ImageType::Extra },
127 { "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, ImageType::BootCritical },
128 { "dts", "dt.img", "dt.sig", "dts", true, ImageType::BootCritical },
129 { "odm", "odm.img", "odm.sig", "odm", true, ImageType::Normal },
130 { "odm_dlkm", "odm_dlkm.img", "odm_dlkm.sig", "odm_dlkm", true, ImageType::Normal },
131 { "product", "product.img", "product.sig", "product", true, ImageType::Normal },
132 { "pvmfw", "pvmfw.img", "pvmfw.sig", "pvmfw", true, ImageType::BootCritical },
133 { "radio", "radio.img", "", "radio", true, ImageType::Extra },
134 { "recovery", "recovery.img", "recovery.sig", "recovery", true, ImageType::BootCritical },
135 { "super", "super.img", "super.sig", "super", true, ImageType::Extra },
136 { "system", "system.img", "system.sig", "system", false, ImageType::Normal },
137 { "system_dlkm",
138 "system_dlkm.img", "system_dlkm.sig",
139 "system_dlkm",
140 true, ImageType::Normal },
141 { "system_ext",
142 "system_ext.img", "system_ext.sig",
143 "system_ext",
144 true, ImageType::Normal },
145 { "", "system_other.img", "system.sig", "system", true, ImageType::Normal },
146 { "userdata", "userdata.img", "userdata.sig", "userdata", true, ImageType::Extra },
147 { "vbmeta", "vbmeta.img", "vbmeta.sig", "vbmeta", true, ImageType::BootCritical },
148 { "vbmeta_system",
149 "vbmeta_system.img",
150 "vbmeta_system.sig",
151 "vbmeta_system",
152 true, ImageType::BootCritical },
153 { "vbmeta_vendor",
154 "vbmeta_vendor.img",
155 "vbmeta_vendor.sig",
156 "vbmeta_vendor",
157 true, ImageType::BootCritical },
158 { "vendor", "vendor.img", "vendor.sig", "vendor", true, ImageType::Normal },
159 { "vendor_boot",
160 "vendor_boot.img", "vendor_boot.sig",
161 "vendor_boot",
162 true, ImageType::BootCritical },
163 { "vendor_dlkm",
164 "vendor_dlkm.img", "vendor_dlkm.sig",
165 "vendor_dlkm",
166 true, ImageType::Normal },
167 { "vendor_kernel_boot",
168 "vendor_kernel_boot.img",
169 "vendor_kernel_boot.sig",
170 "vendor_kernel_boot",
171 true, ImageType::BootCritical },
172 { "", "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
173 // clang-format on
174 };
175
get_android_product_out()176 char* get_android_product_out() {
177 char* dir = getenv("ANDROID_PRODUCT_OUT");
178 if (dir == nullptr || dir[0] == '\0') {
179 return nullptr;
180 }
181 return dir;
182 }
183
find_item_given_name(const std::string & img_name)184 static std::string find_item_given_name(const std::string& img_name) {
185 char* dir = get_android_product_out();
186 if (!dir) {
187 die("ANDROID_PRODUCT_OUT not set");
188 }
189 return std::string(dir) + "/" + img_name;
190 }
191
find_item(const std::string & item)192 std::string find_item(const std::string& item) {
193 for (size_t i = 0; i < images.size(); ++i) {
194 if (!images[i].nickname.empty() && item == images[i].nickname) {
195 return find_item_given_name(images[i].img_name);
196 }
197 }
198
199 fprintf(stderr, "unknown partition '%s'\n", item.c_str());
200 return "";
201 }
202
203 double last_start_time;
204
Status(const std::string & message)205 static void Status(const std::string& message) {
206 if (!message.empty()) {
207 static constexpr char kStatusFormat[] = "%-50s ";
208 fprintf(stderr, kStatusFormat, message.c_str());
209 }
210 last_start_time = now();
211 }
212
Epilog(int status)213 static void Epilog(int status) {
214 if (status) {
215 fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
216 die("Command failed");
217 } else {
218 double split = now();
219 fprintf(stderr, "OKAY [%7.3fs]\n", (split - last_start_time));
220 }
221 }
222
InfoMessage(const std::string & info)223 static void InfoMessage(const std::string& info) {
224 fprintf(stderr, "(bootloader) %s\n", info.c_str());
225 }
226
TextMessage(const std::string & text)227 static void TextMessage(const std::string& text) {
228 fprintf(stderr, "%s", text.c_str());
229 }
230
ReadFileToVector(const std::string & file,std::vector<char> * out)231 bool ReadFileToVector(const std::string& file, std::vector<char>* out) {
232 out->clear();
233
234 unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY)));
235 if (fd == -1) {
236 return false;
237 }
238
239 out->resize(get_file_size(fd));
240 return ReadFully(fd, out->data(), out->size());
241 }
242
match_fastboot_with_serial(usb_ifc_info * info,const char * local_serial)243 static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
244 if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) {
245 return -1;
246 }
247
248 // require matching serial number or device path if requested
249 // at the command line with the -s option.
250 if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
251 strcmp(local_serial, info->device_path) != 0))
252 return -1;
253 return 0;
254 }
255
match_fastboot(const char * local_serial=serial)256 static ifc_match_func match_fastboot(const char* local_serial = serial) {
257 return [local_serial](usb_ifc_info* info) -> int {
258 return match_fastboot_with_serial(info, local_serial);
259 };
260 }
261
262 // output compatible with "adb devices"
PrintDevice(const char * local_serial,const char * status=nullptr,const char * details=nullptr)263 static void PrintDevice(const char* local_serial, const char* status = nullptr,
264 const char* details = nullptr) {
265 if (local_serial == nullptr || strlen(local_serial) == 0) {
266 return;
267 }
268
269 if (g_long_listing) {
270 printf("%-22s", local_serial);
271 } else {
272 printf("%s\t", local_serial);
273 }
274
275 if (status != nullptr && strlen(status) > 0) {
276 printf(" %s", status);
277 }
278
279 if (g_long_listing) {
280 if (details != nullptr && strlen(details) > 0) {
281 printf(" %s", details);
282 }
283 }
284
285 putchar('\n');
286 }
287
list_devices_callback(usb_ifc_info * info)288 static int list_devices_callback(usb_ifc_info* info) {
289 if (match_fastboot_with_serial(info, nullptr) == 0) {
290 std::string serial = info->serial_number;
291 std::string interface = info->interface;
292 if (interface.empty()) {
293 interface = "fastboot";
294 }
295 if (!info->writable) {
296 serial = UsbNoPermissionsShortHelpText();
297 }
298 if (!serial[0]) {
299 serial = "????????????";
300 }
301
302 PrintDevice(serial.c_str(), interface.c_str(), info->device_path);
303 }
304
305 return -1;
306 }
307
ParseNetworkSerial(const std::string & serial)308 Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial) {
309 Socket::Protocol protocol;
310 const char* net_address = nullptr;
311 int port = 0;
312
313 if (android::base::StartsWith(serial, "tcp:")) {
314 protocol = Socket::Protocol::kTcp;
315 net_address = serial.c_str() + strlen("tcp:");
316 port = tcp::kDefaultPort;
317 } else if (android::base::StartsWith(serial, "udp:")) {
318 protocol = Socket::Protocol::kUdp;
319 net_address = serial.c_str() + strlen("udp:");
320 port = udp::kDefaultPort;
321 } else {
322 return Error<FastbootError>(FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX)
323 << "protocol prefix ('tcp:' or 'udp:') is missed: " << serial << ". "
324 << "Expected address format:\n"
325 << "<protocol>:<address>:<port> (tcp:localhost:5554)";
326 }
327
328 std::string error;
329 std::string host;
330 if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) {
331 return Error<FastbootError>(FastbootError::Type::NETWORK_SERIAL_WRONG_ADDRESS)
332 << "invalid network address '" << net_address << "': " << error;
333 }
334
335 return NetworkSerial{protocol, host, port};
336 }
337
338 // Opens a new Transport connected to the particular device.
339 // arguments:
340 //
341 // local_serial - device to connect (can be a network or usb serial name)
342 // wait_for_device - flag indicates whether we need to wait for device
343 // announce - flag indicates whether we need to print error to stdout in case
344 // we cannot connect to the device
345 //
346 // The returned Transport is a singleton, so multiple calls to this function will return the same
347 // object, and the caller should not attempt to delete the returned Transport.
open_device(const char * local_serial,bool wait_for_device=true,bool announce=true)348 static std::unique_ptr<Transport> open_device(const char* local_serial, bool wait_for_device = true,
349 bool announce = true) {
350 const Result<NetworkSerial, FastbootError> network_serial = ParseNetworkSerial(local_serial);
351
352 std::unique_ptr<Transport> transport;
353 while (true) {
354 if (network_serial.ok()) {
355 std::string error;
356 if (network_serial->protocol == Socket::Protocol::kTcp) {
357 transport = tcp::Connect(network_serial->address, network_serial->port, &error);
358 } else if (network_serial->protocol == Socket::Protocol::kUdp) {
359 transport = udp::Connect(network_serial->address, network_serial->port, &error);
360 }
361
362 if (!transport && announce) {
363 LOG(ERROR) << "error: " << error;
364 }
365 } else if (network_serial.error().code() ==
366 FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX) {
367 // WRONG_PREFIX is special because it happens when user wants to communicate with USB
368 // device
369 transport = usb_open(match_fastboot(local_serial));
370 } else {
371 Expect(network_serial);
372 }
373
374 if (transport) {
375 return transport;
376 }
377
378 if (!wait_for_device) {
379 return transport;
380 }
381
382 if (announce) {
383 announce = false;
384 LOG(ERROR) << "< waiting for " << local_serial << ">";
385 }
386 std::this_thread::sleep_for(std::chrono::seconds(1));
387 }
388 }
389
NetworkDeviceConnected(bool print=false)390 static std::unique_ptr<Transport> NetworkDeviceConnected(bool print = false) {
391 std::unique_ptr<Transport> transport;
392 std::unique_ptr<Transport> result;
393
394 ConnectedDevicesStorage storage;
395 std::set<std::string> devices;
396 if (storage.Exists()) {
397 FileLock lock = storage.Lock();
398 devices = storage.ReadDevices(lock);
399 }
400
401 for (const std::string& device : devices) {
402 transport = open_device(device.c_str(), false, false);
403
404 if (print) {
405 PrintDevice(device.c_str(), transport ? "fastboot" : "offline");
406 }
407
408 if (transport) {
409 result = std::move(transport);
410 }
411 }
412
413 return result;
414 }
415
416 // Detects the fastboot connected device to open a new Transport.
417 // Detecting logic:
418 //
419 // if serial is provided - try to connect to this particular usb/network device
420 // othervise:
421 // 1. Check connected usb devices and return the last connected one
422 // 2. Check connected network devices and return the last connected one
423 // 2. If nothing is connected - wait for any device by repeating p. 1 and 2
424 //
425 // The returned Transport is a singleton, so multiple calls to this function will return the same
426 // object, and the caller should not attempt to delete the returned Transport.
open_device()427 static std::unique_ptr<Transport> open_device() {
428 if (serial != nullptr) {
429 return open_device(serial);
430 }
431
432 bool announce = true;
433 std::unique_ptr<Transport> transport;
434 while (true) {
435 transport = usb_open(match_fastboot(nullptr));
436 if (transport) {
437 return transport;
438 }
439
440 transport = NetworkDeviceConnected();
441 if (transport) {
442 return transport;
443 }
444
445 if (announce) {
446 announce = false;
447 LOG(ERROR) << "< waiting for any device >";
448 }
449 std::this_thread::sleep_for(std::chrono::seconds(1));
450 }
451
452 return transport;
453 }
454
Connect(int argc,char * argv[])455 static int Connect(int argc, char* argv[]) {
456 if (argc != 1) {
457 LOG(FATAL) << "connect command requires to receive only 1 argument. Usage:" << std::endl
458 << "fastboot connect [tcp:|udp:host:port]";
459 }
460
461 const char* local_serial = *argv;
462 Expect(ParseNetworkSerial(local_serial));
463
464 if (!open_device(local_serial, false)) {
465 return 1;
466 }
467
468 ConnectedDevicesStorage storage;
469 {
470 FileLock lock = storage.Lock();
471 std::set<std::string> devices = storage.ReadDevices(lock);
472 devices.insert(local_serial);
473 storage.WriteDevices(lock, devices);
474 }
475
476 return 0;
477 }
478
Disconnect(const char * local_serial)479 static int Disconnect(const char* local_serial) {
480 Expect(ParseNetworkSerial(local_serial));
481
482 ConnectedDevicesStorage storage;
483 {
484 FileLock lock = storage.Lock();
485 std::set<std::string> devices = storage.ReadDevices(lock);
486 devices.erase(local_serial);
487 storage.WriteDevices(lock, devices);
488 }
489
490 return 0;
491 }
492
Disconnect()493 static int Disconnect() {
494 ConnectedDevicesStorage storage;
495 {
496 FileLock lock = storage.Lock();
497 storage.Clear(lock);
498 }
499
500 return 0;
501 }
502
Disconnect(int argc,char * argv[])503 static int Disconnect(int argc, char* argv[]) {
504 switch (argc) {
505 case 0: {
506 return Disconnect();
507 }
508 case 1: {
509 return Disconnect(*argv);
510 }
511 default:
512 LOG(FATAL) << "disconnect command can receive only 0 or 1 arguments. Usage:"
513 << std::endl
514 << "fastboot disconnect # disconnect all devices" << std::endl
515 << "fastboot disconnect [tcp:|udp:host:port] # disconnect device";
516 }
517
518 return 0;
519 }
520
list_devices()521 static void list_devices() {
522 // We don't actually open a USB device here,
523 // just getting our callback called so we can
524 // list all the connected devices.
525 usb_open(list_devices_callback);
526 NetworkDeviceConnected(/* print */ true);
527 }
528
syntax_error(const char * fmt,...)529 void syntax_error(const char* fmt, ...) {
530 fprintf(stderr, "fastboot: usage: ");
531
532 va_list ap;
533 va_start(ap, fmt);
534 vfprintf(stderr, fmt, ap);
535 va_end(ap);
536
537 fprintf(stderr, "\n");
538 exit(1);
539 }
540
show_help()541 static int show_help() {
542 // clang-format off
543 fprintf(stdout,
544 // 1 2 3 4 5 6 7 8
545 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
546 "usage: fastboot [OPTION...] COMMAND...\n"
547 "\n"
548 "flashing:\n"
549 " update ZIP Flash all partitions from an update.zip package.\n"
550 " flashall Flash all partitions from $ANDROID_PRODUCT_OUT.\n"
551 " On A/B devices, flashed slot is set as active.\n"
552 " Secondary images may be flashed to inactive slot.\n"
553 " flash PARTITION [FILENAME] Flash given partition, using the image from\n"
554 " $ANDROID_PRODUCT_OUT if no filename is given.\n"
555 " flash vendor_boot:RAMDISK [FILENAME]\n"
556 " Flash vendor_boot ramdisk, fetching the existing\n"
557 " vendor_boot image and repackaging it with the new\n"
558 " ramdisk.\n"
559 " --dtb DTB If set with flash vendor_boot:RAMDISK, then\n"
560 " update the vendor_boot image with provided DTB.\n"
561 "\n"
562 "basics:\n"
563 " devices [-l] List devices in bootloader (-l: with device paths).\n"
564 " getvar NAME Display given bootloader variable.\n"
565 " reboot [bootloader] Reboot device.\n"
566 "\n"
567 "locking/unlocking:\n"
568 " flashing lock|unlock Lock/unlock partitions for flashing\n"
569 " flashing lock_critical|unlock_critical\n"
570 " Lock/unlock 'critical' bootloader partitions.\n"
571 " flashing get_unlock_ability\n"
572 " Check whether unlocking is allowed (1) or not(0).\n"
573 "\n"
574 "advanced:\n"
575 " erase PARTITION Erase a flash partition.\n"
576 " format[:FS_TYPE[:SIZE]] PARTITION\n"
577 " Format a flash partition.\n"
578 " set_active SLOT Set the active slot.\n"
579 " oem [COMMAND...] Execute OEM-specific command.\n"
580 " gsi wipe|disable|status Wipe, disable or show status of a GSI installation\n"
581 " (fastbootd only).\n"
582 " wipe-super [SUPER_EMPTY] Wipe the super partition. This will reset it to\n"
583 " contain an empty set of default dynamic partitions.\n"
584 " create-logical-partition NAME SIZE\n"
585 " Create a logical partition with the given name and\n"
586 " size, in the super partition.\n"
587 " delete-logical-partition NAME\n"
588 " Delete a logical partition with the given name.\n"
589 " resize-logical-partition NAME SIZE\n"
590 " Change the size of the named logical partition.\n"
591 " snapshot-update cancel On devices that support snapshot-based updates, cancel\n"
592 " an in-progress update. This may make the device\n"
593 " unbootable until it is reflashed.\n"
594 " snapshot-update merge On devices that support snapshot-based updates, finish\n"
595 " an in-progress update if it is in the \"merging\"\n"
596 " phase.\n"
597 " fetch PARTITION OUT_FILE Fetch a partition image from the device."
598 "\n"
599 "boot image:\n"
600 " boot KERNEL [RAMDISK [SECOND]]\n"
601 " Download and boot kernel from RAM.\n"
602 " flash:raw PARTITION KERNEL [RAMDISK [SECOND]]\n"
603 " Create boot image and flash it.\n"
604 " --dtb DTB Specify path to DTB for boot image header version 2.\n"
605 " --cmdline CMDLINE Override kernel command line.\n"
606 " --base ADDRESS Set kernel base address (default: 0x10000000).\n"
607 " --kernel-offset Set kernel offset (default: 0x00008000).\n"
608 " --ramdisk-offset Set ramdisk offset (default: 0x01000000).\n"
609 " --tags-offset Set tags offset (default: 0x00000100).\n"
610 " --dtb-offset Set dtb offset (default: 0x01100000).\n"
611 " --page-size BYTES Set flash page size (default: 2048).\n"
612 " --header-version VERSION Set boot image header version.\n"
613 " --os-version MAJOR[.MINOR[.PATCH]]\n"
614 " Set boot image OS version (default: 0.0.0).\n"
615 " --os-patch-level YYYY-MM-DD\n"
616 " Set boot image OS security patch level.\n"
617 // TODO: still missing: `second_addr`, `name`, `id`, `recovery_dtbo_*`.
618 "\n"
619 // TODO: what device(s) used this? is there any documentation?
620 //" continue Continue with autoboot.\n"
621 //"\n"
622 "Android Things:\n"
623 " stage IN_FILE Sends given file to stage for the next command.\n"
624 " get_staged OUT_FILE Writes data staged by the last command to a file.\n"
625 "\n"
626 "options:\n"
627 " -w Wipe userdata.\n"
628 " -s SERIAL Specify a USB device.\n"
629 " -s tcp|udp:HOST[:PORT] Specify a network device.\n"
630 " -S SIZE[K|M|G] Break into sparse files no larger than SIZE.\n"
631 " --force Force a flash operation that may be unsafe.\n"
632 " --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n"
633 " non-current slot (default: current active slot).\n"
634 " --set-active[=SLOT] Sets the active slot before rebooting.\n"
635 " --skip-secondary Don't flash secondary slots in flashall/update.\n"
636 " --skip-reboot Don't reboot device after flashing.\n"
637 " --disable-verity Sets disable-verity when flashing vbmeta.\n"
638 " --disable-verification Sets disable-verification when flashing vbmeta.\n"
639 " --disable-super-optimization\n"
640 " Disables optimizations on flashing super partition.\n"
641 " --disable-fastboot-info Will collects tasks from image list rather than $OUT/fastboot-info.txt.\n"
642 " --fs-options=OPTION[,OPTION]\n"
643 " Enable filesystem features. OPTION supports casefold, projid, compress\n"
644 // TODO: remove --unbuffered?
645 " --unbuffered Don't buffer input or output.\n"
646 " --verbose, -v Verbose output.\n"
647 " --version Display version.\n"
648 " --help, -h Show this message.\n"
649 );
650 // clang-format on
651 return 0;
652 }
653
LoadBootableImage(const std::string & kernel,const std::string & ramdisk,const std::string & second_stage)654 static std::vector<char> LoadBootableImage(const std::string& kernel, const std::string& ramdisk,
655 const std::string& second_stage) {
656 std::vector<char> kernel_data;
657 if (!ReadFileToVector(kernel, &kernel_data)) {
658 die("cannot load '%s': %s", kernel.c_str(), strerror(errno));
659 }
660
661 // Is this actually a boot image?
662 if (kernel_data.size() < sizeof(boot_img_hdr_v3)) {
663 die("cannot load '%s': too short", kernel.c_str());
664 }
665 if (!memcmp(kernel_data.data(), BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
666 if (!g_cmdline.empty()) {
667 bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v2*>(kernel_data.data()), g_cmdline);
668 }
669
670 if (!ramdisk.empty()) die("cannot boot a boot.img *and* ramdisk");
671
672 return kernel_data;
673 }
674
675 std::vector<char> ramdisk_data;
676 if (!ramdisk.empty()) {
677 if (!ReadFileToVector(ramdisk, &ramdisk_data)) {
678 die("cannot load '%s': %s", ramdisk.c_str(), strerror(errno));
679 }
680 }
681
682 std::vector<char> second_stage_data;
683 if (!second_stage.empty()) {
684 if (!ReadFileToVector(second_stage, &second_stage_data)) {
685 die("cannot load '%s': %s", second_stage.c_str(), strerror(errno));
686 }
687 }
688
689 std::vector<char> dtb_data;
690 if (!g_dtb_path.empty()) {
691 if (g_boot_img_hdr.header_version != 2) {
692 die("Argument dtb not supported for boot image header version %d\n",
693 g_boot_img_hdr.header_version);
694 }
695 if (!ReadFileToVector(g_dtb_path, &dtb_data)) {
696 die("cannot load '%s': %s", g_dtb_path.c_str(), strerror(errno));
697 }
698 }
699
700 fprintf(stderr, "creating boot image...\n");
701
702 std::vector<char> out;
703 mkbootimg(kernel_data, ramdisk_data, second_stage_data, dtb_data, g_base_addr, g_boot_img_hdr,
704 &out);
705
706 if (!g_cmdline.empty()) {
707 bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v2*>(out.data()), g_cmdline);
708 }
709 fprintf(stderr, "creating boot image - %zu bytes\n", out.size());
710 return out;
711 }
712
UnzipToMemory(ZipArchiveHandle zip,const std::string & entry_name,std::vector<char> * out)713 static bool UnzipToMemory(ZipArchiveHandle zip, const std::string& entry_name,
714 std::vector<char>* out) {
715 ZipEntry64 zip_entry;
716 if (FindEntry(zip, entry_name, &zip_entry) != 0) {
717 fprintf(stderr, "archive does not contain '%s'\n", entry_name.c_str());
718 return false;
719 }
720
721 if (zip_entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
722 die("entry '%s' is too large: %" PRIu64, entry_name.c_str(), zip_entry.uncompressed_length);
723 }
724 out->resize(zip_entry.uncompressed_length);
725
726 fprintf(stderr, "extracting %s (%zu MB) to RAM...\n", entry_name.c_str(),
727 out->size() / 1024 / 1024);
728
729 int error =
730 ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()), out->size());
731 if (error != 0) die("failed to extract '%s': %s", entry_name.c_str(), ErrorCodeString(error));
732
733 return true;
734 }
735
736 #if defined(_WIN32)
737
738 // TODO: move this to somewhere it can be shared.
739
740 #include <windows.h>
741
742 // Windows' tmpfile(3) requires administrator rights because
743 // it creates temporary files in the root directory.
win32_tmpfile()744 static FILE* win32_tmpfile() {
745 char temp_path[PATH_MAX];
746 DWORD nchars = GetTempPath(sizeof(temp_path), temp_path);
747 if (nchars == 0 || nchars >= sizeof(temp_path)) {
748 die("GetTempPath failed, error %ld", GetLastError());
749 }
750
751 char filename[PATH_MAX];
752 if (GetTempFileName(temp_path, "fastboot", 0, filename) == 0) {
753 die("GetTempFileName failed, error %ld", GetLastError());
754 }
755
756 return fopen(filename, "w+bTD");
757 }
758
759 #define tmpfile win32_tmpfile
760
make_temporary_fd(const char *)761 static int make_temporary_fd(const char* /*what*/) {
762 // TODO: reimplement to avoid leaking a FILE*.
763 return fileno(tmpfile());
764 }
765
766 #else
767
make_temporary_template()768 static std::string make_temporary_template() {
769 const char* tmpdir = getenv("TMPDIR");
770 if (tmpdir == nullptr) tmpdir = P_tmpdir;
771 return std::string(tmpdir) + "/fastboot_userdata_XXXXXX";
772 }
773
make_temporary_fd(const char * what)774 static int make_temporary_fd(const char* what) {
775 std::string path_template(make_temporary_template());
776 int fd = mkstemp(&path_template[0]);
777 if (fd == -1) {
778 die("failed to create temporary file for %s with template %s: %s\n", path_template.c_str(),
779 what, strerror(errno));
780 }
781 unlink(path_template.c_str());
782 return fd;
783 }
784
785 #endif
786
UnzipToFile(ZipArchiveHandle zip,const char * entry_name)787 static unique_fd UnzipToFile(ZipArchiveHandle zip, const char* entry_name) {
788 unique_fd fd(make_temporary_fd(entry_name));
789
790 ZipEntry64 zip_entry;
791 if (FindEntry(zip, entry_name, &zip_entry) != 0) {
792 fprintf(stderr, "archive does not contain '%s'\n", entry_name);
793 errno = ENOENT;
794 return unique_fd();
795 }
796
797 fprintf(stderr, "extracting %s (%" PRIu64 " MB) to disk...", entry_name,
798 zip_entry.uncompressed_length / 1024 / 1024);
799 double start = now();
800 int error = ExtractEntryToFile(zip, &zip_entry, fd.get());
801 if (error != 0) {
802 die("\nfailed to extract '%s': %s", entry_name, ErrorCodeString(error));
803 }
804
805 if (lseek(fd.get(), 0, SEEK_SET) != 0) {
806 die("\nlseek on extracted file '%s' failed: %s", entry_name, strerror(errno));
807 }
808
809 fprintf(stderr, " took %.3fs\n", now() - start);
810
811 return fd;
812 }
813
CheckRequirement(const std::string & cur_product,const std::string & var,const std::string & product,bool invert,const std::vector<std::string> & options)814 static bool CheckRequirement(const std::string& cur_product, const std::string& var,
815 const std::string& product, bool invert,
816 const std::vector<std::string>& options) {
817 Status("Checking '" + var + "'");
818
819 double start = now();
820
821 if (!product.empty()) {
822 if (product != cur_product) {
823 double split = now();
824 fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n",
825 cur_product.c_str(), product.c_str(), (split - start));
826 return true;
827 }
828 }
829
830 std::string var_value;
831 if (fb->GetVar(var, &var_value) != fastboot::SUCCESS) {
832 fprintf(stderr, "FAILED\n\n");
833 fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(), fb->Error().c_str());
834 return false;
835 }
836
837 bool match = false;
838 for (const auto& option : options) {
839 if (option == var_value ||
840 (option.back() == '*' &&
841 !var_value.compare(0, option.length() - 1, option, 0, option.length() - 1))) {
842 match = true;
843 break;
844 }
845 }
846
847 if (invert) {
848 match = !match;
849 }
850
851 if (match) {
852 double split = now();
853 fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
854 return true;
855 }
856
857 fprintf(stderr, "FAILED\n\n");
858 fprintf(stderr, "Device %s is '%s'.\n", var.c_str(), var_value.c_str());
859 fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", options[0].c_str());
860 for (auto it = std::next(options.begin()); it != options.end(); ++it) {
861 fprintf(stderr, " or '%s'", it->c_str());
862 }
863 fprintf(stderr, ".\n\n");
864 return false;
865 }
866
ParseRequirementLine(const std::string & line,std::string * name,std::string * product,bool * invert,std::vector<std::string> * options)867 bool ParseRequirementLine(const std::string& line, std::string* name, std::string* product,
868 bool* invert, std::vector<std::string>* options) {
869 // "require product=alpha|beta|gamma"
870 // "require version-bootloader=1234"
871 // "require-for-product:gamma version-bootloader=istanbul|constantinople"
872 // "require partition-exists=vendor"
873 *product = "";
874 *invert = false;
875
876 auto require_reject_regex = std::regex{"(require\\s+|reject\\s+)?\\s*(\\S+)\\s*=\\s*(.*)"};
877 auto require_product_regex =
878 std::regex{"require-for-product:\\s*(\\S+)\\s+(\\S+)\\s*=\\s*(.*)"};
879 std::smatch match_results;
880
881 if (std::regex_match(line, match_results, require_reject_regex)) {
882 *invert = Trim(match_results[1]) == "reject";
883 } else if (std::regex_match(line, match_results, require_product_regex)) {
884 *product = match_results[1];
885 } else {
886 return false;
887 }
888
889 *name = match_results[2];
890 // Work around an unfortunate name mismatch.
891 if (*name == "board") {
892 *name = "product";
893 }
894
895 auto raw_options = Split(match_results[3], "|");
896 for (const auto& option : raw_options) {
897 auto trimmed_option = Trim(option);
898 options->emplace_back(trimmed_option);
899 }
900
901 return true;
902 }
903
904 // "require partition-exists=x" is a special case, added because of the trouble we had when
905 // Pixel 2 shipped with new partitions and users used old versions of fastboot to flash them,
906 // missing out new partitions. A device with new partitions can use "partition-exists" to
907 // override the fields `optional_if_no_image` in the `images` array.
HandlePartitionExists(const std::vector<std::string> & options)908 static void HandlePartitionExists(const std::vector<std::string>& options) {
909 const std::string& partition_name = options[0];
910 std::string has_slot;
911 if (fb->GetVar("has-slot:" + partition_name, &has_slot) != fastboot::SUCCESS ||
912 (has_slot != "yes" && has_slot != "no")) {
913 die("device doesn't have required partition %s!", partition_name.c_str());
914 }
915 bool known_partition = false;
916 for (size_t i = 0; i < images.size(); ++i) {
917 if (!images[i].nickname.empty() && images[i].nickname == partition_name) {
918 images[i].optional_if_no_image = false;
919 known_partition = true;
920 }
921 }
922 if (!known_partition) {
923 die("device requires partition %s which is not known to this version of fastboot",
924 partition_name.c_str());
925 }
926 }
927
CheckRequirements(const std::string & data,bool force_flash)928 static void CheckRequirements(const std::string& data, bool force_flash) {
929 std::string cur_product;
930 if (fb->GetVar("product", &cur_product) != fastboot::SUCCESS) {
931 fprintf(stderr, "getvar:product FAILED (%s)\n", fb->Error().c_str());
932 }
933
934 auto lines = Split(data, "\n");
935 for (const auto& line : lines) {
936 if (line.empty()) {
937 continue;
938 }
939
940 std::string name;
941 std::string product;
942 bool invert;
943 std::vector<std::string> options;
944
945 if (!ParseRequirementLine(line, &name, &product, &invert, &options)) {
946 fprintf(stderr, "android-info.txt syntax error: %s\n", line.c_str());
947 continue;
948 }
949 if (name == "partition-exists") {
950 HandlePartitionExists(options);
951 } else {
952 bool met = CheckRequirement(cur_product, name, product, invert, options);
953 if (!met) {
954 if (!force_flash) {
955 die("requirements not met!");
956 } else {
957 fprintf(stderr, "requirements not met! but proceeding due to --force\n");
958 }
959 }
960 }
961 }
962 }
963
DisplayVarOrError(const std::string & label,const std::string & var)964 static void DisplayVarOrError(const std::string& label, const std::string& var) {
965 std::string value;
966
967 if (fb->GetVar(var, &value) != fastboot::SUCCESS) {
968 Status("getvar:" + var);
969 fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
970 return;
971 }
972 fprintf(stderr, "%s: %s\n", label.c_str(), value.c_str());
973 }
974
DumpInfo()975 static void DumpInfo() {
976 fprintf(stderr, "--------------------------------------------\n");
977 DisplayVarOrError("Bootloader Version...", "version-bootloader");
978 DisplayVarOrError("Baseband Version.....", "version-baseband");
979 DisplayVarOrError("Serial Number........", "serialno");
980 fprintf(stderr, "--------------------------------------------\n");
981 }
982
resparse_file(sparse_file * s,int64_t max_size)983 std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size) {
984 if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) {
985 die("invalid max size %" PRId64, max_size);
986 }
987
988 const int files = sparse_file_resparse(s, max_size, nullptr, 0);
989 if (files < 0) die("Failed to compute resparse boundaries");
990
991 auto temp = std::make_unique<sparse_file*[]>(files);
992 const int rv = sparse_file_resparse(s, max_size, temp.get(), files);
993 if (rv < 0) die("Failed to resparse");
994
995 std::vector<SparsePtr> out_s;
996 for (int i = 0; i < files; i++) {
997 out_s.emplace_back(temp[i], sparse_file_destroy);
998 }
999 return out_s;
1000 }
1001
load_sparse_files(int fd,int64_t max_size)1002 static std::vector<SparsePtr> load_sparse_files(int fd, int64_t max_size) {
1003 SparsePtr s(sparse_file_import_auto(fd, false, true), sparse_file_destroy);
1004 if (!s) die("cannot sparse read file");
1005
1006 return resparse_file(s.get(), max_size);
1007 }
1008
get_uint_var(const char * var_name,fastboot::IFastBootDriver * fb)1009 static uint64_t get_uint_var(const char* var_name, fastboot::IFastBootDriver* fb) {
1010 std::string value_str;
1011 if (fb->GetVar(var_name, &value_str) != fastboot::SUCCESS || value_str.empty()) {
1012 verbose("target didn't report %s", var_name);
1013 return 0;
1014 }
1015
1016 // Some bootloaders (angler, for example) send spurious whitespace too.
1017 value_str = android::base::Trim(value_str);
1018
1019 uint64_t value;
1020 if (!android::base::ParseUint(value_str, &value)) {
1021 fprintf(stderr, "couldn't parse %s '%s'\n", var_name, value_str.c_str());
1022 return 0;
1023 }
1024 if (value > 0) verbose("target reported %s of %" PRId64 " bytes", var_name, value);
1025 return value;
1026 }
1027
get_sparse_limit(int64_t size,const FlashingPlan * fp)1028 int64_t get_sparse_limit(int64_t size, const FlashingPlan* fp) {
1029 if (!fp) return 0;
1030
1031 int64_t limit = int64_t(fp->sparse_limit);
1032 if (limit == 0) {
1033 // Unlimited, so see what the target device's limit is.
1034 // TODO: shouldn't we apply this limit even if you've used -S?
1035 if (target_sparse_limit == -1) {
1036 target_sparse_limit = static_cast<int64_t>(get_uint_var("max-download-size", fp->fb));
1037 }
1038 if (target_sparse_limit > 0) {
1039 limit = target_sparse_limit;
1040 } else {
1041 return 0;
1042 }
1043 }
1044
1045 if (size > limit) {
1046 return std::min(limit, RESPARSE_LIMIT);
1047 }
1048
1049 return 0;
1050 }
1051
load_buf_fd(unique_fd fd,struct fastboot_buffer * buf,const FlashingPlan * fp)1052 static bool load_buf_fd(unique_fd fd, struct fastboot_buffer* buf, const FlashingPlan* fp) {
1053 int64_t sz = get_file_size(fd);
1054 if (sz == -1) {
1055 return false;
1056 }
1057
1058 if (sparse_file* s = sparse_file_import(fd.get(), false, false)) {
1059 buf->image_size = sparse_file_len(s, false, false);
1060 if (buf->image_size < 0) {
1061 LOG(ERROR) << "Could not compute length of sparse file";
1062 return false;
1063 }
1064 sparse_file_destroy(s);
1065 buf->file_type = FB_BUFFER_SPARSE;
1066 } else {
1067 buf->image_size = sz;
1068 buf->file_type = FB_BUFFER_FD;
1069 }
1070
1071 lseek(fd.get(), 0, SEEK_SET);
1072 int64_t limit = get_sparse_limit(sz, fp);
1073 buf->fd = std::move(fd);
1074 if (limit) {
1075 buf->files = load_sparse_files(buf->fd.get(), limit);
1076 if (buf->files.empty()) {
1077 return false;
1078 }
1079 buf->type = FB_BUFFER_SPARSE;
1080 } else {
1081 buf->type = FB_BUFFER_FD;
1082 buf->sz = sz;
1083 }
1084
1085 return true;
1086 }
1087
load_buf(const char * fname,struct fastboot_buffer * buf,const FlashingPlan * fp)1088 static bool load_buf(const char* fname, struct fastboot_buffer* buf, const FlashingPlan* fp) {
1089 unique_fd fd(TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_BINARY)));
1090
1091 if (fd == -1) {
1092 return false;
1093 }
1094
1095 struct stat s;
1096 if (fstat(fd.get(), &s)) {
1097 return false;
1098 }
1099 if (!S_ISREG(s.st_mode)) {
1100 errno = S_ISDIR(s.st_mode) ? EISDIR : EINVAL;
1101 return false;
1102 }
1103
1104 return load_buf_fd(std::move(fd), buf, fp);
1105 }
1106
rewrite_vbmeta_buffer(struct fastboot_buffer * buf,bool vbmeta_in_boot)1107 static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf, bool vbmeta_in_boot) {
1108 // Buffer needs to be at least the size of the VBMeta struct which
1109 // is 256 bytes.
1110 if (buf->sz < 256) {
1111 return;
1112 }
1113
1114 std::string data;
1115 if (!android::base::ReadFdToString(buf->fd, &data)) {
1116 die("Failed reading from vbmeta");
1117 }
1118
1119 uint64_t vbmeta_offset = 0;
1120 if (vbmeta_in_boot) {
1121 // Tries to locate top-level vbmeta from boot.img footer.
1122 uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
1123 if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
1124 die("Failed to find AVB_FOOTER at offset: %" PRId64 ", is BOARD_AVB_ENABLE true?",
1125 footer_offset);
1126 }
1127 const AvbFooter* footer = reinterpret_cast<const AvbFooter*>(data.c_str() + footer_offset);
1128 vbmeta_offset = be64toh(footer->vbmeta_offset);
1129 }
1130 // Ensures there is AVB_MAGIC at vbmeta_offset.
1131 if (0 != data.compare(vbmeta_offset, AVB_MAGIC_LEN, AVB_MAGIC)) {
1132 die("Failed to find AVB_MAGIC at offset: %" PRId64, vbmeta_offset);
1133 }
1134
1135 fprintf(stderr, "Rewriting vbmeta struct at offset: %" PRId64 "\n", vbmeta_offset);
1136
1137 // There's a 32-bit big endian |flags| field at offset 120 where
1138 // bit 0 corresponds to disable-verity and bit 1 corresponds to
1139 // disable-verification.
1140 //
1141 // See external/avb/libavb/avb_vbmeta_image.h for the layout of
1142 // the VBMeta struct.
1143 uint64_t flags_offset = 123 + vbmeta_offset;
1144 if (g_disable_verity) {
1145 data[flags_offset] |= 0x01;
1146 }
1147 if (g_disable_verification) {
1148 data[flags_offset] |= 0x02;
1149 }
1150
1151 unique_fd fd(make_temporary_fd("vbmeta rewriting"));
1152 if (!android::base::WriteStringToFd(data, fd)) {
1153 die("Failed writing to modified vbmeta");
1154 }
1155 buf->fd = std::move(fd);
1156 lseek(buf->fd.get(), 0, SEEK_SET);
1157 }
1158
has_vbmeta_partition()1159 static bool has_vbmeta_partition() {
1160 std::string partition_type;
1161 return fb->GetVar("partition-type:vbmeta", &partition_type) == fastboot::SUCCESS ||
1162 fb->GetVar("partition-type:vbmeta_a", &partition_type) == fastboot::SUCCESS ||
1163 fb->GetVar("partition-type:vbmeta_b", &partition_type) == fastboot::SUCCESS;
1164 }
1165
is_vbmeta_partition(const std::string & partition)1166 static bool is_vbmeta_partition(const std::string& partition) {
1167 return android::base::EndsWith(partition, "vbmeta") ||
1168 android::base::EndsWith(partition, "vbmeta_a") ||
1169 android::base::EndsWith(partition, "vbmeta_b");
1170 }
1171
1172 // Note: this only works in userspace fastboot. In the bootloader, use
1173 // should_flash_in_userspace().
is_logical(const std::string & partition)1174 bool is_logical(const std::string& partition) {
1175 std::string value;
1176 return fb->GetVar("is-logical:" + partition, &value) == fastboot::SUCCESS && value == "yes";
1177 }
1178
get_partition_size(const std::string & partition)1179 static uint64_t get_partition_size(const std::string& partition) {
1180 std::string partition_size_str;
1181 if (fb->GetVar("partition-size:" + partition, &partition_size_str) != fastboot::SUCCESS) {
1182 if (!is_logical(partition)) {
1183 return 0;
1184 }
1185 die("cannot get partition size for %s", partition.c_str());
1186 }
1187
1188 partition_size_str = fb_fix_numeric_var(partition_size_str);
1189 uint64_t partition_size;
1190 if (!android::base::ParseUint(partition_size_str, &partition_size)) {
1191 if (!is_logical(partition)) {
1192 return 0;
1193 }
1194 die("Couldn't parse partition size '%s'.", partition_size_str.c_str());
1195 }
1196 return partition_size;
1197 }
1198
copy_avb_footer(const ImageSource * source,const std::string & partition,struct fastboot_buffer * buf)1199 static void copy_avb_footer(const ImageSource* source, const std::string& partition,
1200 struct fastboot_buffer* buf) {
1201 if (buf->sz < AVB_FOOTER_SIZE || is_logical(partition) ||
1202 should_flash_in_userspace(source, partition)) {
1203 return;
1204 }
1205
1206 // If the image is sparse, moving the footer will simply corrupt the sparse
1207 // format, so currently we don't support moving the footer on sparse files.
1208 if (buf->file_type == FB_BUFFER_SPARSE) {
1209 LOG(ERROR) << "Warning: skip copying " << partition << " image avb footer due to sparse "
1210 << "image.";
1211 return;
1212 }
1213
1214 // If overflows and negative, it should be < buf->sz.
1215 int64_t partition_size = static_cast<int64_t>(get_partition_size(partition));
1216
1217 if (partition_size == buf->sz) {
1218 return;
1219 }
1220 // Some device bootloaders might not implement `fastboot getvar partition-size:boot[_a|_b]`.
1221 // In this case, partition_size will be zero.
1222 if (partition_size < buf->sz) {
1223 fprintf(stderr,
1224 "Warning: skip copying %s image avb footer"
1225 " (%s partition size: %" PRId64 ", %s image size: %" PRId64 ").\n",
1226 partition.c_str(), partition.c_str(), partition_size, partition.c_str(), buf->sz);
1227 return;
1228 }
1229
1230 // IMPORTANT: after the following read, we need to reset buf->fd before return (if not die).
1231 // Because buf->fd will still be used afterwards.
1232 std::string data;
1233 if (!android::base::ReadFdToString(buf->fd, &data)) {
1234 die("Failed reading from %s", partition.c_str());
1235 }
1236
1237 uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
1238 if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
1239 lseek(buf->fd.get(), 0, SEEK_SET); // IMPORTANT: resets buf->fd before return.
1240 return;
1241 }
1242
1243 const std::string tmp_fd_template = partition + " rewriting";
1244 unique_fd fd(make_temporary_fd(tmp_fd_template.c_str()));
1245 if (!android::base::WriteStringToFd(data, fd)) {
1246 die("Failed writing to modified %s", partition.c_str());
1247 }
1248 lseek(fd.get(), partition_size - AVB_FOOTER_SIZE, SEEK_SET);
1249 if (!android::base::WriteStringToFd(data.substr(footer_offset), fd)) {
1250 die("Failed copying AVB footer in %s", partition.c_str());
1251 }
1252 buf->fd = std::move(fd);
1253 buf->sz = partition_size;
1254 lseek(buf->fd.get(), 0, SEEK_SET);
1255 }
1256
flash_partition_files(const std::string & partition,const std::vector<SparsePtr> & files)1257 void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files) {
1258 for (size_t i = 0; i < files.size(); i++) {
1259 sparse_file* s = files[i].get();
1260 int64_t sz = sparse_file_len(s, true, false);
1261 if (sz < 0) {
1262 LOG(FATAL) << "Could not compute length of sparse image for " << partition;
1263 }
1264 fb->FlashPartition(partition, s, sz, i + 1, files.size());
1265 }
1266 }
1267
flash_buf(const ImageSource * source,const std::string & partition,struct fastboot_buffer * buf,const bool apply_vbmeta)1268 static void flash_buf(const ImageSource* source, const std::string& partition,
1269 struct fastboot_buffer* buf, const bool apply_vbmeta) {
1270 copy_avb_footer(source, partition, buf);
1271
1272 // Rewrite vbmeta if that's what we're flashing and modification has been requested.
1273 if (g_disable_verity || g_disable_verification) {
1274 // The vbmeta partition might have additional prefix if running in virtual machine
1275 // e.g., guest_vbmeta_a.
1276 if (apply_vbmeta) {
1277 rewrite_vbmeta_buffer(buf, false /* vbmeta_in_boot */);
1278 } else if (!has_vbmeta_partition() &&
1279 (partition == "boot" || partition == "boot_a" || partition == "boot_b")) {
1280 rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */);
1281 }
1282 }
1283
1284 switch (buf->type) {
1285 case FB_BUFFER_SPARSE: {
1286 flash_partition_files(partition, buf->files);
1287 break;
1288 }
1289 case FB_BUFFER_FD:
1290 fb->FlashPartition(partition, buf->fd, buf->sz);
1291 break;
1292 default:
1293 die("unknown buffer type: %d", buf->type);
1294 }
1295 }
1296
get_current_slot()1297 std::string get_current_slot() {
1298 std::string current_slot;
1299 if (fb->GetVar("current-slot", ¤t_slot) != fastboot::SUCCESS) return "";
1300 if (current_slot[0] == '_') current_slot.erase(0, 1);
1301 return current_slot;
1302 }
1303
get_slot_count(fastboot::IFastBootDriver * fb)1304 static int get_slot_count(fastboot::IFastBootDriver* fb) {
1305 std::string var;
1306 int count = 0;
1307 if (fb->GetVar("slot-count", &var) != fastboot::SUCCESS ||
1308 !android::base::ParseInt(var, &count)) {
1309 return 0;
1310 }
1311 return count;
1312 }
1313
supports_AB(fastboot::IFastBootDriver * fb)1314 bool supports_AB(fastboot::IFastBootDriver* fb) {
1315 return get_slot_count(fb) >= 2;
1316 }
1317
1318 // Given a current slot, this returns what the 'other' slot is.
get_other_slot(const std::string & current_slot,int count)1319 static std::string get_other_slot(const std::string& current_slot, int count) {
1320 if (count == 0) return "";
1321
1322 char next = (current_slot[0] - 'a' + 1) % count + 'a';
1323 return std::string(1, next);
1324 }
1325
get_other_slot(const std::string & current_slot)1326 static std::string get_other_slot(const std::string& current_slot) {
1327 return get_other_slot(current_slot, get_slot_count(fb));
1328 }
1329
get_other_slot(int count)1330 static std::string get_other_slot(int count) {
1331 return get_other_slot(get_current_slot(), count);
1332 }
1333
get_other_slot()1334 static std::string get_other_slot() {
1335 return get_other_slot(get_current_slot(), get_slot_count(fb));
1336 }
1337
verify_slot(const std::string & slot_name,bool allow_all)1338 static std::string verify_slot(const std::string& slot_name, bool allow_all) {
1339 std::string slot = slot_name;
1340 if (slot == "all") {
1341 if (allow_all) {
1342 return "all";
1343 } else {
1344 int count = get_slot_count(fb);
1345 if (count > 0) {
1346 return "a";
1347 } else {
1348 die("No known slots");
1349 }
1350 }
1351 }
1352
1353 int count = get_slot_count(fb);
1354 if (count == 0) die("Device does not support slots");
1355
1356 if (slot == "other") {
1357 std::string other = get_other_slot(count);
1358 if (other == "") {
1359 die("No known slots");
1360 }
1361 return other;
1362 }
1363
1364 if (slot.size() == 1 && (slot[0] - 'a' >= 0 && slot[0] - 'a' < count)) return slot;
1365
1366 fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot.c_str());
1367 for (int i = 0; i < count; i++) {
1368 fprintf(stderr, "%c\n", (char)(i + 'a'));
1369 }
1370
1371 exit(1);
1372 }
1373
verify_slot(const std::string & slot)1374 static std::string verify_slot(const std::string& slot) {
1375 return verify_slot(slot, true);
1376 }
1377
do_for_partition(const std::string & part,const std::string & slot,const std::function<void (const std::string &)> & func,bool force_slot)1378 static void do_for_partition(const std::string& part, const std::string& slot,
1379 const std::function<void(const std::string&)>& func, bool force_slot) {
1380 std::string has_slot;
1381 std::string current_slot;
1382 // |part| can be vendor_boot:default. Append slot to the first token.
1383 auto part_tokens = android::base::Split(part, ":");
1384
1385 if (fb->GetVar("has-slot:" + part_tokens[0], &has_slot) != fastboot::SUCCESS) {
1386 /* If has-slot is not supported, the answer is no. */
1387 has_slot = "no";
1388 }
1389 if (has_slot == "yes") {
1390 if (slot == "") {
1391 current_slot = get_current_slot();
1392 if (current_slot == "") {
1393 die("Failed to identify current slot");
1394 }
1395 part_tokens[0] += "_" + current_slot;
1396 } else {
1397 part_tokens[0] += "_" + slot;
1398 }
1399 func(android::base::Join(part_tokens, ":"));
1400 } else {
1401 if (force_slot && slot != "") {
1402 fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n",
1403 part_tokens[0].c_str(), slot.c_str());
1404 }
1405 func(part);
1406 }
1407 }
1408
1409 /* This function will find the real partition name given a base name, and a slot. If slot is NULL or
1410 * empty, it will use the current slot. If slot is "all", it will return a list of all possible
1411 * partition names. If force_slot is true, it will fail if a slot is specified, and the given
1412 * partition does not support slots.
1413 */
do_for_partitions(const std::string & part,const std::string & slot,const std::function<void (const std::string &)> & func,bool force_slot)1414 void do_for_partitions(const std::string& part, const std::string& slot,
1415 const std::function<void(const std::string&)>& func, bool force_slot) {
1416 std::string has_slot;
1417 // |part| can be vendor_boot:default. Query has-slot on the first token only.
1418 auto part_tokens = android::base::Split(part, ":");
1419
1420 if (slot == "all") {
1421 if (fb->GetVar("has-slot:" + part_tokens[0], &has_slot) != fastboot::SUCCESS) {
1422 die("Could not check if partition %s has slot %s", part_tokens[0].c_str(),
1423 slot.c_str());
1424 }
1425 if (has_slot == "yes") {
1426 for (int i = 0; i < get_slot_count(fb); i++) {
1427 do_for_partition(part, std::string(1, (char)(i + 'a')), func, force_slot);
1428 }
1429 } else {
1430 do_for_partition(part, "", func, force_slot);
1431 }
1432 } else {
1433 do_for_partition(part, slot, func, force_slot);
1434 }
1435 }
1436
1437 // Fetch a partition from the device to a given fd. This is a wrapper over FetchToFd to fetch
1438 // the full image.
fetch_partition(const std::string & partition,borrowed_fd fd,fastboot::IFastBootDriver * fb)1439 static uint64_t fetch_partition(const std::string& partition, borrowed_fd fd,
1440 fastboot::IFastBootDriver* fb) {
1441 uint64_t fetch_size = get_uint_var(FB_VAR_MAX_FETCH_SIZE, fb);
1442 if (fetch_size == 0) {
1443 die("Unable to get %s. Device does not support fetch command.", FB_VAR_MAX_FETCH_SIZE);
1444 }
1445 uint64_t partition_size = get_partition_size(partition);
1446 if (partition_size <= 0) {
1447 die("Invalid partition size for partition %s: %" PRId64, partition.c_str(), partition_size);
1448 }
1449
1450 uint64_t offset = 0;
1451 while (offset < partition_size) {
1452 uint64_t chunk_size = std::min(fetch_size, partition_size - offset);
1453 if (fb->FetchToFd(partition, fd, offset, chunk_size) != fastboot::RetCode::SUCCESS) {
1454 die("Unable to fetch %s (offset=%" PRIx64 ", size=%" PRIx64 ")", partition.c_str(),
1455 offset, chunk_size);
1456 }
1457 offset += chunk_size;
1458 }
1459 return partition_size;
1460 }
1461
do_fetch(const std::string & partition,const std::string & slot_override,const std::string & outfile,fastboot::IFastBootDriver * fb)1462 static void do_fetch(const std::string& partition, const std::string& slot_override,
1463 const std::string& outfile, fastboot::IFastBootDriver* fb) {
1464 unique_fd fd(TEMP_FAILURE_RETRY(
1465 open(outfile.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY, 0644)));
1466 auto fetch = std::bind(fetch_partition, _1, borrowed_fd(fd), fb);
1467 do_for_partitions(partition, slot_override, fetch, false /* force slot */);
1468 }
1469
1470 // Return immediately if not flashing a vendor boot image. If flashing a vendor boot image,
1471 // repack vendor_boot image with an updated ramdisk. After execution, buf is set
1472 // to the new image to flash, and return value is the real partition name to flash.
repack_ramdisk(const char * pname,struct fastboot_buffer * buf,fastboot::IFastBootDriver * fb)1473 static std::string repack_ramdisk(const char* pname, struct fastboot_buffer* buf,
1474 fastboot::IFastBootDriver* fb) {
1475 std::string_view pname_sv{pname};
1476 struct fastboot_buffer dtb_buf = {.sz = 0, .fd = unique_fd(-1)};
1477
1478 if (!android::base::StartsWith(pname_sv, "vendor_boot:") &&
1479 !android::base::StartsWith(pname_sv, "vendor_boot_a:") &&
1480 !android::base::StartsWith(pname_sv, "vendor_boot_b:")) {
1481 return std::string(pname_sv);
1482 }
1483 if (buf->type != FB_BUFFER_FD) {
1484 die("Flashing sparse vendor ramdisk image is not supported.");
1485 }
1486 if (buf->sz <= 0) {
1487 die("repack_ramdisk() sees negative size: %" PRId64, buf->sz);
1488 }
1489 std::string partition(pname_sv.substr(0, pname_sv.find(':')));
1490 std::string ramdisk(pname_sv.substr(pname_sv.find(':') + 1));
1491
1492 if (!g_dtb_path.empty()) {
1493 if (!load_buf(g_dtb_path.c_str(), &dtb_buf, nullptr)) {
1494 die("cannot load '%s': %s", g_dtb_path.c_str(), strerror(errno));
1495 }
1496
1497 if (dtb_buf.type != FB_BUFFER_FD) {
1498 die("Flashing sparse vendor ramdisk image with dtb is not supported.");
1499 }
1500 if (dtb_buf.sz <= 0) {
1501 die("repack_ramdisk() sees invalid dtb size: %" PRId64, buf->sz);
1502 }
1503 verbose("Updating DTB with %s", pname_sv.data());
1504 }
1505
1506 unique_fd vendor_boot(make_temporary_fd("vendor boot repack"));
1507 uint64_t vendor_boot_size = fetch_partition(partition, vendor_boot, fb);
1508 auto repack_res = replace_vendor_ramdisk(vendor_boot, vendor_boot_size, ramdisk, buf->fd,
1509 static_cast<uint64_t>(buf->sz), dtb_buf.fd,
1510 static_cast<uint64_t>(dtb_buf.sz));
1511 if (!repack_res.ok()) {
1512 die("%s", repack_res.error().message().c_str());
1513 }
1514
1515 buf->fd = std::move(vendor_boot);
1516 buf->sz = vendor_boot_size;
1517 buf->image_size = vendor_boot_size;
1518 return partition;
1519 }
1520
do_flash(const char * pname,const char * fname,const bool apply_vbmeta,const FlashingPlan * fp)1521 void do_flash(const char* pname, const char* fname, const bool apply_vbmeta,
1522 const FlashingPlan* fp) {
1523 if (!fp) {
1524 die("do flash was called without a valid flashing plan");
1525 }
1526 verbose("Do flash %s %s", pname, fname);
1527 struct fastboot_buffer buf;
1528
1529 if (fp->source) {
1530 unique_fd fd = fp->source->OpenFile(fname);
1531 if (fd < 0 || !load_buf_fd(std::move(fd), &buf, fp)) {
1532 die("could not load '%s': %s", fname, strerror(errno));
1533 }
1534 std::vector<char> signature_data;
1535 std::string file_string(fname);
1536 if (fp->source->ReadFile(file_string.substr(0, file_string.find('.')) + ".sig",
1537 &signature_data)) {
1538 fb->Download("signature", signature_data);
1539 fb->RawCommand("signature", "installing signature");
1540 }
1541 } else if (!load_buf(fname, &buf, fp)) {
1542 die("cannot load '%s': %s", fname, strerror(errno));
1543 }
1544
1545 if (is_logical(pname)) {
1546 fb->ResizePartition(pname, std::to_string(buf.image_size));
1547 }
1548 std::string flash_pname = repack_ramdisk(pname, &buf, fp->fb);
1549 flash_buf(fp->source.get(), flash_pname, &buf, apply_vbmeta);
1550 }
1551
1552 // Sets slot_override as the active slot. If slot_override is blank,
1553 // set current slot as active instead. This clears slot-unbootable.
set_active(const std::string & slot_override)1554 static void set_active(const std::string& slot_override) {
1555 if (!supports_AB(fb)) return;
1556
1557 if (slot_override != "") {
1558 fb->SetActive(slot_override);
1559 } else {
1560 std::string current_slot = get_current_slot();
1561 if (current_slot != "") {
1562 fb->SetActive(current_slot);
1563 }
1564 }
1565 }
1566
is_userspace_fastboot()1567 bool is_userspace_fastboot() {
1568 std::string value;
1569 return fb->GetVar("is-userspace", &value) == fastboot::SUCCESS && value == "yes";
1570 }
1571
reboot_to_userspace_fastboot()1572 void reboot_to_userspace_fastboot() {
1573 fb->RebootTo("fastboot");
1574 if (fb->WaitForDisconnect() != fastboot::SUCCESS) {
1575 die("Error waiting for USB disconnect.");
1576 }
1577 fb->set_transport(nullptr);
1578
1579 // Not all platforms support WaitForDisconnect. There also isn't a great way to tell whether
1580 // or not WaitForDisconnect is supported. So, just wait a bit extra for everyone, in order to
1581 // make sure that the device has had time to initiate its reboot and disconnect itself.
1582 std::this_thread::sleep_for(std::chrono::seconds(1));
1583
1584 fb->set_transport(open_device());
1585
1586 if (!is_userspace_fastboot()) {
1587 die("Failed to boot into userspace fastboot; one or more components might be unbootable.");
1588 }
1589
1590 // Reset target_sparse_limit after reboot to userspace fastboot. Max
1591 // download sizes may differ in bootloader and fastbootd.
1592 target_sparse_limit = -1;
1593 }
1594
CancelSnapshotIfNeeded()1595 static void CancelSnapshotIfNeeded() {
1596 std::string merge_status = "none";
1597 if (fb->GetVar(FB_VAR_SNAPSHOT_UPDATE_STATUS, &merge_status) == fastboot::SUCCESS &&
1598 !merge_status.empty() && merge_status != "none") {
1599 fb->SnapshotUpdateCommand("cancel");
1600 }
1601 }
1602
GetPartitionName(const ImageEntry & entry,const std::string & current_slot)1603 std::string GetPartitionName(const ImageEntry& entry, const std::string& current_slot) {
1604 auto slot = entry.second;
1605 if (slot.empty()) {
1606 slot = current_slot;
1607 }
1608 if (slot.empty()) {
1609 return entry.first->part_name;
1610 }
1611 if (slot == "all") {
1612 LOG(FATAL) << "Cannot retrieve a singular name when using all slots";
1613 }
1614 return entry.first->part_name + "_" + slot;
1615 }
1616
ParseFlashCommand(const FlashingPlan * fp,const std::vector<std::string> & parts)1617 std::unique_ptr<FlashTask> ParseFlashCommand(const FlashingPlan* fp,
1618 const std::vector<std::string>& parts) {
1619 bool apply_vbmeta = false;
1620 std::string slot = fp->slot_override;
1621 std::string partition;
1622 std::string img_name;
1623 for (auto& part : parts) {
1624 if (part == "--apply-vbmeta") {
1625 apply_vbmeta = true;
1626 } else if (part == "--slot-other") {
1627 slot = fp->secondary_slot;
1628 } else if (partition.empty()) {
1629 partition = part;
1630 } else if (img_name.empty()) {
1631 img_name = part;
1632 } else {
1633 LOG(ERROR) << "unknown argument" << part
1634 << " in fastboot-info.txt. parts: " << android::base::Join(parts, " ");
1635 return nullptr;
1636 }
1637 }
1638 if (partition.empty()) {
1639 LOG(ERROR) << "partition name not found when parsing fastboot-info.txt. parts: "
1640 << android::base::Join(parts, " ");
1641 return nullptr;
1642 }
1643 if (img_name.empty()) {
1644 img_name = partition + ".img";
1645 }
1646 return std::make_unique<FlashTask>(slot, partition, img_name, apply_vbmeta, fp);
1647 }
1648
ParseRebootCommand(const FlashingPlan * fp,const std::vector<std::string> & parts)1649 std::unique_ptr<RebootTask> ParseRebootCommand(const FlashingPlan* fp,
1650 const std::vector<std::string>& parts) {
1651 if (parts.empty()) return std::make_unique<RebootTask>(fp);
1652 if (parts.size() > 1) {
1653 LOG(ERROR) << "unknown arguments in reboot {target} in fastboot-info.txt: "
1654 << android::base::Join(parts, " ");
1655 return nullptr;
1656 }
1657 return std::make_unique<RebootTask>(fp, parts[0]);
1658 }
1659
ParseWipeCommand(const FlashingPlan * fp,const std::vector<std::string> & parts)1660 std::unique_ptr<WipeTask> ParseWipeCommand(const FlashingPlan* fp,
1661 const std::vector<std::string>& parts) {
1662 if (parts.size() != 1) {
1663 LOG(ERROR) << "unknown arguments in erase {partition} in fastboot-info.txt: "
1664 << android::base::Join(parts, " ");
1665 return nullptr;
1666 }
1667 return std::make_unique<WipeTask>(fp, parts[0]);
1668 }
1669
ParseFastbootInfoLine(const FlashingPlan * fp,const std::vector<std::string> & command)1670 std::unique_ptr<Task> ParseFastbootInfoLine(const FlashingPlan* fp,
1671 const std::vector<std::string>& command) {
1672 if (command.size() == 0) {
1673 return nullptr;
1674 }
1675 std::unique_ptr<Task> task;
1676
1677 if (command[0] == "flash") {
1678 task = ParseFlashCommand(fp, std::vector<std::string>{command.begin() + 1, command.end()});
1679 } else if (command[0] == "reboot") {
1680 task = ParseRebootCommand(fp, std::vector<std::string>{command.begin() + 1, command.end()});
1681 } else if (command[0] == "update-super" && command.size() == 1) {
1682 task = std::make_unique<UpdateSuperTask>(fp);
1683 } else if (command[0] == "erase" && command.size() == 2) {
1684 task = ParseWipeCommand(fp, std::vector<std::string>{command.begin() + 1, command.end()});
1685 }
1686 if (!task) {
1687 LOG(ERROR) << "unknown command parsing fastboot-info.txt line: "
1688 << android::base::Join(command, " ");
1689 }
1690 return task;
1691 }
1692
AddResizeTasks(const FlashingPlan * fp,std::vector<std::unique_ptr<Task>> * tasks)1693 bool AddResizeTasks(const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>* tasks) {
1694 // expands "resize-partitions" into individual commands : resize {os_partition_1}, resize
1695 // {os_partition_2}, etc.
1696 std::vector<std::unique_ptr<Task>> resize_tasks;
1697 std::optional<size_t> loc;
1698 std::vector<char> contents;
1699 if (!fp->source->ReadFile("super_empty.img", &contents)) {
1700 return false;
1701 }
1702 auto metadata = android::fs_mgr::ReadFromImageBlob(contents.data(), contents.size());
1703 if (!metadata) {
1704 return false;
1705 }
1706 for (size_t i = 0; i < tasks->size(); i++) {
1707 if (auto flash_task = tasks->at(i)->AsFlashTask()) {
1708 if (FlashTask::IsDynamicPartition(fp->source.get(), flash_task)) {
1709 if (!loc) {
1710 loc = i;
1711 }
1712 resize_tasks.emplace_back(std::make_unique<ResizeTask>(
1713 fp, flash_task->GetPartition(), "0", fp->slot_override));
1714 }
1715 }
1716 }
1717 // if no logical partitions (although should never happen since system will always need to be
1718 // flashed)
1719 if (!loc) {
1720 return false;
1721 }
1722 tasks->insert(tasks->begin() + loc.value(), std::make_move_iterator(resize_tasks.begin()),
1723 std::make_move_iterator(resize_tasks.end()));
1724 return true;
1725 }
1726
IsIgnore(const std::vector<std::string> & command)1727 static bool IsIgnore(const std::vector<std::string>& command) {
1728 if (command.size() == 0 || command[0][0] == '#') {
1729 return true;
1730 }
1731 return false;
1732 }
1733
CheckFastbootInfoRequirements(const std::vector<std::string> & command,uint32_t host_tool_version)1734 bool CheckFastbootInfoRequirements(const std::vector<std::string>& command,
1735 uint32_t host_tool_version) {
1736 if (command.size() != 2) {
1737 LOG(ERROR) << "unknown characters in version info in fastboot-info.txt -> "
1738 << android::base::Join(command, " ");
1739 return false;
1740 }
1741 if (command[0] != "version") {
1742 LOG(ERROR) << "unknown characters in version info in fastboot-info.txt -> "
1743 << android::base::Join(command, " ");
1744 return false;
1745 }
1746
1747 uint32_t fastboot_info_version;
1748 if (!android::base::ParseUint(command[1], &fastboot_info_version)) {
1749 LOG(ERROR) << "version number contains non-numeric characters in fastboot-info.txt -> "
1750 << android::base::Join(command, " ");
1751 return false;
1752 }
1753
1754 LOG(VERBOSE) << "Checking 'fastboot-info.txt version'";
1755 if (fastboot_info_version <= host_tool_version) {
1756 return true;
1757 }
1758
1759 LOG(ERROR) << "fasboot-info.txt version: " << command[1]
1760 << " not compatible with host tool version --> " << host_tool_version;
1761 return false;
1762 }
1763
ParseFastbootInfo(const FlashingPlan * fp,const std::vector<std::string> & file)1764 std::vector<std::unique_ptr<Task>> ParseFastbootInfo(const FlashingPlan* fp,
1765 const std::vector<std::string>& file) {
1766 std::vector<std::unique_ptr<Task>> tasks;
1767 // Get os_partitions that need to be resized
1768 for (auto& text : file) {
1769 std::vector<std::string> command = android::base::Tokenize(text, " ");
1770 if (IsIgnore(command)) {
1771 continue;
1772 }
1773 if (command.size() > 1 && command[0] == "version") {
1774 if (!CheckFastbootInfoRequirements(command, FASTBOOT_INFO_VERSION)) {
1775 return {};
1776 }
1777 continue;
1778 } else if (command.size() >= 2 && command[0] == "if-wipe") {
1779 if (!fp->wants_wipe) {
1780 continue;
1781 }
1782 command.erase(command.begin());
1783 }
1784 auto task = ParseFastbootInfoLine(fp, command);
1785 if (!task) {
1786 return {};
1787 }
1788 tasks.emplace_back(std::move(task));
1789 }
1790
1791 if (auto flash_super_task = OptimizedFlashSuperTask::Initialize(fp, tasks)) {
1792 tasks.emplace_back(std::move(flash_super_task));
1793 } else {
1794 if (!AddResizeTasks(fp, &tasks)) {
1795 LOG(WARNING) << "Failed to add resize tasks";
1796 }
1797 }
1798
1799 return tasks;
1800 }
1801
FlashAllTool(FlashingPlan * fp)1802 FlashAllTool::FlashAllTool(FlashingPlan* fp) : fp_(fp) {}
1803
Flash()1804 void FlashAllTool::Flash() {
1805 DumpInfo();
1806 CheckRequirements();
1807
1808 // Change the slot first, so we boot into the correct recovery image when
1809 // using fastbootd.
1810 if (fp_->slot_override == "all") {
1811 set_active("a");
1812 } else {
1813 set_active(fp_->slot_override);
1814 }
1815
1816 DetermineSlot();
1817
1818 CancelSnapshotIfNeeded();
1819
1820 tasks_ = CollectTasks();
1821
1822 for (auto& task : tasks_) {
1823 task->Run();
1824 }
1825 return;
1826 }
1827
CollectTasks()1828 std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasks() {
1829 std::vector<std::unique_ptr<Task>> tasks;
1830 if (fp_->should_use_fastboot_info) {
1831 tasks = CollectTasksFromFastbootInfo();
1832
1833 } else {
1834 tasks = CollectTasksFromImageList();
1835 }
1836 if (fp_->exclude_dynamic_partitions) {
1837 auto is_non_static_flash_task = [&](const auto& task) -> bool {
1838 if (auto flash_task = task->AsFlashTask()) {
1839 if (!should_flash_in_userspace(fp_->source.get(),
1840 flash_task->GetPartitionAndSlot())) {
1841 return false;
1842 }
1843 }
1844 return true;
1845 };
1846 tasks.erase(std::remove_if(tasks.begin(), tasks.end(), is_non_static_flash_task),
1847 tasks.end());
1848 }
1849 return tasks;
1850 }
1851
CheckRequirements()1852 void FlashAllTool::CheckRequirements() {
1853 std::vector<char> contents;
1854 if (!fp_->source->ReadFile("android-info.txt", &contents)) {
1855 die("could not read android-info.txt");
1856 }
1857 ::CheckRequirements({contents.data(), contents.size()}, fp_->force_flash);
1858 }
1859
DetermineSlot()1860 void FlashAllTool::DetermineSlot() {
1861 if (fp_->slot_override.empty()) {
1862 fp_->current_slot = get_current_slot();
1863 } else {
1864 fp_->current_slot = fp_->slot_override;
1865 }
1866
1867 if (fp_->skip_secondary) {
1868 return;
1869 }
1870 if (fp_->slot_override != "" && fp_->slot_override != "all") {
1871 fp_->secondary_slot = get_other_slot(fp_->slot_override);
1872 } else {
1873 fp_->secondary_slot = get_other_slot();
1874 }
1875 if (fp_->secondary_slot == "") {
1876 if (supports_AB(fb)) {
1877 fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
1878 }
1879 fp_->skip_secondary = true;
1880 }
1881 }
1882
CollectImages()1883 void FlashAllTool::CollectImages() {
1884 for (size_t i = 0; i < images.size(); ++i) {
1885 std::string slot = fp_->slot_override;
1886 if (images[i].IsSecondary()) {
1887 if (fp_->skip_secondary) {
1888 continue;
1889 }
1890 slot = fp_->secondary_slot;
1891 }
1892 if (images[i].type == ImageType::BootCritical) {
1893 boot_images_.emplace_back(&images[i], slot);
1894 } else if (images[i].type == ImageType::Normal) {
1895 os_images_.emplace_back(&images[i], slot);
1896 }
1897 }
1898 }
1899
CollectTasksFromImageList()1900 std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasksFromImageList() {
1901 CollectImages();
1902 // First flash boot partitions. We allow this to happen either in userspace
1903 // or in bootloader fastboot.
1904 std::vector<std::unique_ptr<Task>> tasks;
1905 AddFlashTasks(boot_images_, tasks);
1906
1907 // Sync the super partition. This will reboot to userspace fastboot if needed.
1908 tasks.emplace_back(std::make_unique<UpdateSuperTask>(fp_));
1909
1910 AddFlashTasks(os_images_, tasks);
1911
1912 if (auto flash_super_task = OptimizedFlashSuperTask::Initialize(fp_, tasks)) {
1913 tasks.emplace_back(std::move(flash_super_task));
1914 } else {
1915 // Resize any logical partition to 0, so each partition is reset to 0
1916 // extents, and will achieve more optimal allocation.
1917 if (!AddResizeTasks(fp_, &tasks)) {
1918 LOG(WARNING) << "Failed to add resize tasks";
1919 }
1920 }
1921
1922 return tasks;
1923 }
1924
CollectTasksFromFastbootInfo()1925 std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasksFromFastbootInfo() {
1926 std::vector<std::unique_ptr<Task>> tasks;
1927 std::vector<char> contents;
1928 if (!fp_->source->ReadFile("fastboot-info.txt", &contents)) {
1929 LOG(VERBOSE) << "Flashing from hardcoded images. fastboot-info.txt is empty or does not "
1930 "exist";
1931 return CollectTasksFromImageList();
1932 }
1933 tasks = ParseFastbootInfo(fp_, Split({contents.data(), contents.size()}, "\n"));
1934 return tasks;
1935 }
1936
AddFlashTasks(const std::vector<std::pair<const Image *,std::string>> & images,std::vector<std::unique_ptr<Task>> & tasks)1937 void FlashAllTool::AddFlashTasks(const std::vector<std::pair<const Image*, std::string>>& images,
1938 std::vector<std::unique_ptr<Task>>& tasks) {
1939 for (const auto& [image, slot] : images) {
1940 fastboot_buffer buf;
1941 unique_fd fd = fp_->source->OpenFile(image->img_name);
1942 if (fd < 0 || !load_buf_fd(std::move(fd), &buf, fp_)) {
1943 if (image->optional_if_no_image) {
1944 continue;
1945 }
1946 die("could not load '%s': %s", image->img_name.c_str(), strerror(errno));
1947 }
1948 tasks.emplace_back(std::make_unique<FlashTask>(slot, image->part_name, image->img_name,
1949 is_vbmeta_partition(image->part_name), fp_));
1950 }
1951 }
1952
ReadFile(const std::string & name,std::vector<char> * out) const1953 bool ZipImageSource::ReadFile(const std::string& name, std::vector<char>* out) const {
1954 return UnzipToMemory(zip_, name, out);
1955 }
1956
OpenFile(const std::string & name) const1957 unique_fd ZipImageSource::OpenFile(const std::string& name) const {
1958 return UnzipToFile(zip_, name.c_str());
1959 }
1960
do_update(const char * filename,FlashingPlan * fp)1961 static void do_update(const char* filename, FlashingPlan* fp) {
1962 ZipArchiveHandle zip;
1963 int error = OpenArchive(filename, &zip);
1964 if (error != 0) {
1965 die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
1966 }
1967 fp->source.reset(new ZipImageSource(zip));
1968 FlashAllTool tool(fp);
1969 tool.Flash();
1970
1971 CloseArchive(zip);
1972 }
1973
ReadFile(const std::string & name,std::vector<char> * out) const1974 bool LocalImageSource::ReadFile(const std::string& name, std::vector<char>* out) const {
1975 auto path = find_item_given_name(name);
1976 if (path.empty()) {
1977 return false;
1978 }
1979 return ReadFileToVector(path, out);
1980 }
1981
OpenFile(const std::string & name) const1982 unique_fd LocalImageSource::OpenFile(const std::string& name) const {
1983 auto path = find_item_given_name(name);
1984 return unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_BINARY)));
1985 }
1986
do_flashall(FlashingPlan * fp)1987 static void do_flashall(FlashingPlan* fp) {
1988 fp->source.reset(new LocalImageSource());
1989 FlashAllTool tool(fp);
1990 tool.Flash();
1991 }
1992
next_arg(std::vector<std::string> * args)1993 static std::string next_arg(std::vector<std::string>* args) {
1994 if (args->empty()) syntax_error("expected argument");
1995 std::string result = args->front();
1996 args->erase(args->begin());
1997 return result;
1998 }
1999
do_oem_command(const std::string & cmd,std::vector<std::string> * args)2000 static void do_oem_command(const std::string& cmd, std::vector<std::string>* args) {
2001 if (args->empty()) syntax_error("empty oem command");
2002
2003 std::string command(cmd);
2004 while (!args->empty()) {
2005 command += " " + next_arg(args);
2006 }
2007 fb->RawCommand(command, "");
2008 }
2009
fb_get_flash_block_size(std::string name)2010 static unsigned fb_get_flash_block_size(std::string name) {
2011 std::string sizeString;
2012 if (fb->GetVar(name, &sizeString) != fastboot::SUCCESS || sizeString.empty()) {
2013 // This device does not report flash block sizes, so return 0.
2014 return 0;
2015 }
2016 sizeString = fb_fix_numeric_var(sizeString);
2017
2018 unsigned size;
2019 if (!android::base::ParseUint(sizeString, &size)) {
2020 fprintf(stderr, "Couldn't parse %s '%s'.\n", name.c_str(), sizeString.c_str());
2021 return 0;
2022 }
2023 if ((size & (size - 1)) != 0) {
2024 fprintf(stderr, "Invalid %s %u: must be a power of 2.\n", name.c_str(), size);
2025 return 0;
2026 }
2027 return size;
2028 }
2029
fb_perform_format(const std::string & partition,int skip_if_not_supported,const std::string & type_override,const std::string & size_override,const unsigned fs_options,const FlashingPlan * fp)2030 void fb_perform_format(const std::string& partition, int skip_if_not_supported,
2031 const std::string& type_override, const std::string& size_override,
2032 const unsigned fs_options, const FlashingPlan* fp) {
2033 std::string partition_type, partition_size;
2034
2035 struct fastboot_buffer buf;
2036 const char* errMsg = nullptr;
2037 const struct fs_generator* gen = nullptr;
2038 TemporaryFile output;
2039 unique_fd fd;
2040
2041 unsigned int limit = INT_MAX;
2042 if (target_sparse_limit > 0 && target_sparse_limit < limit) {
2043 limit = target_sparse_limit;
2044 }
2045 if (fp->sparse_limit > 0 && fp->sparse_limit < limit) {
2046 limit = fp->sparse_limit;
2047 }
2048
2049 if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) {
2050 errMsg = "Can't determine partition type.\n";
2051 goto failed;
2052 }
2053 if (!type_override.empty()) {
2054 if (partition_type != type_override) {
2055 fprintf(stderr, "Warning: %s type is %s, but %s was requested for formatting.\n",
2056 partition.c_str(), partition_type.c_str(), type_override.c_str());
2057 }
2058 partition_type = type_override;
2059 }
2060
2061 if (fb->GetVar("partition-size:" + partition, &partition_size) != fastboot::SUCCESS) {
2062 errMsg = "Unable to get partition size\n";
2063 goto failed;
2064 }
2065 if (!size_override.empty()) {
2066 if (partition_size != size_override) {
2067 fprintf(stderr, "Warning: %s size is %s, but %s was requested for formatting.\n",
2068 partition.c_str(), partition_size.c_str(), size_override.c_str());
2069 }
2070 partition_size = size_override;
2071 }
2072 partition_size = fb_fix_numeric_var(partition_size);
2073
2074 gen = fs_get_generator(partition_type);
2075 if (!gen) {
2076 if (skip_if_not_supported) {
2077 fprintf(stderr, "Erase successful, but not automatically formatting.\n");
2078 fprintf(stderr, "File system type %s not supported.\n", partition_type.c_str());
2079 return;
2080 }
2081 die("Formatting is not supported for file system with type '%s'.", partition_type.c_str());
2082 }
2083
2084 int64_t size;
2085 if (!android::base::ParseInt(partition_size, &size)) {
2086 die("Couldn't parse partition size '%s'.", partition_size.c_str());
2087 }
2088
2089 unsigned eraseBlkSize, logicalBlkSize;
2090 eraseBlkSize = fb_get_flash_block_size("erase-block-size");
2091 logicalBlkSize = fb_get_flash_block_size("logical-block-size");
2092
2093 if (fs_generator_generate(gen, output.path, size, eraseBlkSize, logicalBlkSize, fs_options)) {
2094 die("Cannot generate image for %s", partition.c_str());
2095 }
2096
2097 fd.reset(open(output.path, O_RDONLY));
2098 if (fd == -1) {
2099 die("Cannot open generated image: %s", strerror(errno));
2100 }
2101 if (!load_buf_fd(std::move(fd), &buf, fp)) {
2102 die("Cannot read image: %s", strerror(errno));
2103 }
2104
2105 flash_buf(fp->source.get(), partition, &buf, is_vbmeta_partition(partition));
2106 return;
2107
2108 failed:
2109 if (skip_if_not_supported) {
2110 fprintf(stderr, "Erase successful, but not automatically formatting.\n");
2111 if (errMsg) fprintf(stderr, "%s", errMsg);
2112 }
2113 fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
2114 if (!skip_if_not_supported) {
2115 die("Command failed");
2116 }
2117 }
2118
should_flash_in_userspace(const ImageSource * source,const std::string & partition_name)2119 bool should_flash_in_userspace(const ImageSource* source, const std::string& partition_name) {
2120 if (!source) {
2121 if (!get_android_product_out()) {
2122 return false;
2123 }
2124 auto path = find_item_given_name("super_empty.img");
2125 if (path.empty() || access(path.c_str(), R_OK)) {
2126 return false;
2127 }
2128 auto metadata = android::fs_mgr::ReadFromImageFile(path);
2129 if (!metadata) {
2130 return false;
2131 }
2132 return should_flash_in_userspace(*metadata.get(), partition_name);
2133 }
2134 std::vector<char> contents;
2135 if (!source->ReadFile("super_empty.img", &contents)) {
2136 return false;
2137 }
2138 auto metadata = android::fs_mgr::ReadFromImageBlob(contents.data(), contents.size());
2139 return should_flash_in_userspace(*metadata.get(), partition_name);
2140 }
2141
wipe_super(const android::fs_mgr::LpMetadata & metadata,const std::string & slot,std::string * message,const FlashingPlan * fp)2142 static bool wipe_super(const android::fs_mgr::LpMetadata& metadata, const std::string& slot,
2143 std::string* message, const FlashingPlan* fp) {
2144 auto super_device = GetMetadataSuperBlockDevice(metadata);
2145 auto block_size = metadata.geometry.logical_block_size;
2146 auto super_bdev_name = android::fs_mgr::GetBlockDevicePartitionName(*super_device);
2147
2148 if (super_bdev_name != "super") {
2149 // retrofit devices do not allow flashing to the retrofit partitions,
2150 // so enable it if we can.
2151 fb->RawCommand("oem allow-flash-super");
2152 }
2153
2154 // Note: do not use die() in here, since we want TemporaryDir's destructor
2155 // to be called.
2156 TemporaryDir temp_dir;
2157
2158 bool ok;
2159 if (metadata.block_devices.size() > 1) {
2160 ok = WriteSplitImageFiles(temp_dir.path, metadata, block_size, {}, true);
2161 } else {
2162 auto image_path = std::string(temp_dir.path) + "/" + std::string(super_bdev_name) + ".img";
2163 ok = WriteToImageFile(image_path, metadata, block_size, {}, true);
2164 }
2165 if (!ok) {
2166 *message = "Could not generate a flashable super image file";
2167 return false;
2168 }
2169
2170 for (const auto& block_device : metadata.block_devices) {
2171 auto partition = android::fs_mgr::GetBlockDevicePartitionName(block_device);
2172 bool force_slot = !!(block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED);
2173
2174 std::string image_name;
2175 if (metadata.block_devices.size() > 1) {
2176 image_name = "super_" + partition + ".img";
2177 } else {
2178 image_name = partition + ".img";
2179 }
2180
2181 auto image_path = std::string(temp_dir.path) + "/" + image_name;
2182 auto flash = [&](const std::string& partition_name) {
2183 do_flash(partition_name.c_str(), image_path.c_str(), false, fp);
2184 };
2185 do_for_partitions(partition, slot, flash, force_slot);
2186
2187 unlink(image_path.c_str());
2188 }
2189 return true;
2190 }
2191
do_wipe_super(const std::string & image,const std::string & slot_override,const FlashingPlan * fp)2192 static void do_wipe_super(const std::string& image, const std::string& slot_override,
2193 const FlashingPlan* fp) {
2194 if (access(image.c_str(), R_OK) != 0) {
2195 die("Could not read image: %s", image.c_str());
2196 }
2197 auto metadata = android::fs_mgr::ReadFromImageFile(image);
2198 if (!metadata) {
2199 die("Could not parse image: %s", image.c_str());
2200 }
2201
2202 auto slot = slot_override;
2203 if (slot.empty()) {
2204 slot = get_current_slot();
2205 }
2206
2207 std::string message;
2208 if (!wipe_super(*metadata.get(), slot, &message, fp)) {
2209 die(message);
2210 }
2211 }
2212
FastbootLogger(android::base::LogId,android::base::LogSeverity severity,const char *,const char *,unsigned int,const char * message)2213 static void FastbootLogger(android::base::LogId /* id */, android::base::LogSeverity severity,
2214 const char* /* tag */, const char* /* file */, unsigned int /* line */,
2215 const char* message) {
2216 switch (severity) {
2217 case android::base::INFO:
2218 fprintf(stdout, "%s\n", message);
2219 break;
2220 case android::base::ERROR:
2221 fprintf(stderr, "%s\n", message);
2222 break;
2223 default:
2224 verbose("%s\n", message);
2225 }
2226 }
2227
FastbootAborter(const char * message)2228 static void FastbootAborter(const char* message) {
2229 die("%s", message);
2230 }
2231
Main(int argc,char * argv[])2232 int FastBootTool::Main(int argc, char* argv[]) {
2233 android::base::InitLogging(argv, FastbootLogger, FastbootAborter);
2234 std::unique_ptr<FlashingPlan> fp = std::make_unique<FlashingPlan>();
2235
2236 int longindex;
2237 std::string next_active;
2238
2239 g_boot_img_hdr.kernel_addr = 0x00008000;
2240 g_boot_img_hdr.ramdisk_addr = 0x01000000;
2241 g_boot_img_hdr.second_addr = 0x00f00000;
2242 g_boot_img_hdr.tags_addr = 0x00000100;
2243 g_boot_img_hdr.page_size = 2048;
2244 g_boot_img_hdr.dtb_addr = 0x01100000;
2245
2246 const struct option longopts[] = {{"base", required_argument, 0, 0},
2247 {"cmdline", required_argument, 0, 0},
2248 {"disable-verification", no_argument, 0, 0},
2249 {"disable-verity", no_argument, 0, 0},
2250 {"disable-super-optimization", no_argument, 0, 0},
2251 {"exclude-dynamic-partitions", no_argument, 0, 0},
2252 {"disable-fastboot-info", no_argument, 0, 0},
2253 {"force", no_argument, 0, 0},
2254 {"fs-options", required_argument, 0, 0},
2255 {"header-version", required_argument, 0, 0},
2256 {"help", no_argument, 0, 'h'},
2257 {"kernel-offset", required_argument, 0, 0},
2258 {"os-patch-level", required_argument, 0, 0},
2259 {"os-version", required_argument, 0, 0},
2260 {"page-size", required_argument, 0, 0},
2261 {"ramdisk-offset", required_argument, 0, 0},
2262 {"set-active", optional_argument, 0, 'a'},
2263 {"skip-reboot", no_argument, 0, 0},
2264 {"skip-secondary", no_argument, 0, 0},
2265 {"slot", required_argument, 0, 0},
2266 {"tags-offset", required_argument, 0, 0},
2267 {"dtb", required_argument, 0, 0},
2268 {"dtb-offset", required_argument, 0, 0},
2269 {"unbuffered", no_argument, 0, 0},
2270 {"verbose", no_argument, 0, 'v'},
2271 {"version", no_argument, 0, 0},
2272 {0, 0, 0, 0}};
2273
2274 serial = getenv("FASTBOOT_DEVICE");
2275 if (!serial) {
2276 serial = getenv("ANDROID_SERIAL");
2277 }
2278
2279 int c;
2280 while ((c = getopt_long(argc, argv, "a::hls:S:vw", longopts, &longindex)) != -1) {
2281 if (c == 0) {
2282 std::string name{longopts[longindex].name};
2283 if (name == "base") {
2284 g_base_addr = strtoul(optarg, 0, 16);
2285 } else if (name == "cmdline") {
2286 g_cmdline = optarg;
2287 } else if (name == "disable-verification") {
2288 g_disable_verification = true;
2289 } else if (name == "disable-verity") {
2290 g_disable_verity = true;
2291 } else if (name == "disable-super-optimization") {
2292 fp->should_optimize_flash_super = false;
2293 } else if (name == "exclude-dynamic-partitions") {
2294 fp->exclude_dynamic_partitions = true;
2295 fp->should_optimize_flash_super = false;
2296 } else if (name == "disable-fastboot-info") {
2297 fp->should_use_fastboot_info = false;
2298 } else if (name == "force") {
2299 fp->force_flash = true;
2300 } else if (name == "fs-options") {
2301 fp->fs_options = ParseFsOption(optarg);
2302 } else if (name == "header-version") {
2303 g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0);
2304 } else if (name == "dtb") {
2305 g_dtb_path = optarg;
2306 } else if (name == "kernel-offset") {
2307 g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16);
2308 } else if (name == "os-patch-level") {
2309 ParseOsPatchLevel(&g_boot_img_hdr, optarg);
2310 } else if (name == "os-version") {
2311 ParseOsVersion(&g_boot_img_hdr, optarg);
2312 } else if (name == "page-size") {
2313 g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0);
2314 if (g_boot_img_hdr.page_size == 0) die("invalid page size");
2315 } else if (name == "ramdisk-offset") {
2316 g_boot_img_hdr.ramdisk_addr = strtoul(optarg, 0, 16);
2317 } else if (name == "skip-reboot") {
2318 fp->skip_reboot = true;
2319 } else if (name == "skip-secondary") {
2320 fp->skip_secondary = true;
2321 } else if (name == "slot") {
2322 fp->slot_override = optarg;
2323 } else if (name == "dtb-offset") {
2324 g_boot_img_hdr.dtb_addr = strtoul(optarg, 0, 16);
2325 } else if (name == "tags-offset") {
2326 g_boot_img_hdr.tags_addr = strtoul(optarg, 0, 16);
2327 } else if (name == "unbuffered") {
2328 setvbuf(stdout, nullptr, _IONBF, 0);
2329 setvbuf(stderr, nullptr, _IONBF, 0);
2330 } else if (name == "version") {
2331 fprintf(stdout, "fastboot version %s-%s\n", PLATFORM_TOOLS_VERSION,
2332 android::build::GetBuildNumber().c_str());
2333 fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str());
2334 return 0;
2335 } else {
2336 die("unknown option %s", longopts[longindex].name);
2337 }
2338 } else {
2339 switch (c) {
2340 case 'a':
2341 fp->wants_set_active = true;
2342 if (optarg) next_active = optarg;
2343 break;
2344 case 'h':
2345 return show_help();
2346 case 'l':
2347 g_long_listing = true;
2348 break;
2349 case 's':
2350 serial = optarg;
2351 break;
2352 case 'S':
2353 if (!android::base::ParseByteCount(optarg, &fp->sparse_limit)) {
2354 die("invalid sparse limit %s", optarg);
2355 }
2356 break;
2357 case 'v':
2358 set_verbose();
2359 break;
2360 case 'w':
2361 fp->wants_wipe = true;
2362 break;
2363 case '?':
2364 return 1;
2365 default:
2366 abort();
2367 }
2368 }
2369 }
2370
2371 argc -= optind;
2372 argv += optind;
2373
2374 if (argc == 0 && !fp->wants_wipe && !fp->wants_set_active) syntax_error("no command");
2375
2376 if (argc > 0 && !strcmp(*argv, "devices")) {
2377 list_devices();
2378 return 0;
2379 }
2380
2381 if (argc > 0 && !strcmp(*argv, "connect")) {
2382 argc -= optind;
2383 argv += optind;
2384 return Connect(argc, argv);
2385 }
2386
2387 if (argc > 0 && !strcmp(*argv, "disconnect")) {
2388 argc -= optind;
2389 argv += optind;
2390 return Disconnect(argc, argv);
2391 }
2392
2393 if (argc > 0 && !strcmp(*argv, "help")) {
2394 return show_help();
2395 }
2396
2397 std::unique_ptr<Transport> transport = open_device();
2398 if (!transport) {
2399 return 1;
2400 }
2401 fastboot::DriverCallbacks driver_callbacks = {
2402 .prolog = Status,
2403 .epilog = Epilog,
2404 .info = InfoMessage,
2405 .text = TextMessage,
2406 };
2407
2408 fastboot::FastBootDriver fastboot_driver(std::move(transport), driver_callbacks, false);
2409 fb = &fastboot_driver;
2410 fp->fb = &fastboot_driver;
2411
2412 const double start = now();
2413
2414 if (fp->slot_override != "") fp->slot_override = verify_slot(fp->slot_override);
2415 if (next_active != "") next_active = verify_slot(next_active, false);
2416
2417 if (fp->wants_set_active) {
2418 if (next_active == "") {
2419 if (fp->slot_override == "") {
2420 std::string current_slot;
2421 if (fb->GetVar("current-slot", ¤t_slot) == fastboot::SUCCESS) {
2422 if (current_slot[0] == '_') current_slot.erase(0, 1);
2423 next_active = verify_slot(current_slot, false);
2424 } else {
2425 fp->wants_set_active = false;
2426 }
2427 } else {
2428 next_active = verify_slot(fp->slot_override, false);
2429 }
2430 }
2431 }
2432 std::vector<std::unique_ptr<Task>> tasks;
2433 std::vector<std::string> args(argv, argv + argc);
2434 while (!args.empty()) {
2435 std::string command = next_arg(&args);
2436
2437 if (command == FB_CMD_GETVAR) {
2438 std::string variable = next_arg(&args);
2439 DisplayVarOrError(variable, variable);
2440 } else if (command == FB_CMD_ERASE) {
2441 std::string partition = next_arg(&args);
2442 auto erase = [&](const std::string& partition) {
2443 std::string partition_type;
2444 if (fb->GetVar("partition-type:" + partition, &partition_type) ==
2445 fastboot::SUCCESS &&
2446 fs_get_generator(partition_type) != nullptr) {
2447 fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n",
2448 partition_type.c_str());
2449 }
2450
2451 fb->Erase(partition);
2452 };
2453 do_for_partitions(partition, fp->slot_override, erase, true);
2454 } else if (android::base::StartsWith(command, "format")) {
2455 // Parsing for: "format[:[type][:[size]]]"
2456 // Some valid things:
2457 // - select only the size, and leave default fs type:
2458 // format::0x4000000 userdata
2459 // - default fs type and size:
2460 // format userdata
2461 // format:: userdata
2462 std::vector<std::string> pieces = android::base::Split(command, ":");
2463 std::string type_override;
2464 if (pieces.size() > 1) type_override = pieces[1].c_str();
2465 std::string size_override;
2466 if (pieces.size() > 2) size_override = pieces[2].c_str();
2467
2468 std::string partition = next_arg(&args);
2469
2470 auto format = [&](const std::string& partition) {
2471 fb_perform_format(partition, 0, type_override, size_override, fp->fs_options,
2472 fp.get());
2473 };
2474 do_for_partitions(partition, fp->slot_override, format, true);
2475 } else if (command == "signature") {
2476 std::string filename = next_arg(&args);
2477 std::vector<char> data;
2478 if (!ReadFileToVector(filename, &data)) {
2479 die("could not load '%s': %s", filename.c_str(), strerror(errno));
2480 }
2481 if (data.size() != 256) die("signature must be 256 bytes (got %zu)", data.size());
2482 fb->Download("signature", data);
2483 fb->RawCommand("signature", "installing signature");
2484 } else if (command == FB_CMD_REBOOT) {
2485 if (args.size() == 1) {
2486 std::string reboot_target = next_arg(&args);
2487 tasks.emplace_back(std::make_unique<RebootTask>(fp.get(), reboot_target));
2488 } else if (!fp->skip_reboot) {
2489 tasks.emplace_back(std::make_unique<RebootTask>(fp.get()));
2490 }
2491 if (!args.empty()) syntax_error("junk after reboot command");
2492 } else if (command == FB_CMD_REBOOT_BOOTLOADER) {
2493 tasks.emplace_back(std::make_unique<RebootTask>(fp.get(), "bootloader"));
2494 } else if (command == FB_CMD_REBOOT_RECOVERY) {
2495 tasks.emplace_back(std::make_unique<RebootTask>(fp.get(), "recovery"));
2496 } else if (command == FB_CMD_REBOOT_FASTBOOT) {
2497 tasks.emplace_back(std::make_unique<RebootTask>(fp.get(), "fastboot"));
2498 } else if (command == FB_CMD_CONTINUE) {
2499 fb->Continue();
2500 } else if (command == FB_CMD_BOOT) {
2501 std::string kernel = next_arg(&args);
2502 std::string ramdisk;
2503 if (!args.empty()) ramdisk = next_arg(&args);
2504 std::string second_stage;
2505 if (!args.empty()) second_stage = next_arg(&args);
2506 auto data = LoadBootableImage(kernel, ramdisk, second_stage);
2507 fb->Download("boot.img", data);
2508 fb->Boot();
2509 } else if (command == FB_CMD_FLASH) {
2510 std::string pname = next_arg(&args);
2511 std::string fname;
2512 if (!args.empty()) {
2513 fname = next_arg(&args);
2514 } else {
2515 fname = find_item(pname);
2516 }
2517 if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
2518
2519 FlashTask task(fp->slot_override, pname, fname, is_vbmeta_partition(pname), fp.get());
2520 task.Run();
2521 } else if (command == "flash:raw") {
2522 std::string partition = next_arg(&args);
2523 std::string kernel = next_arg(&args);
2524 std::string ramdisk;
2525 if (!args.empty()) ramdisk = next_arg(&args);
2526 std::string second_stage;
2527 if (!args.empty()) second_stage = next_arg(&args);
2528
2529 auto data = LoadBootableImage(kernel, ramdisk, second_stage);
2530 auto flashraw = [&data](const std::string& partition) {
2531 fb->FlashPartition(partition, data);
2532 };
2533 do_for_partitions(partition, fp->slot_override, flashraw, true);
2534 } else if (command == "flashall") {
2535 if (fp->slot_override == "all") {
2536 fprintf(stderr,
2537 "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
2538 fp->skip_secondary = true;
2539 }
2540 do_flashall(fp.get());
2541
2542 if (!fp->skip_reboot) {
2543 tasks.emplace_back(std::make_unique<RebootTask>(fp.get()));
2544 }
2545 } else if (command == "update") {
2546 bool slot_all = (fp->slot_override == "all");
2547 if (slot_all) {
2548 fprintf(stderr,
2549 "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
2550 }
2551 std::string filename = "update.zip";
2552 if (!args.empty()) {
2553 filename = next_arg(&args);
2554 }
2555 do_update(filename.c_str(), fp.get());
2556 if (!fp->skip_reboot) {
2557 tasks.emplace_back(std::make_unique<RebootTask>(fp.get()));
2558 }
2559 } else if (command == FB_CMD_SET_ACTIVE) {
2560 std::string slot = verify_slot(next_arg(&args), false);
2561 fb->SetActive(slot);
2562 } else if (command == "stage") {
2563 std::string filename = next_arg(&args);
2564
2565 struct fastboot_buffer buf;
2566 if (!load_buf(filename.c_str(), &buf, fp.get()) || buf.type != FB_BUFFER_FD) {
2567 die("cannot load '%s'", filename.c_str());
2568 }
2569 fb->Download(filename, buf.fd.get(), buf.sz);
2570 } else if (command == "get_staged") {
2571 std::string filename = next_arg(&args);
2572 fb->Upload(filename);
2573 } else if (command == FB_CMD_OEM) {
2574 do_oem_command(FB_CMD_OEM, &args);
2575 } else if (command == "flashing") {
2576 if (args.empty()) {
2577 syntax_error("missing 'flashing' command");
2578 } else if (args.size() == 1 &&
2579 (args[0] == "unlock" || args[0] == "lock" || args[0] == "unlock_critical" ||
2580 args[0] == "lock_critical" || args[0] == "get_unlock_ability")) {
2581 do_oem_command("flashing", &args);
2582 } else {
2583 syntax_error("unknown 'flashing' command %s", args[0].c_str());
2584 }
2585 } else if (command == FB_CMD_CREATE_PARTITION) {
2586 std::string partition = next_arg(&args);
2587 std::string size = next_arg(&args);
2588 fb->CreatePartition(partition, size);
2589 } else if (command == FB_CMD_DELETE_PARTITION) {
2590 std::string partition = next_arg(&args);
2591 tasks.emplace_back(std::make_unique<DeleteTask>(fp.get(), partition));
2592 } else if (command == FB_CMD_RESIZE_PARTITION) {
2593 std::string partition = next_arg(&args);
2594 std::string size = next_arg(&args);
2595 std::unique_ptr<ResizeTask> resize_task =
2596 std::make_unique<ResizeTask>(fp.get(), partition, size, fp->slot_override);
2597 resize_task->Run();
2598 } else if (command == "gsi") {
2599 if (args.empty()) syntax_error("invalid gsi command");
2600 std::string cmd("gsi");
2601 while (!args.empty()) {
2602 cmd += ":" + next_arg(&args);
2603 }
2604 fb->RawCommand(cmd, "");
2605 } else if (command == "wipe-super") {
2606 std::string image;
2607 if (args.empty()) {
2608 image = find_item_given_name("super_empty.img");
2609 } else {
2610 image = next_arg(&args);
2611 }
2612 do_wipe_super(image, fp->slot_override, fp.get());
2613 } else if (command == "snapshot-update") {
2614 std::string arg;
2615 if (!args.empty()) {
2616 arg = next_arg(&args);
2617 }
2618 if (!arg.empty() && (arg != "cancel" && arg != "merge")) {
2619 syntax_error("expected: snapshot-update [cancel|merge]");
2620 }
2621 fb->SnapshotUpdateCommand(arg);
2622 } else if (command == FB_CMD_FETCH) {
2623 std::string partition = next_arg(&args);
2624 std::string outfile = next_arg(&args);
2625 do_fetch(partition, fp->slot_override, outfile, fp->fb);
2626 } else {
2627 syntax_error("unknown command %s", command.c_str());
2628 }
2629 }
2630
2631 if (fp->wants_wipe) {
2632 if (fp->force_flash) {
2633 CancelSnapshotIfNeeded();
2634 }
2635 std::vector<std::unique_ptr<Task>> wipe_tasks;
2636 std::vector<std::string> partitions = {"userdata", "cache", "metadata"};
2637 for (const auto& partition : partitions) {
2638 wipe_tasks.emplace_back(std::make_unique<WipeTask>(fp.get(), partition));
2639 }
2640 tasks.insert(tasks.begin(), std::make_move_iterator(wipe_tasks.begin()),
2641 std::make_move_iterator(wipe_tasks.end()));
2642 }
2643 if (fp->wants_set_active) {
2644 fb->SetActive(next_active);
2645 }
2646 for (auto& task : tasks) {
2647 task->Run();
2648 }
2649 fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
2650
2651 return 0;
2652 }
2653
ParseOsPatchLevel(boot_img_hdr_v1 * hdr,const char * arg)2654 void FastBootTool::ParseOsPatchLevel(boot_img_hdr_v1* hdr, const char* arg) {
2655 unsigned year, month, day;
2656 if (sscanf(arg, "%u-%u-%u", &year, &month, &day) != 3) {
2657 syntax_error("OS patch level should be YYYY-MM-DD: %s", arg);
2658 }
2659 if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year);
2660 if (month < 1 || month > 12) syntax_error("month out of range: %d", month);
2661 hdr->SetOsPatchLevel(year, month);
2662 }
2663
ParseOsVersion(boot_img_hdr_v1 * hdr,const char * arg)2664 void FastBootTool::ParseOsVersion(boot_img_hdr_v1* hdr, const char* arg) {
2665 unsigned major = 0, minor = 0, patch = 0;
2666 std::vector<std::string> versions = android::base::Split(arg, ".");
2667 if (versions.size() < 1 || versions.size() > 3 ||
2668 (versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) ||
2669 (versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) ||
2670 (versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) ||
2671 (major > 0x7f || minor > 0x7f || patch > 0x7f)) {
2672 syntax_error("bad OS version: %s", arg);
2673 }
2674 hdr->SetOsVersion(major, minor, patch);
2675 }
2676
ParseFsOption(const char * arg)2677 unsigned FastBootTool::ParseFsOption(const char* arg) {
2678 unsigned fsOptions = 0;
2679
2680 std::vector<std::string> options = android::base::Split(arg, ",");
2681 if (options.size() < 1) syntax_error("bad options: %s", arg);
2682
2683 for (size_t i = 0; i < options.size(); ++i) {
2684 if (options[i] == "casefold")
2685 fsOptions |= (1 << FS_OPT_CASEFOLD);
2686 else if (options[i] == "projid")
2687 fsOptions |= (1 << FS_OPT_PROJID);
2688 else if (options[i] == "compress")
2689 fsOptions |= (1 << FS_OPT_COMPRESS);
2690 else
2691 syntax_error("unsupported options: %s", options[i].c_str());
2692 }
2693 return fsOptions;
2694 }
2695