summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--init/devices.c29
-rwxr-xr-xinit/init.c7
-rw-r--r--init/ueventd.c9
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();