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