Loading fastboot/fastboot.c +171 −95 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <bootimg.h> #include <sparse/sparse.h> Loading @@ -54,6 +55,8 @@ #define O_BINARY 0 #endif #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) char cur_product[FB_RESPONSE_SZ + 1]; void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline); Loading Loading @@ -81,6 +84,27 @@ unsigned ramdisk_offset = 0x01000000; unsigned second_offset = 0x00f00000; unsigned tags_offset = 0x00000100; enum fb_buffer_type { FB_BUFFER, FB_BUFFER_SPARSE, }; struct fastboot_buffer { enum fb_buffer_type type; void *data; unsigned int sz; }; static struct { char img_name[13]; char sig_name[13]; char part_name[9]; bool is_optional; } images[3] = { {"boot.img", "boot.sig", "boot", false}, {"recovery.img", "recovery.sig", "recovery", true}, {"system.img", "system.sig", "system", false}, }; void die(const char *fmt, ...) { Loading Loading @@ -135,40 +159,28 @@ char *find_item(const char *item, const char *product) return strdup(path); } #if defined(__APPLE__) && defined(__MACH__) #define lseek64 lseek #define off64_t off_t #endif static int64_t file_size(const char *fn) static int64_t file_size(int fd) { off64_t off; int fd; struct stat st; int ret; fd = open(fn, O_RDONLY | O_BINARY); if (fd < 0) return -1; off = lseek64(fd, 0, SEEK_END); close(fd); ret = fstat(fd, &st); return off; return ret ? -1 : st.st_size; } static void *load_file(const char *fn, unsigned *_sz) static void *load_fd(int fd, unsigned *_sz) { char *data; int sz; int fd; int errno_tmp; data = 0; fd = open(fn, O_RDONLY | O_BINARY); 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; sz = file_size(fd); if (sz < 0) { goto oops; } data = (char*) malloc(sz); if(data == 0) goto oops; Loading @@ -187,6 +199,16 @@ oops: return 0; } static void *load_file(const char *fn, unsigned *_sz) { int fd; 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) { if(!(vendor_id && (info->dev_vendor == vendor_id)) && Loading Loading @@ -392,6 +414,31 @@ void *unzip_file(zipfile_t zip, const char *name, unsigned *sz) return data; } static int unzip_to_file(zipfile_t zip, char *name) { int fd; char *data; unsigned sz; fd = fileno(tmpfile()); if (fd < 0) { return -1; } data = unzip_file(zip, name, &sz); if (data == 0) { return -1; } if (write(fd, data, sz) != sz) { fd = -1; } free(data); lseek(fd, 0, SEEK_SET); return fd; } static char *strip(char *s) { int n; Loading Loading @@ -490,27 +537,20 @@ void queue_info_dump(void) fb_queue_notice("--------------------------------------------"); } struct sparse_file **load_sparse_files(const char *fname, int max_size) static struct sparse_file **load_sparse_files(int fd, int max_size) { int fd; struct sparse_file *s; int files; struct sparse_file **out_s; fd = open(fname, O_RDONLY | O_BINARY); if (fd < 0) { die("cannot open '%s'\n", fname); } s = sparse_file_import_auto(fd, false); if (!s) { die("cannot sparse read file '%s'\n", fname); die("cannot sparse read file\n"); } files = sparse_file_resparse(s, max_size, NULL, 0); if (files < 0) { die("Failed to resparse '%s'\n", fname); die("Failed to resparse\n"); } out_s = calloc(sizeof(struct sparse_file *), files + 1); Loading @@ -520,7 +560,7 @@ struct sparse_file **load_sparse_files(const char *fname, int max_size) files = sparse_file_resparse(s, max_size, out_s, files); if (files < 0) { die("Failed to resparse '%s'\n", fname); die("Failed to resparse\n"); } return out_s; Loading Loading @@ -581,29 +621,78 @@ static int needs_erase(const char *part) return fb_format_supported(usb, part); } void do_flash(usb_handle *usb, const char *pname, const char *fname) static int load_buf_fd(usb_handle *usb, int fd, struct fastboot_buffer *buf) { int64_t sz64; void *data; int64_t limit; sz64 = file_size(fname); sz64 = file_size(fd); if (sz64 < 0) { return -1; } limit = get_sparse_limit(usb, sz64); if (limit) { struct sparse_file **s = load_sparse_files(fname, limit); struct sparse_file **s = load_sparse_files(fd, limit); if (s == NULL) { die("cannot sparse load '%s'\n", fname); return -1; } buf->type = FB_BUFFER_SPARSE; buf->data = s; } else { unsigned int sz; data = load_fd(fd, &sz); if (data == 0) return -1; buf->type = FB_BUFFER; buf->data = data; buf->sz = sz; } return 0; } static int load_buf(usb_handle *usb, const char *fname, struct fastboot_buffer *buf) { int fd; fd = open(fname, O_RDONLY | O_BINARY); if (fd < 0) { die("cannot open '%s'\n", fname); } return load_buf_fd(usb, fd, buf); } static void flash_buf(const char *pname, struct fastboot_buffer *buf) { struct sparse_file **s; switch (buf->type) { case FB_BUFFER_SPARSE: s = buf->data; while (*s) { sz64 = sparse_file_len(*s, true, false); int64_t sz64 = sparse_file_len(*s, true, false); fb_queue_flash_sparse(pname, *s++, sz64); } } else { unsigned int sz; data = load_file(fname, &sz); if (data == 0) die("cannot load '%s': %s\n", fname, strerror(errno)); fb_queue_flash(pname, data, sz); break; case FB_BUFFER: fb_queue_flash(pname, buf->data, buf->sz); break; default: die("unknown buffer type: %d", buf->type); } } void do_flash(usb_handle *usb, const char *pname, const char *fname) { struct fastboot_buffer buf; if (load_buf(usb, fname, &buf)) { die("cannot load '%s'", fname); } flash_buf(pname, &buf); } void do_update_signature(zipfile_t zip, char *fn) Loading @@ -616,13 +705,17 @@ void do_update_signature(zipfile_t zip, char *fn) fb_queue_command("signature", "installing signature"); } void do_update(char *fn, int erase_first) void do_update(usb_handle *usb, char *fn, int erase_first) { void *zdata; unsigned zsize; void *data; unsigned sz; zipfile_t zip; int fd; int rc; struct fastboot_buffer buf; int i; queue_info_dump(); Loading Loading @@ -651,30 +744,25 @@ void do_update(char *fn, int erase_first) setup_requirements(data, sz); data = unzip_file(zip, "boot.img", &sz); if (data == 0) die("update package missing boot.img"); do_update_signature(zip, "boot.sig"); if (erase_first && needs_erase("boot")) { fb_queue_erase("boot"); } fb_queue_flash("boot", data, sz); data = unzip_file(zip, "recovery.img", &sz); if (data != 0) { do_update_signature(zip, "recovery.sig"); if (erase_first && needs_erase("recovery")) { fb_queue_erase("recovery"); } fb_queue_flash("recovery", data, sz); } data = unzip_file(zip, "system.img", &sz); if (data == 0) die("update package missing system.img"); do_update_signature(zip, "system.sig"); if (erase_first && needs_erase("system")) { fb_queue_erase("system"); for (i = 0; i < ARRAY_SIZE(images); i++) { fd = unzip_to_file(zip, images[i].img_name); if (fd < 0) { if (images[i].is_optional) continue; die("update package missing %s", images[i].img_name); } rc = load_buf_fd(usb, fd, &buf); if (rc) die("cannot load %s from flash", images[i].img_name); do_update_signature(zip, images[i].sig_name); if (erase_first && needs_erase(images[i].part_name)) { fb_queue_erase(images[i].part_name); } flash_buf(images[i].part_name, &buf); /* not closing the fd here since the sparse code keeps the fd around * but hasn't mmaped data yet. The tmpfile will get cleaned up when the * program exits. */ } fb_queue_flash("system", data, sz); } void do_send_signature(char *fn) Loading @@ -695,11 +783,13 @@ void do_send_signature(char *fn) fb_queue_command("signature", "installing signature"); } void do_flashall(int erase_first) void do_flashall(usb_handle *usb, int erase_first) { char *fname; void *data; unsigned sz; struct fastboot_buffer buf; int i; queue_info_dump(); Loading @@ -711,33 +801,19 @@ void do_flashall(int erase_first) if (data == 0) die("could not load android-info.txt: %s", strerror(errno)); setup_requirements(data, sz); fname = find_item("boot", product); data = load_file(fname, &sz); if (data == 0) die("could not load boot.img: %s", strerror(errno)); do_send_signature(fname); if (erase_first && needs_erase("boot")) { fb_queue_erase("boot"); for (i = 0; i < ARRAY_SIZE(images); i++) { fname = find_item(images[i].part_name, product); if (load_buf(usb, fname, &buf)) { if (images[i].is_optional) continue; die("could not load %s\n", images[i].img_name); } fb_queue_flash("boot", data, sz); fname = find_item("recovery", product); data = load_file(fname, &sz); if (data != 0) { do_send_signature(fname); if (erase_first && needs_erase("recovery")) { fb_queue_erase("recovery"); } fb_queue_flash("recovery", data, sz); if (erase_first && needs_erase(images[i].part_name)) { fb_queue_erase(images[i].part_name); } fname = find_item("system", product); data = load_file(fname, &sz); if (data == 0) die("could not load system.img: %s", strerror(errno)); do_send_signature(fname); if (erase_first && needs_erase("system")) { fb_queue_erase("system"); flash_buf(images[i].part_name, &buf); } fb_queue_flash("system", data, sz); } #define skip(n) do { argc -= (n); argv += (n); } while (0) Loading Loading @@ -997,14 +1073,14 @@ int main(int argc, char **argv) fb_queue_flash(pname, data, sz); } else if(!strcmp(*argv, "flashall")) { skip(1); do_flashall(erase_first); do_flashall(usb, erase_first); wants_reboot = 1; } else if(!strcmp(*argv, "update")) { if (argc > 1) { do_update(argv[1], erase_first); do_update(usb, argv[1], erase_first); skip(2); } else { do_update("update.zip", erase_first); do_update(usb, "update.zip", erase_first); skip(1); } wants_reboot = 1; Loading Loading
fastboot/fastboot.c +171 −95 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <bootimg.h> #include <sparse/sparse.h> Loading @@ -54,6 +55,8 @@ #define O_BINARY 0 #endif #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) char cur_product[FB_RESPONSE_SZ + 1]; void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline); Loading Loading @@ -81,6 +84,27 @@ unsigned ramdisk_offset = 0x01000000; unsigned second_offset = 0x00f00000; unsigned tags_offset = 0x00000100; enum fb_buffer_type { FB_BUFFER, FB_BUFFER_SPARSE, }; struct fastboot_buffer { enum fb_buffer_type type; void *data; unsigned int sz; }; static struct { char img_name[13]; char sig_name[13]; char part_name[9]; bool is_optional; } images[3] = { {"boot.img", "boot.sig", "boot", false}, {"recovery.img", "recovery.sig", "recovery", true}, {"system.img", "system.sig", "system", false}, }; void die(const char *fmt, ...) { Loading Loading @@ -135,40 +159,28 @@ char *find_item(const char *item, const char *product) return strdup(path); } #if defined(__APPLE__) && defined(__MACH__) #define lseek64 lseek #define off64_t off_t #endif static int64_t file_size(const char *fn) static int64_t file_size(int fd) { off64_t off; int fd; struct stat st; int ret; fd = open(fn, O_RDONLY | O_BINARY); if (fd < 0) return -1; off = lseek64(fd, 0, SEEK_END); close(fd); ret = fstat(fd, &st); return off; return ret ? -1 : st.st_size; } static void *load_file(const char *fn, unsigned *_sz) static void *load_fd(int fd, unsigned *_sz) { char *data; int sz; int fd; int errno_tmp; data = 0; fd = open(fn, O_RDONLY | O_BINARY); 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; sz = file_size(fd); if (sz < 0) { goto oops; } data = (char*) malloc(sz); if(data == 0) goto oops; Loading @@ -187,6 +199,16 @@ oops: return 0; } static void *load_file(const char *fn, unsigned *_sz) { int fd; 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) { if(!(vendor_id && (info->dev_vendor == vendor_id)) && Loading Loading @@ -392,6 +414,31 @@ void *unzip_file(zipfile_t zip, const char *name, unsigned *sz) return data; } static int unzip_to_file(zipfile_t zip, char *name) { int fd; char *data; unsigned sz; fd = fileno(tmpfile()); if (fd < 0) { return -1; } data = unzip_file(zip, name, &sz); if (data == 0) { return -1; } if (write(fd, data, sz) != sz) { fd = -1; } free(data); lseek(fd, 0, SEEK_SET); return fd; } static char *strip(char *s) { int n; Loading Loading @@ -490,27 +537,20 @@ void queue_info_dump(void) fb_queue_notice("--------------------------------------------"); } struct sparse_file **load_sparse_files(const char *fname, int max_size) static struct sparse_file **load_sparse_files(int fd, int max_size) { int fd; struct sparse_file *s; int files; struct sparse_file **out_s; fd = open(fname, O_RDONLY | O_BINARY); if (fd < 0) { die("cannot open '%s'\n", fname); } s = sparse_file_import_auto(fd, false); if (!s) { die("cannot sparse read file '%s'\n", fname); die("cannot sparse read file\n"); } files = sparse_file_resparse(s, max_size, NULL, 0); if (files < 0) { die("Failed to resparse '%s'\n", fname); die("Failed to resparse\n"); } out_s = calloc(sizeof(struct sparse_file *), files + 1); Loading @@ -520,7 +560,7 @@ struct sparse_file **load_sparse_files(const char *fname, int max_size) files = sparse_file_resparse(s, max_size, out_s, files); if (files < 0) { die("Failed to resparse '%s'\n", fname); die("Failed to resparse\n"); } return out_s; Loading Loading @@ -581,29 +621,78 @@ static int needs_erase(const char *part) return fb_format_supported(usb, part); } void do_flash(usb_handle *usb, const char *pname, const char *fname) static int load_buf_fd(usb_handle *usb, int fd, struct fastboot_buffer *buf) { int64_t sz64; void *data; int64_t limit; sz64 = file_size(fname); sz64 = file_size(fd); if (sz64 < 0) { return -1; } limit = get_sparse_limit(usb, sz64); if (limit) { struct sparse_file **s = load_sparse_files(fname, limit); struct sparse_file **s = load_sparse_files(fd, limit); if (s == NULL) { die("cannot sparse load '%s'\n", fname); return -1; } buf->type = FB_BUFFER_SPARSE; buf->data = s; } else { unsigned int sz; data = load_fd(fd, &sz); if (data == 0) return -1; buf->type = FB_BUFFER; buf->data = data; buf->sz = sz; } return 0; } static int load_buf(usb_handle *usb, const char *fname, struct fastboot_buffer *buf) { int fd; fd = open(fname, O_RDONLY | O_BINARY); if (fd < 0) { die("cannot open '%s'\n", fname); } return load_buf_fd(usb, fd, buf); } static void flash_buf(const char *pname, struct fastboot_buffer *buf) { struct sparse_file **s; switch (buf->type) { case FB_BUFFER_SPARSE: s = buf->data; while (*s) { sz64 = sparse_file_len(*s, true, false); int64_t sz64 = sparse_file_len(*s, true, false); fb_queue_flash_sparse(pname, *s++, sz64); } } else { unsigned int sz; data = load_file(fname, &sz); if (data == 0) die("cannot load '%s': %s\n", fname, strerror(errno)); fb_queue_flash(pname, data, sz); break; case FB_BUFFER: fb_queue_flash(pname, buf->data, buf->sz); break; default: die("unknown buffer type: %d", buf->type); } } void do_flash(usb_handle *usb, const char *pname, const char *fname) { struct fastboot_buffer buf; if (load_buf(usb, fname, &buf)) { die("cannot load '%s'", fname); } flash_buf(pname, &buf); } void do_update_signature(zipfile_t zip, char *fn) Loading @@ -616,13 +705,17 @@ void do_update_signature(zipfile_t zip, char *fn) fb_queue_command("signature", "installing signature"); } void do_update(char *fn, int erase_first) void do_update(usb_handle *usb, char *fn, int erase_first) { void *zdata; unsigned zsize; void *data; unsigned sz; zipfile_t zip; int fd; int rc; struct fastboot_buffer buf; int i; queue_info_dump(); Loading Loading @@ -651,30 +744,25 @@ void do_update(char *fn, int erase_first) setup_requirements(data, sz); data = unzip_file(zip, "boot.img", &sz); if (data == 0) die("update package missing boot.img"); do_update_signature(zip, "boot.sig"); if (erase_first && needs_erase("boot")) { fb_queue_erase("boot"); } fb_queue_flash("boot", data, sz); data = unzip_file(zip, "recovery.img", &sz); if (data != 0) { do_update_signature(zip, "recovery.sig"); if (erase_first && needs_erase("recovery")) { fb_queue_erase("recovery"); } fb_queue_flash("recovery", data, sz); } data = unzip_file(zip, "system.img", &sz); if (data == 0) die("update package missing system.img"); do_update_signature(zip, "system.sig"); if (erase_first && needs_erase("system")) { fb_queue_erase("system"); for (i = 0; i < ARRAY_SIZE(images); i++) { fd = unzip_to_file(zip, images[i].img_name); if (fd < 0) { if (images[i].is_optional) continue; die("update package missing %s", images[i].img_name); } rc = load_buf_fd(usb, fd, &buf); if (rc) die("cannot load %s from flash", images[i].img_name); do_update_signature(zip, images[i].sig_name); if (erase_first && needs_erase(images[i].part_name)) { fb_queue_erase(images[i].part_name); } flash_buf(images[i].part_name, &buf); /* not closing the fd here since the sparse code keeps the fd around * but hasn't mmaped data yet. The tmpfile will get cleaned up when the * program exits. */ } fb_queue_flash("system", data, sz); } void do_send_signature(char *fn) Loading @@ -695,11 +783,13 @@ void do_send_signature(char *fn) fb_queue_command("signature", "installing signature"); } void do_flashall(int erase_first) void do_flashall(usb_handle *usb, int erase_first) { char *fname; void *data; unsigned sz; struct fastboot_buffer buf; int i; queue_info_dump(); Loading @@ -711,33 +801,19 @@ void do_flashall(int erase_first) if (data == 0) die("could not load android-info.txt: %s", strerror(errno)); setup_requirements(data, sz); fname = find_item("boot", product); data = load_file(fname, &sz); if (data == 0) die("could not load boot.img: %s", strerror(errno)); do_send_signature(fname); if (erase_first && needs_erase("boot")) { fb_queue_erase("boot"); for (i = 0; i < ARRAY_SIZE(images); i++) { fname = find_item(images[i].part_name, product); if (load_buf(usb, fname, &buf)) { if (images[i].is_optional) continue; die("could not load %s\n", images[i].img_name); } fb_queue_flash("boot", data, sz); fname = find_item("recovery", product); data = load_file(fname, &sz); if (data != 0) { do_send_signature(fname); if (erase_first && needs_erase("recovery")) { fb_queue_erase("recovery"); } fb_queue_flash("recovery", data, sz); if (erase_first && needs_erase(images[i].part_name)) { fb_queue_erase(images[i].part_name); } fname = find_item("system", product); data = load_file(fname, &sz); if (data == 0) die("could not load system.img: %s", strerror(errno)); do_send_signature(fname); if (erase_first && needs_erase("system")) { fb_queue_erase("system"); flash_buf(images[i].part_name, &buf); } fb_queue_flash("system", data, sz); } #define skip(n) do { argc -= (n); argv += (n); } while (0) Loading Loading @@ -997,14 +1073,14 @@ int main(int argc, char **argv) fb_queue_flash(pname, data, sz); } else if(!strcmp(*argv, "flashall")) { skip(1); do_flashall(erase_first); do_flashall(usb, erase_first); wants_reboot = 1; } else if(!strcmp(*argv, "update")) { if (argc > 1) { do_update(argv[1], erase_first); do_update(usb, argv[1], erase_first); skip(2); } else { do_update("update.zip", erase_first); do_update(usb, "update.zip", erase_first); skip(1); } wants_reboot = 1; Loading