1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * All rights reserved.
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redistribution and use in source and binary forms, with or without
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * modification, are permitted provided that the following conditions
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * are met:
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  * Redistributions of source code must retain the above copyright
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer in
12ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang *    the documentation and/or other materials provided with the
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    distribution.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * SUCH DAMAGE.
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#define _LARGEFILE64_SOURCE
30f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
315957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <ctype.h>
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
348879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross#include <getopt.h>
35cf86e2f85d98ed10cf5e0672e41631f6ea7e3e34Ying Wang#include <inttypes.h>
365957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <limits.h>
375957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <stdint.h>
385957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <stdio.h>
395957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <stdlib.h>
405957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <string.h>
415957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <sys/stat.h>
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/time.h>
43f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#include <sys/types.h>
445957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <unistd.h>
452ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
46b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg#include <functional>
479da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao#include <utility>
489da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao#include <vector>
49f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
504f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/parseint.h>
512ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell#include <android-base/parsenetaddress.h>
5289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light#include <android-base/stringprintf.h>
534f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/strings.h>
54f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#include <sparse/sparse.h>
55d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes#include <ziparchive/zip_archive.h>
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes#include "bootimg_utils.h"
581b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#include "diagnose_usb.h"
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "fastboot.h"
60e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg#include "fs.h"
612ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell#include "tcp.h"
620b156638307db890e5539b52521fd24beb3440cbDavid Pursell#include "transport.h"
635a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include "udp.h"
640b156638307db890e5539b52521fd24beb3440cbDavid Pursell#include "usb.h"
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#ifndef O_BINARY
67f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#define O_BINARY 0
68f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#endif
69f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
70622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
71622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
72b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Savillechar cur_product[FB_RESPONSE_SZ + 1];
73b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
742ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic const char* serial = nullptr;
752ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic const char* product = nullptr;
762ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic const char* cmdline = nullptr;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned short vendor_id = 0;
7813081c6915220db03886b177f1a8e0b2c63467c9Scott Andersonstatic int long_listing = 0;
79f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t sparse_limit = -1;
80f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t target_sparse_limit = -1;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned page_size = 2048;
83fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned base_addr      = 0x10000000;
84fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned kernel_offset  = 0x00008000;
85fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned ramdisk_offset = 0x01000000;
86fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned second_offset  = 0x00f00000;
87fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned tags_offset    = 0x00000100;
887b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
898f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic const std::string convert_fbe_marker_filename("convert_fbe");
908f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
91622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandenum fb_buffer_type {
92622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    FB_BUFFER,
93622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    FB_BUFFER_SPARSE,
94622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
95622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
96622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstruct fastboot_buffer {
97622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    enum fb_buffer_type type;
98fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* data;
99fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
100622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
101622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
102622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic struct {
10389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    char img_name[17];
10489eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    char sig_name[17];
105622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    char part_name[9];
106622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    bool is_optional;
10789eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    bool is_secondary;
108f530c93c4aab818de51fd7123199bef6621047f8Daniel Rosenberg} images[] = {
10989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    {"boot.img", "boot.sig", "boot", false, false},
11089eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    {"boot_other.img", "boot.sig", "boot", true, true},
11189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    {"recovery.img", "recovery.sig", "recovery", true, false},
11289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    {"system.img", "system.sig", "system", false, false},
11389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    {"system_other.img", "system.sig", "system", true, true},
11489eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    {"vendor.img", "vendor.sig", "vendor", true, false},
11589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    {"vendor_other.img", "vendor.sig", "vendor", true, true},
116622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
1172a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland
11889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Lightstatic std::string find_item_given_name(const char* img_name, const char* product) {
1199914284d6afb1734747940de2c466f67078e4365Daniel Rosenberg    char path_c_str[PATH_MAX + 128];
1206c98509c34d152007cf953c2cacb5750745dd464Daniel Rosenberg
12189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    if(product) {
1229914284d6afb1734747940de2c466f67078e4365Daniel Rosenberg        get_my_path(path_c_str);
1239914284d6afb1734747940de2c466f67078e4365Daniel Rosenberg        std::string path = path_c_str;
1249914284d6afb1734747940de2c466f67078e4365Daniel Rosenberg        path.erase(path.find_last_of('/'));
1259914284d6afb1734747940de2c466f67078e4365Daniel Rosenberg        return android::base::StringPrintf("%s/../../../target/product/%s/%s",
1269914284d6afb1734747940de2c466f67078e4365Daniel Rosenberg                                           path.c_str(), product, img_name);
12789eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    }
12889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light
1299914284d6afb1734747940de2c466f67078e4365Daniel Rosenberg    char *dir = getenv("ANDROID_PRODUCT_OUT");
1309914284d6afb1734747940de2c466f67078e4365Daniel Rosenberg    if (dir == nullptr || dir[0] == '\0') {
13189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
13289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    }
13389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light
13489eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    return android::base::StringPrintf("%s/%s", dir, img_name);
13589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light}
13689eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light
13789eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Lightstd::string find_item(const char* item, const char* product) {
13889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    const char *fn;
13989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strcmp(item,"boot")) {
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "boot.img";
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"recovery")) {
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "recovery.img";
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"system")) {
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "system.img";
146f530c93c4aab818de51fd7123199bef6621047f8Daniel Rosenberg    } else if(!strcmp(item,"vendor")) {
147f530c93c4aab818de51fd7123199bef6621047f8Daniel Rosenberg        fn = "vendor.img";
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"userdata")) {
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "userdata.img";
150d7608a40d6bed0d8ca686414a5a4f44b6d4d0435Jean-Baptiste Queru    } else if(!strcmp(item,"cache")) {
151d7608a40d6bed0d8ca686414a5a4f44b6d4d0435Jean-Baptiste Queru        fn = "cache.img";
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"info")) {
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "android-info.txt";
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"unknown partition '%s'\n", item);
15689eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        return "";
157520573f2bb8a27e72c0727f250cee574e473b8eaEd Heyl    }
158520573f2bb8a27e72c0727f250cee574e473b8eaEd Heyl
15989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    return find_item_given_name(fn, product);
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
162fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic int64_t get_file_size(int fd) {
163fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    struct stat sb;
164fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    return fstat(fd, &sb) == -1 ? -1 : sb.st_size;
165f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
166f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
167fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void* load_fd(int fd, int64_t* sz) {
16864ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    int errno_tmp;
169fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    char* data = nullptr;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
171fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    *sz = get_file_size(fd);
172fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (*sz < 0) {
173622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        goto oops;
174622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    data = (char*) malloc(*sz);
177fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) goto oops;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
179fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if(read(fd, data, *sz) != *sz) goto oops;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return data;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectoops:
18564ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    errno_tmp = errno;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(data != 0) free(data);
18864ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    errno = errno_tmp;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
192fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void* load_file(const char* fn, int64_t* sz) {
193fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int fd = open(fn, O_RDONLY | O_BINARY);
194fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (fd == -1) return nullptr;
195fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    return load_fd(fd, sz);
196622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
198fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
199e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes    // Require a matching vendor id if the user specified one with -i.
200b46964f3c9f5389dc9d000dcc5e740a3833d3a81Elliott Hughes    if (vendor_id != 0 && info->dev_vendor != vendor_id) {
201e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes        return -1;
202e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes    }
203e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes
204e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes    if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) {
205e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes        return -1;
206e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes    }
207e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes
20813081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson    // require matching serial number or device path if requested
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // at the command line with the -s option.
210a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrall    if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
211a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrall                   strcmp(local_serial, info->device_path) != 0)) return -1;
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic int match_fastboot(usb_ifc_info* info) {
2167b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    return match_fastboot_with_serial(info, serial);
2177b8970c577c788c9af582dac797c63b3134b201eJP Abgrall}
2187b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
219fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic int list_devices_callback(usb_ifc_info* info) {
220fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (match_fastboot_with_serial(info, nullptr) == 0) {
2211b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes        std::string serial = info->serial_number;
222b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes        if (!info->writable) {
2231b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes            serial = UsbNoPermissionsShortHelpText();
224b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes        }
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!serial[0]) {
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            serial = "????????????";
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
228866b1bd5051db4f22b634df1f8a06bc1c9aa2e26Scott Anderson        // output compatible with "adb devices"
22913081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        if (!long_listing) {
2301b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes            printf("%s\tfastboot", serial.c_str());
23113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        } else {
2321b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes            printf("%-22s fastboot", serial.c_str());
2331b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes            if (strlen(info->device_path) > 0) printf(" %s", info->device_path);
23413081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        }
2351b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes        putchar('\n');
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2412ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// Opens a new Transport connected to a device. If |serial| is non-null it will be used to identify
2422ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// a specific device, otherwise the first USB device found will be used.
2432ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell//
2442ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// If |serial| is non-null but invalid, this prints an error message to stderr and returns nullptr.
2452ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// Otherwise it blocks until the target is available.
2462ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell//
2472ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// The returned Transport is a singleton, so multiple calls to this function will return the same
2482ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// object, and the caller should not attempt to delete the returned Transport.
2490b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic Transport* open_device() {
2500b156638307db890e5539b52521fd24beb3440cbDavid Pursell    static Transport* transport = nullptr;
2512ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    bool announce = true;
2522ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
2532ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (transport != nullptr) {
2542ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return transport;
2552ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
2562ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
2575a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    Socket::Protocol protocol = Socket::Protocol::kTcp;
2582ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    std::string host;
2595a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    int port = 0;
2605a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (serial != nullptr) {
2615a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        const char* net_address = nullptr;
2625a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2635a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (android::base::StartsWith(serial, "tcp:")) {
2645a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            protocol = Socket::Protocol::kTcp;
2655a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            port = tcp::kDefaultPort;
2665a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            net_address = serial + strlen("tcp:");
2675a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        } else if (android::base::StartsWith(serial, "udp:")) {
2685a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            protocol = Socket::Protocol::kUdp;
2695a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            port = udp::kDefaultPort;
2705a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            net_address = serial + strlen("udp:");
2715a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        }
2725a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2735a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (net_address != nullptr) {
2745a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            std::string error;
2755a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) {
2765a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                fprintf(stderr, "error: Invalid network address '%s': %s\n", net_address,
2775a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                        error.c_str());
2785a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                return nullptr;
2795a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            }
2802ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        }
2812ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2832ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    while (true) {
2842ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        if (!host.empty()) {
2852ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            std::string error;
2865a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            if (protocol == Socket::Protocol::kTcp) {
2875a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                transport = tcp::Connect(host, port, &error).release();
2885a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            } else if (protocol == Socket::Protocol::kUdp) {
2895a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                transport = udp::Connect(host, port, &error).release();
2905a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            }
2915a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2922ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            if (transport == nullptr && announce) {
2932ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell                fprintf(stderr, "error: %s\n", error.c_str());
2942ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            }
2952ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        } else {
2962ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            transport = usb_open(match_fastboot);
2972ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        }
2982ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
2992ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        if (transport != nullptr) {
3002ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            return transport;
3012ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        }
302ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
3030b156638307db890e5539b52521fd24beb3440cbDavid Pursell        if (announce) {
3042ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            announce = false;
305b46964f3c9f5389dc9d000dcc5e740a3833d3a81Elliott Hughes            fprintf(stderr, "< waiting for %s >\n", serial ? serial : "any device");
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
3075957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn        usleep(1000);
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
311fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void list_devices() {
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // We don't actually open a USB device here,
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // just getting our callback called so we can
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // list all the connected devices.
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_open(list_devices_callback);
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
318fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void usage() {
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*           1234567890123456789012345678901234567890123456789012345678901234567890123456 */
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "usage: fastboot [ <option> ] <command>\n"
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "\n"
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "commands:\n"
32408df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  update <filename>                        Reflash device from update.zip.\n"
3259c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg            "                                           Sets the flashed slot as active.\n"
32608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashall                                 Flash boot, system, vendor, and --\n"
3279c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg            "                                           if found -- recovery. If the device\n"
3289c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg            "                                           supports slots, the slot that has\n"
3299c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg            "                                           been flashed to is set as active.\n"
33089eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            "                                           Secondary images may be flashed to\n"
33189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            "                                           an inactive slot.\n"
33208df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flash <partition> [ <filename> ]         Write a file to a flash partition.\n"
33308df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing lock                            Locks the device. Prevents flashing.\n"
33408df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing unlock                          Unlocks the device. Allows flashing\n"
33508df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           any partition except\n"
33608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           bootloader-related partitions.\n"
33708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing lock_critical                   Prevents flashing bootloader-related\n"
33808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           partitions.\n"
33908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing unlock_critical                 Enables flashing bootloader-related\n"
34008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           partitions.\n"
34108df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing get_unlock_ability              Queries bootloader to see if the\n"
34208df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           device is unlocked.\n"
34351e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            "  flashing get_unlock_bootloader_nonce     Queries the bootloader to get the\n"
34445be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughes            "                                           unlock nonce.\n"
34545be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughes            "  flashing unlock_bootloader <request>     Issue unlock bootloader using request.\n"
34651e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            "  flashing lock_bootloader                 Locks the bootloader to prevent\n"
34745be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughes            "                                           bootloader version rollback.\n"
34808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  erase <partition>                        Erase a flash partition.\n"
34908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  format[:[<fs type>][:[<size>]] <partition>\n"
35008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           Format a flash partition. Can\n"
35108df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           override the fs type and/or size\n"
35208df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           the bootloader reports.\n"
35308df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  getvar <variable>                        Display a bootloader variable.\n"
354563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "  set_active <slot>                        Sets the active slot. If slots are\n"
3559b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            "                                           not supported, this does nothing.\n"
35608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n"
35708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flash:raw boot <kernel> [ <ramdisk> [ <second> ] ]\n"
35808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           Create bootimage and flash it.\n"
35908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  devices [-l]                             List all connected devices [with\n"
36008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           device paths].\n"
36108df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  continue                                 Continue with autoboot.\n"
36208df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  reboot [bootloader]                      Reboot device [into bootloader].\n"
36308df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  reboot-bootloader                        Reboot device into bootloader.\n"
36408df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  help                                     Show this help message.\n"
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "\n"
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "options:\n"
36708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -w                                       Erase userdata and cache (and format\n"
36808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           if supported by partition type).\n"
36908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -u                                       Do not erase partition before\n"
37008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           formatting.\n"
3712ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            "  -s <specific device>                     Specify a device. For USB, provide either\n"
3722ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            "                                           a serial number or path to device port.\n"
3733f8cacc857273a79a656fae722a296449a618ea1Daniel Rosenberg            "                                           For ethernet, provide an address in the\n"
3743f8cacc857273a79a656fae722a296449a618ea1Daniel Rosenberg            "                                           form <protocol>:<hostname>[:port] where\n"
3755a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            "                                           <protocol> is either tcp or udp.\n"
37608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -p <product>                             Specify product name.\n"
37708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -c <cmdline>                             Override kernel commandline.\n"
37808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -i <vendor id>                           Specify a custom USB vendor id.\n"
3797aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  -b, --base <base_addr>                   Specify a custom kernel base\n"
38008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           address (default: 0x10000000).\n"
3817aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --kernel-offset                          Specify a custom kernel offset.\n"
3827aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "                                           (default: 0x00008000)\n"
3837aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --ramdisk-offset                         Specify a custom ramdisk offset.\n"
3847aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "                                           (default: 0x01000000)\n"
3857aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --tags-offset                            Specify a custom tags offset.\n"
3867aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "                                           (default: 0x00000100)\n"
3877aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  -n, --page-size <page size>              Specify the nand page size\n"
38808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           (default: 2048).\n"
38908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -S <size>[K|M|G]                         Automatically sparse files greater\n"
39008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           than 'size'. 0 to disable.\n"
391563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "  --slot <slot>                            Specify slot name to be used if the\n"
392563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           device supports slots. All operations\n"
393563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           on partitions that support slots will\n"
394563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           be done on the slot specified.\n"
395563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           'all' can be given to refer to all slots.\n"
396563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           'other' can be given to refer to a\n"
397563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           non-current slot. If this flag is not\n"
398563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           used, slotted partitions will default\n"
399563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           to the current active slot.\n"
400563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "  -a, --set-active[=<slot>]                Sets the active slot. If no slot is\n"
4010d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            "                                           provided, this will default to the value\n"
4020d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            "                                           given by --slot. If slots are not\n"
403563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           supported, this sets the current slot\n"
404563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           to be active. This will run after all\n"
405563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            "                                           non-reboot commands.\n"
406e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            "  --skip-secondary                         Will not flash secondary slots when\n"
407e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            "                                           performing a flashall or update. This\n"
408e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            "                                           will preserve data on other slots.\n"
4098f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#if !defined(_WIN32)
4108f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            "  --wipe-and-use-fbe                       On devices which support it,\n"
4118f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            "                                           erase userdata and cache, and\n"
4128f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            "                                           enable file-based encryption\n"
4138f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#endif
4147aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --unbuffered                             Do not buffer input or output.\n"
4157aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --version                                Display version.\n"
4167aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  -h, --help                               show this message.\n"
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
4198f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
420fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void* load_bootable_image(const char* kernel, const char* ramdisk,
421fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                                 const char* secondstage, int64_t* sz,
422fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                                 const char* cmdline) {
423fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (kernel == nullptr) {
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "no image specified\n");
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
428fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t ksize;
429fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* kdata = load_file(kernel, &ksize);
430fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (kdata == nullptr) {
43164ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel        fprintf(stderr, "cannot load '%s': %s\n", kernel, strerror(errno));
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
434ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
435fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    // Is this actually a boot image?
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
437fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
438ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
439fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (ramdisk) {
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n");
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
443ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *sz = ksize;
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return kdata;
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
448fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* rdata = nullptr;
449fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t rsize = 0;
450fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (ramdisk) {
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rdata = load_file(ramdisk, &rsize);
452fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (rdata == nullptr) {
45364ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel            fprintf(stderr,"cannot load '%s': %s\n", ramdisk, strerror(errno));
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return  0;
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
458fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* sdata = nullptr;
459fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t ssize = 0;
460a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella    if (secondstage) {
461a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella        sdata = load_file(secondstage, &ssize);
462fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (sdata == nullptr) {
463a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
464a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            return  0;
465a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella        }
466a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella    }
467a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"creating boot image...\n");
469fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t bsize = 0;
470fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* bdata = mkbootimg(kdata, ksize, kernel_offset,
4717b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                      rdata, rsize, ramdisk_offset,
472a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                      sdata, ssize, second_offset,
4737b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                      page_size, base_addr, tags_offset, &bsize);
474fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (bdata == nullptr) {
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"failed to create boot.img\n");
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
478fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
479fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", bsize);
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *sz = bsize;
481ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return bdata;
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
485fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void* unzip_file(ZipArchiveHandle zip, const char* entry_name, int64_t* sz)
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
48707447544adbde8f688806b43f47c182eaeda4bb3Yusuke Sato    ZipString zip_entry_name(entry_name);
488d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    ZipEntry zip_entry;
489d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
490a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "archive does not contain '%s'\n", entry_name);
4918d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
494d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    *sz = zip_entry.uncompressed_length;
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
496d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
497fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) {
498fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        fprintf(stderr, "failed to allocate %" PRId64 " bytes for '%s'\n", *sz, entry_name);
4998d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
502a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    int error = ExtractToMemory(zip, &zip_entry, data, zip_entry.uncompressed_length);
503a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    if (error != 0) {
504a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(data);
5068d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
5088d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return data;
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
512a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes#if defined(_WIN32)
513a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
514a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes// TODO: move this to somewhere it can be shared.
515a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
516a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes#include <windows.h>
517a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
518a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes// Windows' tmpfile(3) requires administrator rights because
519a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes// it creates temporary files in the root directory.
520a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughesstatic FILE* win32_tmpfile() {
521a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    char temp_path[PATH_MAX];
522a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    DWORD nchars = GetTempPath(sizeof(temp_path), temp_path);
523a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    if (nchars == 0 || nchars >= sizeof(temp_path)) {
524a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes        fprintf(stderr, "GetTempPath failed, error %ld\n", GetLastError());
525a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes        return nullptr;
526a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    }
527a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
528a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    char filename[PATH_MAX];
529a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    if (GetTempFileName(temp_path, "fastboot", 0, filename) == 0) {
530a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes        fprintf(stderr, "GetTempFileName failed, error %ld\n", GetLastError());
531a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes        return nullptr;
532a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    }
533a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
534a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    return fopen(filename, "w+bTD");
535a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes}
536a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
537a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes#define tmpfile win32_tmpfile
538a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
5398f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic std::string make_temporary_directory() {
5408f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    fprintf(stderr, "make_temporary_directory not supported under Windows, sorry!");
5418f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    return "";
5428f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley}
5438f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
5448f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#else
5458f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
5468f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic std::string make_temporary_directory() {
5478f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    const char *tmpdir = getenv("TMPDIR");
5488f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (tmpdir == nullptr) {
5498f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        tmpdir = P_tmpdir;
5508f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5518f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    std::string result = std::string(tmpdir) + "/fastboot_userdata_XXXXXX";
5528f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (mkdtemp(&result[0]) == NULL) {
5538f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to create temporary directory: %s\n",
5548f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            strerror(errno));
5558f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return "";
5568f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5578f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    return result;
5588f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley}
5598f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
560a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes#endif
561a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
5628f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic std::string create_fbemarker_tmpdir() {
5638f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    std::string dir = make_temporary_directory();
5648f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (dir.empty()) {
5658f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to create local temp directory for FBE marker\n");
5668f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return "";
5678f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5688f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    std::string marker_file = dir + "/" + convert_fbe_marker_filename;
5698f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    int fd = open(marker_file.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, 0666);
5708f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (fd == -1) {
5718f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to create FBE marker file %s locally: %d, %s\n",
5728f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            marker_file.c_str(), errno, strerror(errno));
5738f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return "";
5748f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5758f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    close(fd);
5768f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    return dir;
5778f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley}
5788f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
5798f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic void delete_fbemarker_tmpdir(const std::string& dir) {
5808f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    std::string marker_file = dir + "/" + convert_fbe_marker_filename;
5818f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (unlink(marker_file.c_str()) == -1) {
5828f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to delete FBE marker file %s locally: %d, %s\n",
5838f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            marker_file.c_str(), errno, strerror(errno));
5848f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return;
5858f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5868f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (rmdir(dir.c_str()) == -1) {
5878f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to delete FBE marker directory %s locally: %d, %s\n",
5888f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            dir.c_str(), errno, strerror(errno));
5898f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return;
5908f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5918f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley}
5928f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
593a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughesstatic int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
594a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    FILE* fp = tmpfile();
595fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (fp == nullptr) {
596a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "failed to create temporary file for '%s': %s\n",
597a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes                entry_name, strerror(errno));
5988d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return -1;
599622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
600622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
60107447544adbde8f688806b43f47c182eaeda4bb3Yusuke Sato    ZipString zip_entry_name(entry_name);
602a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    ZipEntry zip_entry;
603a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
604a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "archive does not contain '%s'\n", entry_name);
605622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        return -1;
606622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
607622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
608a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    int fd = fileno(fp);
609a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    int error = ExtractEntryToFile(zip, &zip_entry, fd);
610a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    if (error != 0) {
611a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
612a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        return -1;
613622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
614622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
6158d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    lseek(fd, 0, SEEK_SET);
616622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return fd;
617622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
618622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char *strip(char *s)
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int n;
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(*s && isspace(*s)) s++;
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = strlen(s);
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(n-- > 0) {
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!isspace(s[n])) break;
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s[n] = 0;
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define MAX_OPTIONS 32
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int setup_requirement_line(char *name)
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *val[MAX_OPTIONS];
635fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    char *prod = nullptr;
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned n, count;
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *x;
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int invert = 0;
639ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strncmp(name, "reject ", 7)) {
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name += 7;
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        invert = 1;
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(name, "require ", 8)) {
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name += 8;
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        invert = 0;
646b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    } else if (!strncmp(name, "require-for-product:", 20)) {
647b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        // Get the product and point name past it
648b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        prod = name + 20;
649b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        name = strchr(name, ' ');
650b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        if (!name) return -1;
651b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        *name = 0;
652b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        name += 1;
653b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        invert = 0;
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = strchr(name, '=');
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (x == 0) return 0;
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *x = 0;
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    val[0] = x + 1;
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(count = 1; count < MAX_OPTIONS; count++) {
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x = strchr(val[count - 1],'|');
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (x == 0) break;
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x = 0;
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        val[count] = x + 1;
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
667ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    name = strip(name);
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0; n < count; n++) val[n] = strip(val[n]);
670ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    name = strip(name);
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (name == 0) return -1;
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
674253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    const char* var = name;
675253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    // Work around an unfortunate name mismatch.
676253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    if (!strcmp(name,"board")) var = "product";
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
678253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    const char** out = reinterpret_cast<const char**>(malloc(sizeof(char*) * count));
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (out == 0) return -1;
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0; n < count; n++) {
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        out[n] = strdup(strip(val[n]));
68314e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes        if (out[n] == 0) {
68414e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            for(size_t i = 0; i < n; ++i) {
68514e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes                free((char*) out[i]);
68614e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            }
68714e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            free(out);
68814e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            return -1;
68914e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes        }
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
692253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    fb_queue_require(prod, var, invert, n, out);
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
696fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void setup_requirements(char* data, int64_t sz) {
697fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    char* s = data;
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (sz-- > 0) {
699fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (*s == '\n') {
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *s++ = 0;
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (setup_requirement_line(data)) {
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                die("out of memory");
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            data = s;
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s++;
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
711fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void queue_info_dump() {
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_notice("--------------------------------------------");
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("version-bootloader", "Bootloader Version...");
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("version-baseband",   "Baseband Version.....");
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("serialno",           "Serial Number........");
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_notice("--------------------------------------------");
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
719622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic struct sparse_file **load_sparse_files(int fd, int max_size)
720f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
72180cc1f6864288f166b786a61ad57f12081114225Mohamad Ayyash    struct sparse_file* s = sparse_file_import_auto(fd, false, true);
722f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (!s) {
723622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("cannot sparse read file\n");
724f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
725f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
726fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int files = sparse_file_resparse(s, max_size, nullptr, 0);
727f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (files < 0) {
728622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("Failed to resparse\n");
729f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
730f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
731253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    sparse_file** out_s = reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file *), files + 1));
732f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (!out_s) {
733f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        die("Failed to allocate sparse file array\n");
734f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
735f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
736f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    files = sparse_file_resparse(s, max_size, out_s, files);
737f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (files < 0) {
738622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("Failed to resparse\n");
739f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
740f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
741f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return out_s;
742f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
743f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
7440b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic int64_t get_target_sparse_limit(Transport* transport) {
7452fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    std::string max_download_size;
7460b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, "max-download-size", &max_download_size) ||
7470b156638307db890e5539b52521fd24beb3440cbDavid Pursell            max_download_size.empty()) {
7483ab05869d84357dd54ee27f971bde6514475bcb6Elliott Hughes        fprintf(stderr, "target didn't report max-download-size\n");
7492fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        return 0;
750f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
751f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
75277c0e66bef637aa749c5618e2bdec1c829f79e58Elliott Hughes    // Some bootloaders (angler, for example) send spurious whitespace too.
75377c0e66bef637aa749c5618e2bdec1c829f79e58Elliott Hughes    max_download_size = android::base::Trim(max_download_size);
75477c0e66bef637aa749c5618e2bdec1c829f79e58Elliott Hughes
7552fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    uint64_t limit;
7562fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (!android::base::ParseUint(max_download_size.c_str(), &limit)) {
7573ab05869d84357dd54ee27f971bde6514475bcb6Elliott Hughes        fprintf(stderr, "couldn't parse max-download-size '%s'\n", max_download_size.c_str());
7582fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        return 0;
7592fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
7602fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (limit > 0) {
7612fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n", limit);
7622fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
763f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return limit;
764f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
765f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
7660b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic int64_t get_sparse_limit(Transport* transport, int64_t size) {
767f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int64_t limit;
768f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
769f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (sparse_limit == 0) {
770f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return 0;
771f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (sparse_limit > 0) {
772f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        limit = sparse_limit;
773f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else {
774f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (target_sparse_limit == -1) {
7750b156638307db890e5539b52521fd24beb3440cbDavid Pursell            target_sparse_limit = get_target_sparse_limit(transport);
776f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
777f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (target_sparse_limit > 0) {
778f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            limit = target_sparse_limit;
779f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        } else {
7800bbfb3976e9491b3e1a872ebdaa850ef868a24aaColin Cross            return 0;
781f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
782f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
783f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
784f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (size > limit) {
785f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return limit;
786f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
787f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
788f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return 0;
789f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
790f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
7912fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes// Until we get lazy inode table init working in make_ext4fs, we need to
7922fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes// erase partitions of type ext4 before flashing a filesystem so no stale
7932fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes// inodes are left lying around.  Otherwise, e2fsck gets very upset.
7940b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic bool needs_erase(Transport* transport, const char* partition) {
7958ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes    std::string partition_type;
7960b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) {
7978ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes        return false;
7988ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes    }
7998ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes    return partition_type == "ext4";
8005ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall}
8015ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
8020b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic int load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* buf) {
803fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz = get_file_size(fd);
804fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (sz == -1) {
8058d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return -1;
806622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
807e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
808fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    lseek64(fd, 0, SEEK_SET);
8090b156638307db890e5539b52521fd24beb3440cbDavid Pursell    int64_t limit = get_sparse_limit(transport, sz);
810f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (limit) {
811fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        sparse_file** s = load_sparse_files(fd, limit);
812fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (s == nullptr) {
813622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            return -1;
814f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
815622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->type = FB_BUFFER_SPARSE;
816622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->data = s;
817f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else {
818fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        void* data = load_fd(fd, &sz);
819fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (data == nullptr) return -1;
820622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->type = FB_BUFFER;
821782111b3bc5d372afc8d66ab6023e834b7c23b88Sasha Levitskiy        buf->data = data;
8228d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        buf->sz = sz;
823622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
824622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
825622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return 0;
826622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
827622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
8280b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic int load_buf(Transport* transport, const char *fname, struct fastboot_buffer *buf)
829622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
830622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    int fd;
831622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
832622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    fd = open(fname, O_RDONLY | O_BINARY);
833622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    if (fd < 0) {
83482280594ef7e9dc908aa67f3da8661ff54a96c9eDaniel Rosenberg        return -1;
835f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
836622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
8370b156638307db890e5539b52521fd24beb3440cbDavid Pursell    return load_buf_fd(transport, fd, buf);
838622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
839622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
840622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic void flash_buf(const char *pname, struct fastboot_buffer *buf)
841622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
842253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    sparse_file** s;
843622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
844622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    switch (buf->type) {
8459da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao        case FB_BUFFER_SPARSE: {
8469da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao            std::vector<std::pair<sparse_file*, int64_t>> sparse_files;
847253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes            s = reinterpret_cast<sparse_file**>(buf->data);
848622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            while (*s) {
849fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                int64_t sz = sparse_file_len(*s, true, false);
8509da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                sparse_files.emplace_back(*s, sz);
8519da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                ++s;
8529da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao            }
8539da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao
8549da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao            for (size_t i = 0; i < sparse_files.size(); ++i) {
8559da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                const auto& pair = sparse_files[i];
8569da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                fb_queue_flash_sparse(pname, pair.first, pair.second, i + 1, sparse_files.size());
857622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            }
858622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            break;
8599da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao        }
8609da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao
861622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        case FB_BUFFER:
862622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            fb_queue_flash(pname, buf->data, buf->sz);
863622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            break;
864622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        default:
865622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            die("unknown buffer type: %d", buf->type);
866f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
867f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
868f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
869563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic std::string get_current_slot(Transport* transport)
870563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg{
871563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    std::string current_slot;
872563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (fb_getvar(transport, "current-slot", &current_slot)) {
873563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        if (current_slot == "_a") return "a"; // Legacy support
874563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        if (current_slot == "_b") return "b"; // Legacy support
875563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        return current_slot;
876563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    }
877563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    return "";
878563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg}
879563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg
880563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg// Legacy support
881563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic std::vector<std::string> get_suffixes_obsolete(Transport* transport) {
882b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    std::vector<std::string> suffixes;
883b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    std::string suffix_list;
8840b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, "slot-suffixes", &suffix_list)) {
885190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg        return suffixes;
886b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
887190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg    suffixes = android::base::Split(suffix_list, ",");
888190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg    // Unfortunately some devices will return an error message in the
889190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg    // guise of a valid value. If we only see only one suffix, it's probably
890190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg    // not real.
891190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg    if (suffixes.size() == 1) {
892190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg        suffixes.clear();
893190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg    }
894190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg    return suffixes;
895190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg}
896190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg
897563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg// Legacy support
898563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic bool supports_AB_obsolete(Transport* transport) {
899563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg  return !get_suffixes_obsolete(transport).empty();
900563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg}
901563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg
902563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic int get_slot_count(Transport* transport) {
903563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    std::string var;
904563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    int count;
905563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (!fb_getvar(transport, "slot-count", &var)) {
906563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        if (supports_AB_obsolete(transport)) return 2; // Legacy support
907563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    }
908563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (!android::base::ParseInt(var.c_str(), &count)) return 0;
909563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    return count;
910563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg}
911563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg
91289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Lightstatic bool supports_AB(Transport* transport) {
913563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg  return get_slot_count(transport) >= 2;
91489eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light}
91589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light
916190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg// Given a current slot, this returns what the 'other' slot is.
917563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic std::string get_other_slot(const std::string& current_slot, int count) {
918563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (count == 0) return "";
919563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg
920563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    char next = (current_slot[0] - 'a' + 1)%count + 'a';
921563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    return std::string(1, next);
922563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg}
923563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg
92489eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Lightstatic std::string get_other_slot(Transport* transport, const std::string& current_slot) {
925563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    return get_other_slot(current_slot, get_slot_count(transport));
926563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg}
927190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg
928563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic std::string get_other_slot(Transport* transport, int count) {
929563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    return get_other_slot(get_current_slot(transport), count);
930b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
931b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
93289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Lightstatic std::string get_other_slot(Transport* transport) {
933563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    return get_other_slot(get_current_slot(transport), get_slot_count(transport));
93489eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light}
93589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light
936563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic std::string verify_slot(Transport* transport, const std::string& slot_name, bool allow_all) {
937563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    std::string slot = slot_name;
938563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (slot == "_a") slot = "a"; // Legacy support
939563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (slot == "_b") slot = "b"; // Legacy support
940563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (slot == "all") {
9419b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        if (allow_all) {
9429b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            return "all";
9439b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        } else {
944563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            int count = get_slot_count(transport);
945563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            if (count > 0) {
946563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg                return "a";
9479b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            } else {
948c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg                die("No known slots.");
9499b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            }
9509b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        }
951b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
952c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg
953563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    int count = get_slot_count(transport);
954563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (count == 0) die("Device does not support slots.\n");
955c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg
956563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (slot == "other") {
957563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        std::string other = get_other_slot(transport, count);
958190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg        if (other == "") {
959190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg           die("No known slots.");
9608c32da39434e408e5316e462343d0d96070bc919Daniel Rosenberg        }
961190d968414b3889441843e1bbebdf7acc2dc88c8Daniel Rosenberg        return other;
962c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg    }
963c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg
964563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (slot.size() == 1 && (slot[0]-'a' >= 0 && slot[0]-'a' < count)) return slot;
965563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg
966563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot.c_str());
967563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    for (int i=0; i<count; i++) {
968563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        fprintf(stderr, "%c\n", (char)(i + 'a'));
969b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
970563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg
971b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    exit(1);
972b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
973b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
974563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic std::string verify_slot(Transport* transport, const std::string& slot) {
9759b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg   return verify_slot(transport, slot, true);
9769b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg}
9779b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg
978563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic void do_for_partition(Transport* transport, const std::string& part, const std::string& slot,
9790b156638307db890e5539b52521fd24beb3440cbDavid Pursell                             std::function<void(const std::string&)> func, bool force_slot) {
980a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg    std::string has_slot;
981b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    std::string current_slot;
982b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
983563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (!fb_getvar(transport, "has-slot:" + part, &has_slot)) {
984a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg        /* If has-slot is not supported, the answer is no. */
985a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg        has_slot = "no";
986b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
987a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg    if (has_slot == "yes") {
988563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        if (slot == "") {
989563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            current_slot = get_current_slot(transport);
990563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            if (current_slot == "") {
991b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                die("Failed to identify current slot.\n");
992b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            }
993563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            func(part + "_" + current_slot);
994b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        } else {
995563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            func(part + '_' + slot);
996b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        }
997b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    } else {
998563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        if (force_slot && slot != "") {
9990b156638307db890e5539b52521fd24beb3440cbDavid Pursell             fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n",
1000563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg                     part.c_str(), slot.c_str());
1001b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        }
1002b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        func(part);
1003b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
1004b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
1005b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
10060b156638307db890e5539b52521fd24beb3440cbDavid Pursell/* This function will find the real partition name given a base name, and a slot. If slot is NULL or
10070b156638307db890e5539b52521fd24beb3440cbDavid Pursell * empty, it will use the current slot. If slot is "all", it will return a list of all possible
10080b156638307db890e5539b52521fd24beb3440cbDavid Pursell * partition names. If force_slot is true, it will fail if a slot is specified, and the given
10090b156638307db890e5539b52521fd24beb3440cbDavid Pursell * partition does not support slots.
1010b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg */
1011563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenbergstatic void do_for_partitions(Transport* transport, const std::string& part, const std::string& slot,
10120b156638307db890e5539b52521fd24beb3440cbDavid Pursell                              std::function<void(const std::string&)> func, bool force_slot) {
1013a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg    std::string has_slot;
1014b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1015563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (slot == "all") {
1016563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        if (!fb_getvar(transport, "has-slot:" + part, &has_slot)) {
1017563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            die("Could not check if partition %s has slot.", part.c_str());
1018b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        }
1019a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg        if (has_slot == "yes") {
1020563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            for (int i=0; i < get_slot_count(transport); i++) {
1021563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg                do_for_partition(transport, part, std::string(1, (char)(i + 'a')), func, force_slot);
1022b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            }
1023b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        } else {
10240b156638307db890e5539b52521fd24beb3440cbDavid Pursell            do_for_partition(transport, part, "", func, force_slot);
1025b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        }
1026b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    } else {
10270b156638307db890e5539b52521fd24beb3440cbDavid Pursell        do_for_partition(transport, part, slot, func, force_slot);
1028b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
1029b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
1030b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
10310b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic void do_flash(Transport* transport, const char* pname, const char* fname) {
1032622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    struct fastboot_buffer buf;
1033622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
10340b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (load_buf(transport, fname, &buf)) {
1035622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("cannot load '%s'", fname);
1036622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
1037622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    flash_buf(pname, &buf);
1038f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
1039f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1040fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void do_update_signature(ZipArchiveHandle zip, char* fn) {
1041fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
1042d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    void* data = unzip_file(zip, fn, &sz);
1043fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) return;
1044dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_download("signature", data, sz);
1045dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_command("signature", "installing signature");
1046dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1047dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10489c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg// Sets slot_override as the active slot. If slot_override is blank,
10499c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg// set current slot as active instead. This clears slot-unbootable.
105089eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Lightstatic void set_active(Transport* transport, const std::string& slot_override) {
1051563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    std::string separator = "";
105289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    if (!supports_AB(transport)) {
1053563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        if (supports_AB_obsolete(transport)) {
1054563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            separator = "_"; // Legacy support
1055563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        } else {
1056563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            return;
1057563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        }
1058563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    }
1059563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (slot_override != "") {
1060563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        fb_set_active((separator + slot_override).c_str());
10619c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg    } else {
1062563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        std::string current_slot = get_current_slot(transport);
1063563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        if (current_slot != "") {
1064563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            fb_set_active((separator + current_slot).c_str());
10659c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg        }
10669c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg    }
10679c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg}
10689c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg
1069e180929866b218b901ba2069615794f076d06b13Daniel Rosenbergstatic void do_update(Transport* transport, const char* filename, const std::string& slot_override, bool erase_first, bool skip_secondary) {
1070dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    queue_info_dump();
1071dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1072b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    fb_queue_query_save("product", cur_product, sizeof(cur_product));
1073b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
1074d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    ZipArchiveHandle zip;
1075a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    int error = OpenArchive(filename, &zip);
1076a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    if (error != 0) {
1077f6e9ffbc734c7100914e8164f735317a85151033Narayan Kamath        CloseArchive(zip);
1078a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
1079d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    }
1080dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1081fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
1082253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    void* data = unzip_file(zip, "android-info.txt", &sz);
1083fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) {
1084f6e9ffbc734c7100914e8164f735317a85151033Narayan Kamath        CloseArchive(zip);
10857c6d884e2b4d48716f6d9403234403b8c101fb58Elliott Hughes        die("update package '%s' has no android-info.txt", filename);
1086dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1087dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1088253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    setup_requirements(reinterpret_cast<char*>(data), sz);
1089dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109089eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    std::string secondary;
1091e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    if (!skip_secondary) {
109289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        if (slot_override != "") {
109389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            secondary = get_other_slot(transport, slot_override);
109489eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        } else {
109589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            secondary = get_other_slot(transport);
109689eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        }
109789eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        if (secondary == "") {
109889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            if (supports_AB(transport)) {
109989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light                fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
110089eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            }
1101e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            skip_secondary = true;
110289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        }
110389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    }
1104acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes    for (size_t i = 0; i < ARRAY_SIZE(images); ++i) {
110589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        const char* slot = slot_override.c_str();
110689eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        if (images[i].is_secondary) {
1107e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            if (!skip_secondary) {
110889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light                slot = secondary.c_str();
110989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            } else {
111089eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light                continue;
111189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            }
111289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        }
111389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light
1114253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes        int fd = unzip_to_file(zip, images[i].img_name);
1115acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes        if (fd == -1) {
1116acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes            if (images[i].is_optional) {
1117622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                continue;
1118acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes            }
1119f6e9ffbc734c7100914e8164f735317a85151033Narayan Kamath            CloseArchive(zip);
1120acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes            exit(1); // unzip_to_file already explained why.
11215ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall        }
1122253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes        fastboot_buffer buf;
11230b156638307db890e5539b52521fd24beb3440cbDavid Pursell        int rc = load_buf_fd(transport, fd, &buf);
1124622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        if (rc) die("cannot load %s from flash", images[i].img_name);
1125b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1126b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        auto update = [&](const std::string &partition) {
1127b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            do_update_signature(zip, images[i].sig_name);
11280b156638307db890e5539b52521fd24beb3440cbDavid Pursell            if (erase_first && needs_erase(transport, partition.c_str())) {
1129b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                fb_queue_erase(partition.c_str());
1130b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            }
1131b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            flash_buf(partition.c_str(), &buf);
1132b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            /* not closing the fd here since the sparse code keeps the fd around
1133b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg             * but hasn't mmaped data yet. The tmpfile will get cleaned up when the
1134b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg             * program exits.
1135b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg             */
1136b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        };
113789eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        do_for_partitions(transport, images[i].part_name, slot, update, false);
11385ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall    }
1139d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes
1140d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    CloseArchive(zip);
1141e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    if (slot_override == "all") {
1142e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg        set_active(transport, "a");
1143e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    } else {
1144e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg        set_active(transport, slot_override);
1145e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    }
1146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
114889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Lightstatic void do_send_signature(const std::string& fn) {
114989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    std::size_t extension_loc = fn.find(".img");
115089eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    if (extension_loc == std::string::npos) return;
1151fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes
115289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    std::string fs_sig = fn.substr(0, extension_loc) + ".sig";
1153fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes
1154fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
115589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    void* data = load_file(fs_sig.c_str(), &sz);
1156fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) return;
1157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_download("signature", data, sz);
1158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_command("signature", "installing signature");
1159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1161e180929866b218b901ba2069615794f076d06b13Daniel Rosenbergstatic void do_flashall(Transport* transport, const std::string& slot_override, int erase_first, bool skip_secondary) {
116289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    std::string fname;
1163e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    queue_info_dump();
1164e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg
1165e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    fb_queue_query_save("product", cur_product, sizeof(cur_product));
1166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1167e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    fname = find_item("info", product);
1168e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    if (fname == "") die("cannot find android-info.txt");
1169b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
1170e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    int64_t sz;
1171e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    void* data = load_file(fname.c_str(), &sz);
1172e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno));
1173253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes
1174e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    setup_requirements(reinterpret_cast<char*>(data), sz);
1175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117689eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    std::string secondary;
1177e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    if (!skip_secondary) {
117889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        if (slot_override != "") {
117989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            secondary = get_other_slot(transport, slot_override);
118089eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        } else {
118189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            secondary = get_other_slot(transport);
118289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        }
118389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        if (secondary == "") {
118489eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            if (supports_AB(transport)) {
118589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light                fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
118689eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            }
1187e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            skip_secondary = true;
118889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        }
118989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light    }
1190253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes
1191253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
119289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        const char* slot = NULL;
119389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        if (images[i].is_secondary) {
1194e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            if (!skip_secondary) slot = secondary.c_str();
119589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        } else {
1196e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            slot = slot_override.c_str();
119789eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        }
119889eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        if (!slot) continue;
119989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        fname = find_item_given_name(images[i].img_name, product);
1200253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes        fastboot_buffer buf;
120189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        if (load_buf(transport, fname.c_str(), &buf)) {
120289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            if (images[i].is_optional) continue;
1203622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            die("could not load %s\n", images[i].img_name);
1204622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        }
1205b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1206b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        auto flashall = [&](const std::string &partition) {
1207b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            do_send_signature(fname);
12080b156638307db890e5539b52521fd24beb3440cbDavid Pursell            if (erase_first && needs_erase(transport, partition.c_str())) {
1209b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                fb_queue_erase(partition.c_str());
1210b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            }
1211b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            flash_buf(partition.c_str(), &buf);
1212b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        };
121389eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light        do_for_partitions(transport, images[i].part_name, slot, flashall, false);
12145ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall    }
12159c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg
1216e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    if (slot_override == "all") {
1217e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg        set_active(transport, "a");
1218e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    } else {
1219e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg        set_active(transport, slot_override);
1220e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    }
1221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define skip(n) do { argc -= (n); argv += (n); } while (0)
12242d13d1408bef9e26cc418e6fc2579dfd12378a3cJP Abgrall#define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0)
1225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122645be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughesstatic int do_bypass_unlock_command(int argc, char **argv)
122751e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin{
122851e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    if (argc <= 2) return 0;
122951e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    skip(2);
123051e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin
123151e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    /*
123251e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin     * Process unlock_bootloader, we have to load the message file
123351e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin     * and send that to the remote device.
123451e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin     */
123551e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    require(1);
1236259ad4a8e798025119b0cec3c11199239b59fa12Elliott Hughes
1237259ad4a8e798025119b0cec3c11199239b59fa12Elliott Hughes    int64_t sz;
1238259ad4a8e798025119b0cec3c11199239b59fa12Elliott Hughes    void* data = load_file(*argv, &sz);
1239259ad4a8e798025119b0cec3c11199239b59fa12Elliott Hughes    if (data == nullptr) die("could not load '%s': %s", *argv, strerror(errno));
124051e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    fb_queue_download("unlock_message", data, sz);
124151e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    fb_queue_command("flashing unlock_bootloader", "unlocking bootloader");
124251e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    skip(1);
124351e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    return 0;
124451e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin}
124551e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin
124645be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughesstatic int do_oem_command(int argc, char **argv)
1247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char command[256];
1249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (argc <= 1) return 0;
1250ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
1251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    command[0] = 0;
1252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(1) {
1253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcat(command,*argv);
1254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        skip(1);
1255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(argc == 0) break;
1256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcat(command," ");
1257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1259ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    fb_queue_command(command,"");
1260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
1261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1263f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t parse_num(const char *arg)
1264f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
1265f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    char *endptr;
1266f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    unsigned long long num;
1267f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1268f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    num = strtoull(arg, &endptr, 0);
1269f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (endptr == arg) {
1270f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
1271f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
1272f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1273f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (*endptr == 'k' || *endptr == 'K') {
1274f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / 1024) {
1275f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
1276f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
1277f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL;
1278f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
1279f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (*endptr == 'm' || *endptr == 'M') {
1280f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / (1024 * 1024)) {
1281f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
1282f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
1283f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL * 1024LL;
1284f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
1285f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (*endptr == 'g' || *endptr == 'G') {
1286f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / (1024 * 1024 * 1024)) {
1287f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
1288f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
1289f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL * 1024LL * 1024LL;
1290f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
1291f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
1292f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1293f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (*endptr != '\0') {
1294f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
1295f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
1296f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1297f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (num > INT64_MAX) {
1298f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
1299f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
1300f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1301f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return num;
1302f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
1303f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
13040b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic void fb_perform_format(Transport* transport,
13052fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes                              const char* partition, int skip_if_not_supported,
13068f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                              const char* type_override, const char* size_override,
13078f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                              const std::string& initial_dir) {
13082fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    std::string partition_type, partition_size;
13092fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes
1310e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    struct fastboot_buffer buf;
13112fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    const char* errMsg = nullptr;
13122fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    const struct fs_generator* gen = nullptr;
1313e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    int fd;
1314e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
13152fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    unsigned int limit = INT_MAX;
13162fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (target_sparse_limit > 0 && target_sparse_limit < limit) {
1317e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        limit = target_sparse_limit;
13182fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
13192fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (sparse_limit > 0 && sparse_limit < limit) {
1320e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        limit = sparse_limit;
13212fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
1322e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
13230b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) {
1324e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        errMsg = "Can't determine partition type.\n";
1325e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        goto failed;
1326e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
13277e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    if (type_override) {
13282fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        if (partition_type != type_override) {
13292fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fprintf(stderr, "Warning: %s type is %s, but %s was requested for formatting.\n",
13302fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes                    partition, partition_type.c_str(), type_override);
13317e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        }
13322fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        partition_type = type_override;
13337e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    }
1334e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
13350b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, std::string("partition-size:") + partition, &partition_size)) {
1336e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        errMsg = "Unable to get partition size\n";
1337e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        goto failed;
1338e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
13397e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    if (size_override) {
13402fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        if (partition_size != size_override) {
13412fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fprintf(stderr, "Warning: %s size is %s, but %s was requested for formatting.\n",
13422fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes                    partition, partition_size.c_str(), size_override);
13437e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        }
13442fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        partition_size = size_override;
13457e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    }
1346a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    // Some bootloaders (angler, for example), send spurious leading whitespace.
1347a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    partition_size = android::base::Trim(partition_size);
1348a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    // Some bootloaders (hammerhead, for example) use implicit hex.
1349a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    // This code used to use strtol with base 16.
1350a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    if (!android::base::StartsWith(partition_size, "0x")) partition_size = "0x" + partition_size;
1351e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
13528ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes    gen = fs_get_generator(partition_type);
1353e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (!gen) {
1354e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        if (skip_if_not_supported) {
1355e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg            fprintf(stderr, "Erase successful, but not automatically formatting.\n");
13562fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fprintf(stderr, "File system type %s not supported.\n", partition_type.c_str());
1357e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg            return;
1358e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        }
13592fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "Formatting is not supported for file system with type '%s'.\n",
13602fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes                partition_type.c_str());
1361e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
1362e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
1363e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
13642fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    int64_t size;
13652fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (!android::base::ParseInt(partition_size.c_str(), &size)) {
13662fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "Couldn't parse partition size '%s'.\n", partition_size.c_str());
13672fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        return;
13682fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
1369e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
1370e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    fd = fileno(tmpfile());
13718f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (fs_generator_generate(gen, fd, size, initial_dir)) {
13722fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "Cannot generate image: %s\n", strerror(errno));
1373e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        close(fd);
1374e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
1375e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
1376e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
13770b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (load_buf_fd(transport, fd, &buf)) {
13782fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "Cannot read image: %s\n", strerror(errno));
1379e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        close(fd);
1380e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
1381e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
1382e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    flash_buf(partition, &buf);
1383e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    return;
1384e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
1385e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinbergfailed:
1386e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (skip_if_not_supported) {
1387e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        fprintf(stderr, "Erase successful, but not automatically formatting.\n");
13882fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        if (errMsg) fprintf(stderr, "%s", errMsg);
1389e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
1390e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    fprintf(stderr,"FAILED (%s)\n", fb_get_error());
1391e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg}
1392e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
1393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint main(int argc, char **argv)
1394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
13950d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    bool wants_wipe = false;
13960d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    bool wants_reboot = false;
13970d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    bool wants_reboot_bootloader = false;
13980d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    bool wants_set_active = false;
1399e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg    bool skip_secondary = false;
1400fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    bool erase_first = true;
14018f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    bool set_fbe_marker = false;
1402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *data;
1403fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
140427ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle    int longindex;
1405b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    std::string slot_override;
14060d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    std::string next_active;
1407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
14087b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    const struct option longopts[] = {
14097b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"base", required_argument, 0, 'b'},
14107b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"kernel_offset", required_argument, 0, 'k'},
14117aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"kernel-offset", required_argument, 0, 'k'},
14127b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"page_size", required_argument, 0, 'n'},
14137aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"page-size", required_argument, 0, 'n'},
14147b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"ramdisk_offset", required_argument, 0, 'r'},
14157aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"ramdisk-offset", required_argument, 0, 'r'},
141629fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash        {"tags_offset", required_argument, 0, 't'},
14177aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"tags-offset", required_argument, 0, 't'},
1418379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes        {"help", no_argument, 0, 'h'},
1419379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes        {"unbuffered", no_argument, 0, 0},
1420379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes        {"version", no_argument, 0, 0},
1421b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        {"slot", required_argument, 0, 0},
14220d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        {"set_active", optional_argument, 0, 'a'},
14237aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"set-active", optional_argument, 0, 'a'},
1424e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg        {"skip-secondary", no_argument, 0, 0},
14258f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#if !defined(_WIN32)
14268f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        {"wipe-and-use-fbe", no_argument, 0, 0},
14278f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#endif
14287b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {0, 0, 0, 0}
14297b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    };
14308879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
14318879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    serial = getenv("ANDROID_SERIAL");
14328879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
14338879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    while (1) {
14340d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:ha::", longopts, &longindex);
14358879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        if (c < 0) {
14368879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
14378879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        }
14387b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        /* Alphabetical cases */
14398879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        switch (c) {
14400d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        case 'a':
14410d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_set_active = true;
14420d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            if (optarg)
14430d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg                next_active = optarg;
14440d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            break;
14458879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 'b':
14468879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            base_addr = strtoul(optarg, 0, 16);
14478879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
14487b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'c':
14497b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            cmdline = optarg;
14507b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
14517b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'h':
14527b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            usage();
14537b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            return 1;
14547b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'i': {
1455fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                char *endptr = nullptr;
14567b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                unsigned long val;
14577b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
14587b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                val = strtoul(optarg, &endptr, 0);
14597b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                if (!endptr || *endptr != '\0' || (val & ~0xffff))
14607b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                    die("invalid vendor id '%s'", optarg);
14617b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                vendor_id = (unsigned short)val;
14627b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                break;
14637b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            }
14647b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'k':
14657b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            kernel_offset = strtoul(optarg, 0, 16);
14667b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
14677b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'l':
14687b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            long_listing = 1;
14697b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
14708879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 'n':
1471fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            page_size = (unsigned)strtoul(optarg, nullptr, 0);
14728879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            if (!page_size) die("invalid page size");
14738879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
14747b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'p':
14757b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            product = optarg;
14767b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
14777b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'r':
14787b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            ramdisk_offset = strtoul(optarg, 0, 16);
14797b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
148029fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash        case 't':
148129fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash            tags_offset = strtoul(optarg, 0, 16);
148229fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash            break;
14838879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 's':
14848879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            serial = optarg;
14858879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
1486f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        case 'S':
1487f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            sparse_limit = parse_num(optarg);
1488f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            if (sparse_limit < 0) {
1489f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross                    die("invalid sparse limit");
1490f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            }
1491f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            break;
14927b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'u':
1493fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            erase_first = false;
14948879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
14957b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'w':
14960d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_wipe = true;
14978879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
14988879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case '?':
14998879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            return 1;
150027ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle        case 0:
150127ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle            if (strcmp("unbuffered", longopts[longindex].name) == 0) {
1502fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                setvbuf(stdout, nullptr, _IONBF, 0);
1503fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                setvbuf(stderr, nullptr, _IONBF, 0);
1504379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes            } else if (strcmp("version", longopts[longindex].name) == 0) {
1505379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes                fprintf(stdout, "fastboot version %s\n", FASTBOOT_REVISION);
1506379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes                return 0;
1507b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            } else if (strcmp("slot", longopts[longindex].name) == 0) {
1508b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                slot_override = std::string(optarg);
1509e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            } else if (strcmp("skip-secondary", longopts[longindex].name) == 0 ) {
1510e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg                skip_secondary = true;
15118f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#if !defined(_WIN32)
15128f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            } else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) {
15138f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                wants_wipe = true;
15148f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                set_fbe_marker = true;
15158f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#endif
15168f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            } else {
15178f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                fprintf(stderr, "Internal error in options processing for %s\n",
15188f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                    longopts[longindex].name);
15198f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                return 1;
152027ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle            }
152127ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle            break;
15228879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        default:
15238879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            abort();
15248879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        }
15258879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    }
1526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
15278879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    argc -= optind;
15288879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    argv += optind;
15298879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
15300d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    if (argc == 0 && !wants_wipe && !wants_set_active) {
1531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usage();
1532eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom        return 1;
1533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
15358fb6e06ba44b92258bf44110ea5361496257e24eColin Cross    if (argc > 0 && !strcmp(*argv, "devices")) {
15368879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        skip(1);
1537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        list_devices();
1538ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang        return 0;
1539ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    }
1540ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
1541c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross    if (argc > 0 && !strcmp(*argv, "help")) {
1542c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross        usage();
1543c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross        return 0;
1544c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross    }
1545c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross
15460b156638307db890e5539b52521fd24beb3440cbDavid Pursell    Transport* transport = open_device();
15472ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (transport == nullptr) {
15482ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return 1;
15492ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
15502ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1551563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (!supports_AB(transport) && supports_AB_obsolete(transport)) {
1552563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg        fprintf(stderr, "Warning: Device A/B support is outdated. Bootloader update required.\n");
1553563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    }
1554563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (slot_override != "") slot_override = verify_slot(transport, slot_override);
1555563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg    if (next_active != "") next_active = verify_slot(transport, next_active, false);
15560d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg
15570d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    if (wants_set_active) {
15580d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        if (next_active == "") {
15590d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            if (slot_override == "") {
15609c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg                std::string current_slot;
15619c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg                if (fb_getvar(transport, "current-slot", &current_slot)) {
1562563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg                    next_active = verify_slot(transport, current_slot, false);
15639c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg                } else {
15649c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg                    wants_set_active = false;
15659c9a6c62e5a6dde562a291a11602d4f32b2c1c80Daniel Rosenberg                }
15660d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            } else {
1567563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg                next_active = verify_slot(transport, slot_override, false);
15680d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            }
15690d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        }
15700d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    }
157131dbed7b60d8237d6d05dc6bf230167a5854b77aElliott Hughes
1572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (argc > 0) {
15732fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        if (!strcmp(*argv, "getvar")) {
1574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_display(argv[1], argv[1]);
1576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
1577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "erase")) {
1578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
15795ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
1580b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            auto erase = [&](const std::string &partition) {
15810b156638307db890e5539b52521fd24beb3440cbDavid Pursell                std::string partition_type;
15820b156638307db890e5539b52521fd24beb3440cbDavid Pursell                if (fb_getvar(transport, std::string("partition-type:") + argv[1], &partition_type) &&
1583b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                    fs_get_generator(partition_type) != nullptr) {
1584b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                    fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n",
1585b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                            partition_type.c_str());
1586b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                }
15875ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
1588b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                fb_queue_erase(partition.c_str());
1589b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            };
1590563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            do_for_partitions(transport, argv[1], slot_override, erase, true);
1591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
15927e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        } else if(!strncmp(*argv, "format", strlen("format"))) {
15937e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            char *overrides;
1594fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            char *type_override = nullptr;
1595fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            char *size_override = nullptr;
1596c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau            require(2);
15977e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            /*
15987e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             * Parsing for: "format[:[type][:[size]]]"
15997e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             * Some valid things:
16007e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *  - select ontly the size, and leave default fs type:
16017e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format::0x4000000 userdata
16027e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *  - default fs type and size:
16037e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format userdata
16047e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format:: userdata
16057e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             */
16067e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            overrides = strchr(*argv, ':');
16077e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            if (overrides) {
16087e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                overrides++;
16097e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                size_override = strchr(overrides, ':');
16107e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                if (size_override) {
16117e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    size_override[0] = '\0';
16127e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    size_override++;
16137e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                }
16147e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                type_override = overrides;
16157e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            }
1616fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            if (type_override && !type_override[0]) type_override = nullptr;
1617fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            if (size_override && !size_override[0]) size_override = nullptr;
1618b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1619b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            auto format = [&](const std::string &partition) {
16200b156638307db890e5539b52521fd24beb3440cbDavid Pursell                if (erase_first && needs_erase(transport, partition.c_str())) {
1621b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                    fb_queue_erase(partition.c_str());
1622b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                }
16238f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                fb_perform_format(transport, partition.c_str(), 0,
16248f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                    type_override, size_override, "");
1625b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            };
1626563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            do_for_partitions(transport, argv[1], slot_override, format, true);
1627c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau            skip(2);
1628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "signature")) {
1629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            data = load_file(argv[1], &sz);
1631fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            if (data == nullptr) die("could not load '%s': %s", argv[1], strerror(errno));
1632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (sz != 256) die("signature must be 256 bytes");
1633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_download("signature", data, sz);
1634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("signature", "installing signature");
1635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
1636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "reboot")) {
16370d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_reboot = true;
1638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1639ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes            if (argc > 0) {
1640ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes                if (!strcmp(*argv, "bootloader")) {
16410d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg                    wants_reboot = false;
16420d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg                    wants_reboot_bootloader = true;
1643ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes                    skip(1);
1644ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes                }
1645ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes            }
1646ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes            require(0);
1647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "reboot-bootloader")) {
16480d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_reboot_bootloader = true;
1649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strcmp(*argv, "continue")) {
1651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("continue", "resuming boot");
1652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "boot")) {
1654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *kname = 0;
1655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *rname = 0;
1656a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            char *sname = 0;
1657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 0) {
1659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kname = argv[0];
1660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 0) {
1663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                rname = argv[0];
1664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1666a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            if (argc > 0) {
1667a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                sname = argv[0];
1668a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                skip(1);
1669a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            }
1670a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
1671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (data == 0) return 1;
1672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_download("boot.img", data, sz);
1673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("boot", "booting");
1674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flash")) {
1675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *pname = argv[1];
167689eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            std::string fname;
1677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 2) {
1679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fname = argv[2];
1680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(3);
1681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
1682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fname = find_item(pname, product);
1683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(2);
1684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
168589eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            if (fname == "") die("cannot determine image filename for '%s'", pname);
1686b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1687b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            auto flash = [&](const std::string &partition) {
16880b156638307db890e5539b52521fd24beb3440cbDavid Pursell                if (erase_first && needs_erase(transport, partition.c_str())) {
1689b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                    fb_queue_erase(partition.c_str());
1690b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                }
169189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light                do_flash(transport, partition.c_str(), fname.c_str());
1692b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            };
1693563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            do_for_partitions(transport, pname, slot_override, flash, true);
1694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flash:raw")) {
1695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *kname = argv[2];
1696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *rname = 0;
1697a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            char *sname = 0;
1698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(3);
1699a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            skip(3);
1700a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            if (argc > 0) {
1701a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                rname = argv[0];
1702a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                skip(1);
1703a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            }
1704a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            if (argc > 0) {
1705a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                sname = argv[0];
1706a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                skip(1);
1707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1708a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
1709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (data == 0) die("cannot load bootable image");
1710b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            auto flashraw = [&](const std::string &partition) {
1711b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                fb_queue_flash(partition.c_str(), data, sz);
1712b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            };
1713563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            do_for_partitions(transport, argv[1], slot_override, flashraw, true);
1714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flashall")) {
1715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
171689eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            if (slot_override == "all") {
1717e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg                fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
1718e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg                do_flashall(transport, slot_override, erase_first, true);
171989eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            } else {
1720e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg                do_flashall(transport, slot_override, erase_first, skip_secondary);
172189eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            }
172289eb689d5cdc153f1daa7eb87de4ac04381494f0Alex Light            wants_reboot = true;
1723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "update")) {
1724e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            bool slot_all = (slot_override == "all");
1725e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            if (slot_all) {
1726e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg                fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
1727e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg            }
1728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 1) {
1729e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg                do_update(transport, argv[1], slot_override, erase_first, skip_secondary || slot_all);
1730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(2);
1731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
1732e180929866b218b901ba2069615794f076d06b13Daniel Rosenberg                do_update(transport, "update.zip", slot_override, erase_first, skip_secondary || slot_all);
1733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
17359b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            wants_reboot = 1;
17369b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        } else if(!strcmp(*argv, "set_active")) {
17379b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            require(2);
1738563fcf6f697c898cf35fa4a1b5672d6b4890c283Daniel Rosenberg            std::string slot = verify_slot(transport, std::string(argv[1]), false);
17399b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            fb_set_active(slot.c_str());
17409b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            skip(2);
1741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "oem")) {
1742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            argc = do_oem_command(argc, argv);
174351e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin        } else if(!strcmp(*argv, "flashing")) {
174451e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            if (argc == 2 && (!strcmp(*(argv+1), "unlock") ||
174551e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "lock") ||
174651e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "unlock_critical") ||
174751e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "lock_critical") ||
174851e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "get_unlock_ability") ||
174951e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "get_unlock_bootloader_nonce") ||
175051e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "lock_bootloader"))) {
175151e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                argc = do_oem_command(argc, argv);
175251e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            } else
175351e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            if (argc == 3 && !strcmp(*(argv+1), "unlock_bootloader")) {
175451e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                argc = do_bypass_unlock_command(argc, argv);
1755bf11095f92c9278cb794a5336e1cce264f9b734dBadhri Jagan Sridharan            } else {
1756bf11095f92c9278cb794a5336e1cce264f9b734dBadhri Jagan Sridharan              usage();
1757bf11095f92c9278cb794a5336e1cce264f9b734dBadhri Jagan Sridharan              return 1;
1758bf11095f92c9278cb794a5336e1cce264f9b734dBadhri Jagan Sridharan            }
1759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            usage();
1761ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang            return 1;
1762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (wants_wipe) {
17662fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "wiping userdata...\n");
1767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_erase("userdata");
17688f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        if (set_fbe_marker) {
17698f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            fprintf(stderr, "setting FBE marker...\n");
17708f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            std::string initial_userdata_dir = create_fbemarker_tmpdir();
17718f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            if (initial_userdata_dir.empty()) {
17728f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                return 1;
17738f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            }
17748f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            fb_perform_format(transport, "userdata", 1, nullptr, nullptr, initial_userdata_dir);
17758f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            delete_fbemarker_tmpdir(initial_userdata_dir);
17768f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        } else {
17778f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            fb_perform_format(transport, "userdata", 1, nullptr, nullptr, "");
17788f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        }
17792fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes
17802fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        std::string cache_type;
17810b156638307db890e5539b52521fd24beb3440cbDavid Pursell        if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
17822fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fprintf(stderr, "wiping cache...\n");
17832fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fb_queue_erase("cache");
17848f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            fb_perform_format(transport, "cache", 1, nullptr, nullptr, "");
17852fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        }
1786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
17870d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    if (wants_set_active) {
17880d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        fb_set_active(next_active.c_str());
17890d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    }
1790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (wants_reboot) {
1791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_reboot();
1792ec25e7bc4bb8c203f89f133136a62a08410d6cebMark Wachsler        fb_queue_wait_for_disconnect();
1793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (wants_reboot_bootloader) {
1794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_command("reboot-bootloader", "rebooting into bootloader");
1795157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler        fb_queue_wait_for_disconnect();
1796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17980b156638307db890e5539b52521fd24beb3440cbDavid Pursell    return fb_execute_queue(transport) ? EXIT_FAILURE : EXIT_SUCCESS;
1799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1800