fastboot.cpp revision ec25e7bc4bb8c203f89f133136a62a08410d6ceb
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 <stdbool.h>
385957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <stdint.h>
395957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <stdio.h>
405957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <stdlib.h>
415957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <string.h>
425957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <sys/stat.h>
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/time.h>
44f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#include <sys/types.h>
455957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <unistd.h>
46f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <bootimg.h>
48f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#include <sparse/sparse.h>
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <zipfile/zipfile.h>
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "fastboot.h"
52e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg#include "fs.h"
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
54f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#ifndef O_BINARY
55f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#define O_BINARY 0
56f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross#endif
57f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
58622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
59622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
60b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Savillechar cur_product[FB_RESPONSE_SZ + 1];
61b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
622a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandvoid bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
632a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland
647b8970c577c788c9af582dac797c63b3134b201eJP Abgrallboot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
657b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                        void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
667b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                        void *second, unsigned second_size, unsigned second_offset,
677b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                        unsigned page_size, unsigned base, unsigned tags_offset,
682a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland                        unsigned *bootimg_size);
692a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic usb_handle *usb = 0;
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const char *serial = 0;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const char *product = 0;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const char *cmdline = 0;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic unsigned short vendor_id = 0;
7513081c6915220db03886b177f1a8e0b2c63467c9Scott Andersonstatic int long_listing = 0;
76f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t sparse_limit = -1;
77f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t target_sparse_limit = -1;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
797b8970c577c788c9af582dac797c63b3134b201eJP Abgrallunsigned page_size = 2048;
807b8970c577c788c9af582dac797c63b3134b201eJP Abgrallunsigned base_addr      = 0x10000000;
817b8970c577c788c9af582dac797c63b3134b201eJP Abgrallunsigned kernel_offset  = 0x00008000;
827b8970c577c788c9af582dac797c63b3134b201eJP Abgrallunsigned ramdisk_offset = 0x01000000;
837b8970c577c788c9af582dac797c63b3134b201eJP Abgrallunsigned second_offset  = 0x00f00000;
847b8970c577c788c9af582dac797c63b3134b201eJP Abgrallunsigned tags_offset    = 0x00000100;
857b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
86622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandenum fb_buffer_type {
87622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    FB_BUFFER,
88622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    FB_BUFFER_SPARSE,
89622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
90622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
91622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstruct fastboot_buffer {
92622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    enum fb_buffer_type type;
93622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    void *data;
948d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    unsigned int sz;
95622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
96622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
97622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic struct {
98622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    char img_name[13];
99622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    char sig_name[13];
100622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    char part_name[9];
101622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    bool is_optional;
10273a4ad288ffdabfbdac0930737def7fdcf65d07cDaniel Rosenberg} images[4] = {
103622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    {"boot.img", "boot.sig", "boot", false},
104622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    {"recovery.img", "recovery.sig", "recovery", true},
105622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    {"system.img", "system.sig", "system", false},
10673a4ad288ffdabfbdac0930737def7fdcf65d07cDaniel Rosenberg    {"tos.img", "tos.sig", "tos", true},
107622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand};
1082a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid get_my_path(char *path);
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectchar *find_item(const char *item, const char *product)
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *dir;
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *fn;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char path[PATH_MAX + 128];
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strcmp(item,"boot")) {
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "boot.img";
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"recovery")) {
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "recovery.img";
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"system")) {
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "system.img";
12373a4ad288ffdabfbdac0930737def7fdcf65d07cDaniel Rosenberg    } else if(!strcmp(item,"tos")) {
12473a4ad288ffdabfbdac0930737def7fdcf65d07cDaniel Rosenberg        fn = "tos.img";
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"userdata")) {
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "userdata.img";
127d7608a40d6bed0d8ca686414a5a4f44b6d4d0435Jean-Baptiste Queru    } else if(!strcmp(item,"cache")) {
128d7608a40d6bed0d8ca686414a5a4f44b6d4d0435Jean-Baptiste Queru        fn = "cache.img";
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strcmp(item,"info")) {
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fn = "android-info.txt";
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"unknown partition '%s'\n", item);
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(product) {
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        get_my_path(path);
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(path + strlen(path),
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                "../../../target/product/%s/%s", product, fn);
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return strdup(path);
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
142ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dir = getenv("ANDROID_PRODUCT_OUT");
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((dir == 0) || (dir[0] == 0)) {
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
148ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sprintf(path, "%s/%s", dir, fn);
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return strdup(path);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1538d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiystatic int64_t file_size(int fd)
154f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
155622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    struct stat st;
156622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    int ret;
157f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
158622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    ret = fstat(fd, &st);
159f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
160622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return ret ? -1 : st.st_size;
161f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
162f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
1638d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiystatic void *load_fd(int fd, unsigned *_sz)
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1658d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    char *data;
1668d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    int sz;
16764ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    int errno_tmp;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1698d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    data = 0;
1708d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy
1718d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    sz = file_size(fd);
172622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    if (sz < 0) {
173622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        goto oops;
174622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = (char*) malloc(sz);
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(data == 0) goto oops;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(read(fd, data, sz) != sz) goto oops;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(_sz) *_sz = sz;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return data;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectoops:
18664ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    errno_tmp = errno;
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(data != 0) free(data);
18964ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    errno = errno_tmp;
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1938d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiystatic void *load_file(const char *fn, unsigned *_sz)
194622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
195622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    int fd;
196622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
197622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    fd = open(fn, O_RDONLY | O_BINARY);
198622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    if(fd < 0) return 0;
199622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
200622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return load_fd(fd, _sz);
201622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
203a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrallint match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial)
204a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrall{
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!(vendor_id && (info->dev_vendor == vendor_id)) &&
20609070d9e8685645f4ca8ecca62ae489472aed646Mike Lockwood       (info->dev_vendor != 0x18d1) &&  // Google
207f60e8638282d66c108f1e1dea030856312f65892Wu, Hao       (info->dev_vendor != 0x8087) &&  // Intel
208f614d64d4b4dfcd20c77ac3ccf2d9c9090a49303The Android Open Source Project       (info->dev_vendor != 0x0451) &&
209e25ff1c682ae5cc87af5e76de7e31a2702b620f3Robert CH Chou       (info->dev_vendor != 0x0502) &&
210509f7399b8f246f506307b22039e63323ec09622Dima Zavin       (info->dev_vendor != 0x0fce) &&  // Sony Ericsson
211509f7399b8f246f506307b22039e63323ec09622Dima Zavin       (info->dev_vendor != 0x05c6) &&  // Qualcomm
21209070d9e8685645f4ca8ecca62ae489472aed646Mike Lockwood       (info->dev_vendor != 0x22b8) &&  // Motorola
21337e9e904360d6a8757c958dacaab1343eacb7fa8Erik Gilling       (info->dev_vendor != 0x0955) &&  // Nvidia
214af82f21df7b87af2b378a46c8f338ebdd9c66175Xavier Ducrohet       (info->dev_vendor != 0x413c) &&  // DELL
215746f3243f6d30ab51a36dcfea76eac3ba29ac625Xavier Ducrohet       (info->dev_vendor != 0x2314) &&  // INQ Mobile
21673c019b30a7c70c50d2a854982143d5eb8c74f8cRamanan Rajeswaran       (info->dev_vendor != 0x0b05) &&  // Asus
21709070d9e8685645f4ca8ecca62ae489472aed646Mike Lockwood       (info->dev_vendor != 0x0bb4))    // HTC
21809070d9e8685645f4ca8ecca62ae489472aed646Mike Lockwood            return -1;
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(info->ifc_class != 0xff) return -1;
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(info->ifc_subclass != 0x42) return -1;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(info->ifc_protocol != 0x03) return -1;
22213081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson    // require matching serial number or device path if requested
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // at the command line with the -s option.
224a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrall    if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
225a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrall                   strcmp(local_serial, info->device_path) != 0)) return -1;
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2297b8970c577c788c9af582dac797c63b3134b201eJP Abgrallint match_fastboot(usb_ifc_info *info)
2307b8970c577c788c9af582dac797c63b3134b201eJP Abgrall{
2317b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    return match_fastboot_with_serial(info, serial);
2327b8970c577c788c9af582dac797c63b3134b201eJP Abgrall}
2337b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint list_devices_callback(usb_ifc_info *info)
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
236a032dedefe275b1d5a08b9856dfcfcb12579b4a7JP Abgrall    if (match_fastboot_with_serial(info, NULL) == 0) {
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char* serial = info->serial_number;
238b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes        if (!info->writable) {
239b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes            serial = "no permissions"; // like "adb devices"
240b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes        }
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!serial[0]) {
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            serial = "????????????";
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
244866b1bd5051db4f22b634df1f8a06bc1c9aa2e26Scott Anderson        // output compatible with "adb devices"
24513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        if (!long_listing) {
24613081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson            printf("%s\tfastboot\n", serial);
247866b1bd5051db4f22b634df1f8a06bc1c9aa2e26Scott Anderson        } else if (!info->device_path) {
248866b1bd5051db4f22b634df1f8a06bc1c9aa2e26Scott Anderson            printf("%-22s fastboot\n", serial);
24913081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        } else {
250866b1bd5051db4f22b634df1f8a06bc1c9aa2e26Scott Anderson            printf("%-22s fastboot %s\n", serial, info->device_path);
25113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        }
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectusb_handle *open_device(void)
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    static usb_handle *usb = 0;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int announce = 1;
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(usb) return usb;
263ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb = usb_open(match_fastboot);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(usb) return usb;
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(announce) {
268ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang            announce = 0;
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr,"< waiting for device >\n");
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
2715957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn        usleep(1000);
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid list_devices(void) {
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // We don't actually open a USB device here,
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // just getting our callback called so we can
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // list all the connected devices.
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_open(list_devices_callback);
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usage(void)
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*           1234567890123456789012345678901234567890123456789012345678901234567890123456 */
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "usage: fastboot [ <option> ] <command>\n"
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "\n"
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "commands:\n"
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  update <filename>                        reflash device from update.zip\n"
2907e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "  flashall                                 flash boot, system, and if found,\n"
2917e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "                                           recovery, tos\n"
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  flash <partition> [ <filename> ]         write a file to a flash partition\n"
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  erase <partition>                        erase a flash partition\n"
2947e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "  format[:[<fs type>][:[<size>]] <partition> format a flash partition.\n"
2957e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "                                           Can override the fs type and/or\n"
2967e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "                                           size the bootloader reports.\n"
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  getvar <variable>                        display a bootloader variable\n"
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  boot <kernel> [ <ramdisk> ]              download and boot kernel\n"
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  flash:raw boot <kernel> [ <ramdisk> ]    create bootimage and flash it\n"
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  devices                                  list all connected devices\n"
30124ce4bc8d7c4706286ef0530870dea80a1a0cd11Bruce Beare            "  continue                                 continue with autoboot\n"
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  reboot                                   reboot device normally\n"
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  reboot-bootloader                        reboot device into bootloader\n"
304ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang            "  help                                     show this help message\n"
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "\n"
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "options:\n"
3075ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            "  -w                                       erase userdata and cache (and format\n"
3085ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            "                                           if supported by partition type)\n"
3095ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            "  -u                                       do not first erase partition before\n"
3105ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            "                                           formatting\n"
31113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson            "  -s <specific device>                     specify device serial number\n"
31213081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson            "                                           or path to device port\n"
31313081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson            "  -l                                       with \"devices\", lists device paths\n"
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  -p <product>                             specify product name\n"
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  -c <cmdline>                             override kernel commandline\n"
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "  -i <vendor id>                           specify a custom USB vendor id\n"
3177e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "  -b <base_addr>                           specify a custom kernel base address.\n"
3187e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "                                           default: 0x10000000\n"
3197e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "  -n <page size>                           specify the nand page size.\n"
3207e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "                                           default: 2048\n"
3217e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "  -S <size>[K|M|G]                         automatically sparse files greater\n"
3227e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            "                                           than size.  0 to disable\n"
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3267b8970c577c788c9af582dac797c63b3134b201eJP Abgrallvoid *load_bootable_image(const char *kernel, const char *ramdisk,
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          unsigned *sz, const char *cmdline)
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *kdata = 0, *rdata = 0;
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned ksize = 0, rsize = 0;
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *bdata;
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned bsize;
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(kernel == 0) {
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "no image specified\n");
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kdata = load_file(kernel, &ksize);
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(kdata == 0) {
34164ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel        fprintf(stderr, "cannot load '%s': %s\n", kernel, strerror(errno));
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
344ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* is this actually a boot image? */
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
348ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ramdisk) {
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n");
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
353ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *sz = ksize;
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return kdata;
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ramdisk) {
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rdata = load_file(ramdisk, &rsize);
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(rdata == 0) {
36164ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel            fprintf(stderr,"cannot load '%s': %s\n", ramdisk, strerror(errno));
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return  0;
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"creating boot image...\n");
3677b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    bdata = mkbootimg(kdata, ksize, kernel_offset,
3687b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                      rdata, rsize, ramdisk_offset,
3697b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                      0, 0, second_offset,
3707b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                      page_size, base_addr, tags_offset, &bsize);
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(bdata == 0) {
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"failed to create boot.img\n");
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"creating boot image - %d bytes\n", bsize);
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *sz = bsize;
378ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return bdata;
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3828d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiyvoid *unzip_file(zipfile_t zip, const char *name, unsigned *sz)
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *data;
3858d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    zipentry_t entry;
3868d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    unsigned datasz;
387ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
3888d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    entry = lookup_zipentry(zip, name);
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (entry == NULL) {
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "archive does not contain '%s'\n", name);
3918d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3948d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    *sz = get_zipentry_size(entry);
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3968d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    datasz = *sz * 1.001;
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = malloc(datasz);
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3998d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    if(data == 0) {
4008d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        fprintf(stderr, "failed to allocate %d bytes\n", *sz);
4018d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (decompress_zipentry(entry, data, datasz)) {
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "failed to unzip '%s' from archive\n", name);
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(data);
4078d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return 0;
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
4098d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return data;
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
413622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic int unzip_to_file(zipfile_t zip, char *name)
414622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
415622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    int fd;
416622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    char *data;
4178d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    unsigned sz;
418622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
419622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    fd = fileno(tmpfile());
420622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    if (fd < 0) {
4218d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return -1;
422622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
423622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
424622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    data = unzip_file(zip, name, &sz);
4258d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    if (data == 0) {
426622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        return -1;
427622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
428622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
4295957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn    if (write(fd, data, sz) != (ssize_t)sz) {
430622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        fd = -1;
431622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
432622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
433622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    free(data);
4348d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    lseek(fd, 0, SEEK_SET);
435622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return fd;
436622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
437622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char *strip(char *s)
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int n;
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(*s && isspace(*s)) s++;
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = strlen(s);
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(n-- > 0) {
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!isspace(s[n])) break;
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        s[n] = 0;
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s;
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define MAX_OPTIONS 32
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int setup_requirement_line(char *name)
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *val[MAX_OPTIONS];
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char **out;
455b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    char *prod = NULL;
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned n, count;
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *x;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int invert = 0;
459ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strncmp(name, "reject ", 7)) {
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name += 7;
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        invert = 1;
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(name, "require ", 8)) {
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name += 8;
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        invert = 0;
466b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    } else if (!strncmp(name, "require-for-product:", 20)) {
467b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        // Get the product and point name past it
468b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        prod = name + 20;
469b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        name = strchr(name, ' ');
470b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        if (!name) return -1;
471b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        *name = 0;
472b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        name += 1;
473b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        invert = 0;
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = strchr(name, '=');
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (x == 0) return 0;
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *x = 0;
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    val[0] = x + 1;
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(count = 1; count < MAX_OPTIONS; count++) {
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x = strchr(val[count - 1],'|');
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (x == 0) break;
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x = 0;
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        val[count] = x + 1;
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
487ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    name = strip(name);
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0; n < count; n++) val[n] = strip(val[n]);
490ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    name = strip(name);
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (name == 0) return -1;
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* work around an unfortunate name mismatch */
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strcmp(name,"board")) name = "product";
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    out = malloc(sizeof(char*) * count);
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (out == 0) return -1;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0; n < count; n++) {
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        out[n] = strdup(strip(val[n]));
50214e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes        if (out[n] == 0) {
50314e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            for(size_t i = 0; i < n; ++i) {
50414e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes                free((char*) out[i]);
50514e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            }
50614e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            free(out);
50714e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes            return -1;
50814e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes        }
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
511b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    fb_queue_require(prod, name, invert, n, out);
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5158d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiystatic void setup_requirements(char *data, unsigned sz)
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
5178d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    char *s;
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5198d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    s = data;
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (sz-- > 0) {
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(*s == '\n') {
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *s++ = 0;
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (setup_requirement_line(data)) {
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                die("out of memory");
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            data = s;
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s++;
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid queue_info_dump(void)
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_notice("--------------------------------------------");
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("version-bootloader", "Bootloader Version...");
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("version-baseband",   "Baseband Version.....");
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_display("serialno",           "Serial Number........");
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_notice("--------------------------------------------");
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
542622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic struct sparse_file **load_sparse_files(int fd, int max_size)
543f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
544f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    struct sparse_file *s;
545f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int files;
546f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    struct sparse_file **out_s;
547f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
548f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    s = sparse_file_import_auto(fd, false);
549f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (!s) {
550622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("cannot sparse read file\n");
551f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
552f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
553f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    files = sparse_file_resparse(s, max_size, NULL, 0);
554f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (files < 0) {
555622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("Failed to resparse\n");
556f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
557f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
558f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    out_s = calloc(sizeof(struct sparse_file *), files + 1);
559f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (!out_s) {
560f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        die("Failed to allocate sparse file array\n");
561f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
562f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
563f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    files = sparse_file_resparse(s, max_size, out_s, files);
564f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (files < 0) {
565622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("Failed to resparse\n");
566f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
567f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
568f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return out_s;
569f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
570f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
571f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t get_target_sparse_limit(struct usb_handle *usb)
572f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
573f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int64_t limit = 0;
574f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    char response[FB_RESPONSE_SZ + 1];
575f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int status = fb_getvar(usb, response, "max-download-size");
576f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
577f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (!status) {
578f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        limit = strtoul(response, NULL, 0);
579f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (limit > 0) {
580cf86e2f85d98ed10cf5e0672e41631f6ea7e3e34Ying Wang            fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n",
581f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross                    limit);
582f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
583f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
584f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
585f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return limit;
586f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
587f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
588f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t get_sparse_limit(struct usb_handle *usb, int64_t size)
589f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
590f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    int64_t limit;
591f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
592f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (sparse_limit == 0) {
593f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return 0;
594f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (sparse_limit > 0) {
595f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        limit = sparse_limit;
596f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else {
597f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (target_sparse_limit == -1) {
598f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            target_sparse_limit = get_target_sparse_limit(usb);
599f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
600f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (target_sparse_limit > 0) {
601f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            limit = target_sparse_limit;
602f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        } else {
6030bbfb3976e9491b3e1a872ebdaa850ef868a24aaColin Cross            return 0;
604f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
605f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
606f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
607f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (size > limit) {
608f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return limit;
609f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
610f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
611f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return 0;
612f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
613f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
6145ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall/* Until we get lazy inode table init working in make_ext4fs, we need to
6155ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall * erase partitions of type ext4 before flashing a filesystem so no stale
6165ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall * inodes are left lying around.  Otherwise, e2fsck gets very upset.
6175ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall */
6185ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrallstatic int needs_erase(const char *part)
6195ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall{
6205ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall    /* The function fb_format_supported() currently returns the value
6215ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall     * we want, so just call it.
6225ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall     */
6237e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall     return fb_format_supported(usb, part, NULL);
6245ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall}
6255ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
626622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic int load_buf_fd(usb_handle *usb, int fd,
627622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        struct fastboot_buffer *buf)
628f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
629782111b3bc5d372afc8d66ab6023e834b7c23b88Sasha Levitskiy    int64_t sz64;
6308d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    void *data;
6318d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    int64_t limit;
632f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
6338d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy
6348d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    sz64 = file_size(fd);
6358d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    if (sz64 < 0) {
6368d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        return -1;
637622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
638e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
639e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    lseek(fd, 0, SEEK_SET);
640f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    limit = get_sparse_limit(usb, sz64);
641f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (limit) {
642622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        struct sparse_file **s = load_sparse_files(fd, limit);
643f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (s == NULL) {
644622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            return -1;
645f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
646622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->type = FB_BUFFER_SPARSE;
647622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->data = s;
648f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else {
6498d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        unsigned int sz;
650622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        data = load_fd(fd, &sz);
6518d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        if (data == 0) return -1;
652622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        buf->type = FB_BUFFER;
653782111b3bc5d372afc8d66ab6023e834b7c23b88Sasha Levitskiy        buf->data = data;
6548d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        buf->sz = sz;
655622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
656622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
657622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return 0;
658622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
659622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
660622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic int load_buf(usb_handle *usb, const char *fname,
661622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        struct fastboot_buffer *buf)
662622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
663622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    int fd;
664622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
665622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    fd = open(fname, O_RDONLY | O_BINARY);
666622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    if (fd < 0) {
66782280594ef7e9dc908aa67f3da8661ff54a96c9eDaniel Rosenberg        return -1;
668f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
669622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
670622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    return load_buf_fd(usb, fd, buf);
671622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand}
672622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
673622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandstatic void flash_buf(const char *pname, struct fastboot_buffer *buf)
674622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
675622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    struct sparse_file **s;
676622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
677622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    switch (buf->type) {
678622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        case FB_BUFFER_SPARSE:
679622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            s = buf->data;
680622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            while (*s) {
681622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                int64_t sz64 = sparse_file_len(*s, true, false);
682622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                fb_queue_flash_sparse(pname, *s++, sz64);
683622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            }
684622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            break;
685622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        case FB_BUFFER:
686622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            fb_queue_flash(pname, buf->data, buf->sz);
687622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            break;
688622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        default:
689622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            die("unknown buffer type: %d", buf->type);
690f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
691f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
692f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
693622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandvoid do_flash(usb_handle *usb, const char *pname, const char *fname)
694622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand{
695622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    struct fastboot_buffer buf;
696622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand
697622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    if (load_buf(usb, fname, &buf)) {
698622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        die("cannot load '%s'", fname);
699622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    }
700622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    flash_buf(pname, &buf);
701f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
702f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid do_update_signature(zipfile_t zip, char *fn)
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
7058d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    void *data;
7068d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    unsigned sz;
7078d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    data = unzip_file(zip, fn, &sz);
7088d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    if (data == 0) return;
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_download("signature", data, sz);
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_command("signature", "installing signature");
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
713622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandvoid do_update(usb_handle *usb, char *fn, int erase_first)
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *zdata;
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned zsize;
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *data;
7188d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    unsigned sz;
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    zipfile_t zip;
720622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    int fd;
721622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    int rc;
722622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    struct fastboot_buffer buf;
7235957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn    size_t i;
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    queue_info_dump();
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
727b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    fb_queue_query_save("product", cur_product, sizeof(cur_product));
728b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    zdata = load_file(fn, &zsize);
73064ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    if (zdata == 0) die("failed to load '%s': %s", fn, strerror(errno));
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    zip = init_zipfile(zdata, zsize);
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(zip == 0) die("failed to access zipdata in '%s'");
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = unzip_file(zip, "android-info.txt", &sz);
7368d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    if (data == 0) {
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *tmp;
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* fallback for older zipfiles */
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        data = unzip_file(zip, "android-product.txt", &sz);
7408d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy        if ((data == 0) || (sz < 1)) {
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            die("update package has no android-info.txt or android-product.txt");
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp = malloc(sz + 128);
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmp == 0) die("out of memory");
745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sprintf(tmp,"board=%sversion-baseband=0.66.04.19\n",(char*)data);
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        data = tmp;
747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sz = strlen(tmp);
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
749dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
750dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    setup_requirements(data, sz);
751dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
752622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    for (i = 0; i < ARRAY_SIZE(images); i++) {
753622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        fd = unzip_to_file(zip, images[i].img_name);
754622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        if (fd < 0) {
755622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            if (images[i].is_optional)
756622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                continue;
757622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            die("update package missing %s", images[i].img_name);
7585ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall        }
759622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        rc = load_buf_fd(usb, fd, &buf);
760622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        if (rc) die("cannot load %s from flash", images[i].img_name);
761622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        do_update_signature(zip, images[i].sig_name);
762622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        if (erase_first && needs_erase(images[i].part_name)) {
763622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            fb_queue_erase(images[i].part_name);
764622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        }
765622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        flash_buf(images[i].part_name, &buf);
766622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        /* not closing the fd here since the sparse code keeps the fd around
767622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand         * but hasn't mmaped data yet. The tmpfile will get cleaned up when the
768622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand         * program exits.
769622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand         */
7705ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall    }
771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid do_send_signature(char *fn)
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *data;
7768d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    unsigned sz;
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *xtn;
778ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    xtn = strrchr(fn, '.');
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!xtn) return;
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (strcmp(xtn, ".img")) return;
782ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy(xtn,".sig");
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = load_file(fn, &sz);
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy(xtn,".img");
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (data == 0) return;
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_download("signature", data, sz);
788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fb_queue_command("signature", "installing signature");
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
791622810ceff6d98779171c68391465c7434adeb1dRom Lemarchandvoid do_flashall(usb_handle *usb, int erase_first)
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *fname;
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *data;
7958d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    unsigned sz;
796622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    struct fastboot_buffer buf;
7975957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn    size_t i;
798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    queue_info_dump();
800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
801b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    fb_queue_query_save("product", cur_product, sizeof(cur_product));
802b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fname = find_item("info", product);
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fname == 0) die("cannot find android-info.txt");
805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = load_file(fname, &sz);
80664ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel    if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    setup_requirements(data, sz);
808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
809622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand    for (i = 0; i < ARRAY_SIZE(images); i++) {
810622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        fname = find_item(images[i].part_name, product);
811622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        if (load_buf(usb, fname, &buf)) {
812622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            if (images[i].is_optional)
813622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                continue;
814622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            die("could not load %s\n", images[i].img_name);
815622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        }
816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do_send_signature(fname);
817622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        if (erase_first && needs_erase(images[i].part_name)) {
818622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            fb_queue_erase(images[i].part_name);
8195ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall        }
820622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand        flash_buf(images[i].part_name, &buf);
8215ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall    }
822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
823dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
824dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define skip(n) do { argc -= (n); argv += (n); } while (0)
8252d13d1408bef9e26cc418e6fc2579dfd12378a3cJP Abgrall#define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0)
826dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint do_oem_command(int argc, char **argv)
828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char command[256];
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (argc <= 1) return 0;
831ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    command[0] = 0;
833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(1) {
834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcat(command,*argv);
835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        skip(1);
836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(argc == 0) break;
837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcat(command," ");
838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
840ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    fb_queue_command(command,"");
841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
844f838788e6a4d57634a53eb597ee76a597feffcb5Colin Crossstatic int64_t parse_num(const char *arg)
845f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross{
846f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    char *endptr;
847f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    unsigned long long num;
848f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
849f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    num = strtoull(arg, &endptr, 0);
850f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (endptr == arg) {
851f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
852f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
853f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
854f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (*endptr == 'k' || *endptr == 'K') {
855f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / 1024) {
856f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
857f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
858f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL;
859f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
860f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (*endptr == 'm' || *endptr == 'M') {
861f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / (1024 * 1024)) {
862f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
863f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
864f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL * 1024LL;
865f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
866f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    } else if (*endptr == 'g' || *endptr == 'G') {
867f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        if (num >= (-1ULL) / (1024 * 1024 * 1024)) {
868f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            return -1;
869f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        }
870f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        num *= 1024LL * 1024LL * 1024LL;
871f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        endptr++;
872f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
873f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
874f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (*endptr != '\0') {
875f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
876f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
877f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
878f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    if (num > INT64_MAX) {
879f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        return -1;
880f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    }
881f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
882f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    return num;
883f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
884f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
8857e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrallvoid fb_perform_format(const char *partition, int skip_if_not_supported,
8867e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                       const char *type_override, const char *size_override)
887e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg{
8887e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    char pTypeBuff[FB_RESPONSE_SZ + 1], pSizeBuff[FB_RESPONSE_SZ + 1];
8897e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    char *pType = pTypeBuff;
8907e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    char *pSize = pSizeBuff;
891e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    unsigned int limit = INT_MAX;
892e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    struct fastboot_buffer buf;
893e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    const char *errMsg = NULL;
894e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    const struct fs_generator *gen;
895e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    uint64_t pSz;
896e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    int status;
897e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    int fd;
898e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
899e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (target_sparse_limit > 0 && target_sparse_limit < limit)
900e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        limit = target_sparse_limit;
901e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (sparse_limit > 0 && sparse_limit < limit)
902e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        limit = sparse_limit;
903e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
904e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    status = fb_getvar(usb, pType, "partition-type:%s", partition);
905e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (status) {
906e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        errMsg = "Can't determine partition type.\n";
907e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        goto failed;
908e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
9097e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    if (type_override) {
9107e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        if (strcmp(type_override, pType)) {
9117e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            fprintf(stderr,
9127e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    "Warning: %s type is %s, but %s was requested for formating.\n",
9137e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    partition, pType, type_override);
9147e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        }
9155957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn        pType = (char *)type_override;
9167e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    }
917e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
918e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    status = fb_getvar(usb, pSize, "partition-size:%s", partition);
919e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (status) {
920e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        errMsg = "Unable to get partition size\n";
921e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        goto failed;
922e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
9237e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    if (size_override) {
9247e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        if (strcmp(size_override, pSize)) {
9257e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            fprintf(stderr,
9267e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    "Warning: %s size is %s, but %s was requested for formating.\n",
9277e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    partition, pSize, size_override);
9287e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        }
9295957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn        pSize = (char *)size_override;
9307e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall    }
931e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
932e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    gen = fs_get_generator(pType);
933e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (!gen) {
934e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        if (skip_if_not_supported) {
935e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg            fprintf(stderr, "Erase successful, but not automatically formatting.\n");
936e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg            fprintf(stderr, "File system type %s not supported.\n", pType);
937e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg            return;
938e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        }
939e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        fprintf(stderr, "Formatting is not supported for filesystem with type '%s'.\n", pType);
940e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
941e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
942e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
943e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    pSz = strtoll(pSize, (char **)NULL, 16);
944e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
945e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    fd = fileno(tmpfile());
946e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (fs_generator_generate(gen, fd, pSz)) {
947e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        close(fd);
948e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        fprintf(stderr, "Cannot generate image.\n");
949e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
950e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
951e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
952e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (load_buf_fd(usb, fd, &buf)) {
953e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        fprintf(stderr, "Cannot read image.\n");
954e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        close(fd);
955e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        return;
956e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
957e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    flash_buf(partition, &buf);
958e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
959e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    return;
960e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
961e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
962e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinbergfailed:
963e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    if (skip_if_not_supported) {
964e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        fprintf(stderr, "Erase successful, but not automatically formatting.\n");
965e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg        if (errMsg)
966e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg            fprintf(stderr, "%s", errMsg);
967e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    }
968e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg    fprintf(stderr,"FAILED (%s)\n", fb_get_error());
969e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg}
970e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg
971dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint main(int argc, char **argv)
972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
973dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int wants_wipe = 0;
974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int wants_reboot = 0;
975dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int wants_reboot_bootloader = 0;
9765ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall    int erase_first = 1;
977dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *data;
9788d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiy    unsigned sz;
979eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom    int status;
9808879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    int c;
981dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
9827b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    const struct option longopts[] = {
9837b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"base", required_argument, 0, 'b'},
9847b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"kernel_offset", required_argument, 0, 'k'},
9857b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"page_size", required_argument, 0, 'n'},
9867b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"ramdisk_offset", required_argument, 0, 'r'},
98729fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash        {"tags_offset", required_argument, 0, 't'},
9887b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {"help", 0, 0, 'h'},
9897b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        {0, 0, 0, 0}
9907b8970c577c788c9af582dac797c63b3134b201eJP Abgrall    };
9918879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
9928879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    serial = getenv("ANDROID_SERIAL");
9938879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
9948879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    while (1) {
99529fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash        c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:h", longopts, NULL);
9968879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        if (c < 0) {
9978879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
9988879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        }
9997b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        /* Alphabetical cases */
10008879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        switch (c) {
10018879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 'b':
10028879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            base_addr = strtoul(optarg, 0, 16);
10038879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
10047b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'c':
10057b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            cmdline = optarg;
10067b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
10077b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'h':
10087b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            usage();
10097b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            return 1;
10107b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'i': {
10117b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                char *endptr = NULL;
10127b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                unsigned long val;
10137b8970c577c788c9af582dac797c63b3134b201eJP Abgrall
10147b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                val = strtoul(optarg, &endptr, 0);
10157b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                if (!endptr || *endptr != '\0' || (val & ~0xffff))
10167b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                    die("invalid vendor id '%s'", optarg);
10177b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                vendor_id = (unsigned short)val;
10187b8970c577c788c9af582dac797c63b3134b201eJP Abgrall                break;
10197b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            }
10207b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'k':
10217b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            kernel_offset = strtoul(optarg, 0, 16);
10227b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
10237b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'l':
10247b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            long_listing = 1;
10257b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
10268879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 'n':
10278879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            page_size = (unsigned)strtoul(optarg, NULL, 0);
10288879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            if (!page_size) die("invalid page size");
10298879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
10307b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'p':
10317b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            product = optarg;
10327b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
10337b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'r':
10347b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            ramdisk_offset = strtoul(optarg, 0, 16);
10357b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            break;
103629fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash        case 't':
103729fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash            tags_offset = strtoul(optarg, 0, 16);
103829fd7b1f4f86e4955cf78156a9de174c5b7233c1Mohamad Ayyash            break;
10398879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case 's':
10408879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            serial = optarg;
10418879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
1042f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        case 'S':
1043f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            sparse_limit = parse_num(optarg);
1044f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            if (sparse_limit < 0) {
1045f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross                    die("invalid sparse limit");
1046f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            }
1047f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            break;
10487b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'u':
10497b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            erase_first = 0;
10508879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
10517b8970c577c788c9af582dac797c63b3134b201eJP Abgrall        case 'w':
10527b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            wants_wipe = 1;
10538879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            break;
10548879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        case '?':
10558879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            return 1;
10568879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        default:
10578879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross            abort();
10588879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        }
10598879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    }
1060dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10618879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    argc -= optind;
10628879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    argv += optind;
10638879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross
10648879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    if (argc == 0 && !wants_wipe) {
1065dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usage();
1066eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom        return 1;
1067dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1068dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10698fb6e06ba44b92258bf44110ea5361496257e24eColin Cross    if (argc > 0 && !strcmp(*argv, "devices")) {
10708879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        skip(1);
1071dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        list_devices();
1072ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang        return 0;
1073ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    }
1074ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
1075c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross    if (argc > 0 && !strcmp(*argv, "help")) {
1076c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross        usage();
1077c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross        return 0;
1078c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross    }
1079c7b75dcc1aa121574d7677c97ff7d9b4ba91e624Colin Cross
10808879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross    usb = open_device();
108131dbed7b60d8237d6d05dc6bf230167a5854b77aElliott Hughes
1082dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (argc > 0) {
10838879f988bac8d4cb46fb82e3d82ad69a9ed89b16Colin Cross        if(!strcmp(*argv, "getvar")) {
1084dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1085dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_display(argv[1], argv[1]);
1086dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
1087dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "erase")) {
1088dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
10895ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
10907e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            if (fb_format_supported(usb, argv[1], NULL)) {
10915ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall                fprintf(stderr, "******** Did you mean to fastboot format this partition?\n");
10925ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            }
10935ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall
1094dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_erase(argv[1]);
1095dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
10967e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        } else if(!strncmp(*argv, "format", strlen("format"))) {
10977e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            char *overrides;
10987e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            char *type_override = NULL;
10997e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            char *size_override = NULL;
1100c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau            require(2);
11017e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            /*
11027e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             * Parsing for: "format[:[type][:[size]]]"
11037e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             * Some valid things:
11047e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *  - select ontly the size, and leave default fs type:
11057e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format::0x4000000 userdata
11067e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *  - default fs type and size:
11077e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format userdata
11087e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             *    format:: userdata
11097e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall             */
11107e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            overrides = strchr(*argv, ':');
11117e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            if (overrides) {
11127e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                overrides++;
11137e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                size_override = strchr(overrides, ':');
11147e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                if (size_override) {
11157e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    size_override[0] = '\0';
11167e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                    size_override++;
11177e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                }
11187e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall                type_override = overrides;
11197e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            }
11207e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            if (type_override && !type_override[0]) type_override = NULL;
11217e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            if (size_override && !size_override[0]) size_override = NULL;
11225ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            if (erase_first && needs_erase(argv[1])) {
11235ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall                fb_queue_erase(argv[1]);
11245ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            }
11257e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall            fb_perform_format(argv[1], 0, type_override, size_override);
1126c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau            skip(2);
1127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "signature")) {
1128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            data = load_file(argv[1], &sz);
113064ba258b7a17fd5f0abd788c1b021ad45ad732b9Matt Gumbel            if (data == 0) die("could not load '%s': %s", argv[1], strerror(errno));
1131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (sz != 256) die("signature must be 256 bytes");
1132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_download("signature", data, sz);
1133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("signature", "installing signature");
1134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(2);
1135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "reboot")) {
1136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            wants_reboot = 1;
1137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "reboot-bootloader")) {
1139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            wants_reboot_bootloader = 1;
1140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strcmp(*argv, "continue")) {
1142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("continue", "resuming boot");
1143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "boot")) {
1145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *kname = 0;
1146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *rname = 0;
1147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 0) {
1149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kname = argv[0];
1150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 0) {
1153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                rname = argv[0];
1154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
11567b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            data = load_bootable_image(kname, rname, &sz, cmdline);
1157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (data == 0) return 1;
1158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_download("boot.img", data, sz);
1159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_command("boot", "booting");
1160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flash")) {
1161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *pname = argv[1];
1162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *fname = 0;
1163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(2);
1164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 2) {
1165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fname = argv[2];
1166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(3);
1167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
1168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fname = find_item(pname, product);
1169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(2);
1170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fname == 0) die("cannot determine image filename for '%s'", pname);
11725ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            if (erase_first && needs_erase(pname)) {
11735ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall                fb_queue_erase(pname);
11745ee5d389d6cb90b3cd2856730f8ff12211bc95d2Ken Sumrall            }
1175f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            do_flash(usb, pname, fname);
1176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flash:raw")) {
1177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *pname = argv[1];
1178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *kname = argv[2];
1179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *rname = 0;
1180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            require(3);
1181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(argc > 3) {
1182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                rname = argv[3];
1183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(4);
1184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
1185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(3);
1186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
11877b8970c577c788c9af582dac797c63b3134b201eJP Abgrall            data = load_bootable_image(kname, rname, &sz, cmdline);
1188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (data == 0) die("cannot load bootable image");
1189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb_queue_flash(pname, data, sz);
1190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "flashall")) {
1191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            skip(1);
1192622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand            do_flashall(usb, erase_first);
1193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            wants_reboot = 1;
1194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "update")) {
1195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (argc > 1) {
1196622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                do_update(usb, argv[1], erase_first);
1197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(2);
1198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
1199622810ceff6d98779171c68391465c7434adeb1dRom Lemarchand                do_update(usb, "update.zip", erase_first);
1200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                skip(1);
1201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            wants_reboot = 1;
1203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(*argv, "oem")) {
1204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            argc = do_oem_command(argc, argv);
1205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            usage();
1207ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang            return 1;
1208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (wants_wipe) {
1212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_erase("userdata");
12137e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        fb_perform_format("userdata", 1, NULL, NULL);
1214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_erase("cache");
12157e85974fc2fc48a0cea7bb9bafcfcda863138eb6JP Abgrall        fb_perform_format("cache", 1, NULL, NULL);
1216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (wants_reboot) {
1218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_reboot();
1219ec25e7bc4bb8c203f89f133136a62a08410d6cebMark Wachsler        fb_queue_wait_for_disconnect();
1220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (wants_reboot_bootloader) {
1221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb_queue_command("reboot-bootloader", "rebooting into bootloader");
1222157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler        fb_queue_wait_for_disconnect();
1223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson    if (fb_queue_is_empty())
122613081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        return 0;
122713081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson
1228eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom    status = fb_execute_queue(usb);
1229eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom    return (status) ? 1 : 0;
1230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1231