diff options
Diffstat (limited to 'init')
-rw-r--r-- | init/builtins.c | 59 | ||||
-rw-r--r-- | init/devices.c | 374 | ||||
-rwxr-xr-x | init/init.c | 89 | ||||
-rw-r--r-- | init/init.h | 2 | ||||
-rw-r--r-- | init/init_parser.c | 16 | ||||
-rw-r--r-- | init/keywords.h | 3 | ||||
-rw-r--r-- | init/list.h | 51 | ||||
-rw-r--r-- | init/log.h | 13 | ||||
-rw-r--r-- | init/parser.c | 1 | ||||
-rw-r--r-- | init/property_service.c | 16 | ||||
-rw-r--r-- | init/property_service.h | 4 | ||||
-rw-r--r-- | init/signal_handler.c | 2 | ||||
-rw-r--r-- | init/ueventd.c | 30 | ||||
-rw-r--r-- | init/ueventd_parser.c | 1 | ||||
-rwxr-xr-x | init/util.c | 87 | ||||
-rw-r--r-- | init/util.h | 1 |
16 files changed, 415 insertions, 334 deletions
diff --git a/init/builtins.c b/init/builtins.c index f2f76b7..eccda3f 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -30,6 +30,7 @@ #include <sys/mount.h> #include <sys/resource.h> #include <linux/loop.h> +#include <cutils/partition_utils.h> #include "init.h" #include "keywords.h" @@ -225,14 +226,10 @@ int do_insmod(int nargs, char **args) return do_insmod_inner(nargs, args, size); } -int do_import(int nargs, char **args) -{ - return init_parse_config_file(args[1]); -} - int do_mkdir(int nargs, char **args) { mode_t mode = 0755; + int ret; /* mkdir <path> [mode] [owner] [group] */ @@ -240,7 +237,12 @@ int do_mkdir(int nargs, char **args) mode = strtoul(args[2], 0, 8); } - if (mkdir(args[1], mode)) { + ret = mkdir(args[1], mode); + /* chmod in case the directory already exists */ + if (ret == -1 && errno == EEXIST) { + ret = chmod(args[1], mode); + } + if (ret == -1) { return -errno; } @@ -367,7 +369,9 @@ int do_mount(int nargs, char **args) if (wait) wait_for_file(source, COMMAND_RETRY_TIMEOUT); if (mount(source, target, system, flags, options) < 0) { - /* If this fails, it may be an encrypted filesystem. + /* If this fails, it may be an encrypted filesystem + * or it could just be wiped. If wiped, that will be + * handled later in the boot process. * We only support encrypting /data. Check * if we're trying to mount it, and if so, * assume it's encrypted, mount a tmpfs instead. @@ -375,7 +379,7 @@ int do_mount(int nargs, char **args) * for vold to query when it mounts the real * encrypted /data. */ - if (!strcmp(target, DATA_MNT_POINT)) { + if (!strcmp(target, DATA_MNT_POINT) && !partition_wiped(source)) { const char *tmpfs_options; tmpfs_options = property_get("ro.crypto.tmpfs_options"); @@ -442,7 +446,24 @@ int do_setkey(int nargs, char **args) int do_setprop(int nargs, char **args) { - property_set(args[1], args[2]); + const char *name = args[1]; + const char *value = args[2]; + + if (value[0] == '$') { + /* Use the value of a system property if value starts with '$' */ + value++; + if (value[0] != '$') { + value = property_get(value); + if (!value) { + ERROR("property %s has no value for assigning to %s\n", value, name); + return -EINVAL; + } + } /* else fall through to support double '$' prefix for setting properties + * to string literals that start with '$' + */ + } + + property_set(name, value); return 0; } @@ -524,7 +545,23 @@ int do_sysclktz(int nargs, char **args) int do_write(int nargs, char **args) { - return write_file(args[1], args[2]); + const char *path = args[1]; + const char *value = args[2]; + if (value[0] == '$') { + /* Write the value of a system property if value starts with '$' */ + value++; + if (value[0] != '$') { + value = property_get(value); + if (!value) { + ERROR("property %s has no value for writing to %s\n", value, path); + return -EINVAL; + } + } /* else fall through to support double '$' prefix for writing + * string literals that start with '$' + */ + } + + return write_file(path, value); } int do_copy(int nargs, char **args) @@ -626,7 +663,7 @@ int do_chmod(int nargs, char **args) { int do_loglevel(int nargs, char **args) { if (nargs == 2) { - log_set_level(atoi(args[1])); + klog_set_level(atoi(args[1])); return 0; } return -1; diff --git a/init/devices.c b/init/devices.c index 9c07e99..a2f84aa 100644 --- a/init/devices.c +++ b/init/devices.c @@ -34,12 +34,12 @@ #include <asm/page.h> #include <sys/wait.h> +#include <cutils/list.h> #include <cutils/uevent.h> #include "devices.h" #include "util.h" #include "log.h" -#include "list.h" #define SYSFS_PREFIX "/sys" #define FIRMWARE_DIR1 "/etc/firmware" @@ -58,33 +58,6 @@ struct uevent { int minor; }; -static int open_uevent_socket(void) -{ - struct sockaddr_nl addr; - int sz = 64*1024; // XXX larger? udev uses 16MB! - int on = 1; - int s; - - memset(&addr, 0, sizeof(addr)); - addr.nl_family = AF_NETLINK; - addr.nl_pid = getpid(); - addr.nl_groups = 0xffffffff; - - s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); - if(s < 0) - return -1; - - setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); - setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); - - if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - close(s); - return -1; - } - - return s; -} - struct perms_ { char *name; char *attr; @@ -99,8 +72,15 @@ struct perm_node { struct listnode plist; }; +struct platform_node { + char *name; + int name_len; + struct listnode list; +}; + static list_declare(sys_perms); static list_declare(dev_perms); +static list_declare(platform_names); int add_dev_perms(const char *name, const char *attr, mode_t perm, unsigned int uid, unsigned int gid, @@ -214,6 +194,68 @@ static void make_device(const char *path, setegid(AID_ROOT); } +static void add_platform_device(const char *name) +{ + int name_len = strlen(name); + struct listnode *node; + struct platform_node *bus; + + list_for_each_reverse(node, &platform_names) { + bus = node_to_item(node, struct platform_node, list); + if ((bus->name_len < name_len) && + (name[bus->name_len] == '/') && + !strncmp(name, bus->name, bus->name_len)) + /* subdevice of an existing platform, ignore it */ + return; + } + + INFO("adding platform device %s\n", name); + + bus = calloc(1, sizeof(struct platform_node)); + bus->name = strdup(name); + bus->name_len = name_len; + list_add_tail(&platform_names, &bus->list); +} + +/* + * given a name that may start with a platform device, find the length of the + * platform device prefix. If it doesn't start with a platform device, return + * 0. + */ +static const char *find_platform_device(const char *name) +{ + int name_len = strlen(name); + struct listnode *node; + struct platform_node *bus; + + list_for_each_reverse(node, &platform_names) { + bus = node_to_item(node, struct platform_node, list); + if ((bus->name_len < name_len) && + (name[bus->name_len] == '/') && + !strncmp(name, bus->name, bus->name_len)) + return bus->name; + } + + return NULL; +} + +static void remove_platform_device(const char *name) +{ + struct listnode *node; + struct platform_node *bus; + + list_for_each_reverse(node, &platform_names) { + bus = node_to_item(node, struct platform_node, list); + if (!strcmp(name, bus->name)) { + INFO("removing platform device %s\n", name); + free(bus->name); + list_remove(node); + free(bus); + return; + } + } +} + #if LOG_UEVENTS static inline suseconds_t get_usecs(void) @@ -334,7 +376,7 @@ err: static char **parse_platform_block_device(struct uevent *uevent) { - const char *driver; + const char *device; const char *path; char *slash; int width; @@ -354,16 +396,14 @@ static char **parse_platform_block_device(struct uevent *uevent) /* Drop "/devices/platform/" */ path = uevent->path; - driver = path + 18; - slash = strchr(driver, '/'); - if (!slash) - goto err; - width = slash - driver; - if (width <= 0) + device = path + 18; + device = find_platform_device(device); + if (!device) goto err; - snprintf(link_path, sizeof(link_path), "/dev/block/platform/%.*s", - width, driver); + INFO("found platform device %s\n", device); + + snprintf(link_path, sizeof(link_path), "/dev/block/platform/%s", device); if (uevent->partition_name) { p = strdup(uevent->partition_name); @@ -395,104 +435,20 @@ err: return NULL; } -static void handle_device_event(struct uevent *uevent) +static void handle_device(const char *action, const char *devpath, + const char *path, int block, int major, int minor, char **links) { - char devpath[96]; - int devpath_ready = 0; - char *base, *name; - char **links = NULL; - int block; int i; - if (!strcmp(uevent->action,"add")) - fixup_sys_perms(uevent->path); - - /* if it's not a /dev device, nothing else to do */ - if((uevent->major < 0) || (uevent->minor < 0)) - return; - - /* do we have a name? */ - name = strrchr(uevent->path, '/'); - if(!name) - return; - name++; - - /* too-long names would overrun our buffer */ - if(strlen(name) > 64) - return; - - /* are we block or char? where should we live? */ - if(!strncmp(uevent->subsystem, "block", 5)) { - block = 1; - base = "/dev/block/"; - mkdir(base, 0755); - if (!strncmp(uevent->path, "/devices/platform/", 18)) - links = parse_platform_block_device(uevent); - } else { - block = 0; - /* this should probably be configurable somehow */ - if (!strncmp(uevent->subsystem, "usb", 3)) { - if (!strcmp(uevent->subsystem, "usb")) { - /* This imitates the file system that would be created - * if we were using devfs instead. - * Minors are broken up into groups of 128, starting at "001" - */ - int bus_id = uevent->minor / 128 + 1; - int device_id = uevent->minor % 128 + 1; - /* build directories */ - mkdir("/dev/bus", 0755); - mkdir("/dev/bus/usb", 0755); - snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id); - mkdir(devpath, 0755); - snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id); - devpath_ready = 1; - } else { - /* ignore other USB events */ - return; - } - } else if (!strncmp(uevent->subsystem, "graphics", 8)) { - base = "/dev/graphics/"; - mkdir(base, 0755); - } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) { - base = "/dev/oncrpc/"; - mkdir(base, 0755); - } else if (!strncmp(uevent->subsystem, "adsp", 4)) { - base = "/dev/adsp/"; - mkdir(base, 0755); - } else if (!strncmp(uevent->subsystem, "msm_camera", 10)) { - base = "/dev/msm_camera/"; - mkdir(base, 0755); - } else if(!strncmp(uevent->subsystem, "input", 5)) { - base = "/dev/input/"; - mkdir(base, 0755); - } else if(!strncmp(uevent->subsystem, "mtd", 3)) { - base = "/dev/mtd/"; - mkdir(base, 0755); - } else if(!strncmp(uevent->subsystem, "sound", 5)) { - base = "/dev/snd/"; - mkdir(base, 0755); - } else if(!strncmp(uevent->subsystem, "misc", 4) && - !strncmp(name, "log_", 4)) { - base = "/dev/log/"; - mkdir(base, 0755); - name += 4; - } else - base = "/dev/"; - links = get_character_device_symlinks(uevent); - } - - if (!devpath_ready) - snprintf(devpath, sizeof(devpath), "%s%s", base, name); - - if(!strcmp(uevent->action, "add")) { - make_device(devpath, uevent->path, block, uevent->major, uevent->minor); + if(!strcmp(action, "add")) { + make_device(devpath, path, block, major, minor); if (links) { for (i = 0; links[i]; i++) make_link(devpath, links[i]); } } - if(!strcmp(uevent->action, "remove")) { + if(!strcmp(action, "remove")) { if (links) { for (i = 0; links[i]; i++) remove_link(devpath, links[i]); @@ -507,6 +463,138 @@ static void handle_device_event(struct uevent *uevent) } } +static void handle_platform_device_event(struct uevent *uevent) +{ + const char *name = uevent->path + 18; /* length of /devices/platform/ */ + + if (!strcmp(uevent->action, "add")) + add_platform_device(name); + else if (!strcmp(uevent->action, "remove")) + remove_platform_device(name); +} + +static const char *parse_device_name(struct uevent *uevent, unsigned int len) +{ + const char *name; + + /* if it's not a /dev device, nothing else to do */ + if((uevent->major < 0) || (uevent->minor < 0)) + return NULL; + + /* do we have a name? */ + name = strrchr(uevent->path, '/'); + if(!name) + return NULL; + name++; + + /* too-long names would overrun our buffer */ + if(strlen(name) > len) + return NULL; + + return name; +} + +static void handle_block_device_event(struct uevent *uevent) +{ + const char *base = "/dev/block/"; + const char *name; + char devpath[96]; + char **links = NULL; + + name = parse_device_name(uevent, 64); + if (!name) + return; + + snprintf(devpath, sizeof(devpath), "%s%s", base, name); + mkdir(base, 0755); + + if (!strncmp(uevent->path, "/devices/platform/", 18)) + links = parse_platform_block_device(uevent); + + handle_device(uevent->action, devpath, uevent->path, 1, + uevent->major, uevent->minor, links); +} + +static void handle_generic_device_event(struct uevent *uevent) +{ + char *base; + const char *name; + char devpath[96] = {0}; + char **links = NULL; + + name = parse_device_name(uevent, 64); + if (!name) + return; + + if (!strncmp(uevent->subsystem, "usb", 3)) { + if (!strcmp(uevent->subsystem, "usb")) { + /* This imitates the file system that would be created + * if we were using devfs instead. + * Minors are broken up into groups of 128, starting at "001" + */ + int bus_id = uevent->minor / 128 + 1; + int device_id = uevent->minor % 128 + 1; + /* build directories */ + mkdir("/dev/bus", 0755); + mkdir("/dev/bus/usb", 0755); + snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id); + mkdir(devpath, 0755); + snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id); + } else { + /* ignore other USB events */ + return; + } + } else if (!strncmp(uevent->subsystem, "graphics", 8)) { + base = "/dev/graphics/"; + mkdir(base, 0755); + } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) { + base = "/dev/oncrpc/"; + mkdir(base, 0755); + } else if (!strncmp(uevent->subsystem, "adsp", 4)) { + base = "/dev/adsp/"; + mkdir(base, 0755); + } else if (!strncmp(uevent->subsystem, "msm_camera", 10)) { + base = "/dev/msm_camera/"; + mkdir(base, 0755); + } else if(!strncmp(uevent->subsystem, "input", 5)) { + base = "/dev/input/"; + mkdir(base, 0755); + } else if(!strncmp(uevent->subsystem, "mtd", 3)) { + base = "/dev/mtd/"; + mkdir(base, 0755); + } else if(!strncmp(uevent->subsystem, "sound", 5)) { + base = "/dev/snd/"; + mkdir(base, 0755); + } else if(!strncmp(uevent->subsystem, "misc", 4) && + !strncmp(name, "log_", 4)) { + base = "/dev/log/"; + mkdir(base, 0755); + name += 4; + } else + base = "/dev/"; + links = get_character_device_symlinks(uevent); + + if (!devpath[0]) + snprintf(devpath, sizeof(devpath), "%s%s", base, name); + + handle_device(uevent->action, devpath, uevent->path, 0, + uevent->major, uevent->minor, links); +} + +static void handle_device_event(struct uevent *uevent) +{ + if (!strcmp(uevent->action,"add")) + fixup_sys_perms(uevent->path); + + if (!strncmp(uevent->subsystem, "block", 5)) { + handle_block_device_event(uevent); + } else if (!strncmp(uevent->subsystem, "platform", 8)) { + handle_platform_device_event(uevent); + } else { + handle_generic_device_event(uevent); + } +} + static int load_firmware(int fw_fd, int loading_fd, int data_fd) { struct stat st; @@ -553,13 +641,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) @@ -589,19 +683,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: @@ -622,7 +726,6 @@ root_free_out: static void handle_firmware_event(struct uevent *uevent) { pid_t pid; - int status; int ret; if(strcmp(uevent->subsystem, "firmware")) @@ -636,10 +739,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); } } @@ -648,7 +747,7 @@ void handle_device_fd() { char msg[UEVENT_MSG_LEN+2]; int n; - while ((n = uevent_checked_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) { + while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) { if(n >= UEVENT_MSG_LEN) /* overflow -- discard */ continue; @@ -721,7 +820,8 @@ void device_init(void) struct stat info; int fd; - device_fd = open_uevent_socket(); + /* is 64K enough? udev uses 16MB! */ + device_fd = uevent_open_socket(64*1024, true); if(device_fd < 0) return; diff --git a/init/init.c b/init/init.c index bb27c4e..7b4a963 100755 --- a/init/init.c +++ b/init/init.c @@ -33,6 +33,7 @@ #include <sys/un.h> #include <libgen.h> +#include <cutils/list.h> #include <cutils/sockets.h> #include <cutils/iosched_policy.h> #include <private/android_filesystem_config.h> @@ -42,7 +43,6 @@ #include "devices.h" #include "init.h" -#include "list.h" #include "log.h" #include "property_service.h" #include "bootchart.h" @@ -92,7 +92,7 @@ static const char *ENV[32]; int add_environment(const char *key, const char *val) { int n; - + for (n = 0; n < 31; n++) { if (!ENV[n]) { size_t len = strlen(key) + strlen(val) + 2; @@ -156,7 +156,7 @@ void service_start(struct service *svc, const char *dynamic_args) */ svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET)); svc->time_started = 0; - + /* running processes require no additional work -- if * they're in the process of exiting, we've ensured * that they will immediately restart on exit, unless @@ -381,7 +381,7 @@ static void msg_start(const char *name) svc = service_find_by_name(tmp); } - + if (svc) { service_start(svc, args); } else { @@ -455,43 +455,11 @@ static void import_kernel_nv(char *name, int in_qemu) } } -static void import_kernel_cmdline(int in_qemu) -{ - char cmdline[1024]; - char *ptr; - int fd; - - fd = open("/proc/cmdline", O_RDONLY); - if (fd >= 0) { - int n = read(fd, cmdline, 1023); - if (n < 0) n = 0; - - /* get rid of trailing newline, it happens */ - if (n > 0 && cmdline[n-1] == '\n') n--; - - cmdline[n] = 0; - close(fd); - } else { - cmdline[0] = 0; - } - - ptr = cmdline; - while (ptr && *ptr) { - char *x = strchr(ptr, ' '); - if (x != 0) *x++ = 0; - import_kernel_nv(ptr, in_qemu); - ptr = x; - } - - /* don't expose the raw commandline to nonpriv processes */ - chmod("/proc/cmdline", 0440); -} - static struct command *get_first_command(struct action *act) { struct listnode *node; node = list_head(&act->commands); - if (!node) + if (!node || list_empty(&act->commands)) return NULL; return node_to_item(node, struct command, clist); @@ -548,8 +516,12 @@ static int wait_for_coldboot_done_action(int nargs, char **args) static int property_init_action(int nargs, char **args) { + bool load_defaults = true; + INFO("property init\n"); - property_init(); + if (!strcmp(bootmode, "charger")) + load_defaults = false; + property_init(load_defaults); return 0; } @@ -605,7 +577,7 @@ static int set_init_properties_action(int nargs, char **args) char tmp[PROP_VALUE_MAX]; if (qemu[0]) - import_kernel_cmdline(1); + import_kernel_cmdline(1, import_kernel_nv); if (!strcmp(bootmode,"factory")) property_set("ro.factorytest", "1"); @@ -651,6 +623,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; } @@ -710,6 +686,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. @@ -717,14 +696,15 @@ int main(int argc, char **argv) * talk to the outside world. */ open_devnull_stdio(); - log_init(); - + klog_init(); + INFO("reading config file\n"); init_parse_config_file("/init.rc"); /* pull the kernel commandline and ramdisk properties file in */ - import_kernel_cmdline(0); - + import_kernel_cmdline(0, import_kernel_nv); + /* don't expose the raw commandline to nonpriv processes */ + chmod("/proc/cmdline", 0440); get_hardware_name(hardware, &revision); snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); init_parse_config_file(tmp); @@ -737,20 +717,27 @@ int main(int argc, char **argv) queue_builtin_action(console_init_action, "console_init"); queue_builtin_action(set_init_properties_action, "set_init_properties"); - /* execute all the boot actions to get us started */ + /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); - action_for_each_trigger("early-fs", action_add_queue_tail); - action_for_each_trigger("fs", action_add_queue_tail); - action_for_each_trigger("post-fs", action_add_queue_tail); - action_for_each_trigger("post-fs-data", action_add_queue_tail); + + /* skip mounting filesystems in charger mode */ + if (strcmp(bootmode, "charger") != 0) { + action_for_each_trigger("early-fs", action_add_queue_tail); + action_for_each_trigger("fs", action_add_queue_tail); + action_for_each_trigger("post-fs", action_add_queue_tail); + action_for_each_trigger("post-fs-data", action_add_queue_tail); + } queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); queue_builtin_action(check_startup_action, "check_startup"); - /* execute all the boot actions to get us started */ - action_for_each_trigger("early-boot", action_add_queue_tail); - action_for_each_trigger("boot", action_add_queue_tail); + if (!strcmp(bootmode, "charger")) { + action_for_each_trigger("charger", action_add_queue_tail); + } else { + action_for_each_trigger("early-boot", action_add_queue_tail); + action_for_each_trigger("boot", action_add_queue_tail); + } /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers"); diff --git a/init/init.h b/init/init.h index 05cdfaa..2d98c7c 100644 --- a/init/init.h +++ b/init/init.h @@ -17,7 +17,7 @@ #ifndef _INIT_INIT_H #define _INIT_INIT_H -#include "list.h" +#include <cutils/list.h> #include <sys/stat.h> diff --git a/init/init_parser.c b/init/init_parser.c index e8e65ac..fa813b9 100644 --- a/init/init_parser.c +++ b/init/init_parser.c @@ -27,11 +27,11 @@ #include "parser.h" #include "init_parser.h" #include "log.h" -#include "list.h" #include "property_service.h" #include "util.h" #include <cutils/iosched_policy.h> +#include <cutils/list.h> #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> @@ -179,6 +179,14 @@ void parse_new_section(struct parse_state *state, int kw, return; } break; + case K_import: + if (nargs != 2) { + ERROR("single argument needed for import\n"); + } else { + int ret = init_parse_config_file(args[1]); + if (ret) + ERROR("could not import file %s\n", args[1]); + } } state->parse_line = parse_line_no_op; } @@ -347,7 +355,8 @@ void queue_property_triggers(const char *name, const char *value) if (!strncmp(name, test, name_length) && test[name_length] == '=' && - !strcmp(test + name_length + 1, value)) { + (!strcmp(test + name_length + 1, value) || + !strcmp(test + name_length + 1, "*"))) { action_add_queue_tail(act); } } @@ -377,7 +386,8 @@ void queue_all_property_triggers() /* does the property exist, and match the trigger value? */ value = property_get(prop_name); - if (value && !strcmp(equals + 1, value)) { + if (value && (!strcmp(equals + 1, value) || + !strcmp(equals + 1, "*"))) { action_add_queue_tail(act); } } diff --git a/init/keywords.h b/init/keywords.h index 95acd01..3e3733f 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -11,7 +11,6 @@ int do_export(int nargs, char **args); int do_hostname(int nargs, char **args); int do_ifup(int nargs, char **args); int do_insmod(int nargs, char **args); -int do_import(int nargs, char **args); int do_mkdir(int nargs, char **args); int do_mount(int nargs, char **args); int do_restart(int nargs, char **args); @@ -54,7 +53,7 @@ enum { KEYWORD(hostname, COMMAND, 1, do_hostname) KEYWORD(ifup, COMMAND, 1, do_ifup) KEYWORD(insmod, COMMAND, 1, do_insmod) - KEYWORD(import, COMMAND, 1, do_import) + KEYWORD(import, SECTION, 1, 0) KEYWORD(keycodes, OPTION, 0, 0) KEYWORD(mkdir, COMMAND, 1, do_mkdir) KEYWORD(mount, COMMAND, 3, do_mount) diff --git a/init/list.h b/init/list.h deleted file mode 100644 index 7b9ef32..0000000 --- a/init/list.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _INIT_LIST_H_ -#define _INIT_LIST_H_ - -#include <stddef.h> - -struct listnode -{ - struct listnode *next; - struct listnode *prev; -}; - -#define node_to_item(node, container, member) \ - (container *) (((char*) (node)) - offsetof(container, member)) - -#define list_declare(name) \ - struct listnode name = { \ - .next = &name, \ - .prev = &name, \ - } - -#define list_for_each(node, list) \ - for (node = (list)->next; node != (list); node = node->next) - -#define list_for_each_reverse(node, list) \ - for (node = (list)->prev; node != (list); node = node->prev) - -void list_init(struct listnode *list); -void list_add_tail(struct listnode *list, struct listnode *item); -void list_remove(struct listnode *item); - -#define list_empty(list) ((list) == (list)->next) -#define list_head(list) ((list)->next) -#define list_tail(list) ((list)->prev) - -#endif @@ -17,17 +17,12 @@ #ifndef _INIT_LOG_H_ #define _INIT_LOG_H_ -void log_init(void); -void log_set_level(int level); -void log_close(void); -void log_write(int level, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); +#include <cutils/klog.h> -#define ERROR(x...) log_write(3, "<3>init: " x) -#define NOTICE(x...) log_write(5, "<5>init: " x) -#define INFO(x...) log_write(6, "<6>init: " x) +#define ERROR(x...) KLOG_ERROR("init", x) +#define NOTICE(x...) KLOG_NOTICE("init", x) +#define INFO(x...) KLOG_INFO("init", x) -#define LOG_DEFAULT_LEVEL 3 /* messages <= this level are logged */ #define LOG_UEVENTS 0 /* log uevent messages if 1. verbose */ #endif diff --git a/init/parser.c b/init/parser.c index 3c2ec00..48e7aec 100644 --- a/init/parser.c +++ b/init/parser.c @@ -3,7 +3,6 @@ #include <string.h> #include "parser.h" -#include "list.h" #include "log.h" #define RAW(x...) log_write(6, x) diff --git a/init/property_service.c b/init/property_service.c index c8d6c09..6733437 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -62,10 +62,13 @@ struct { { "net.gprs.", AID_RADIO, 0 }, { "net.ppp", AID_RADIO, 0 }, { "net.qmi", AID_RADIO, 0 }, + { "net.lte", AID_RADIO, 0 }, + { "net.cdma", AID_RADIO, 0 }, { "ril.", AID_RADIO, 0 }, { "gsm.", AID_RADIO, 0 }, { "persist.radio", AID_RADIO, 0 }, { "net.dns", AID_RADIO, 0 }, + { "sys.usb.config", AID_RADIO, 0 }, { "net.", AID_SYSTEM, 0 }, { "dev.", AID_SYSTEM, 0 }, { "runtime.", AID_SYSTEM, 0 }, @@ -75,8 +78,6 @@ struct { { "wlan.", AID_SYSTEM, 0 }, { "dhcp.", AID_SYSTEM, 0 }, { "dhcp.", AID_DHCP, 0 }, - { "vpn.", AID_SYSTEM, 0 }, - { "vpn.", AID_VPN, 0 }, { "debug.", AID_SHELL, 0 }, { "log.", AID_SHELL, 0 }, { "service.adb.root", AID_SHELL, 0 }, @@ -374,11 +375,11 @@ void handle_property_set_fd() return; } - r = recv(s, &msg, sizeof(msg), 0); + r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0)); if(r != sizeof(prop_msg)) { + ERROR("sys_prop: mis-match msg size recieved: %d expected: %d errno: %d\n", + r, sizeof(prop_msg), errno); close(s); - ERROR("sys_prop: mis-match msg size recieved: %d expected: %d\n", - r, sizeof(prop_msg)); return; } @@ -504,10 +505,11 @@ static void load_persistent_properties() persistent_properties_loaded = 1; } -void property_init(void) +void property_init(bool load_defaults) { init_property_area(); - load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT); + if (load_defaults) + load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT); } int properties_inited(void) diff --git a/init/property_service.h b/init/property_service.h index bc97cc4..37c2788 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -17,8 +17,10 @@ #ifndef _INIT_PROPERTY_H #define _INIT_PROPERTY_H +#include <stdbool.h> + extern void handle_property_set_fd(void); -extern void property_init(void); +extern void property_init(bool load_defaults); extern void load_persist_props(void); extern void start_property_service(void); void get_property_workspace(int *fd, int *sz); diff --git a/init/signal_handler.c b/init/signal_handler.c index f89d058..b170132 100644 --- a/init/signal_handler.c +++ b/init/signal_handler.c @@ -24,9 +24,9 @@ #include <sys/wait.h> #include <cutils/sockets.h> #include <cutils/android_reboot.h> +#include <cutils/list.h> #include "init.h" -#include "list.h" #include "util.h" #include "log.h" diff --git a/init/ueventd.c b/init/ueventd.c index 0e97be7..ecf3b9b 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" @@ -31,17 +33,43 @@ static char hardware[32]; static unsigned revision = 0; +static void import_kernel_nv(char *name, int in_qemu) +{ + if (*name != '\0') { + char *value = strchr(name, '='); + if (value != NULL) { + *value++ = 0; + if (!strcmp(name,"androidboot.hardware")) + { + strlcpy(hardware, value, sizeof(hardware)); + } + } + } +} + int ueventd_main(int argc, char **argv) { struct pollfd ufd; 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(); + klog_init(); INFO("starting ueventd\n"); + /* Respect hardware passed in through the kernel cmd line. Here we will look + * for androidboot.hardware param in kernel cmdline, and save its value in + * hardware[]. */ + import_kernel_cmdline(0, import_kernel_nv); + get_hardware_name(hardware, &revision); ueventd_parse_config_file("/ueventd.rc"); diff --git a/init/ueventd_parser.c b/init/ueventd_parser.c index 0dd8b4d..3e60df5 100644 --- a/init/ueventd_parser.c +++ b/init/ueventd_parser.c @@ -22,7 +22,6 @@ #include "ueventd_parser.h" #include "parser.h" #include "log.h" -#include "list.h" #include "util.h" static void parse_line_device(struct parse_state *state, int nargs, char **args); diff --git a/init/util.c b/init/util.c index d8ec88e..13c9ca2 100755 --- a/init/util.c +++ b/init/util.c @@ -34,45 +34,8 @@ #include <private/android_filesystem_config.h> #include "log.h" -#include "list.h" #include "util.h" -static int log_fd = -1; -/* Inital log level before init.rc is parsed and this this is reset. */ -static int log_level = LOG_DEFAULT_LEVEL; - - -void log_set_level(int level) { - log_level = level; -} - -void log_init(void) -{ - static const char *name = "/dev/__kmsg__"; - if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) { - log_fd = open(name, O_WRONLY); - fcntl(log_fd, F_SETFD, FD_CLOEXEC); - unlink(name); - } -} - -#define LOG_BUF_MAX 512 - -void log_write(int level, const char *fmt, ...) -{ - char buf[LOG_BUF_MAX]; - va_list ap; - - if (level > log_level) return; - if (log_fd < 0) return; - - va_start(ap, fmt); - vsnprintf(buf, LOG_BUF_MAX, fmt, ap); - buf[LOG_BUF_MAX - 1] = 0; - va_end(ap); - write(log_fd, buf, strlen(buf)); -} - /* * android_name_to_id - returns the integer uid/gid associated with the given * name, or -1U on error. @@ -192,26 +155,6 @@ oops: return 0; } -void list_init(struct listnode *node) -{ - node->next = node; - node->prev = node; -} - -void list_add_tail(struct listnode *head, struct listnode *item) -{ - item->next = head; - item->prev = head->prev; - head->prev->next = item; - head->prev = item; -} - -void list_remove(struct listnode *item) -{ - item->next->prev = item->prev; - item->prev->next = item->next; -} - #define MAX_MTD_PARTITIONS 16 static struct { @@ -456,3 +399,33 @@ void get_hardware_name(char *hardware, unsigned int *revision) } } } + +void import_kernel_cmdline(int in_qemu, + void (*import_kernel_nv)(char *name, int in_qemu)) +{ + char cmdline[1024]; + char *ptr; + int fd; + + fd = open("/proc/cmdline", O_RDONLY); + if (fd >= 0) { + int n = read(fd, cmdline, 1023); + if (n < 0) n = 0; + + /* get rid of trailing newline, it happens */ + if (n > 0 && cmdline[n-1] == '\n') n--; + + cmdline[n] = 0; + close(fd); + } else { + cmdline[0] = 0; + } + + ptr = cmdline; + while (ptr && *ptr) { + char *x = strchr(ptr, ' '); + if (x != 0) *x++ = 0; + import_kernel_nv(ptr, in_qemu); + ptr = x; + } +} diff --git a/init/util.h b/init/util.h index 2e47369..9247739 100644 --- a/init/util.h +++ b/init/util.h @@ -38,4 +38,5 @@ void remove_link(const char *oldpath, const char *newpath); int wait_for_file(const char *filename, int timeout); void open_devnull_stdio(void); void get_hardware_name(char *hardware, unsigned int *revision); +void import_kernel_cmdline(int in_qemu, void (*import_kernel_nv)(char *name, int in_qemu)); #endif |