diff options
| author | Brian Swetland <swetland@google.com> | 2011-03-24 15:45:30 -0700 |
|---|---|---|
| committer | Brian Swetland <swetland@google.com> | 2011-03-25 13:01:35 -0700 |
| commit | 8d48c8e45724c7103f0ace7885d339e49399908b (patch) | |
| tree | d63d7242a4e8184b7a840a12a65d603c26096fa5 | |
| parent | e31f2cdde626a0ef6c731c98b92b5b2dc5a533f4 (diff) | |
| download | system_core-8d48c8e45724c7103f0ace7885d339e49399908b.tar.gz system_core-8d48c8e45724c7103f0ace7885d339e49399908b.tar.bz2 system_core-8d48c8e45724c7103f0ace7885d339e49399908b.zip | |
defer firmware load until after filesystems are mounted
In some situations a driver could try to request firmware before
/system is mounted. Previously we'd fail the request. Now we
will retry the read-from-filesystem every 100ms until we find the
firmware or we've finished the "fs" and "post-fs" stages of init.
Change-Id: Ie32402f7d41c818bf20f3297286ed5f99705b72c
| -rw-r--r-- | init/devices.c | 29 | ||||
| -rwxr-xr-x | init/init.c | 7 | ||||
| -rw-r--r-- | init/ueventd.c | 9 |
3 files changed, 36 insertions, 9 deletions
diff --git a/init/devices.c b/init/devices.c index 036b8f75..08d23e31 100644 --- a/init/devices.c +++ b/init/devices.c @@ -551,13 +551,19 @@ out: return ret; } +static int is_booting(void) +{ + return access("/dev/.booting", F_OK) == 0; +} + static void process_firmware_event(struct uevent *uevent) { char *root, *loading, *data, *file1 = NULL, *file2 = NULL; int l, loading_fd, data_fd, fw_fd; + int booting = is_booting(); - log_event_print("firmware event { '%s', '%s' }\n", - uevent->path, uevent->firmware); + INFO("firmware: loading '%s' for '%s'\n", + uevent->firmware, uevent->path); l = asprintf(&root, SYSFS_PREFIX"%s/", uevent->path); if (l == -1) @@ -587,19 +593,29 @@ static void process_firmware_event(struct uevent *uevent) if(data_fd < 0) goto loading_close_out; +try_loading_again: fw_fd = open(file1, O_RDONLY); if(fw_fd < 0) { fw_fd = open(file2, O_RDONLY); if (fw_fd < 0) { + if (booting) { + /* If we're not fully booted, we may be missing + * filesystems needed for firmware, wait and retry. + */ + usleep(100000); + booting = is_booting(); + goto try_loading_again; + } + INFO("firmware: could not open '%s' %d\n", uevent->firmware, errno); write(loading_fd, "-1", 2); goto data_close_out; } } if(!load_firmware(fw_fd, loading_fd, data_fd)) - log_event_print("firmware copy success { '%s', '%s' }\n", root, uevent->firmware); + INFO("firmware: copy success { '%s', '%s' }\n", root, uevent->firmware); else - log_event_print("firmware copy failure { '%s', '%s' }\n", root, uevent->firmware); + INFO("firmware: copy failure { '%s', '%s' }\n", root, uevent->firmware); close(fw_fd); data_close_out: @@ -620,7 +636,6 @@ root_free_out: static void handle_firmware_event(struct uevent *uevent) { pid_t pid; - int status; int ret; if(strcmp(uevent->subsystem, "firmware")) @@ -634,10 +649,6 @@ static void handle_firmware_event(struct uevent *uevent) if (!pid) { process_firmware_event(uevent); exit(EXIT_SUCCESS); - } else { - do { - ret = waitpid(pid, &status, 0); - } while (ret == -1 && errno == EINTR); } } diff --git a/init/init.c b/init/init.c index e13d4b18..1e31cf95 100755 --- a/init/init.c +++ b/init/init.c @@ -651,6 +651,10 @@ static int check_startup_action(int nargs, char **args) ERROR("init startup failure\n"); exit(1); } + + /* signal that we hit this point */ + unlink("/dev/.booting"); + return 0; } @@ -708,6 +712,9 @@ int main(int argc, char **argv) mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); + /* indicate that booting is in progress to background fw loaders, etc */ + close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000)); + /* We must have some place other than / to create the * device nodes for kmsg and null, otherwise we won't * be able to remount / read-only later on. diff --git a/init/ueventd.c b/init/ueventd.c index 0e97be76..1328d19a 100644 --- a/init/ueventd.c +++ b/init/ueventd.c @@ -20,6 +20,8 @@ #include <stdlib.h> #include <stdio.h> #include <ctype.h> +#include <signal.h> + #include <private/android_filesystem_config.h> #include "ueventd.h" @@ -37,6 +39,13 @@ int ueventd_main(int argc, char **argv) int nr; char tmp[32]; + /* Prevent fire-and-forget children from becoming zombies. + * If we should need to wait() for some children in the future + * (as opposed to none right now), double-forking here instead + * of ignoring SIGCHLD may be the better solution. + */ + signal(SIGCHLD, SIG_IGN); + open_devnull_stdio(); log_init(); |
