summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
Diffstat (limited to 'init')
-rw-r--r--init/builtins.c59
-rw-r--r--init/devices.c374
-rwxr-xr-xinit/init.c89
-rw-r--r--init/init.h2
-rw-r--r--init/init_parser.c16
-rw-r--r--init/keywords.h3
-rw-r--r--init/list.h51
-rw-r--r--init/log.h13
-rw-r--r--init/parser.c1
-rw-r--r--init/property_service.c16
-rw-r--r--init/property_service.h4
-rw-r--r--init/signal_handler.c2
-rw-r--r--init/ueventd.c30
-rw-r--r--init/ueventd_parser.c1
-rwxr-xr-xinit/util.c87
-rw-r--r--init/util.h1
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
diff --git a/init/log.h b/init/log.h
index 3d93965..4aac3df 100644
--- a/init/log.h
+++ b/init/log.h
@@ -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