diff options
| -rw-r--r-- | fastboot/engine.c | 14 | ||||
| -rw-r--r-- | fastboot/fastboot.c | 271 | ||||
| -rw-r--r-- | fastboot/util_windows.c | 67 | ||||
| -rw-r--r-- | include/system/audio.h | 34 | ||||
| -rw-r--r--[-rwxr-xr-x] | init/init.c | 80 | ||||
| -rw-r--r-- | toolbox/rm.c | 15 | ||||
| -rw-r--r-- | toolbox/touch.c | 35 |
7 files changed, 308 insertions, 208 deletions
diff --git a/fastboot/engine.c b/fastboot/engine.c index 8d46991..b07e742 100644 --- a/fastboot/engine.c +++ b/fastboot/engine.c @@ -286,21 +286,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 447b257..f186c93 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -43,6 +43,7 @@ #include <sys/time.h> #include <sys/types.h> +#include <sys/stat.h> #include <bootimg.h> #include <sparse/sparse.h> @@ -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); @@ -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, ...) { @@ -135,44 +159,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; @@ -190,7 +198,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) { @@ -397,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; @@ -495,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); @@ -525,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; @@ -586,31 +621,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; @@ -621,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(); @@ -656,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"); + 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) @@ -700,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(); @@ -716,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"); - } - 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) @@ -1002,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; 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; -} diff --git a/include/system/audio.h b/include/system/audio.h index da235dd..c49b0ee 100644 --- a/include/system/audio.h +++ b/include/system/audio.h @@ -383,9 +383,41 @@ typedef enum { // controls related to voice calls. AUDIO_OUTPUT_FLAG_FAST = 0x4, // output supports "fast tracks", // defined elsewhere - AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8 // use deep audio buffers + AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, // use deep audio buffers + AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10, // offload playback of compressed + // streams to hardware codec + AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20 // use non-blocking write } audio_output_flags_t; +/* Additional information about compressed streams offloaded to + * hardware playback + * The version and size fields must be initialized by the caller by using + * one of the constants defined here. + */ +typedef struct { + uint16_t version; // version of the info structure + uint16_t size; // total size of the structure including version and size + uint32_t sample_rate; // sample rate in Hz + audio_channel_mask_t channel_mask; // channel mask + audio_format_t format; // audio format + audio_stream_type_t stream_type; // stream type + uint32_t bit_rate; // bit rate in bits per second + int64_t duration_us; // duration in microseconds, -1 if unknown + bool has_video; // true if stream is tied to a video stream + bool is_streaming; // true if streaming, false if local playback +} audio_offload_info_t; + +#define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \ + ((((maj) & 0xff) << 8) | ((min) & 0xff)) + +#define AUDIO_OFFLOAD_INFO_VERSION_0_1 AUDIO_MAKE_OFFLOAD_INFO_VERSION(0, 1) +#define AUDIO_OFFLOAD_INFO_VERSION_CURRENT AUDIO_OFFLOAD_INFO_VERSION_0_1 + +static const audio_offload_info_t AUDIO_INFO_INITIALIZER = { + version: AUDIO_OFFLOAD_INFO_VERSION_CURRENT, + size: sizeof(audio_offload_info_t), +}; + static inline bool audio_is_output_device(audio_devices_t device) { if (((device & AUDIO_DEVICE_BIT_IN) == 0) && diff --git a/init/init.c b/init/init.c index 28d2863..d75adca 100755..100644 --- a/init/init.c +++ b/init/init.c @@ -39,6 +39,7 @@ #include <libgen.h> #include <cutils/list.h> +#include <cutils/android_reboot.h> #include <cutils/sockets.h> #include <cutils/iosched_policy.h> #include <private/android_filesystem_config.h> @@ -73,8 +74,6 @@ static char hardware[32]; static unsigned revision = 0; static char qemu[32]; -static int selinux_enabled = 1; - static struct action *cur_action = NULL; static struct command *cur_command = NULL; static struct listnode *command_queue = NULL; @@ -614,10 +613,6 @@ static void import_kernel_nv(char *name, int for_emulator) *value++ = 0; if (name_len == 0) return; - if (!strcmp(name,"selinux")) { - selinux_enabled = atoi(value); - } - if (for_emulator) { /* in the emulator, export any kernel option with the * ro.kernel. prefix */ @@ -798,9 +793,49 @@ void selinux_init_all_handles(void) sehandle_prop = selinux_android_prop_context_handle(); } +static bool selinux_is_disabled(void) +{ + char tmp[PROP_VALUE_MAX]; + + if (access("/sys/fs/selinux", F_OK) != 0) { + /* SELinux is not compiled into the kernel, or has been disabled + * via the kernel command line "selinux=0". + */ + return true; + } + + if ((property_get("ro.boot.selinux", tmp) != 0) && (strcmp(tmp, "disabled") == 0)) { + /* SELinux is compiled into the kernel, but we've been told to disable it. */ + return true; + } + + return false; +} + +static bool selinux_is_enforcing(void) +{ + char tmp[PROP_VALUE_MAX]; + + if (property_get("ro.boot.selinux", tmp) == 0) { + /* Property is not set. Assume enforcing */ + return true; + } + + if (strcmp(tmp, "permissive") == 0) { + /* SELinux is in the kernel, but we've been told to go into permissive mode */ + return false; + } + + if (strcmp(tmp, "enforcing") != 0) { + ERROR("SELinux: Unknown value of ro.boot.selinux. Got: \"%s\". Assuming enforcing.\n", tmp); + } + + return true; +} + int selinux_reload_policy(void) { - if (!selinux_enabled) { + if (selinux_is_disabled()) { return -1; } @@ -826,6 +861,25 @@ int audit_callback(void *data, security_class_t cls, char *buf, size_t len) return 0; } +static void selinux_initialize(void) +{ + if (selinux_is_disabled()) { + return; + } + + INFO("loading selinux policy\n"); + if (selinux_android_load_policy() < 0) { + ERROR("SELinux: Failed to load policy; rebooting into recovery mode\n"); + android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); + while (1) { pause(); } // never reached + } + + selinux_init_all_handles(); + bool is_enforcing = selinux_is_enforcing(); + INFO("SELinux: security_setenforce(%d)\n", is_enforcing); + security_setenforce(is_enforcing); +} + int main(int argc, char **argv) { int fd_count = 0; @@ -886,17 +940,7 @@ int main(int argc, char **argv) cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); - INFO("loading selinux policy\n"); - if (selinux_enabled) { - if (selinux_android_load_policy() < 0) { - selinux_enabled = 0; - INFO("SELinux: Disabled due to failed policy load\n"); - } else { - selinux_init_all_handles(); - } - } else { - INFO("SELinux: Disabled by command line option\n"); - } + selinux_initialize(); /* These directories were necessarily created before initial policy load * and therefore need their security context restored to the proper value. * This must happen before /dev is populated by ueventd. diff --git a/toolbox/rm.c b/toolbox/rm.c index 127cbc4..957b586 100644 --- a/toolbox/rm.c +++ b/toolbox/rm.c @@ -45,8 +45,10 @@ static int unlink_recursive(const char* name, int flags) continue; sprintf(dn, "%s/%s", name, de->d_name); if (unlink_recursive(dn, flags) < 0) { - fail = 1; - break; + if (!(flags & OPT_FORCE)) { + fail = 1; + break; + } } errno = 0; } @@ -71,6 +73,7 @@ int rm_main(int argc, char *argv[]) int ret; int i, c; int flags = 0; + int something_failed = 0; if (argc < 2) return usage(); @@ -110,10 +113,14 @@ int rm_main(int argc, char *argv[]) if (ret < 0) { fprintf(stderr, "rm failed for %s, %s\n", argv[i], strerror(errno)); - return -1; + if (!(flags & OPT_FORCE)) { + return -1; + } else { + something_failed = 1; + } } } - return 0; + return something_failed; } diff --git a/toolbox/touch.c b/toolbox/touch.c index b8ab310..52ddf2a 100644 --- a/toolbox/touch.c +++ b/toolbox/touch.c @@ -5,13 +5,40 @@ #include <sys/stat.h> #include <stdlib.h> #include <fcntl.h> +#include <time.h> static void usage(void) { - fprintf(stderr, "touch: usage: touch [-alm] [-t time_t] <file>\n"); + fprintf(stderr, "touch: usage: touch [-alm] [-t YYYYMMDD[.hhmmss]] <file>\n"); exit(1); } +static time_t parse_time(char *s) +{ + struct tm tm; + int day = atoi(s); + int hour = 0; + + while (*s && *s != '.') { + s++; + } + + if (*s) { + s++; + hour = atoi(s); + } + + tm.tm_year = day / 10000 - 1900; + tm.tm_mon = (day % 10000) / 100 - 1; + tm.tm_mday = day % 100; + tm.tm_hour = hour / 10000; + tm.tm_min = (hour % 10000) / 100; + tm.tm_sec = hour % 100; + tm.tm_isdst = -1; + + return mktime(&tm); +} + int touch_main(int argc, char *argv[]) { int i, fd, aflag = 0, mflag = 0, debug = 0, flags = 0; @@ -31,9 +58,9 @@ int touch_main(int argc, char *argv[]) case 't': if ((i+1) >= argc) usage(); - specified_time.tv_sec = atol(argv[++i]); - if (specified_time.tv_sec == 0) { - fprintf(stderr, "touch: invalid time_t\n"); + specified_time.tv_sec = parse_time(argv[++i]); + if (specified_time.tv_sec == -1) { + fprintf(stderr, "touch: invalid timestamp specified\n"); exit(1); } specified_time.tv_nsec = 0; |
