fastboot.cpp revision 5a0ec81e97f45edb9cc86e9e551864ee6d7ee210
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>
524f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/strings.h>
53f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#include <sparse/sparse.h>
54d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes#include <ziparchive/zip_archive.h>
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
56253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes#include "bootimg_utils.h"
571b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes#include "diagnose_usb.h"
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "fastboot.h"
59e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg#include "fs.h"
602ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell#include "tcp.h"
610b156638307db890e5539b52521fd24beb3440cbDavid Pursell#include "transport.h"
625a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell#include "udp.h"
630b156638307db890e5539b52521fd24beb3440cbDavid Pursell#include "usb.h"
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
65f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#ifndef O_BINARY
66f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#define O_BINARY 0
67f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#endif
68f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
69622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
70622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
71b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Savillechar cur_product[FB_RESPONSE_SZ + 1];
72b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
732ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic const char* serial = nullptr;
742ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic const char* product = nullptr;
752ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursellstatic const char* cmdline = nullptr;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned short vendor_id = 0;
7713081c6915220db03886b177f1a8e0b2c63467c9Scott Andersonstatic int long_listing = 0;
78f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t sparse_limit = -1;
79f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t target_sparse_limit = -1;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
81fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned page_size = 2048;
82fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned base_addr      = 0x10000000;
83fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned kernel_offset  = 0x00008000;
84fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned ramdisk_offset = 0x01000000;
85fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned second_offset  = 0x00f00000;
86fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic unsigned tags_offset    = 0x00000100;
877b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
888f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic const std::string convert_fbe_marker_filename("convert_fbe");
898f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
90622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandenum fb_buffer_type {
91622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    FB_BUFFER,
92622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    FB_BUFFER_SPARSE,
93622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
94622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
95622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstruct fastboot_buffer {
96622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    enum fb_buffer_type type;
97fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* data;
98fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
99622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
100622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
101622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic struct {
102622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    char img_name[13];
103622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    char sig_name[13];
104622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    char part_name[9];
105622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    bool is_optional;
106f530c93c4aab818de51fd7123199bef6621047f8Daniel Rosenberg} images[] = {
107622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    {"boot.img", "boot.sig", "boot", false},
108622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    {"recovery.img", "recovery.sig", "recovery", true},
109622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    {"system.img", "system.sig", "system", false},
110f530c93c4aab818de51fd7123199bef6621047f8Daniel Rosenberg    {"vendor.img", "vendor.sig", "vendor", true},
111622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
1122a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland
113fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic char* find_item(const char* item, const char* product) {
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *dir;
115253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    const char *fn;
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char path[PATH_MAX + 128];
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strcmp(item,"boot")) {
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "boot.img";
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"recovery")) {
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "recovery.img";
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"system")) {
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "system.img";
124f530c93c4aab818de51fd7123199bef6621047f8Daniel Rosenberg    } else if(!strcmp(item,"vendor")) {
125f530c93c4aab818de51fd7123199bef6621047f8Daniel Rosenberg        fn = "vendor.img";
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"userdata")) {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "userdata.img";
128d7608a40d6bed0d8ca686414a5a4f44b6d4d0435Jean-Baptiste Queru    } else if(!strcmp(item,"cache")) {
129d7608a40d6bed0d8ca686414a5a4f44b6d4d0435Jean-Baptiste Queru        fn = "cache.img";
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"info")) {
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "android-info.txt";
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"unknown partition '%s'\n", item);
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(product) {
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        get_my_path(path);
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(path + strlen(path),
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                "../../../target/product/%s/%s", product, fn);
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return strdup(path);
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
143ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dir = getenv("ANDROID_PRODUCT_OUT");
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((dir == 0) || (dir[0] == 0)) {
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
149ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sprintf(path, "%s/%s", dir, fn);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return strdup(path);
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic int64_t get_file_size(int fd) {
155fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    struct stat sb;
156fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    return fstat(fd, &sb) == -1 ? -1 : sb.st_size;
157f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
158f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
159fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void* load_fd(int fd, int64_t* sz) {
16064ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    int errno_tmp;
161fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    char* data = nullptr;
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
163fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    *sz = get_file_size(fd);
164fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (*sz < 0) {
165622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        goto oops;
166622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
168fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    data = (char*) malloc(*sz);
169fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) goto oops;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
171fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if(read(fd, data, *sz) != *sz) goto oops;
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return data;
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectoops:
17764ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    errno_tmp = errno;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(data != 0) free(data);
18064ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    errno = errno_tmp;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
184fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void* load_file(const char* fn, int64_t* sz) {
185fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int fd = open(fn, O_RDONLY | O_BINARY);
186fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (fd == -1) return nullptr;
187fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    return load_fd(fd, sz);
188622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
190fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
191e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes    // Require a matching vendor id if the user specified one with -i.
192b46964f3c9f5389dc9d000dcc5e740a3833d3a81Elliott Hughes    if (vendor_id != 0 && info->dev_vendor != vendor_id) {
193e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes        return -1;
194e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes    }
195e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes
196e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes    if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) {
197e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes        return -1;
198e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes    }
199e1746fda6a30ebaea22e492bc7821a9dee5face8Elliott Hughes
20013081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson    // require matching serial number or device path if requested
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // at the command line with the -s option.
202a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrall    if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
203a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrall                   strcmp(local_serial, info->device_path) != 0)) return -1;
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
207fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic int match_fastboot(usb_ifc_info* info) {
2087b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    return match_fastboot_with_serial(info, serial);
2097b8970c577c788c9af582dac797c63b3134b201eJP Abgrall}
2107b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
211fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic int list_devices_callback(usb_ifc_info* info) {
212fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (match_fastboot_with_serial(info, nullptr) == 0) {
2131b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes        std::string serial = info->serial_number;
214b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes        if (!info->writable) {
2151b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes            serial = UsbNoPermissionsShortHelpText();
216b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes        }
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!serial[0]) {
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            serial = "????????????";
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
220866b1bd5051db4f22b634df1f8a06bc1c9aa2e26Scott Anderson        // output compatible with "adb devices"
22113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        if (!long_listing) {
2221b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes            printf("%s\tfastboot", serial.c_str());
22313081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        } else {
2241b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes            printf("%-22s fastboot", serial.c_str());
2251b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes            if (strlen(info->device_path) > 0) printf(" %s", info->device_path);
22613081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        }
2271b708d368f29e6053064c9cf6949ab6ebdbb7ac5Elliott Hughes        putchar('\n');
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2332ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// Opens a new Transport connected to a device. If |serial| is non-null it will be used to identify
2342ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// a specific device, otherwise the first USB device found will be used.
2352ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell//
2362ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// If |serial| is non-null but invalid, this prints an error message to stderr and returns nullptr.
2372ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// Otherwise it blocks until the target is available.
2382ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell//
2392ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// The returned Transport is a singleton, so multiple calls to this function will return the same
2402ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell// object, and the caller should not attempt to delete the returned Transport.
2410b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic Transport* open_device() {
2420b156638307db890e5539b52521fd24beb3440cbDavid Pursell    static Transport* transport = nullptr;
2432ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    bool announce = true;
2442ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
2452ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (transport != nullptr) {
2462ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return transport;
2472ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
2482ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
2495a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    Socket::Protocol protocol = Socket::Protocol::kTcp;
2502ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    std::string host;
2515a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    int port = 0;
2525a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell    if (serial != nullptr) {
2535a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        const char* net_address = nullptr;
2545a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2555a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (android::base::StartsWith(serial, "tcp:")) {
2565a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            protocol = Socket::Protocol::kTcp;
2575a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            port = tcp::kDefaultPort;
2585a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            net_address = serial + strlen("tcp:");
2595a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        } else if (android::base::StartsWith(serial, "udp:")) {
2605a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            protocol = Socket::Protocol::kUdp;
2615a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            port = udp::kDefaultPort;
2625a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            net_address = serial + strlen("udp:");
2635a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        }
2645a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2655a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell        if (net_address != nullptr) {
2665a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            std::string error;
2675a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) {
2685a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                fprintf(stderr, "error: Invalid network address '%s': %s\n", net_address,
2695a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                        error.c_str());
2705a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                return nullptr;
2715a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            }
2722ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        }
2732ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2752ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    while (true) {
2762ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        if (!host.empty()) {
2772ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            std::string error;
2785a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            if (protocol == Socket::Protocol::kTcp) {
2795a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                transport = tcp::Connect(host, port, &error).release();
2805a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            } else if (protocol == Socket::Protocol::kUdp) {
2815a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell                transport = udp::Connect(host, port, &error).release();
2825a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            }
2835a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell
2842ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            if (transport == nullptr && announce) {
2852ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell                fprintf(stderr, "error: %s\n", error.c_str());
2862ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            }
2872ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        } else {
2882ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            transport = usb_open(match_fastboot);
2892ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        }
2902ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
2912ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        if (transport != nullptr) {
2922ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            return transport;
2932ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        }
294ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
2950b156638307db890e5539b52521fd24beb3440cbDavid Pursell        if (announce) {
2962ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            announce = false;
297b46964f3c9f5389dc9d000dcc5e740a3833d3a81Elliott Hughes            fprintf(stderr, "< waiting for %s >\n", serial ? serial : "any device");
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
2995957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn        usleep(1000);
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
303fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void list_devices() {
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // We don't actually open a USB device here,
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // just getting our callback called so we can
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // list all the connected devices.
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_open(list_devices_callback);
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
310fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void usage() {
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*           1234567890123456789012345678901234567890123456789012345678901234567890123456 */
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "usage: fastboot [ <option> ] <command>\n"
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "\n"
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "commands:\n"
31608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  update <filename>                        Reflash device from update.zip.\n"
31708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashall                                 Flash boot, system, vendor, and --\n"
31808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           if found -- recovery.\n"
31908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flash <partition> [ <filename> ]         Write a file to a flash partition.\n"
32008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing lock                            Locks the device. Prevents flashing.\n"
32108df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing unlock                          Unlocks the device. Allows flashing\n"
32208df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           any partition except\n"
32308df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           bootloader-related partitions.\n"
32408df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing lock_critical                   Prevents flashing bootloader-related\n"
32508df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           partitions.\n"
32608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing unlock_critical                 Enables flashing bootloader-related\n"
32708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           partitions.\n"
32808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flashing get_unlock_ability              Queries bootloader to see if the\n"
32908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           device is unlocked.\n"
33051e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            "  flashing get_unlock_bootloader_nonce     Queries the bootloader to get the\n"
33145be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughes            "                                           unlock nonce.\n"
33245be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughes            "  flashing unlock_bootloader <request>     Issue unlock bootloader using request.\n"
33351e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            "  flashing lock_bootloader                 Locks the bootloader to prevent\n"
33445be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughes            "                                           bootloader version rollback.\n"
33508df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  erase <partition>                        Erase a flash partition.\n"
33608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  format[:[<fs type>][:[<size>]] <partition>\n"
33708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           Format a flash partition. Can\n"
33808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           override the fs type and/or size\n"
33908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           the bootloader reports.\n"
34008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  getvar <variable>                        Display a bootloader variable.\n"
3419b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            "  set_active <suffix>                      Sets the active slot. If slots are\n"
3429b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            "                                           not supported, this does nothing.\n"
34308df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n"
34408df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  flash:raw boot <kernel> [ <ramdisk> [ <second> ] ]\n"
34508df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           Create bootimage and flash it.\n"
34608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  devices [-l]                             List all connected devices [with\n"
34708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           device paths].\n"
34808df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  continue                                 Continue with autoboot.\n"
34908df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  reboot [bootloader]                      Reboot device [into bootloader].\n"
35008df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  reboot-bootloader                        Reboot device into bootloader.\n"
35108df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  help                                     Show this help message.\n"
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "\n"
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "options:\n"
35408df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -w                                       Erase userdata and cache (and format\n"
35508df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           if supported by partition type).\n"
35608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -u                                       Do not erase partition before\n"
35708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           formatting.\n"
3582ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            "  -s <specific device>                     Specify a device. For USB, provide either\n"
3592ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell            "                                           a serial number or path to device port.\n"
3605a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            "                                           For ethernet, provide an address in the"
3615a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            "                                           form <protocol>:<hostname>[:port] where"
3625a0ec81e97f45edb9cc86e9e551864ee6d7ee210David Pursell            "                                           <protocol> is either tcp or udp.\n"
36308df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -p <product>                             Specify product name.\n"
36408df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -c <cmdline>                             Override kernel commandline.\n"
36508df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -i <vendor id>                           Specify a custom USB vendor id.\n"
3667aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  -b, --base <base_addr>                   Specify a custom kernel base\n"
36708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           address (default: 0x10000000).\n"
3687aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --kernel-offset                          Specify a custom kernel offset.\n"
3697aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "                                           (default: 0x00008000)\n"
3707aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --ramdisk-offset                         Specify a custom ramdisk offset.\n"
3717aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "                                           (default: 0x01000000)\n"
3727aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --tags-offset                            Specify a custom tags offset.\n"
3737aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "                                           (default: 0x00000100)\n"
3747aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  -n, --page-size <page size>              Specify the nand page size\n"
37508df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           (default: 2048).\n"
37608df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "  -S <size>[K|M|G]                         Automatically sparse files greater\n"
37708df533e2af49e49e958176a79b2747eb2539ac4Elliott Hughes            "                                           than 'size'. 0 to disable.\n"
378b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            "  --slot <suffix>                          Specify slot suffix to be used if the\n"
379b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            "                                           device supports slots. This will be\n"
380b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            "                                           added to all partition names that use\n"
381b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            "                                           slots. 'all' can be given to refer\n"
382c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg            "                                           to all slots. 'other' can be given to\n"
383c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg            "                                           refer to a non-current slot. If this\n"
384c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg            "                                           flag is not used, slotted partitions\n"
385c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg            "                                           will default to the current active slot.\n"
3867aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  -a, --set-active[=<suffix>]              Sets the active slot. If no suffix is\n"
3870d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            "                                           provided, this will default to the value\n"
3880d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            "                                           given by --slot. If slots are not\n"
3899b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            "                                           supported, this does nothing. This will\n"
3909b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            "                                           run after all non-reboot commands.\n"
3918f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#if !defined(_WIN32)
3928f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            "  --wipe-and-use-fbe                       On devices which support it,\n"
3938f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            "                                           erase userdata and cache, and\n"
3948f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            "                                           enable file-based encryption\n"
3958f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#endif
3967aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --unbuffered                             Do not buffer input or output.\n"
3977aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  --version                                Display version.\n"
3987aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg            "  -h, --help                               show this message.\n"
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
4018f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
402fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void* load_bootable_image(const char* kernel, const char* ramdisk,
403fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                                 const char* secondstage, int64_t* sz,
404fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                                 const char* cmdline) {
405fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (kernel == nullptr) {
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "no image specified\n");
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
410fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t ksize;
411fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* kdata = load_file(kernel, &ksize);
412fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (kdata == nullptr) {
41364ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel        fprintf(stderr, "cannot load '%s': %s\n", kernel, strerror(errno));
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
416ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
417fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    // Is this actually a boot image?
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
419fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
420ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
421fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (ramdisk) {
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n");
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
425ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *sz = ksize;
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return kdata;
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
430fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* rdata = nullptr;
431fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t rsize = 0;
432fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (ramdisk) {
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rdata = load_file(ramdisk, &rsize);
434fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (rdata == nullptr) {
43564ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel            fprintf(stderr,"cannot load '%s': %s\n", ramdisk, strerror(errno));
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return  0;
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
440fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* sdata = nullptr;
441fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t ssize = 0;
442a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella    if (secondstage) {
443a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella        sdata = load_file(secondstage, &ssize);
444fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (sdata == nullptr) {
445a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
446a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            return  0;
447a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella        }
448a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella    }
449a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"creating boot image...\n");
451fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t bsize = 0;
452fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* bdata = mkbootimg(kdata, ksize, kernel_offset,
4537b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                      rdata, rsize, ramdisk_offset,
454a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                      sdata, ssize, second_offset,
4557b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                      page_size, base_addr, tags_offset, &bsize);
456fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (bdata == nullptr) {
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"failed to create boot.img\n");
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
460fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
461fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", bsize);
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *sz = bsize;
463ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return bdata;
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
467fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void* unzip_file(ZipArchiveHandle zip, const char* entry_name, int64_t* sz)
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
46907447544adbde8f688806b43f47c182eaeda4bb3Yusuke Sato    ZipString zip_entry_name(entry_name);
470d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    ZipEntry zip_entry;
471d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
472a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "archive does not contain '%s'\n", entry_name);
4738d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
476d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    *sz = zip_entry.uncompressed_length;
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
478d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
479fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) {
480fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        fprintf(stderr, "failed to allocate %" PRId64 " bytes for '%s'\n", *sz, entry_name);
4818d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
484a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    int error = ExtractToMemory(zip, &zip_entry, data, zip_entry.uncompressed_length);
485a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    if (error != 0) {
486a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(data);
4888d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
4908d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return data;
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
494a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes#if defined(_WIN32)
495a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
496a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes// TODO: move this to somewhere it can be shared.
497a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
498a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes#include <windows.h>
499a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
500a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes// Windows' tmpfile(3) requires administrator rights because
501a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes// it creates temporary files in the root directory.
502a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughesstatic FILE* win32_tmpfile() {
503a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    char temp_path[PATH_MAX];
504a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    DWORD nchars = GetTempPath(sizeof(temp_path), temp_path);
505a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    if (nchars == 0 || nchars >= sizeof(temp_path)) {
506a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes        fprintf(stderr, "GetTempPath failed, error %ld\n", GetLastError());
507a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes        return nullptr;
508a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    }
509a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
510a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    char filename[PATH_MAX];
511a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    if (GetTempFileName(temp_path, "fastboot", 0, filename) == 0) {
512a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes        fprintf(stderr, "GetTempFileName failed, error %ld\n", GetLastError());
513a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes        return nullptr;
514a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    }
515a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
516a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes    return fopen(filename, "w+bTD");
517a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes}
518a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
519a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes#define tmpfile win32_tmpfile
520a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
5218f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic std::string make_temporary_directory() {
5228f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    fprintf(stderr, "make_temporary_directory not supported under Windows, sorry!");
5238f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    return "";
5248f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley}
5258f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
5268f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#else
5278f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
5288f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic std::string make_temporary_directory() {
5298f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    const char *tmpdir = getenv("TMPDIR");
5308f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (tmpdir == nullptr) {
5318f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        tmpdir = P_tmpdir;
5328f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5338f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    std::string result = std::string(tmpdir) + "/fastboot_userdata_XXXXXX";
5348f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (mkdtemp(&result[0]) == NULL) {
5358f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to create temporary directory: %s\n",
5368f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            strerror(errno));
5378f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return "";
5388f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5398f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    return result;
5408f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley}
5418f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
542a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes#endif
543a26fbeeaa4298ea3bb09c53bdaefb6d968c6b72fElliott Hughes
5448f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic std::string create_fbemarker_tmpdir() {
5458f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    std::string dir = make_temporary_directory();
5468f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (dir.empty()) {
5478f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to create local temp directory for FBE marker\n");
5488f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return "";
5498f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5508f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    std::string marker_file = dir + "/" + convert_fbe_marker_filename;
5518f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    int fd = open(marker_file.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, 0666);
5528f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (fd == -1) {
5538f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to create FBE marker file %s locally: %d, %s\n",
5548f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            marker_file.c_str(), errno, strerror(errno));
5558f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return "";
5568f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5578f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    close(fd);
5588f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    return dir;
5598f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley}
5608f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
5618f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowleystatic void delete_fbemarker_tmpdir(const std::string& dir) {
5628f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    std::string marker_file = dir + "/" + convert_fbe_marker_filename;
5638f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (unlink(marker_file.c_str()) == -1) {
5648f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to delete FBE marker file %s locally: %d, %s\n",
5658f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            marker_file.c_str(), errno, strerror(errno));
5668f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return;
5678f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5688f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (rmdir(dir.c_str()) == -1) {
5698f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        fprintf(stderr, "Unable to delete FBE marker directory %s locally: %d, %s\n",
5708f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            dir.c_str(), errno, strerror(errno));
5718f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        return;
5728f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    }
5738f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley}
5748f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley
575a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughesstatic int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
576a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    FILE* fp = tmpfile();
577fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (fp == nullptr) {
578a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "failed to create temporary file for '%s': %s\n",
579a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes                entry_name, strerror(errno));
5808d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return -1;
581622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
582622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
58307447544adbde8f688806b43f47c182eaeda4bb3Yusuke Sato    ZipString zip_entry_name(entry_name);
584a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    ZipEntry zip_entry;
585a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
586a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "archive does not contain '%s'\n", entry_name);
587622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        return -1;
588622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
589622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
590a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    int fd = fileno(fp);
591a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    int error = ExtractEntryToFile(zip, &zip_entry, fd);
592a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    if (error != 0) {
593a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
594a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        return -1;
595622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
596622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
5978d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    lseek(fd, 0, SEEK_SET);
598622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return fd;
599622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
600622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char *strip(char *s)
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int n;
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(*s && isspace(*s)) s++;
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = strlen(s);
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(n-- > 0) {
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!isspace(s[n])) break;
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s[n] = 0;
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define MAX_OPTIONS 32
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int setup_requirement_line(char *name)
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *val[MAX_OPTIONS];
617fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    char *prod = nullptr;
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned n, count;
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *x;
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int invert = 0;
621ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strncmp(name, "reject ", 7)) {
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name += 7;
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        invert = 1;
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(name, "require ", 8)) {
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name += 8;
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        invert = 0;
628b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    } else if (!strncmp(name, "require-for-product:", 20)) {
629b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        // Get the product and point name past it
630b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        prod = name + 20;
631b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        name = strchr(name, ' ');
632b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        if (!name) return -1;
633b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        *name = 0;
634b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        name += 1;
635b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        invert = 0;
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = strchr(name, '=');
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (x == 0) return 0;
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *x = 0;
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    val[0] = x + 1;
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(count = 1; count < MAX_OPTIONS; count++) {
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x = strchr(val[count - 1],'|');
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (x == 0) break;
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x = 0;
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        val[count] = x + 1;
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
649ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    name = strip(name);
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0; n < count; n++) val[n] = strip(val[n]);
652ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    name = strip(name);
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (name == 0) return -1;
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
656253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    const char* var = name;
657253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    // Work around an unfortunate name mismatch.
658253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    if (!strcmp(name,"board")) var = "product";
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
660253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    const char** out = reinterpret_cast<const char**>(malloc(sizeof(char*) * count));
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (out == 0) return -1;
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0; n < count; n++) {
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        out[n] = strdup(strip(val[n]));
66514e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes        if (out[n] == 0) {
66614e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            for(size_t i = 0; i < n; ++i) {
66714e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes                free((char*) out[i]);
66814e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            }
66914e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            free(out);
67014e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            return -1;
67114e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes        }
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
674253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    fb_queue_require(prod, var, invert, n, out);
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
678fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void setup_requirements(char* data, int64_t sz) {
679fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    char* s = data;
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (sz-- > 0) {
681fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (*s == '\n') {
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *s++ = 0;
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (setup_requirement_line(data)) {
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                die("out of memory");
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            data = s;
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s++;
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
693fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void queue_info_dump() {
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_notice("--------------------------------------------");
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("version-bootloader", "Bootloader Version...");
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("version-baseband",   "Baseband Version.....");
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("serialno",           "Serial Number........");
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_notice("--------------------------------------------");
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
701622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic struct sparse_file **load_sparse_files(int fd, int max_size)
702f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
70380cc1f6864288f166b786a61ad57f12081114225Mohamad Ayyash    struct sparse_file* s = sparse_file_import_auto(fd, false, true);
704f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (!s) {
705622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("cannot sparse read file\n");
706f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
707f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
708fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int files = sparse_file_resparse(s, max_size, nullptr, 0);
709f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (files < 0) {
710622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("Failed to resparse\n");
711f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
712f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
713253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    sparse_file** out_s = reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file *), files + 1));
714f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (!out_s) {
715f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        die("Failed to allocate sparse file array\n");
716f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
717f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
718f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    files = sparse_file_resparse(s, max_size, out_s, files);
719f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (files < 0) {
720622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("Failed to resparse\n");
721f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
722f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
723f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return out_s;
724f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
725f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
7260b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic int64_t get_target_sparse_limit(Transport* transport) {
7272fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    std::string max_download_size;
7280b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, "max-download-size", &max_download_size) ||
7290b156638307db890e5539b52521fd24beb3440cbDavid Pursell            max_download_size.empty()) {
7303ab05869d84357dd54ee27f971bde6514475bcb6Elliott Hughes        fprintf(stderr, "target didn't report max-download-size\n");
7312fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        return 0;
732f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
733f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
73477c0e66bef637aa749c5618e2bdec1c829f79e58Elliott Hughes    // Some bootloaders (angler, for example) send spurious whitespace too.
73577c0e66bef637aa749c5618e2bdec1c829f79e58Elliott Hughes    max_download_size = android::base::Trim(max_download_size);
73677c0e66bef637aa749c5618e2bdec1c829f79e58Elliott Hughes
7372fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    uint64_t limit;
7382fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (!android::base::ParseUint(max_download_size.c_str(), &limit)) {
7393ab05869d84357dd54ee27f971bde6514475bcb6Elliott Hughes        fprintf(stderr, "couldn't parse max-download-size '%s'\n", max_download_size.c_str());
7402fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        return 0;
7412fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
7422fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (limit > 0) {
7432fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n", limit);
7442fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
745f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return limit;
746f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
747f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
7480b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic int64_t get_sparse_limit(Transport* transport, int64_t size) {
749f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int64_t limit;
750f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
751f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (sparse_limit == 0) {
752f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return 0;
753f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (sparse_limit > 0) {
754f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        limit = sparse_limit;
755f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else {
756f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (target_sparse_limit == -1) {
7570b156638307db890e5539b52521fd24beb3440cbDavid Pursell            target_sparse_limit = get_target_sparse_limit(transport);
758f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
759f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (target_sparse_limit > 0) {
760f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            limit = target_sparse_limit;
761f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        } else {
7620bbfb3976e9491b3e1a872ebdaa850ef868a24aaColin Cross            return 0;
763f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
764f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
765f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
766f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (size > limit) {
767f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return limit;
768f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
769f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
770f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return 0;
771f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
772f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
7732fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes// Until we get lazy inode table init working in make_ext4fs, we need to
7742fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes// erase partitions of type ext4 before flashing a filesystem so no stale
7752fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes// inodes are left lying around.  Otherwise, e2fsck gets very upset.
7760b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic bool needs_erase(Transport* transport, const char* partition) {
7778ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes    std::string partition_type;
7780b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) {
7798ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes        return false;
7808ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes    }
7818ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes    return partition_type == "ext4";
7825ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall}
7835ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
7840b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic int load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* buf) {
785fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz = get_file_size(fd);
786fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (sz == -1) {
7878d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return -1;
788622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
789e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
790fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    lseek64(fd, 0, SEEK_SET);
7910b156638307db890e5539b52521fd24beb3440cbDavid Pursell    int64_t limit = get_sparse_limit(transport, sz);
792f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (limit) {
793fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        sparse_file** s = load_sparse_files(fd, limit);
794fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (s == nullptr) {
795622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            return -1;
796f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
797622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->type = FB_BUFFER_SPARSE;
798622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->data = s;
799f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else {
800fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        void* data = load_fd(fd, &sz);
801fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes        if (data == nullptr) return -1;
802622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->type = FB_BUFFER;
803782111b3bc5d372afc8d66ab6023e834b7c23b88Sasha Levitskiy        buf->data = data;
8048d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        buf->sz = sz;
805622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
806622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
807622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return 0;
808622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
809622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
8100b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic int load_buf(Transport* transport, const char *fname, struct fastboot_buffer *buf)
811622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
812622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    int fd;
813622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
814622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    fd = open(fname, O_RDONLY | O_BINARY);
815622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    if (fd < 0) {
81682280594ef7e9dc908aa67f3da8661ff54a96c9eDaniel Rosenberg        return -1;
817f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
818622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
8190b156638307db890e5539b52521fd24beb3440cbDavid Pursell    return load_buf_fd(transport, fd, buf);
820622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
821622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
822622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic void flash_buf(const char *pname, struct fastboot_buffer *buf)
823622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
824253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    sparse_file** s;
825622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
826622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    switch (buf->type) {
8279da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao        case FB_BUFFER_SPARSE: {
8289da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao            std::vector<std::pair<sparse_file*, int64_t>> sparse_files;
829253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes            s = reinterpret_cast<sparse_file**>(buf->data);
830622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            while (*s) {
831fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                int64_t sz = sparse_file_len(*s, true, false);
8329da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                sparse_files.emplace_back(*s, sz);
8339da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                ++s;
8349da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao            }
8359da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao
8369da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao            for (size_t i = 0; i < sparse_files.size(); ++i) {
8379da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                const auto& pair = sparse_files[i];
8389da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                fb_queue_flash_sparse(pname, pair.first, pair.second, i + 1, sparse_files.size());
839622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            }
840622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            break;
8419da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao        }
8429da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao
843622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        case FB_BUFFER:
844622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            fb_queue_flash(pname, buf->data, buf->sz);
845622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            break;
846622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        default:
847622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            die("unknown buffer type: %d", buf->type);
848f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
849f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
850f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
8510b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic std::vector<std::string> get_suffixes(Transport* transport) {
852b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    std::vector<std::string> suffixes;
853b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    std::string suffix_list;
8540b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, "slot-suffixes", &suffix_list)) {
855b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        die("Could not get suffixes.\n");
856b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
857b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    return android::base::Split(suffix_list, ",");
858b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
859b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
8609b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenbergstatic std::string verify_slot(Transport* transport, const char *slot, bool allow_all) {
861b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    if (strcmp(slot, "all") == 0) {
8629b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        if (allow_all) {
8639b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            return "all";
8649b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        } else {
8659b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            std::vector<std::string> suffixes = get_suffixes(transport);
8669b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            if (!suffixes.empty()) {
8679b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg                return suffixes[0];
8689b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            } else {
869c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg                die("No known slots.");
8709b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            }
8719b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        }
872b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
873c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg
8740b156638307db890e5539b52521fd24beb3440cbDavid Pursell    std::vector<std::string> suffixes = get_suffixes(transport);
875c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg
876c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg    if (strcmp(slot, "other") == 0) {
877c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg        std::string current_slot;
878c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg        if (!fb_getvar(transport, "current-slot", &current_slot)) {
879c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg            die("Failed to identify current slot.");
880c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg        }
881c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg        if (!suffixes.empty()) {
882c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg            for (size_t i = 0; i < suffixes.size(); i++) {
883c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg                if (current_slot == suffixes[i])
884c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg                    return suffixes[(i+1)%suffixes.size()];
885c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg            }
886c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg        } else {
887c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg            die("No known slots.");
888c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg        }
889c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg    }
890c1743ba0d4eb80d4c7e343dfc046946479e1be84Daniel Rosenberg
891b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    for (const std::string &suffix : suffixes) {
892b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        if (suffix == slot)
893b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            return slot;
894b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
895a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg    fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot);
896b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    for (const std::string &suffix : suffixes) {
897b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        fprintf(stderr, "%s\n", suffix.c_str());
898b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
899b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    exit(1);
900b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
901b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
9029b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenbergstatic std::string verify_slot(Transport* transport, const char *slot) {
9039b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg   return verify_slot(transport, slot, true);
9049b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg}
9059b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg
9060b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic void do_for_partition(Transport* transport, const char *part, const char *slot,
9070b156638307db890e5539b52521fd24beb3440cbDavid Pursell                             std::function<void(const std::string&)> func, bool force_slot) {
908a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg    std::string has_slot;
909b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    std::string current_slot;
910b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
9110b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, std::string("has-slot:")+part, &has_slot)) {
912a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg        /* If has-slot is not supported, the answer is no. */
913a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg        has_slot = "no";
914b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
915a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg    if (has_slot == "yes") {
916b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        if (!slot || slot[0] == 0) {
9170b156638307db890e5539b52521fd24beb3440cbDavid Pursell            if (!fb_getvar(transport, "current-slot", &current_slot)) {
918b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                die("Failed to identify current slot.\n");
919b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            }
920996ecd8b7d6372eb53bb5ec47d202320bdd72431Daniel Rosenberg            func(std::string(part) + current_slot);
921b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        } else {
922996ecd8b7d6372eb53bb5ec47d202320bdd72431Daniel Rosenberg            func(std::string(part) + slot);
923b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        }
924b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    } else {
925b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        if (force_slot && slot && slot[0]) {
9260b156638307db890e5539b52521fd24beb3440cbDavid Pursell             fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n",
9270b156638307db890e5539b52521fd24beb3440cbDavid Pursell                     part, slot);
928b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        }
929b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        func(part);
930b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
931b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
932b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
9330b156638307db890e5539b52521fd24beb3440cbDavid Pursell/* This function will find the real partition name given a base name, and a slot. If slot is NULL or
9340b156638307db890e5539b52521fd24beb3440cbDavid Pursell * empty, it will use the current slot. If slot is "all", it will return a list of all possible
9350b156638307db890e5539b52521fd24beb3440cbDavid Pursell * partition names. If force_slot is true, it will fail if a slot is specified, and the given
9360b156638307db890e5539b52521fd24beb3440cbDavid Pursell * partition does not support slots.
937b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg */
9380b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic void do_for_partitions(Transport* transport, const char *part, const char *slot,
9390b156638307db890e5539b52521fd24beb3440cbDavid Pursell                              std::function<void(const std::string&)> func, bool force_slot) {
940a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg    std::string has_slot;
941b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
942b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    if (slot && strcmp(slot, "all") == 0) {
9430b156638307db890e5539b52521fd24beb3440cbDavid Pursell        if (!fb_getvar(transport, std::string("has-slot:") + part, &has_slot)) {
944b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            die("Could not check if partition %s has slot.", part);
945b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        }
946a797479bd51c286969d5a5defb6bb7a1af265cb4Daniel Rosenberg        if (has_slot == "yes") {
9470b156638307db890e5539b52521fd24beb3440cbDavid Pursell            std::vector<std::string> suffixes = get_suffixes(transport);
948b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            for (std::string &suffix : suffixes) {
9490b156638307db890e5539b52521fd24beb3440cbDavid Pursell                do_for_partition(transport, part, suffix.c_str(), func, force_slot);
950b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            }
951b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        } else {
9520b156638307db890e5539b52521fd24beb3440cbDavid Pursell            do_for_partition(transport, part, "", func, force_slot);
953b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        }
954b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    } else {
9550b156638307db890e5539b52521fd24beb3440cbDavid Pursell        do_for_partition(transport, part, slot, func, force_slot);
956b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    }
957b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
958b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
9590b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic void do_flash(Transport* transport, const char* pname, const char* fname) {
960622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    struct fastboot_buffer buf;
961622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
9620b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (load_buf(transport, fname, &buf)) {
963622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("cannot load '%s'", fname);
964622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
965622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    flash_buf(pname, &buf);
966f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
967f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
968fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void do_update_signature(ZipArchiveHandle zip, char* fn) {
969fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
970d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    void* data = unzip_file(zip, fn, &sz);
971fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) return;
972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_download("signature", data, sz);
973dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_command("signature", "installing signature");
974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
975dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
9760b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic void do_update(Transport* transport, const char* filename, const char* slot_override, bool erase_first) {
977dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    queue_info_dump();
978dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
979b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    fb_queue_query_save("product", cur_product, sizeof(cur_product));
980b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
981d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    ZipArchiveHandle zip;
982a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    int error = OpenArchive(filename, &zip);
983a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes    if (error != 0) {
984f6e9ffbc734c7100914e8164f735317a85151033Narayan Kamath        CloseArchive(zip);
985a82c89da1f8daa55698ce5cd0c79899b7172d8cfElliott Hughes        die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
986d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    }
987dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
988fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
989253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    void* data = unzip_file(zip, "android-info.txt", &sz);
990fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) {
991f6e9ffbc734c7100914e8164f735317a85151033Narayan Kamath        CloseArchive(zip);
9927c6d884e2b4d48716f6d9403234403b8c101fb58Elliott Hughes        die("update package '%s' has no android-info.txt", filename);
993dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
994dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
995253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    setup_requirements(reinterpret_cast<char*>(data), sz);
996dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
997acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes    for (size_t i = 0; i < ARRAY_SIZE(images); ++i) {
998253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes        int fd = unzip_to_file(zip, images[i].img_name);
999acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes        if (fd == -1) {
1000acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes            if (images[i].is_optional) {
1001622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                continue;
1002acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes            }
1003f6e9ffbc734c7100914e8164f735317a85151033Narayan Kamath            CloseArchive(zip);
1004acdbe92c60e662a4913f1fca09c2b8913791376cElliott Hughes            exit(1); // unzip_to_file already explained why.
10055ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall        }
1006253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes        fastboot_buffer buf;
10070b156638307db890e5539b52521fd24beb3440cbDavid Pursell        int rc = load_buf_fd(transport, fd, &buf);
1008622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        if (rc) die("cannot load %s from flash", images[i].img_name);
1009b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1010b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        auto update = [&](const std::string &partition) {
1011b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            do_update_signature(zip, images[i].sig_name);
10120b156638307db890e5539b52521fd24beb3440cbDavid Pursell            if (erase_first && needs_erase(transport, partition.c_str())) {
1013b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                fb_queue_erase(partition.c_str());
1014b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            }
1015b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            flash_buf(partition.c_str(), &buf);
1016b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            /* not closing the fd here since the sparse code keeps the fd around
1017b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg             * but hasn't mmaped data yet. The tmpfile will get cleaned up when the
1018b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg             * program exits.
1019b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg             */
1020b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        };
10210b156638307db890e5539b52521fd24beb3440cbDavid Pursell        do_for_partitions(transport, images[i].part_name, slot_override, update, false);
10225ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall    }
1023d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes
1024d30ad8a2eeefc382e898f2130d0be9461eed0bd9Elliott Hughes    CloseArchive(zip);
1025dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1026dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1027fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstatic void do_send_signature(char* fn) {
1028fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    char* xtn = strrchr(fn, '.');
1029dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!xtn) return;
1030fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes
1031dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (strcmp(xtn, ".img")) return;
1032ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
1033fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    strcpy(xtn, ".sig");
1034fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes
1035fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
1036fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* data = load_file(fn, &sz);
1037fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    strcpy(xtn, ".img");
1038fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) return;
1039dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_download("signature", data, sz);
1040dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_command("signature", "installing signature");
1041dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1042dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10430b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic void do_flashall(Transport* transport, const char* slot_override, int erase_first) {
1044dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    queue_info_dump();
1045dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1046b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    fb_queue_query_save("product", cur_product, sizeof(cur_product));
1047b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
1048253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    char* fname = find_item("info", product);
1049fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (fname == nullptr) die("cannot find android-info.txt");
1050253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes
1051fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
1052253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    void* data = load_file(fname, &sz);
1053fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno));
1054dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1055253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    setup_requirements(reinterpret_cast<char*>(data), sz);
1056253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes
1057253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes    for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
1058622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        fname = find_item(images[i].part_name, product);
1059253c18d2fbab6c16886af8bdfd528df3ebf82b93Elliott Hughes        fastboot_buffer buf;
10600b156638307db890e5539b52521fd24beb3440cbDavid Pursell        if (load_buf(transport, fname, &buf)) {
1061622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            if (images[i].is_optional)
1062622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                continue;
1063622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            die("could not load %s\n", images[i].img_name);
1064622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        }
1065b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1066b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        auto flashall = [&](const std::string &partition) {
1067b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            do_send_signature(fname);
10680b156638307db890e5539b52521fd24beb3440cbDavid Pursell            if (erase_first && needs_erase(transport, partition.c_str())) {
1069b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                fb_queue_erase(partition.c_str());
1070b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            }
1071b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            flash_buf(partition.c_str(), &buf);
1072b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        };
10730b156638307db890e5539b52521fd24beb3440cbDavid Pursell        do_for_partitions(transport, images[i].part_name, slot_override, flashall, false);
10745ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall    }
1075dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1076dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1077dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define skip(n) do { argc -= (n); argv += (n); } while (0)
10782d13d1408bef9e26cc418e6fc2579dfd12378a3cJP Abgrall#define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0)
1079dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
108045be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughesstatic int do_bypass_unlock_command(int argc, char **argv)
108151e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin{
108251e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    if (argc <= 2) return 0;
108351e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    skip(2);
108451e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin
108551e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    /*
108651e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin     * Process unlock_bootloader, we have to load the message file
108751e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin     * and send that to the remote device.
108851e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin     */
108951e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    require(1);
1090259ad4a8e798025119b0cec3c11199239b59fa12Elliott Hughes
1091259ad4a8e798025119b0cec3c11199239b59fa12Elliott Hughes    int64_t sz;
1092259ad4a8e798025119b0cec3c11199239b59fa12Elliott Hughes    void* data = load_file(*argv, &sz);
1093259ad4a8e798025119b0cec3c11199239b59fa12Elliott Hughes    if (data == nullptr) die("could not load '%s': %s", *argv, strerror(errno));
109451e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    fb_queue_download("unlock_message", data, sz);
109551e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    fb_queue_command("flashing unlock_bootloader", "unlocking bootloader");
109651e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    skip(1);
109751e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin    return 0;
109851e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin}
109951e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin
110045be42e89efef8e582c096287c9bdffe8beaf8bdElliott Hughesstatic int do_oem_command(int argc, char **argv)
1101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char command[256];
1103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (argc <= 1) return 0;
1104ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
1105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    command[0] = 0;
1106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(1) {
1107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcat(command,*argv);
1108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        skip(1);
1109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(argc == 0) break;
1110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcat(command," ");
1111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1113ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    fb_queue_command(command,"");
1114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
1115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1117f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t parse_num(const char *arg)
1118f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
1119f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    char *endptr;
1120f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    unsigned long long num;
1121f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1122f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    num = strtoull(arg, &endptr, 0);
1123f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (endptr == arg) {
1124f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
1125f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
1126f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1127f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (*endptr == 'k' || *endptr == 'K') {
1128f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / 1024) {
1129f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
1130f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
1131f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL;
1132f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
1133f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (*endptr == 'm' || *endptr == 'M') {
1134f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / (1024 * 1024)) {
1135f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
1136f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
1137f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL * 1024LL;
1138f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
1139f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (*endptr == 'g' || *endptr == 'G') {
1140f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / (1024 * 1024 * 1024)) {
1141f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
1142f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
1143f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL * 1024LL * 1024LL;
1144f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
1145f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
1146f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1147f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (*endptr != '\0') {
1148f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
1149f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
1150f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1151f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (num > INT64_MAX) {
1152f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
1153f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
1154f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1155f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return num;
1156f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
1157f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
11580b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic void fb_perform_format(Transport* transport,
11592fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes                              const char* partition, int skip_if_not_supported,
11608f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                              const char* type_override, const char* size_override,
11618f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                              const std::string& initial_dir) {
11622fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    std::string partition_type, partition_size;
11632fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes
1164e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    struct fastboot_buffer buf;
11652fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    const char* errMsg = nullptr;
11662fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    const struct fs_generator* gen = nullptr;
1167e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    int fd;
1168e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
11692fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    unsigned int limit = INT_MAX;
11702fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (target_sparse_limit > 0 && target_sparse_limit < limit) {
1171e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        limit = target_sparse_limit;
11722fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
11732fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (sparse_limit > 0 && sparse_limit < limit) {
1174e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        limit = sparse_limit;
11752fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
1176e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
11770b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) {
1178e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        errMsg = "Can't determine partition type.\n";
1179e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        goto failed;
1180e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
11817e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    if (type_override) {
11822fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        if (partition_type != type_override) {
11832fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fprintf(stderr, "Warning: %s type is %s, but %s was requested for formatting.\n",
11842fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes                    partition, partition_type.c_str(), type_override);
11857e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        }
11862fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        partition_type = type_override;
11877e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    }
1188e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
11890b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (!fb_getvar(transport, std::string("partition-size:") + partition, &partition_size)) {
1190e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        errMsg = "Unable to get partition size\n";
1191e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        goto failed;
1192e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
11937e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    if (size_override) {
11942fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        if (partition_size != size_override) {
11952fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fprintf(stderr, "Warning: %s size is %s, but %s was requested for formatting.\n",
11962fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes                    partition, partition_size.c_str(), size_override);
11977e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        }
11982fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        partition_size = size_override;
11997e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    }
1200a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    // Some bootloaders (angler, for example), send spurious leading whitespace.
1201a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    partition_size = android::base::Trim(partition_size);
1202a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    // Some bootloaders (hammerhead, for example) use implicit hex.
1203a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    // This code used to use strtol with base 16.
1204a2db2618ecd9e96cb0b00d05a7f357c8b4b5fc62Elliott Hughes    if (!android::base::StartsWith(partition_size, "0x")) partition_size = "0x" + partition_size;
1205e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
12068ab9a32323cee1f23c5ccbfeabd2cb2253f693d2Elliott Hughes    gen = fs_get_generator(partition_type);
1207e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (!gen) {
1208e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        if (skip_if_not_supported) {
1209e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg            fprintf(stderr, "Erase successful, but not automatically formatting.\n");
12102fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fprintf(stderr, "File system type %s not supported.\n", partition_type.c_str());
1211e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg            return;
1212e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        }
12132fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "Formatting is not supported for file system with type '%s'.\n",
12142fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes                partition_type.c_str());
1215e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
1216e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
1217e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
12182fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    int64_t size;
12192fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    if (!android::base::ParseInt(partition_size.c_str(), &size)) {
12202fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "Couldn't parse partition size '%s'.\n", partition_size.c_str());
12212fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        return;
12222fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
1223e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
1224e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    fd = fileno(tmpfile());
12258f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    if (fs_generator_generate(gen, fd, size, initial_dir)) {
12262fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "Cannot generate image: %s\n", strerror(errno));
1227e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        close(fd);
1228e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
1229e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
1230e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
12310b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (load_buf_fd(transport, fd, &buf)) {
12322fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "Cannot read image: %s\n", strerror(errno));
1233e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        close(fd);
1234e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
1235e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
1236e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    flash_buf(partition, &buf);
1237e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    return;
1238e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
1239e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinbergfailed:
1240e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (skip_if_not_supported) {
1241e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        fprintf(stderr, "Erase successful, but not automatically formatting.\n");
12422fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        if (errMsg) fprintf(stderr, "%s", errMsg);
1243e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
1244e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    fprintf(stderr,"FAILED (%s)\n", fb_get_error());
1245e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg}
1246e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
1247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint main(int argc, char **argv)
1248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
12490d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    bool wants_wipe = false;
12500d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    bool wants_reboot = false;
12510d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    bool wants_reboot_bootloader = false;
12520d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    bool wants_set_active = false;
1253fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    bool erase_first = true;
12548f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley    bool set_fbe_marker = false;
1255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *data;
1256fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    int64_t sz;
125727ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle    int longindex;
1258b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    std::string slot_override;
12590d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    std::string next_active;
1260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
12617b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    const struct option longopts[] = {
12627b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"base", required_argument, 0, 'b'},
12637b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"kernel_offset", required_argument, 0, 'k'},
12647aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"kernel-offset", required_argument, 0, 'k'},
12657b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"page_size", required_argument, 0, 'n'},
12667aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"page-size", required_argument, 0, 'n'},
12677b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"ramdisk_offset", required_argument, 0, 'r'},
12687aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"ramdisk-offset", required_argument, 0, 'r'},
126929fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash        {"tags_offset", required_argument, 0, 't'},
12707aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"tags-offset", required_argument, 0, 't'},
1271379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes        {"help", no_argument, 0, 'h'},
1272379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes        {"unbuffered", no_argument, 0, 0},
1273379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes        {"version", no_argument, 0, 0},
1274b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg        {"slot", required_argument, 0, 0},
12750d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        {"set_active", optional_argument, 0, 'a'},
12767aa38bc54c19b8e89d596cb91a50ca57f0f75bc0Daniel Rosenberg        {"set-active", optional_argument, 0, 'a'},
12778f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#if !defined(_WIN32)
12788f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        {"wipe-and-use-fbe", no_argument, 0, 0},
12798f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#endif
12807b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {0, 0, 0, 0}
12817b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    };
12828879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
12838879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    serial = getenv("ANDROID_SERIAL");
12848879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
12858879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    while (1) {
12860d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:ha::", longopts, &longindex);
12878879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        if (c < 0) {
12888879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
12898879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        }
12907b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        /* Alphabetical cases */
12918879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        switch (c) {
12920d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        case 'a':
12930d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_set_active = true;
12940d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            if (optarg)
12950d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg                next_active = optarg;
12960d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            break;
12978879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 'b':
12988879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            base_addr = strtoul(optarg, 0, 16);
12998879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
13007b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'c':
13017b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            cmdline = optarg;
13027b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
13037b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'h':
13047b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            usage();
13057b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            return 1;
13067b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'i': {
1307fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                char *endptr = nullptr;
13087b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                unsigned long val;
13097b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
13107b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                val = strtoul(optarg, &endptr, 0);
13117b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                if (!endptr || *endptr != '\0' || (val & ~0xffff))
13127b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                    die("invalid vendor id '%s'", optarg);
13137b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                vendor_id = (unsigned short)val;
13147b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                break;
13157b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            }
13167b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'k':
13177b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            kernel_offset = strtoul(optarg, 0, 16);
13187b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
13197b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'l':
13207b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            long_listing = 1;
13217b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
13228879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 'n':
1323fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            page_size = (unsigned)strtoul(optarg, nullptr, 0);
13248879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            if (!page_size) die("invalid page size");
13258879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
13267b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'p':
13277b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            product = optarg;
13287b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
13297b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'r':
13307b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            ramdisk_offset = strtoul(optarg, 0, 16);
13317b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
133229fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash        case 't':
133329fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash            tags_offset = strtoul(optarg, 0, 16);
133429fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash            break;
13358879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 's':
13368879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            serial = optarg;
13378879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
1338f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        case 'S':
1339f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            sparse_limit = parse_num(optarg);
1340f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            if (sparse_limit < 0) {
1341f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross                    die("invalid sparse limit");
1342f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            }
1343f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            break;
13447b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'u':
1345fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            erase_first = false;
13468879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
13477b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'w':
13480d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_wipe = true;
13498879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
13508879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case '?':
13518879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            return 1;
135227ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle        case 0:
135327ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle            if (strcmp("unbuffered", longopts[longindex].name) == 0) {
1354fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                setvbuf(stdout, nullptr, _IONBF, 0);
1355fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                setvbuf(stderr, nullptr, _IONBF, 0);
1356379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes            } else if (strcmp("version", longopts[longindex].name) == 0) {
1357379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes                fprintf(stdout, "fastboot version %s\n", FASTBOOT_REVISION);
1358379646b2ca2cf681be3489eb74a421b3f8c80e26Elliott Hughes                return 0;
1359b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            } else if (strcmp("slot", longopts[longindex].name) == 0) {
1360b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                slot_override = std::string(optarg);
13618f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#if !defined(_WIN32)
13628f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            } else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) {
13638f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                wants_wipe = true;
13648f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                set_fbe_marker = true;
13658f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley#endif
13668f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            } else {
13678f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                fprintf(stderr, "Internal error in options processing for %s\n",
13688f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                    longopts[longindex].name);
13698f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                return 1;
137027ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle            }
137127ded4832d7a1b93d287ea9b968bf069d3628a8bFlorian Bäuerle            break;
13728879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        default:
13738879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            abort();
13748879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        }
13758879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    }
1376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
13778879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    argc -= optind;
13788879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    argv += optind;
13798879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
13800d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    if (argc == 0 && !wants_wipe && !wants_set_active) {
1381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usage();
1382eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom        return 1;
1383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
13858fb6e06ba44b92258bf44110ea5361496257e24eColin Cross    if (argc > 0 && !strcmp(*argv, "devices")) {
13868879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        skip(1);
1387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        list_devices();
1388ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang        return 0;
1389ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    }
1390ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
1391c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross    if (argc > 0 && !strcmp(*argv, "help")) {
1392c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross        usage();
1393c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross        return 0;
1394c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross    }
1395c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross
13960b156638307db890e5539b52521fd24beb3440cbDavid Pursell    Transport* transport = open_device();
13972ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    if (transport == nullptr) {
13982ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell        return 1;
13992ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell    }
14002ec418a4c98f6e8f95395456e1ad4c2956cac007David Pursell
1401b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    if (slot_override != "")
14020b156638307db890e5539b52521fd24beb3440cbDavid Pursell        slot_override = verify_slot(transport, slot_override.c_str());
14030d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    if (next_active != "")
14049b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        next_active = verify_slot(transport, next_active.c_str(), false);
14050d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg
14060d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    if (wants_set_active) {
14070d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        if (next_active == "") {
14080d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            if (slot_override == "") {
14090d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg                wants_set_active = false;
14100d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            } else {
14119b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg                next_active = verify_slot(transport, slot_override.c_str(), false);
14120d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            }
14130d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        }
14140d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    }
141531dbed7b60d8237d6d05dc6bf230167a5854b77aElliott Hughes
1416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (argc > 0) {
14172fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        if (!strcmp(*argv, "getvar")) {
1418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_display(argv[1], argv[1]);
1420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
1421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "erase")) {
1422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
14235ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
1424b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            auto erase = [&](const std::string &partition) {
14250b156638307db890e5539b52521fd24beb3440cbDavid Pursell                std::string partition_type;
14260b156638307db890e5539b52521fd24beb3440cbDavid Pursell                if (fb_getvar(transport, std::string("partition-type:") + argv[1], &partition_type) &&
1427b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                    fs_get_generator(partition_type) != nullptr) {
1428b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                    fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n",
1429b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                            partition_type.c_str());
1430b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                }
14315ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
1432b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                fb_queue_erase(partition.c_str());
1433b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            };
14340b156638307db890e5539b52521fd24beb3440cbDavid Pursell            do_for_partitions(transport, argv[1], slot_override.c_str(), erase, true);
1435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
14367e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        } else if(!strncmp(*argv, "format", strlen("format"))) {
14377e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            char *overrides;
1438fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            char *type_override = nullptr;
1439fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            char *size_override = nullptr;
1440c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau            require(2);
14417e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            /*
14427e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             * Parsing for: "format[:[type][:[size]]]"
14437e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             * Some valid things:
14447e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *  - select ontly the size, and leave default fs type:
14457e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format::0x4000000 userdata
14467e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *  - default fs type and size:
14477e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format userdata
14487e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format:: userdata
14497e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             */
14507e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            overrides = strchr(*argv, ':');
14517e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            if (overrides) {
14527e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                overrides++;
14537e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                size_override = strchr(overrides, ':');
14547e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                if (size_override) {
14557e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    size_override[0] = '\0';
14567e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    size_override++;
14577e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                }
14587e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                type_override = overrides;
14597e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            }
1460fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            if (type_override && !type_override[0]) type_override = nullptr;
1461fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            if (size_override && !size_override[0]) size_override = nullptr;
1462b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1463b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            auto format = [&](const std::string &partition) {
14640b156638307db890e5539b52521fd24beb3440cbDavid Pursell                if (erase_first && needs_erase(transport, partition.c_str())) {
1465b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                    fb_queue_erase(partition.c_str());
1466b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                }
14678f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                fb_perform_format(transport, partition.c_str(), 0,
14688f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                    type_override, size_override, "");
1469b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            };
14700b156638307db890e5539b52521fd24beb3440cbDavid Pursell            do_for_partitions(transport, argv[1], slot_override.c_str(), format, true);
1471c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau            skip(2);
1472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "signature")) {
1473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            data = load_file(argv[1], &sz);
1475fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes            if (data == nullptr) die("could not load '%s': %s", argv[1], strerror(errno));
1476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (sz != 256) die("signature must be 256 bytes");
1477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_download("signature", data, sz);
1478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("signature", "installing signature");
1479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
1480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "reboot")) {
14810d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_reboot = true;
1482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1483ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes            if (argc > 0) {
1484ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes                if (!strcmp(*argv, "bootloader")) {
14850d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg                    wants_reboot = false;
14860d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg                    wants_reboot_bootloader = true;
1487ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes                    skip(1);
1488ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes                }
1489ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes            }
1490ca85df0662735eaefd512e63eab83caf994be1a6Elliott Hughes            require(0);
1491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "reboot-bootloader")) {
14920d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_reboot_bootloader = true;
1493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strcmp(*argv, "continue")) {
1495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("continue", "resuming boot");
1496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "boot")) {
1498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *kname = 0;
1499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *rname = 0;
1500a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            char *sname = 0;
1501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 0) {
1503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kname = argv[0];
1504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 0) {
1507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                rname = argv[0];
1508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1510a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            if (argc > 0) {
1511a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                sname = argv[0];
1512a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                skip(1);
1513a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            }
1514a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
1515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (data == 0) return 1;
1516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_download("boot.img", data, sz);
1517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("boot", "booting");
1518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flash")) {
1519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *pname = argv[1];
1520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *fname = 0;
1521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 2) {
1523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fname = argv[2];
1524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(3);
1525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
1526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fname = find_item(pname, product);
1527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(2);
1528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fname == 0) die("cannot determine image filename for '%s'", pname);
1530b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
1531b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            auto flash = [&](const std::string &partition) {
15320b156638307db890e5539b52521fd24beb3440cbDavid Pursell                if (erase_first && needs_erase(transport, partition.c_str())) {
1533b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                    fb_queue_erase(partition.c_str());
1534b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                }
15350b156638307db890e5539b52521fd24beb3440cbDavid Pursell                do_flash(transport, partition.c_str(), fname);
1536b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            };
15370b156638307db890e5539b52521fd24beb3440cbDavid Pursell            do_for_partitions(transport, pname, slot_override.c_str(), flash, true);
1538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flash:raw")) {
1539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *kname = argv[2];
1540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *rname = 0;
1541a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            char *sname = 0;
1542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(3);
1543a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            skip(3);
1544a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            if (argc > 0) {
1545a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                rname = argv[0];
1546a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                skip(1);
1547a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            }
1548a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            if (argc > 0) {
1549a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                sname = argv[0];
1550a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella                skip(1);
1551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1552a42adff905600219cbf5ef217d2b46670225aca3Jeremy Compostella            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
1553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (data == 0) die("cannot load bootable image");
1554b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            auto flashraw = [&](const std::string &partition) {
1555b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg                fb_queue_flash(partition.c_str(), data, sz);
1556b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg            };
15570b156638307db890e5539b52521fd24beb3440cbDavid Pursell            do_for_partitions(transport, argv[1], slot_override.c_str(), flashraw, true);
1558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flashall")) {
1559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
15600b156638307db890e5539b52521fd24beb3440cbDavid Pursell            do_flashall(transport, slot_override.c_str(), erase_first);
15610d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg            wants_reboot = true;
1562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "update")) {
1563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 1) {
15640b156638307db890e5539b52521fd24beb3440cbDavid Pursell                do_update(transport, argv[1], slot_override.c_str(), erase_first);
1565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(2);
1566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
15670b156638307db890e5539b52521fd24beb3440cbDavid Pursell                do_update(transport, "update.zip", slot_override.c_str(), erase_first);
1568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
15709b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            wants_reboot = 1;
15719b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg        } else if(!strcmp(*argv, "set_active")) {
15729b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            require(2);
15739b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            std::string slot = verify_slot(transport, argv[1], false);
15749b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            fb_set_active(slot.c_str());
15759b432054dcb16b0e31a22538b88e7b75467d1288Daniel Rosenberg            skip(2);
1576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "oem")) {
1577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            argc = do_oem_command(argc, argv);
157851e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin        } else if(!strcmp(*argv, "flashing")) {
157951e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            if (argc == 2 && (!strcmp(*(argv+1), "unlock") ||
158051e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "lock") ||
158151e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "unlock_critical") ||
158251e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "lock_critical") ||
158351e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "get_unlock_ability") ||
158451e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "get_unlock_bootloader_nonce") ||
158551e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                              !strcmp(*(argv+1), "lock_bootloader"))) {
158651e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                argc = do_oem_command(argc, argv);
158751e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            } else
158851e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin            if (argc == 3 && !strcmp(*(argv+1), "unlock_bootloader")) {
158951e8b03f840f611ec7ca9f536e212d40b1b5c4e9Patrick Tjin                argc = do_bypass_unlock_command(argc, argv);
1590bf11095f92c9278cb794a5336e1cce264f9b734dBadhri Jagan Sridharan            } else {
1591bf11095f92c9278cb794a5336e1cce264f9b734dBadhri Jagan Sridharan              usage();
1592bf11095f92c9278cb794a5336e1cce264f9b734dBadhri Jagan Sridharan              return 1;
1593bf11095f92c9278cb794a5336e1cce264f9b734dBadhri Jagan Sridharan            }
1594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            usage();
1596ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang            return 1;
1597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (wants_wipe) {
16012fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        fprintf(stderr, "wiping userdata...\n");
1602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_erase("userdata");
16038f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        if (set_fbe_marker) {
16048f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            fprintf(stderr, "setting FBE marker...\n");
16058f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            std::string initial_userdata_dir = create_fbemarker_tmpdir();
16068f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            if (initial_userdata_dir.empty()) {
16078f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley                return 1;
16088f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            }
16098f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            fb_perform_format(transport, "userdata", 1, nullptr, nullptr, initial_userdata_dir);
16108f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            delete_fbemarker_tmpdir(initial_userdata_dir);
16118f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        } else {
16128f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            fb_perform_format(transport, "userdata", 1, nullptr, nullptr, "");
16138f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley        }
16142fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes
16152fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        std::string cache_type;
16160b156638307db890e5539b52521fd24beb3440cbDavid Pursell        if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
16172fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fprintf(stderr, "wiping cache...\n");
16182fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes            fb_queue_erase("cache");
16198f7f56e25b2f289cd3d025d717fdc7fa422d1f98Paul Crowley            fb_perform_format(transport, "cache", 1, nullptr, nullptr, "");
16202fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes        }
1621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
16220d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    if (wants_set_active) {
16230d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg        fb_set_active(next_active.c_str());
16240d088564168d6759c85292253a8248c1ec97dbb8Daniel Rosenberg    }
1625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (wants_reboot) {
1626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_reboot();
1627ec25e7bc4bb8c203f89f133136a62a08410d6cebMark Wachsler        fb_queue_wait_for_disconnect();
1628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (wants_reboot_bootloader) {
1629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_command("reboot-bootloader", "rebooting into bootloader");
1630157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler        fb_queue_wait_for_disconnect();
1631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
16330b156638307db890e5539b52521fd24beb3440cbDavid Pursell    return fb_execute_queue(transport) ? EXIT_FAILURE : EXIT_SUCCESS;
1634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1635