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