diff options
-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 036b8f7..08d23e3 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 e13d4b1..1e31cf9 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 0e97be7..1328d19 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(); |