am f4603673: am 04b94b25: Merge "Use 64-bit file sizes in fastboot."

* commit 'f46036732f7ac125bb4698d1d742c6a1299f7259':
  Use 64-bit file sizes in fastboot.
This commit is contained in:
Elliott Hughes 2015-08-26 02:25:43 +00:00 committed by Android Git Automerger
commit c32a4361cc
10 changed files with 215 additions and 348 deletions

View file

@ -32,32 +32,27 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline) void bootimg_set_cmdline(boot_img_hdr* h, const char* cmdline)
{ {
strcpy((char*) h->cmdline, cmdline); strcpy((char*) h->cmdline, cmdline);
} }
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset, boot_img_hdr* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset,
void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset, void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset,
void *second, unsigned second_size, unsigned second_offset, void* second, int64_t second_size, off_t second_offset,
unsigned page_size, unsigned base, unsigned tags_offset, size_t page_size, size_t base, off_t tags_offset,
unsigned *bootimg_size) int64_t* bootimg_size)
{ {
unsigned kernel_actual; size_t page_mask = page_size - 1;
unsigned ramdisk_actual;
unsigned second_actual;
unsigned page_mask;
page_mask = page_size - 1; int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask);
int64_t ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask);
kernel_actual = (kernel_size + page_mask) & (~page_mask); int64_t second_actual = (second_size + page_mask) & (~page_mask);
ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask);
second_actual = (second_size + page_mask) & (~page_mask);
*bootimg_size = page_size + kernel_actual + ramdisk_actual + second_actual; *bootimg_size = page_size + kernel_actual + ramdisk_actual + second_actual;
boot_img_hdr* hdr = reinterpret_cast<boot_img_hdr*>(calloc(*bootimg_size, 1)); boot_img_hdr* hdr = reinterpret_cast<boot_img_hdr*>(calloc(*bootimg_size, 1));
if (hdr == 0) { if (hdr == nullptr) {
return hdr; return hdr;
} }
@ -74,12 +69,9 @@ boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offs
hdr->page_size = page_size; hdr->page_size = page_size;
memcpy(hdr->magic + page_size, kernel, kernel_size);
memcpy(hdr->magic + page_size + kernel_actual, ramdisk, ramdisk_size);
memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual, second, second_size);
memcpy(hdr->magic + page_size,
kernel, kernel_size);
memcpy(hdr->magic + page_size + kernel_actual,
ramdisk, ramdisk_size);
memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual,
second, second_size);
return hdr; return hdr;
} }

View file

@ -30,20 +30,14 @@
#define _FASTBOOT_BOOTIMG_UTILS_H_ #define _FASTBOOT_BOOTIMG_UTILS_H_
#include <bootimg.h> #include <bootimg.h>
#include <inttypes.h>
#include <sys/types.h>
#if defined(__cplusplus) void bootimg_set_cmdline(boot_img_hdr* h, const char* cmdline);
extern "C" { boot_img_hdr* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset,
#endif void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset,
void* second, int64_t second_size, off_t second_offset,
void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline); size_t page_size, size_t base, off_t tags_offset,
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset, int64_t* bootimg_size);
void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
void *second, unsigned second_size, unsigned second_offset,
unsigned page_size, unsigned base, unsigned tags_offset,
unsigned *bootimg_size);
#if defined(__cplusplus)
}
#endif
#endif #endif

View file

@ -30,8 +30,6 @@
#include "fs.h" #include "fs.h"
#include <errno.h> #include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -39,12 +37,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#ifdef USE_MINGW
#include <fcntl.h>
#else
#include <sys/mman.h>
#endif
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define OP_DOWNLOAD 1 #define OP_DOWNLOAD 1
@ -58,15 +50,17 @@ typedef struct Action Action;
#define CMD_SIZE 64 #define CMD_SIZE 64
struct Action struct Action {
{
unsigned op; unsigned op;
Action *next; Action* next;
char cmd[CMD_SIZE]; char cmd[CMD_SIZE];
const char *prod; const char* prod;
void *data; void* data;
unsigned size;
// The protocol only supports 32-bit sizes, so you'll have to break
// anything larger into chunks.
uint32_t size;
const char *msg; const char *msg;
int (*func)(Action* a, int status, const char* resp); int (*func)(Action* a, int status, const char* resp);
@ -267,7 +261,7 @@ static int cb_reject(Action* a, int status, const char* resp) {
} }
void fb_queue_require(const char *prod, const char *var, void fb_queue_require(const char *prod, const char *var,
int invert, unsigned nvalues, const char **value) bool invert, size_t nvalues, const char **value)
{ {
Action *a; Action *a;
a = queue_action(OP_QUERY, "getvar:%s", var); a = queue_action(OP_QUERY, "getvar:%s", var);

View file

@ -34,7 +34,6 @@
#include <getopt.h> #include <getopt.h>
#include <inttypes.h> #include <inttypes.h>
#include <limits.h> #include <limits.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -67,12 +66,12 @@ static int long_listing = 0;
static int64_t sparse_limit = -1; static int64_t sparse_limit = -1;
static int64_t target_sparse_limit = -1; static int64_t target_sparse_limit = -1;
unsigned page_size = 2048; static unsigned page_size = 2048;
unsigned base_addr = 0x10000000; static unsigned base_addr = 0x10000000;
unsigned kernel_offset = 0x00008000; static unsigned kernel_offset = 0x00008000;
unsigned ramdisk_offset = 0x01000000; static unsigned ramdisk_offset = 0x01000000;
unsigned second_offset = 0x00f00000; static unsigned second_offset = 0x00f00000;
unsigned tags_offset = 0x00000100; static unsigned tags_offset = 0x00000100;
enum fb_buffer_type { enum fb_buffer_type {
FB_BUFFER, FB_BUFFER,
@ -81,8 +80,8 @@ enum fb_buffer_type {
struct fastboot_buffer { struct fastboot_buffer {
enum fb_buffer_type type; enum fb_buffer_type type;
void *data; void* data;
unsigned int sz; int64_t sz;
}; };
static struct { static struct {
@ -97,8 +96,7 @@ static struct {
{"vendor.img", "vendor.sig", "vendor", true}, {"vendor.img", "vendor.sig", "vendor", true},
}; };
char *find_item(const char *item, const char *product) static char* find_item(const char* item, const char* product) {
{
char *dir; char *dir;
const char *fn; const char *fn;
char path[PATH_MAX + 128]; char path[PATH_MAX + 128];
@ -139,36 +137,26 @@ char *find_item(const char *item, const char *product)
return strdup(path); return strdup(path);
} }
static int64_t file_size(int fd) static int64_t get_file_size(int fd) {
{ struct stat sb;
struct stat st; return fstat(fd, &sb) == -1 ? -1 : sb.st_size;
int ret;
ret = fstat(fd, &st);
return ret ? -1 : st.st_size;
} }
static void *load_fd(int fd, unsigned *_sz) static void* load_fd(int fd, int64_t* sz) {
{
char *data;
int sz;
int errno_tmp; int errno_tmp;
char* data = nullptr;
data = 0; *sz = get_file_size(fd);
if (*sz < 0) {
sz = file_size(fd);
if (sz < 0) {
goto oops; goto oops;
} }
data = (char*) malloc(sz); data = (char*) malloc(*sz);
if(data == 0) goto oops; if (data == nullptr) goto oops;
if(read(fd, data, sz) != sz) goto oops; if(read(fd, data, *sz) != *sz) goto oops;
close(fd); close(fd);
if(_sz) *_sz = sz;
return data; return data;
oops: oops:
@ -179,17 +167,13 @@ oops:
return 0; return 0;
} }
static void *load_file(const char *fn, unsigned *_sz) static void* load_file(const char* fn, int64_t* sz) {
{ int fd = open(fn, O_RDONLY | O_BINARY);
int fd; if (fd == -1) return nullptr;
return load_fd(fd, sz);
fd = open(fn, O_RDONLY | O_BINARY);
if(fd < 0) return 0;
return load_fd(fd, _sz);
} }
int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) { static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
// Require a matching vendor id if the user specified one with -i. // Require a matching vendor id if the user specified one with -i.
if (vendor_id != 0 && info->dev_vendor != vendor_id) { if (vendor_id != 0 && info->dev_vendor != vendor_id) {
return -1; return -1;
@ -206,14 +190,12 @@ int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
return 0; return 0;
} }
int match_fastboot(usb_ifc_info *info) static int match_fastboot(usb_ifc_info* info) {
{
return match_fastboot_with_serial(info, serial); return match_fastboot_with_serial(info, serial);
} }
int list_devices_callback(usb_ifc_info *info) static int list_devices_callback(usb_ifc_info* info) {
{ if (match_fastboot_with_serial(info, nullptr) == 0) {
if (match_fastboot_with_serial(info, NULL) == 0) {
const char* serial = info->serial_number; const char* serial = info->serial_number;
if (!info->writable) { if (!info->writable) {
serial = "no permissions"; // like "adb devices" serial = "no permissions"; // like "adb devices"
@ -234,8 +216,7 @@ int list_devices_callback(usb_ifc_info *info)
return -1; return -1;
} }
usb_handle *open_device(void) static usb_handle* open_device() {
{
static usb_handle *usb = 0; static usb_handle *usb = 0;
int announce = 1; int announce = 1;
@ -252,15 +233,14 @@ usb_handle *open_device(void)
} }
} }
void list_devices(void) { static void list_devices() {
// We don't actually open a USB device here, // We don't actually open a USB device here,
// just getting our callback called so we can // just getting our callback called so we can
// list all the connected devices. // list all the connected devices.
usb_open(list_devices_callback); usb_open(list_devices_callback);
} }
void usage(void) static void usage() {
{
fprintf(stderr, fprintf(stderr,
/* 1234567890123456789012345678901234567890123456789012345678901234567890123456 */ /* 1234567890123456789012345678901234567890123456789012345678901234567890123456 */
"usage: fastboot [ <option> ] <command>\n" "usage: fastboot [ <option> ] <command>\n"
@ -315,31 +295,26 @@ void usage(void)
); );
} }
void *load_bootable_image(const char *kernel, const char *ramdisk, static void* load_bootable_image(const char* kernel, const char* ramdisk,
const char *secondstage, unsigned *sz, const char* secondstage, int64_t* sz,
const char *cmdline) const char* cmdline) {
{ if (kernel == nullptr) {
void *kdata = 0, *rdata = 0, *sdata = 0;
unsigned ksize = 0, rsize = 0, ssize = 0;
void *bdata;
unsigned bsize;
if(kernel == 0) {
fprintf(stderr, "no image specified\n"); fprintf(stderr, "no image specified\n");
return 0; return 0;
} }
kdata = load_file(kernel, &ksize); int64_t ksize;
if(kdata == 0) { void* kdata = load_file(kernel, &ksize);
if (kdata == nullptr) {
fprintf(stderr, "cannot load '%s': %s\n", kernel, strerror(errno)); fprintf(stderr, "cannot load '%s': %s\n", kernel, strerror(errno));
return 0; return 0;
} }
/* is this actually a boot image? */ // Is this actually a boot image?
if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
if(cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline); if (cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
if(ramdisk) { if (ramdisk) {
fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n"); fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n");
return 0; return 0;
} }
@ -348,39 +323,44 @@ void *load_bootable_image(const char *kernel, const char *ramdisk,
return kdata; return kdata;
} }
if(ramdisk) { void* rdata = nullptr;
int64_t rsize = 0;
if (ramdisk) {
rdata = load_file(ramdisk, &rsize); rdata = load_file(ramdisk, &rsize);
if(rdata == 0) { if (rdata == nullptr) {
fprintf(stderr,"cannot load '%s': %s\n", ramdisk, strerror(errno)); fprintf(stderr,"cannot load '%s': %s\n", ramdisk, strerror(errno));
return 0; return 0;
} }
} }
void* sdata = nullptr;
int64_t ssize = 0;
if (secondstage) { if (secondstage) {
sdata = load_file(secondstage, &ssize); sdata = load_file(secondstage, &ssize);
if(sdata == 0) { if (sdata == nullptr) {
fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno)); fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
return 0; return 0;
} }
} }
fprintf(stderr,"creating boot image...\n"); fprintf(stderr,"creating boot image...\n");
bdata = mkbootimg(kdata, ksize, kernel_offset, int64_t bsize = 0;
void* bdata = mkbootimg(kdata, ksize, kernel_offset,
rdata, rsize, ramdisk_offset, rdata, rsize, ramdisk_offset,
sdata, ssize, second_offset, sdata, ssize, second_offset,
page_size, base_addr, tags_offset, &bsize); page_size, base_addr, tags_offset, &bsize);
if(bdata == 0) { if (bdata == nullptr) {
fprintf(stderr,"failed to create boot.img\n"); fprintf(stderr,"failed to create boot.img\n");
return 0; return 0;
} }
if(cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline); if (cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
fprintf(stderr,"creating boot image - %d bytes\n", bsize); fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", bsize);
*sz = bsize; *sz = bsize;
return bdata; return bdata;
} }
static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, unsigned* sz) static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, int64_t* sz)
{ {
ZipString zip_entry_name(entry_name); ZipString zip_entry_name(entry_name);
ZipEntry zip_entry; ZipEntry zip_entry;
@ -392,8 +372,8 @@ static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, unsigned*
*sz = zip_entry.uncompressed_length; *sz = zip_entry.uncompressed_length;
uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length)); uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
if (data == NULL) { if (data == nullptr) {
fprintf(stderr, "failed to allocate %u bytes for '%s'\n", *sz, entry_name); fprintf(stderr, "failed to allocate %" PRId64 " bytes for '%s'\n", *sz, entry_name);
return 0; return 0;
} }
@ -438,7 +418,7 @@ static FILE* win32_tmpfile() {
static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) { static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
FILE* fp = tmpfile(); FILE* fp = tmpfile();
if (fp == NULL) { if (fp == nullptr) {
fprintf(stderr, "failed to create temporary file for '%s': %s\n", fprintf(stderr, "failed to create temporary file for '%s': %s\n",
entry_name, strerror(errno)); entry_name, strerror(errno));
return -1; return -1;
@ -478,7 +458,7 @@ static char *strip(char *s)
static int setup_requirement_line(char *name) static int setup_requirement_line(char *name)
{ {
char *val[MAX_OPTIONS]; char *val[MAX_OPTIONS];
char *prod = NULL; char *prod = nullptr;
unsigned n, count; unsigned n, count;
char *x; char *x;
int invert = 0; int invert = 0;
@ -539,13 +519,10 @@ static int setup_requirement_line(char *name)
return 0; return 0;
} }
static void setup_requirements(char *data, unsigned sz) static void setup_requirements(char* data, int64_t sz) {
{ char* s = data;
char *s;
s = data;
while (sz-- > 0) { while (sz-- > 0) {
if(*s == '\n') { if (*s == '\n') {
*s++ = 0; *s++ = 0;
if (setup_requirement_line(data)) { if (setup_requirement_line(data)) {
die("out of memory"); die("out of memory");
@ -557,8 +534,7 @@ static void setup_requirements(char *data, unsigned sz)
} }
} }
void queue_info_dump(void) static void queue_info_dump() {
{
fb_queue_notice("--------------------------------------------"); fb_queue_notice("--------------------------------------------");
fb_queue_display("version-bootloader", "Bootloader Version..."); fb_queue_display("version-bootloader", "Bootloader Version...");
fb_queue_display("version-baseband", "Baseband Version....."); fb_queue_display("version-baseband", "Baseband Version.....");
@ -573,7 +549,7 @@ static struct sparse_file **load_sparse_files(int fd, int max_size)
die("cannot sparse read file\n"); die("cannot sparse read file\n");
} }
int files = sparse_file_resparse(s, max_size, NULL, 0); int files = sparse_file_resparse(s, max_size, nullptr, 0);
if (files < 0) { if (files < 0) {
die("Failed to resparse\n"); die("Failed to resparse\n");
} }
@ -598,7 +574,7 @@ static int64_t get_target_sparse_limit(struct usb_handle *usb)
int status = fb_getvar(usb, response, "max-download-size"); int status = fb_getvar(usb, response, "max-download-size");
if (!status) { if (!status) {
limit = strtoul(response, NULL, 0); limit = strtoul(response, nullptr, 0);
if (limit > 0) { if (limit > 0) {
fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n", fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n",
limit); limit);
@ -643,35 +619,27 @@ static int needs_erase(usb_handle* usb, const char *part)
/* The function fb_format_supported() currently returns the value /* The function fb_format_supported() currently returns the value
* we want, so just call it. * we want, so just call it.
*/ */
return fb_format_supported(usb, part, NULL); return fb_format_supported(usb, part, nullptr);
} }
static int load_buf_fd(usb_handle *usb, int fd, static int load_buf_fd(usb_handle* usb, int fd, struct fastboot_buffer* buf) {
struct fastboot_buffer *buf) int64_t sz = get_file_size(fd);
{ if (sz == -1) {
int64_t sz64;
void *data;
int64_t limit;
sz64 = file_size(fd);
if (sz64 < 0) {
return -1; return -1;
} }
lseek(fd, 0, SEEK_SET); lseek64(fd, 0, SEEK_SET);
limit = get_sparse_limit(usb, sz64); int64_t limit = get_sparse_limit(usb, sz);
if (limit) { if (limit) {
struct sparse_file **s = load_sparse_files(fd, limit); sparse_file** s = load_sparse_files(fd, limit);
if (s == NULL) { if (s == nullptr) {
return -1; return -1;
} }
buf->type = FB_BUFFER_SPARSE; buf->type = FB_BUFFER_SPARSE;
buf->data = s; buf->data = s;
} else { } else {
unsigned int sz; void* data = load_fd(fd, &sz);
data = load_fd(fd, &sz); if (data == nullptr) return -1;
if (data == 0) return -1;
buf->type = FB_BUFFER; buf->type = FB_BUFFER;
buf->data = data; buf->data = data;
buf->sz = sz; buf->sz = sz;
@ -701,8 +669,8 @@ static void flash_buf(const char *pname, struct fastboot_buffer *buf)
case FB_BUFFER_SPARSE: case FB_BUFFER_SPARSE:
s = reinterpret_cast<sparse_file**>(buf->data); s = reinterpret_cast<sparse_file**>(buf->data);
while (*s) { while (*s) {
int64_t sz64 = sparse_file_len(*s, true, false); int64_t sz = sparse_file_len(*s, true, false);
fb_queue_flash_sparse(pname, *s++, sz64); fb_queue_flash_sparse(pname, *s++, sz);
} }
break; break;
case FB_BUFFER: case FB_BUFFER:
@ -713,8 +681,7 @@ static void flash_buf(const char *pname, struct fastboot_buffer *buf)
} }
} }
void do_flash(usb_handle *usb, const char *pname, const char *fname) static void do_flash(usb_handle* usb, const char* pname, const char* fname) {
{
struct fastboot_buffer buf; struct fastboot_buffer buf;
if (load_buf(usb, fname, &buf)) { if (load_buf(usb, fname, &buf)) {
@ -723,17 +690,15 @@ void do_flash(usb_handle *usb, const char *pname, const char *fname)
flash_buf(pname, &buf); flash_buf(pname, &buf);
} }
void do_update_signature(ZipArchiveHandle zip, char *fn) static void do_update_signature(ZipArchiveHandle zip, char* fn) {
{ int64_t sz;
unsigned sz;
void* data = unzip_file(zip, fn, &sz); void* data = unzip_file(zip, fn, &sz);
if (data == 0) return; if (data == nullptr) return;
fb_queue_download("signature", data, sz); fb_queue_download("signature", data, sz);
fb_queue_command("signature", "installing signature"); fb_queue_command("signature", "installing signature");
} }
void do_update(usb_handle *usb, const char *filename, int erase_first) static void do_update(usb_handle* usb, const char* filename, bool erase_first) {
{
queue_info_dump(); queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product)); fb_queue_query_save("product", cur_product, sizeof(cur_product));
@ -745,9 +710,9 @@ void do_update(usb_handle *usb, const char *filename, int erase_first)
die("failed to open zip file '%s': %s", filename, ErrorCodeString(error)); die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
} }
unsigned sz; int64_t sz;
void* data = unzip_file(zip, "android-info.txt", &sz); void* data = unzip_file(zip, "android-info.txt", &sz);
if (data == 0) { if (data == nullptr) {
CloseArchive(zip); CloseArchive(zip);
die("update package '%s' has no android-info.txt", filename); die("update package '%s' has no android-info.txt", filename);
} }
@ -780,36 +745,33 @@ void do_update(usb_handle *usb, const char *filename, int erase_first)
CloseArchive(zip); CloseArchive(zip);
} }
void do_send_signature(char *fn) static void do_send_signature(char* fn) {
{ char* xtn = strrchr(fn, '.');
void *data;
unsigned sz;
char *xtn;
xtn = strrchr(fn, '.');
if (!xtn) return; if (!xtn) return;
if (strcmp(xtn, ".img")) return; if (strcmp(xtn, ".img")) return;
strcpy(xtn,".sig"); strcpy(xtn, ".sig");
data = load_file(fn, &sz);
strcpy(xtn,".img"); int64_t sz;
if (data == 0) return; void* data = load_file(fn, &sz);
strcpy(xtn, ".img");
if (data == nullptr) return;
fb_queue_download("signature", data, sz); fb_queue_download("signature", data, sz);
fb_queue_command("signature", "installing signature"); fb_queue_command("signature", "installing signature");
} }
void do_flashall(usb_handle *usb, int erase_first) static void do_flashall(usb_handle* usb, int erase_first) {
{
queue_info_dump(); queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product)); fb_queue_query_save("product", cur_product, sizeof(cur_product));
char* fname = find_item("info", product); char* fname = find_item("info", product);
if (fname == 0) die("cannot find android-info.txt"); if (fname == nullptr) die("cannot find android-info.txt");
unsigned sz; int64_t sz;
void* data = load_file(fname, &sz); void* data = load_file(fname, &sz);
if (data == 0) die("could not load android-info.txt: %s", strerror(errno)); if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno));
setup_requirements(reinterpret_cast<char*>(data), sz); setup_requirements(reinterpret_cast<char*>(data), sz);
@ -832,8 +794,7 @@ void do_flashall(usb_handle *usb, int erase_first)
#define skip(n) do { argc -= (n); argv += (n); } while (0) #define skip(n) do { argc -= (n); argv += (n); } while (0)
#define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0) #define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0)
int do_oem_command(int argc, char **argv) static int do_oem_command(int argc, char** argv) {
{
char command[256]; char command[256];
if (argc <= 1) return 0; if (argc <= 1) return 0;
@ -890,16 +851,15 @@ static int64_t parse_num(const char *arg)
return num; return num;
} }
void fb_perform_format(usb_handle* usb, static void fb_perform_format(usb_handle* usb,
const char *partition, int skip_if_not_supported, const char *partition, int skip_if_not_supported,
const char *type_override, const char *size_override) const char *type_override, const char *size_override) {
{
char pTypeBuff[FB_RESPONSE_SZ + 1], pSizeBuff[FB_RESPONSE_SZ + 1]; char pTypeBuff[FB_RESPONSE_SZ + 1], pSizeBuff[FB_RESPONSE_SZ + 1];
char *pType = pTypeBuff; char *pType = pTypeBuff;
char *pSize = pSizeBuff; char *pSize = pSizeBuff;
unsigned int limit = INT_MAX; unsigned int limit = INT_MAX;
struct fastboot_buffer buf; struct fastboot_buffer buf;
const char *errMsg = NULL; const char *errMsg = nullptr;
const struct fs_generator *gen; const struct fs_generator *gen;
uint64_t pSz; uint64_t pSz;
int status; int status;
@ -949,7 +909,7 @@ void fb_perform_format(usb_handle* usb,
return; return;
} }
pSz = strtoll(pSize, (char **)NULL, 16); pSz = strtoll(pSize, (char **)nullptr, 16);
fd = fileno(tmpfile()); fd = fileno(tmpfile());
if (fs_generator_generate(gen, fd, pSz)) { if (fs_generator_generate(gen, fd, pSz)) {
@ -982,9 +942,9 @@ int main(int argc, char **argv)
int wants_wipe = 0; int wants_wipe = 0;
int wants_reboot = 0; int wants_reboot = 0;
int wants_reboot_bootloader = 0; int wants_reboot_bootloader = 0;
int erase_first = 1; bool erase_first = true;
void *data; void *data;
unsigned sz; int64_t sz;
int status; int status;
int c; int c;
int longindex; int longindex;
@ -1020,7 +980,7 @@ int main(int argc, char **argv)
usage(); usage();
return 1; return 1;
case 'i': { case 'i': {
char *endptr = NULL; char *endptr = nullptr;
unsigned long val; unsigned long val;
val = strtoul(optarg, &endptr, 0); val = strtoul(optarg, &endptr, 0);
@ -1036,7 +996,7 @@ int main(int argc, char **argv)
long_listing = 1; long_listing = 1;
break; break;
case 'n': case 'n':
page_size = (unsigned)strtoul(optarg, NULL, 0); page_size = (unsigned)strtoul(optarg, nullptr, 0);
if (!page_size) die("invalid page size"); if (!page_size) die("invalid page size");
break; break;
case 'p': case 'p':
@ -1058,7 +1018,7 @@ int main(int argc, char **argv)
} }
break; break;
case 'u': case 'u':
erase_first = 0; erase_first = false;
break; break;
case 'w': case 'w':
wants_wipe = 1; wants_wipe = 1;
@ -1067,8 +1027,8 @@ int main(int argc, char **argv)
return 1; return 1;
case 0: case 0:
if (strcmp("unbuffered", longopts[longindex].name) == 0) { if (strcmp("unbuffered", longopts[longindex].name) == 0) {
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stderr, nullptr, _IONBF, 0);
} else if (strcmp("version", longopts[longindex].name) == 0) { } else if (strcmp("version", longopts[longindex].name) == 0) {
fprintf(stdout, "fastboot version %s\n", FASTBOOT_REVISION); fprintf(stdout, "fastboot version %s\n", FASTBOOT_REVISION);
return 0; return 0;
@ -1108,7 +1068,7 @@ int main(int argc, char **argv)
} else if(!strcmp(*argv, "erase")) { } else if(!strcmp(*argv, "erase")) {
require(2); require(2);
if (fb_format_supported(usb, argv[1], NULL)) { if (fb_format_supported(usb, argv[1], nullptr)) {
fprintf(stderr, "******** Did you mean to fastboot format this partition?\n"); fprintf(stderr, "******** Did you mean to fastboot format this partition?\n");
} }
@ -1116,8 +1076,8 @@ int main(int argc, char **argv)
skip(2); skip(2);
} else if(!strncmp(*argv, "format", strlen("format"))) { } else if(!strncmp(*argv, "format", strlen("format"))) {
char *overrides; char *overrides;
char *type_override = NULL; char *type_override = nullptr;
char *size_override = NULL; char *size_override = nullptr;
require(2); require(2);
/* /*
* Parsing for: "format[:[type][:[size]]]" * Parsing for: "format[:[type][:[size]]]"
@ -1138,8 +1098,8 @@ int main(int argc, char **argv)
} }
type_override = overrides; type_override = overrides;
} }
if (type_override && !type_override[0]) type_override = NULL; if (type_override && !type_override[0]) type_override = nullptr;
if (size_override && !size_override[0]) size_override = NULL; if (size_override && !size_override[0]) size_override = nullptr;
if (erase_first && needs_erase(usb, argv[1])) { if (erase_first && needs_erase(usb, argv[1])) {
fb_queue_erase(argv[1]); fb_queue_erase(argv[1]);
} }
@ -1148,7 +1108,7 @@ int main(int argc, char **argv)
} else if(!strcmp(*argv, "signature")) { } else if(!strcmp(*argv, "signature")) {
require(2); require(2);
data = load_file(argv[1], &sz); data = load_file(argv[1], &sz);
if (data == 0) die("could not load '%s': %s", argv[1], strerror(errno)); if (data == nullptr) die("could not load '%s': %s", argv[1], strerror(errno));
if (sz != 256) die("signature must be 256 bytes"); if (sz != 256) die("signature must be 256 bytes");
fb_queue_download("signature", data, sz); fb_queue_download("signature", data, sz);
fb_queue_command("signature", "installing signature"); fb_queue_command("signature", "installing signature");
@ -1258,9 +1218,9 @@ int main(int argc, char **argv)
if (wants_wipe) { if (wants_wipe) {
fb_queue_erase("userdata"); fb_queue_erase("userdata");
fb_perform_format(usb, "userdata", 1, NULL, NULL); fb_perform_format(usb, "userdata", 1, nullptr, nullptr);
fb_queue_erase("cache"); fb_queue_erase("cache");
fb_perform_format(usb, "cache", 1, NULL, NULL); fb_perform_format(usb, "cache", 1, nullptr, nullptr);
} }
if (wants_reboot) { if (wants_reboot) {
fb_queue_reboot(); fb_queue_reboot();

View file

@ -29,18 +29,17 @@
#ifndef _FASTBOOT_H_ #ifndef _FASTBOOT_H_
#define _FASTBOOT_H_ #define _FASTBOOT_H_
#include "usb.h" #include <inttypes.h>
#include <stdlib.h>
#if defined(__cplusplus) #include "usb.h"
extern "C" {
#endif
struct sparse_file; struct sparse_file;
/* protocol.c - fastboot protocol */ /* protocol.c - fastboot protocol */
int fb_command(usb_handle *usb, const char *cmd); int fb_command(usb_handle *usb, const char *cmd);
int fb_command_response(usb_handle *usb, const char *cmd, char *response); int fb_command_response(usb_handle *usb, const char *cmd, char *response);
int fb_download_data(usb_handle *usb, const void *data, unsigned size); int fb_download_data(usb_handle *usb, const void *data, uint32_t size);
int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s); int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s);
char *fb_get_error(void); char *fb_get_error(void);
@ -50,17 +49,17 @@ char *fb_get_error(void);
/* engine.c - high level command queue engine */ /* engine.c - high level command queue engine */
int fb_getvar(struct usb_handle *usb, char *response, const char *fmt, ...); int fb_getvar(struct usb_handle *usb, char *response, const char *fmt, ...);
int fb_format_supported(usb_handle *usb, const char *partition, const char *type_override); int fb_format_supported(usb_handle *usb, const char *partition, const char *type_override);
void fb_queue_flash(const char *ptn, void *data, unsigned sz); void fb_queue_flash(const char *ptn, void *data, uint32_t sz);
void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, unsigned sz); void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, uint32_t sz);
void fb_queue_erase(const char *ptn); void fb_queue_erase(const char *ptn);
void fb_queue_format(const char *ptn, int skip_if_not_supported, unsigned int max_chunk_sz); void fb_queue_format(const char *ptn, int skip_if_not_supported, int32_t max_chunk_sz);
void fb_queue_require(const char *prod, const char *var, int invert, void fb_queue_require(const char *prod, const char *var, bool invert,
unsigned nvalues, const char **value); size_t nvalues, const char **value);
void fb_queue_display(const char *var, const char *prettyname); void fb_queue_display(const char *var, const char *prettyname);
void fb_queue_query_save(const char *var, char *dest, unsigned dest_size); void fb_queue_query_save(const char *var, char *dest, uint32_t dest_size);
void fb_queue_reboot(void); void fb_queue_reboot(void);
void fb_queue_command(const char *cmd, const char *msg); void fb_queue_command(const char *cmd, const char *msg);
void fb_queue_download(const char *name, void *data, unsigned size); void fb_queue_download(const char *name, void *data, uint32_t size);
void fb_queue_notice(const char *notice); void fb_queue_notice(const char *notice);
void fb_queue_wait_for_disconnect(void); void fb_queue_wait_for_disconnect(void);
int fb_execute_queue(usb_handle *usb); int fb_execute_queue(usb_handle *usb);
@ -76,8 +75,4 @@ void get_my_path(char *path);
/* Current product */ /* Current product */
extern char cur_product[FB_RESPONSE_SZ + 1]; extern char cur_product[FB_RESPONSE_SZ + 1];
#if defined(__cplusplus)
}
#endif
#endif #endif

View file

@ -41,7 +41,7 @@ Transport and Framing
d. DATA -> the requested command is ready for the data phase. d. DATA -> the requested command is ready for the data phase.
A DATA response packet will be 12 bytes long, in the form of A DATA response packet will be 12 bytes long, in the form of
DATA00000000 where the 8 digit hexidecimal number represents DATA00000000 where the 8 digit hexadecimal number represents
the total data size to transfer. the total data size to transfer.
3. Data phase. Depending on the command, the host or client will 3. Data phase. Depending on the command, the host or client will

View file

@ -6,21 +6,12 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sparse/sparse.h>
#include <unistd.h> #include <unistd.h>
#ifdef USE_MINGW #include <sparse/sparse.h>
#include <fcntl.h>
#else
#include <sys/mman.h>
#endif
static int generate_ext4_image(int fd, long long partSize) static int generate_ext4_image(int fd, long long partSize)
{ {
@ -48,15 +39,13 @@ static const struct fs_generator {
#endif #endif
}; };
const struct fs_generator* fs_get_generator(const char *fs_type) const struct fs_generator* fs_get_generator(const char* fs_type) {
{ for (size_t i = 0; i < sizeof(generators) / sizeof(*generators); i++) {
unsigned i; if (strcmp(generators[i].fs_type, fs_type) == 0) {
for (i = 0; i < sizeof(generators) / sizeof(*generators); i++)
if (!strcmp(generators[i].fs_type, fs_type))
return generators + i; return generators + i;
}
return NULL; }
return nullptr;
} }
int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize) int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize)

View file

@ -3,18 +3,10 @@
#include <stdint.h> #include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
struct fs_generator; struct fs_generator;
const struct fs_generator* fs_get_generator(const char *fs_type); const struct fs_generator* fs_get_generator(const char *fs_type);
int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize); int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize);
#if defined(__cplusplus)
}
#endif
#endif #endif

View file

@ -26,8 +26,6 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#define min(a, b) \
({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
#define round_down(a, b) \ #define round_down(a, b) \
({ typeof(a) _a = (a); typeof(b) _b = (b); _a - (_a % _b); }) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a - (_a % _b); })
@ -36,6 +34,8 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <algorithm>
#include <sparse/sparse.h> #include <sparse/sparse.h>
#include "fastboot.h" #include "fastboot.h"
@ -47,40 +47,38 @@ char *fb_get_error(void)
return ERROR; return ERROR;
} }
static int check_response(usb_handle *usb, unsigned int size, char *response) static int check_response(usb_handle* usb, uint32_t size, char* response) {
{ char status[65];
unsigned char status[65];
int r;
for(;;) { while (true) {
r = usb_read(usb, status, 64); int r = usb_read(usb, status, 64);
if(r < 0) { if (r < 0) {
sprintf(ERROR, "status read failed (%s)", strerror(errno)); sprintf(ERROR, "status read failed (%s)", strerror(errno));
usb_close(usb); usb_close(usb);
return -1; return -1;
} }
status[r] = 0; status[r] = 0;
if(r < 4) { if (r < 4) {
sprintf(ERROR, "status malformed (%d bytes)", r); sprintf(ERROR, "status malformed (%d bytes)", r);
usb_close(usb); usb_close(usb);
return -1; return -1;
} }
if(!memcmp(status, "INFO", 4)) { if (!memcmp(status, "INFO", 4)) {
fprintf(stderr,"(bootloader) %s\n", status + 4); fprintf(stderr,"(bootloader) %s\n", status + 4);
continue; continue;
} }
if(!memcmp(status, "OKAY", 4)) { if (!memcmp(status, "OKAY", 4)) {
if(response) { if (response) {
strcpy(response, (char*) status + 4); strcpy(response, (char*) status + 4);
} }
return 0; return 0;
} }
if(!memcmp(status, "FAIL", 4)) { if (!memcmp(status, "FAIL", 4)) {
if(r > 4) { if (r > 4) {
sprintf(ERROR, "remote: %s", status + 4); sprintf(ERROR, "remote: %s", status + 4);
} else { } else {
strcpy(ERROR, "remote failure"); strcpy(ERROR, "remote failure");
@ -88,9 +86,9 @@ static int check_response(usb_handle *usb, unsigned int size, char *response)
return -1; return -1;
} }
if(!memcmp(status, "DATA", 4) && size > 0){ if (!memcmp(status, "DATA", 4) && size > 0){
unsigned dsize = strtoul((char*) status + 4, 0, 16); uint32_t dsize = strtol(status + 4, 0, 16);
if(dsize > size) { if (dsize > size) {
strcpy(ERROR, "data size too large"); strcpy(ERROR, "data size too large");
usb_close(usb); usb_close(usb);
return -1; return -1;
@ -106,22 +104,19 @@ static int check_response(usb_handle *usb, unsigned int size, char *response)
return -1; return -1;
} }
static int _command_start(usb_handle *usb, const char *cmd, unsigned size, static int _command_start(usb_handle* usb, const char* cmd, uint32_t size, char* response) {
char *response) size_t cmdsize = strlen(cmd);
{ if (cmdsize > 64) {
int cmdsize = strlen(cmd); sprintf(ERROR, "command too large");
if(response) {
response[0] = 0;
}
if(cmdsize > 64) {
sprintf(ERROR,"command too large");
return -1; return -1;
} }
if(usb_write(usb, cmd, cmdsize) != cmdsize) { if (response) {
sprintf(ERROR,"command write failed (%s)", strerror(errno)); response[0] = 0;
}
if (usb_write(usb, cmd, cmdsize) != static_cast<int>(cmdsize)) {
sprintf(ERROR, "command write failed (%s)", strerror(errno));
usb_close(usb); usb_close(usb);
return -1; return -1;
} }
@ -129,45 +124,32 @@ static int _command_start(usb_handle *usb, const char *cmd, unsigned size,
return check_response(usb, size, response); return check_response(usb, size, response);
} }
static int _command_data(usb_handle *usb, const void *data, unsigned size) static int _command_data(usb_handle* usb, const void* data, uint32_t size) {
{ int r = usb_write(usb, data, size);
int r; if (r < 0) {
r = usb_write(usb, data, size);
if(r < 0) {
sprintf(ERROR, "data transfer failure (%s)", strerror(errno)); sprintf(ERROR, "data transfer failure (%s)", strerror(errno));
usb_close(usb); usb_close(usb);
return -1; return -1;
} }
if(r != ((int) size)) { if (r != ((int) size)) {
sprintf(ERROR, "data transfer failure (short transfer)"); sprintf(ERROR, "data transfer failure (short transfer)");
usb_close(usb); usb_close(usb);
return -1; return -1;
} }
return r; return r;
} }
static int _command_end(usb_handle *usb) static int _command_end(usb_handle* usb) {
{ return check_response(usb, 0, 0) < 0 ? -1 : 0;
int r;
r = check_response(usb, 0, 0);
if(r < 0) {
return -1;
}
return 0;
} }
static int _command_send(usb_handle *usb, const char *cmd, static int _command_send(usb_handle* usb, const char* cmd, const void* data, uint32_t size,
const void *data, unsigned size, char* response) {
char *response)
{
int r;
if (size == 0) { if (size == 0) {
return -1; return -1;
} }
r = _command_start(usb, cmd, size, response); int r = _command_start(usb, cmd, size, response);
if (r < 0) { if (r < 0) {
return -1; return -1;
} }
@ -178,42 +160,29 @@ static int _command_send(usb_handle *usb, const char *cmd,
} }
r = _command_end(usb); r = _command_end(usb);
if(r < 0) { if (r < 0) {
return -1; return -1;
} }
return size; return size;
} }
static int _command_send_no_data(usb_handle *usb, const char *cmd, static int _command_send_no_data(usb_handle* usb, const char* cmd, char* response) {
char *response)
{
return _command_start(usb, cmd, 0, response); return _command_start(usb, cmd, 0, response);
} }
int fb_command(usb_handle *usb, const char *cmd) int fb_command(usb_handle* usb, const char* cmd) {
{
return _command_send_no_data(usb, cmd, 0); return _command_send_no_data(usb, cmd, 0);
} }
int fb_command_response(usb_handle *usb, const char *cmd, char *response) int fb_command_response(usb_handle* usb, const char* cmd, char* response) {
{
return _command_send_no_data(usb, cmd, response); return _command_send_no_data(usb, cmd, response);
} }
int fb_download_data(usb_handle *usb, const void *data, unsigned size) int fb_download_data(usb_handle* usb, const void* data, uint32_t size) {
{
char cmd[64]; char cmd[64];
int r;
sprintf(cmd, "download:%08x", size); sprintf(cmd, "download:%08x", size);
r = _command_send(usb, cmd, data, size, 0); return _command_send(usb, cmd, data, size, 0) < 0 ? -1 : 0;
if(r < 0) {
return -1;
} else {
return 0;
}
} }
#define USB_BUF_SIZE 1024 #define USB_BUF_SIZE 1024
@ -228,7 +197,7 @@ static int fb_download_data_sparse_write(void *priv, const void *data, int len)
const char* ptr = reinterpret_cast<const char*>(data); const char* ptr = reinterpret_cast<const char*>(data);
if (usb_buf_len) { if (usb_buf_len) {
to_write = min(USB_BUF_SIZE - usb_buf_len, len); to_write = std::min(USB_BUF_SIZE - usb_buf_len, len);
memcpy(usb_buf + usb_buf_len, ptr, to_write); memcpy(usb_buf + usb_buf_len, ptr, to_write);
usb_buf_len += to_write; usb_buf_len += to_write;
@ -270,32 +239,25 @@ static int fb_download_data_sparse_write(void *priv, const void *data, int len)
return 0; return 0;
} }
static int fb_download_data_sparse_flush(usb_handle *usb) static int fb_download_data_sparse_flush(usb_handle* usb) {
{
int r;
if (usb_buf_len > 0) { if (usb_buf_len > 0) {
r = _command_data(usb, usb_buf, usb_buf_len); if (_command_data(usb, usb_buf, usb_buf_len) != usb_buf_len) {
if (r != usb_buf_len) {
return -1; return -1;
} }
usb_buf_len = 0; usb_buf_len = 0;
} }
return 0; return 0;
} }
int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s) int fb_download_data_sparse(usb_handle* usb, struct sparse_file* s) {
{
char cmd[64];
int r;
int size = sparse_file_len(s, true, false); int size = sparse_file_len(s, true, false);
if (size <= 0) { if (size <= 0) {
return -1; return -1;
} }
char cmd[64];
sprintf(cmd, "download:%08x", size); sprintf(cmd, "download:%08x", size);
r = _command_start(usb, cmd, size, 0); int r = _command_start(usb, cmd, size, 0);
if (r < 0) { if (r < 0) {
return -1; return -1;
} }

View file

@ -29,16 +29,9 @@
#ifndef _USB_H_ #ifndef _USB_H_
#define _USB_H_ #define _USB_H_
#if defined(__cplusplus) struct usb_handle;
extern "C" {
#endif
typedef struct usb_handle usb_handle; struct usb_ifc_info {
typedef struct usb_ifc_info usb_ifc_info;
struct usb_ifc_info
{
/* from device descriptor */ /* from device descriptor */
unsigned short dev_vendor; unsigned short dev_vendor;
unsigned short dev_product; unsigned short dev_product;
@ -68,8 +61,4 @@ int usb_read(usb_handle *h, void *_data, int len);
int usb_write(usb_handle *h, const void *_data, int len); int usb_write(usb_handle *h, const void *_data, int len);
int usb_wait_for_disconnect(usb_handle *h); int usb_wait_for_disconnect(usb_handle *h);
#if defined(__cplusplus)
}
#endif
#endif #endif