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