summaryrefslogtreecommitdiffstats
path: root/fastboot
diff options
context:
space:
mode:
Diffstat (limited to 'fastboot')
-rw-r--r--fastboot/engine.c14
-rw-r--r--fastboot/fastboot.c271
-rw-r--r--fastboot/util_windows.c67
3 files changed, 171 insertions, 181 deletions
diff --git a/fastboot/engine.c b/fastboot/engine.c
index 84ea984..972c4ed 100644
--- a/fastboot/engine.c
+++ b/fastboot/engine.c
@@ -264,21 +264,7 @@ void generate_ext4_image(struct image_data *image)
int fd;
struct stat st;
-#ifdef USE_MINGW
- /* Ideally we should use tmpfile() here, the same as with unix version.
- * But unfortunately it is not portable as it is not clear whether this
- * function opens file in TEXT or BINARY mode.
- *
- * There are also some reports it is buggy:
- * http://pdplab.it.uom.gr/teaching/gcc_manuals/gnulib.html#tmpfile
- * http://www.mega-nerd.com/erikd/Blog/Windiots/tmpfile.html
- */
- char *filename = tempnam(getenv("TEMP"), "fastboot-format.img");
- fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644);
- unlink(filename);
-#else
fd = fileno(tmpfile());
-#endif
make_ext4fs_sparse_fd(fd, image->partition_size, NULL, NULL);
fstat(fd, &st);
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index da2af41..73a6e56 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -42,6 +42,7 @@
#include <sys/time.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <bootimg.h>
#include <sparse/sparse.h>
@@ -53,6 +54,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);
@@ -80,6 +83,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 get_my_path(char *path);
@@ -123,44 +147,28 @@ char *find_item(const char *item, const char *product)
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)
+static int64_t file_size(int fd)
{
- off64_t off;
- int fd;
+ struct stat st;
+ int ret;
- fd = open(fn, O_RDONLY);
- if (fd < 0) return -1;
+ ret = fstat(fd, &st);
- off = lseek64(fd, 0, SEEK_END);
- close(fd);
-
- return off;
+ return ret ? -1 : st.st_size;
}
-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);
- 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;
@@ -178,7 +186,16 @@ oops:
errno = errno_tmp;
return 0;
}
-#endif
+
+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)
{
@@ -385,6 +402,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;
@@ -489,27 +531,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);
@@ -519,7 +554,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;
@@ -580,31 +615,80 @@ 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);
- }
- while (*s) {
- sz64 = sparse_file_len(*s, true, false);
- fb_queue_flash_sparse(pname, *s++, sz64);
+ return -1;
}
+ buf->type = FB_BUFFER_SPARSE;
+ buf->data = s;
} 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);
+ 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) {
+ int64_t sz64 = sparse_file_len(*s, true, false);
+ fb_queue_flash_sparse(pname, *s++, sz64);
+ }
+ 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)
{
void *data;
@@ -615,13 +699,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();
@@ -650,30 +738,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");
+ 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);
}
- 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");
+ 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)
@@ -694,11 +777,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();
@@ -710,33 +795,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");
- }
- fb_queue_flash("boot", data, sz);
-
- fname = find_item("recovery", product);
- data = load_file(fname, &sz);
- if (data != 0) {
+ 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);
+ }
do_send_signature(fname);
- if (erase_first && needs_erase("recovery")) {
- fb_queue_erase("recovery");
+ if (erase_first && needs_erase(images[i].part_name)) {
+ fb_queue_erase(images[i].part_name);
}
- fb_queue_flash("recovery", data, sz);
- }
-
- 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)
@@ -996,14 +1067,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;
diff --git a/fastboot/util_windows.c b/fastboot/util_windows.c
index 9e029fd..74a5c27 100644
--- a/fastboot/util_windows.c
+++ b/fastboot/util_windows.c
@@ -36,29 +36,6 @@
#include <windows.h>
-int64_t file_size(const char *fn)
-{
- HANDLE file;
- char *data;
- DWORD sz;
-
- file = CreateFile( fn,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- 0,
- NULL );
-
- if (file == INVALID_HANDLE_VALUE)
- return -1;
-
- sz = GetFileSize( file, NULL );
- CloseHandle( file );
-
- return sz;
-}
-
void get_my_path(char exe[PATH_MAX])
{
char* r;
@@ -70,47 +47,3 @@ void get_my_path(char exe[PATH_MAX])
*r = 0;
}
-
-void *load_file(const char *fn, unsigned *_sz)
-{
- HANDLE file;
- char *data;
- DWORD sz;
-
- file = CreateFile( fn,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- 0,
- NULL );
-
- if (file == INVALID_HANDLE_VALUE)
- return NULL;
-
- sz = GetFileSize( file, NULL );
- data = NULL;
-
- if (sz > 0) {
- data = (char*) malloc( sz );
- if (data == NULL) {
- fprintf(stderr, "load_file: could not allocate %ld bytes\n", sz );
- sz = 0;
- } else {
- DWORD out_bytes;
-
- if ( !ReadFile( file, data, sz, &out_bytes, NULL ) ||
- out_bytes != sz )
- {
- fprintf(stderr, "load_file: could not read %ld bytes from '%s'\n", sz, fn);
- free(data);
- data = NULL;
- sz = 0;
- }
- }
- }
- CloseHandle( file );
-
- *_sz = (unsigned) sz;
- return data;
-}