diff options
-rw-r--r-- | init/Android.mk | 1 | ||||
-rw-r--r-- | init/devices.cpp | 52 |
2 files changed, 38 insertions, 15 deletions
diff --git a/init/Android.mk b/init/Android.mk index 71faede..99d12c2 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -66,6 +66,7 @@ endif LOCAL_MODULE:= init LOCAL_C_INCLUDES += \ + external/zlib \ system/extras/ext4_utils \ system/core/mkbootimg diff --git a/init/devices.cpp b/init/devices.cpp index 0bc0df7..d8de450 100644 --- a/init/devices.cpp +++ b/init/devices.cpp @@ -48,6 +48,7 @@ #include "util.h" #include "log.h" #include "property_service.h" +#include <zlib.h> #define SYSFS_PREFIX "/sys" static const char *firmware_dirs[] = { "/etc/firmware", @@ -825,23 +826,20 @@ static void handle_device_event(struct uevent *uevent) } } -static int load_firmware(int fw_fd, int loading_fd, int data_fd) +static int load_firmware(int fw_fd, gzFile gz_fd, int loading_fd, int data_fd) { - struct stat st; - long len_to_copy; int ret = 0; - if(fstat(fw_fd, &st) < 0) - return -1; - len_to_copy = st.st_size; - write(loading_fd, "1", 1); /* start transfer */ - while (len_to_copy > 0) { + while (1) { char buf[PAGE_SIZE]; ssize_t nr; - nr = read(fw_fd, buf, sizeof(buf)); + if (gz_fd) + nr = gzread(gz_fd, buf, sizeof(buf)); + else + nr = read(fw_fd, buf, sizeof(buf)); if(!nr) break; if(nr < 0) { @@ -849,7 +847,6 @@ static int load_firmware(int fw_fd, int loading_fd, int data_fd) break; } - len_to_copy -= nr; while (nr > 0) { ssize_t nw = 0; @@ -865,8 +862,10 @@ static int load_firmware(int fw_fd, int loading_fd, int data_fd) out: if(!ret) write(loading_fd, "0", 1); /* successful end of transfer */ - else + else { + ERROR("%s: aborted transfer\n", __func__); write(loading_fd, "-1", 2); /* abort transfer */ + } return ret; } @@ -876,12 +875,29 @@ static int is_booting(void) return access("/dev/.booting", F_OK) == 0; } +gzFile fw_gzopen(const char *fname, const char *mode) +{ + char *file1 = NULL; + int l; + gzFile gz_fd = NULL; + + l = asprintf(&file1, "%s.gz", fname); + if (l == -1) + goto out; + + gz_fd = gzopen(file1, mode); + free(file1); +out: + return gz_fd; +} + static void process_firmware_event(struct uevent *uevent) { char *root, *loading, *data; int l, loading_fd, data_fd, fw_fd; size_t i; int booting = is_booting(); + gzFile gz_fd = NULL; INFO("firmware: loading '%s' for '%s'\n", uevent->firmware, uevent->path); @@ -914,15 +930,18 @@ try_loading_again: goto data_free_out; fw_fd = open(file, O_RDONLY|O_CLOEXEC); free(file); - if (fw_fd >= 0) { - if(!load_firmware(fw_fd, loading_fd, data_fd)) + if (fw_fd < 0){ + gz_fd = fw_gzopen(file, "rb"); + } + if (fw_fd >= 0 || gz_fd) { + if(!load_firmware(fw_fd, gz_fd, loading_fd, data_fd)) INFO("firmware: copy success { '%s', '%s' }\n", root, uevent->firmware); else INFO("firmware: copy failure { '%s', '%s' }\n", root, uevent->firmware); break; } } - if (fw_fd < 0) { + if ((fw_fd < 0) && !gz_fd) { if (booting) { /* If we're not fully booted, we may be missing * filesystems needed for firmware, wait and retry. @@ -936,7 +955,10 @@ try_loading_again: goto data_close_out; } - close(fw_fd); + if (gz_fd) + gzclose(gz_fd); + else + close(fw_fd); data_close_out: close(data_fd); loading_close_out: |