/* * Copyright (C) 2008 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #define _LARGEFILE64_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fastboot.h" #ifndef O_BINARY #define O_BINARY 0 #endif char cur_product[FB_RESPONSE_SZ + 1]; void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline); boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, void *ramdisk, unsigned ramdisk_size, void *second, unsigned second_size, unsigned page_size, unsigned base, unsigned *bootimg_size); static usb_handle *usb = 0; static const char *serial = 0; static const char *product = 0; static const char *cmdline = 0; static int wipe_data = 0; static unsigned short vendor_id = 0; static int long_listing = 0; static int64_t sparse_limit = -1; static int64_t target_sparse_limit = -1; static unsigned base_addr = 0x10000000; void die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr,"error: "); vfprintf(stderr, fmt, ap); fprintf(stderr,"\n"); va_end(ap); exit(1); } void get_my_path(char *path); char *find_item(const char *item, const char *product) { char *dir; char *fn; char path[PATH_MAX + 128]; if(!strcmp(item,"boot")) { fn = "boot.img"; } else if(!strcmp(item,"recovery")) { fn = "recovery.img"; } else if(!strcmp(item,"system")) { fn = "system.img"; } else if(!strcmp(item,"userdata")) { fn = "userdata.img"; } else if(!strcmp(item,"cache")) { fn = "cache.img"; } else if(!strcmp(item,"info")) { fn = "android-info.txt"; } else { fprintf(stderr,"unknown partition '%s'\n", item); return 0; } if(product) { get_my_path(path); sprintf(path + strlen(path), "../../../target/product/%s/%s", product, fn); return strdup(path); } dir = getenv("ANDROID_PRODUCT_OUT"); if((dir == 0) || (dir[0] == 0)) { die("neither -p product specified nor ANDROID_PRODUCT_OUT set"); return 0; } sprintf(path, "%s/%s", dir, fn); return strdup(path); } #ifdef _WIN32 void *load_file(const char *fn, unsigned *_sz); int64_t file_size(const char *fn); #else #if defined(__APPLE__) && defined(__MACH__) #define lseek64 lseek #define off64_t off_t #endif int64_t file_size(const char *fn) { off64_t off; int fd; fd = open(fn, O_RDONLY); if (fd < 0) return -1; off = lseek64(fd, 0, SEEK_END); close(fd); return off; } void *load_file(const char *fn, unsigned *_sz) { char *data; int sz; int fd; int errno_tmp; data = 0; fd = open(fn, O_RDONLY); if(fd < 0) return 0; sz = lseek(fd, 0, SEEK_END); if(sz < 0) goto oops; if(lseek(fd, 0, SEEK_SET) != 0) goto oops; data = (char*) malloc(sz); if(data == 0) goto oops; if(read(fd, data, sz) != sz) goto oops; close(fd); if(_sz) *_sz = sz; return data; oops: errno_tmp = errno; close(fd); if(data != 0) free(data); errno = errno_tmp; return 0; } #endif int match_fastboot(usb_ifc_info *info) { return match_fastboot_with_serial(info, serial); } int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) { if(!(vendor_id && (info->dev_vendor == vendor_id)) && (info->dev_vendor != 0x18d1) && // Google (info->dev_vendor != 0x8087) && // Intel (info->dev_vendor != 0x0451) && (info->dev_vendor != 0x0502) && (info->dev_vendor != 0x0fce) && // Sony Ericsson (info->dev_vendor != 0x05c6) && // Qualcomm (info->dev_vendor != 0x22b8) && // Motorola (info->dev_vendor != 0x0955) && // Nvidia (info->dev_vendor != 0x413c) && // DELL (info->dev_vendor != 0x2314) && // INQ Mobile (info->dev_vendor != 0x0b05) && // Asus (info->dev_vendor != 0x0bb4)) // HTC return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; if(info->ifc_protocol != 0x03) return -1; // require matching serial number or device path if requested // at the command line with the -s option. if (local_serial && (strcmp(local_serial, info->serial_number) != 0 && strcmp(local_serial, info->device_path) != 0)) return -1; return 0; } int list_devices_callback(usb_ifc_info *info) { if (match_fastboot_with_serial(info, NULL) == 0) { char* serial = info->serial_number; if (!info->writable) { serial = "no permissions"; // like "adb devices" } if (!serial[0]) { serial = "????????????"; } // output compatible with "adb devices" if (!long_listing) { printf("%s\tfastboot\n", serial); } else if (!info->device_path) { printf("%-22s fastboot\n", serial); } else { printf("%-22s fastboot %s\n", serial, info->device_path); } } return -1; } usb_handle *open_device(void) { static usb_handle *usb = 0; int announce = 1; if(usb) return usb; for(;;) { usb = usb_open(match_fastboot); if(usb) return usb; if(announce) { announce = 0; fprintf(stderr,"< waiting for device >\n"); } sleep(1); } } void list_devices(void) { // We don't actually open a USB device here, // just getting our callback called so we can // list all the connected devices. usb_open(list_devices_callback); } void usage(void) { fprintf(stderr, /* 1234567890123456789012345678901234567890123456789012345678901234567890123456 */ "usage: fastboot [