diff --git a/init/Android.mk b/init/Android.mk index ecf1bf4d5..9259fb02c 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -13,7 +13,8 @@ LOCAL_SRC_FILES:= \ logo.c \ keychords.c \ signal_handler.c \ - init_parser.c + init_parser.c \ + ueventd.c ifeq ($(strip $(INIT_BOOTCHART)),true) LOCAL_SRC_FILES += bootchart.c @@ -28,9 +29,20 @@ LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) LOCAL_STATIC_LIBRARIES := libcutils libc -#LOCAL_STATIC_LIBRARIES := libcutils libc libminui libpixelflinger_static -#LOCAL_STATIC_LIBRARIES += libminzip libunz libamend libmtdutils libmincrypt -#LOCAL_STATIC_LIBRARIES += libstdc++_static - include $(BUILD_EXECUTABLE) +# Make a symlink from /sbin/ueventd to /init +SYMLINKS := $(TARGET_ROOT_OUT)/sbin/ueventd +$(SYMLINKS): INIT_BINARY := $(LOCAL_MODULE) +$(SYMLINKS): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk + @echo "Symlink: $@ -> /$(INIT_BINARY)" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf /$(INIT_BINARY) $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS) + +# We need this so that the installed files could be picked up based on the +# local module name +ALL_MODULES.$(LOCAL_MODULE).INSTALLED := \ + $(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(SYMLINKS) diff --git a/init/builtins.c b/init/builtins.c index d87d5e400..4326ebcc8 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -557,33 +557,6 @@ int do_loglevel(int nargs, char **args) { return -1; } -int do_device(int nargs, char **args) { - int len; - char tmp[64]; - char *source = args[1]; - int prefix = 0; - - if (nargs != 5) - return -1; - /* Check for wildcard '*' at the end which indicates a prefix. */ - len = strlen(args[1]) - 1; - if (args[1][len] == '*') { - args[1][len] = '\0'; - prefix = 1; - } - /* If path starts with mtd@ lookup the mount number. */ - if (!strncmp(source, "mtd@", 4)) { - int n = mtd_name_to_number(source + 4); - if (n >= 0) { - snprintf(tmp, sizeof(tmp), "/dev/mtd/mtd%d", n); - source = tmp; - } - } - add_devperms_partners(source, get_mode(args[2]), decode_uid(args[3]), - decode_uid(args[4]), prefix); - return 0; -} - int do_wait(int nargs, char **args) { if (nargs == 2) { diff --git a/init/devices.c b/init/devices.c index 452e7e785..3e1c524fe 100644 --- a/init/devices.c +++ b/init/devices.c @@ -738,6 +738,8 @@ static void coldboot(const char *path) void device_init(void) { suseconds_t t0, t1; + struct stat info; + int fd; device_fd = open_uevent_socket(); if(device_fd < 0) @@ -746,13 +748,18 @@ void device_init(void) fcntl(device_fd, F_SETFD, FD_CLOEXEC); fcntl(device_fd, F_SETFL, O_NONBLOCK); - t0 = get_usecs(); - coldboot("/sys/class"); - coldboot("/sys/block"); - coldboot("/sys/devices"); - t1 = get_usecs(); - - log_event_print("coldboot %ld uS\n", ((long) (t1 - t0))); + if (stat(coldboot_done, &info) < 0) { + t0 = get_usecs(); + coldboot("/sys/class"); + coldboot("/sys/block"); + coldboot("/sys/devices"); + t1 = get_usecs(); + fd = open(coldboot_done, O_WRONLY|O_CREAT, 0000); + close(fd); + log_event_print("coldboot %ld uS\n", ((long) (t1 - t0))); + } else { + log_event_print("skipping coldboot, already done\n"); + } } int get_device_fd() diff --git a/init/devices.h b/init/devices.h index e14f4c8a1..8593a1b85 100644 --- a/init/devices.h +++ b/init/devices.h @@ -17,11 +17,11 @@ #ifndef _INIT_DEVICES_H #define _INIT_DEVICES_H +#include + extern void handle_device_fd(); extern void device_init(void); -extern void qemu_init(void); -extern void qemu_cmdline(const char* name, const char *value); -extern int add_devperms_partners(const char *name, mode_t perm, unsigned int uid, - unsigned int gid, unsigned short prefix); +extern int add_dev_perms(const char *name, mode_t perm, unsigned int uid, + unsigned int gid, unsigned short prefix); int get_device_fd(); #endif /* _INIT_DEVICES_H */ diff --git a/init/init.c b/init/init.c index 50f8f4558..4f4059b8d 100755 --- a/init/init.c +++ b/init/init.c @@ -31,9 +31,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -48,6 +50,7 @@ #include "keychords.h" #include "init_parser.h" #include "util.h" +#include "ueventd.h" static int property_triggers_enabled = 0; @@ -412,8 +415,6 @@ static void import_kernel_nv(char *name, int in_qemu) strlcpy(bootloader, value, sizeof(bootloader)); } else if (!strcmp(name,"androidboot.hardware")) { strlcpy(hardware, value, sizeof(hardware)); - } else { - qemu_cmdline(name, value); } } else { /* in the emulator, export any kernel option with the @@ -458,49 +459,6 @@ static void import_kernel_cmdline(int in_qemu) chmod("/proc/cmdline", 0440); } -static void get_hardware_name(void) -{ - char data[1024]; - int fd, n; - char *x, *hw, *rev; - - /* Hardware string was provided on kernel command line */ - if (hardware[0]) - return; - - fd = open("/proc/cpuinfo", O_RDONLY); - if (fd < 0) return; - - n = read(fd, data, 1023); - close(fd); - if (n < 0) return; - - data[n] = 0; - hw = strstr(data, "\nHardware"); - rev = strstr(data, "\nRevision"); - - if (hw) { - x = strstr(hw, ": "); - if (x) { - x += 2; - n = 0; - while (*x && !isspace(*x)) { - hardware[n++] = tolower(*x); - x++; - if (n == 31) break; - } - hardware[n] = 0; - } - } - - if (rev) { - x = strstr(rev, ": "); - if (x) { - revision = strtoul(x + 2, 0, 16); - } - } -} - static struct command *get_first_command(struct action *act) { struct listnode *node; @@ -549,32 +507,14 @@ void execute_one_command(void) INFO("command '%s' r=%d\n", cur_command->args[0], ret); } -void open_devnull_stdio(void) +static int wait_for_coldboot_done_action(int nargs, char **args) { - int fd; - static const char *name = "/dev/__null__"; - if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) { - fd = open(name, O_RDWR); - unlink(name); - if (fd >= 0) { - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - if (fd > 2) { - close(fd); - } - return; - } - } - - exit(1); -} - -static int device_init_action(int nargs, char **args) -{ - INFO("device init\n"); - device_init(); - return 0; + int ret; + INFO("wait for %s\n", coldboot_done); + ret = wait_for_file(coldboot_done, COMMAND_RETRY_TIMEOUT); + if (ret) + ERROR("Timed out waiting for %s\n", coldboot_done); + return ret; } static int property_init_action(int nargs, char **args) @@ -677,8 +617,7 @@ static int signal_init_action(int nargs, char **args) static int check_startup_action(int nargs, char **args) { /* make sure we actually have all the pieces we need */ - if ((get_device_fd() < 0) || - (get_property_set_fd() < 0) || + if ((get_property_set_fd() < 0) || (get_signal_fd() < 0)) { ERROR("init startup failure\n"); exit(1); @@ -715,11 +654,13 @@ int main(int argc, char **argv) char *tmpdev; char* debuggable; char tmp[32]; - int device_fd_init = 0; int property_set_fd_init = 0; int signal_fd_init = 0; int keychord_fd_init = 0; + if (!strcmp(basename(argv[0]), "ueventd")) + return ueventd_main(argc, argv); + /* clear the umask */ umask(0); @@ -751,16 +692,15 @@ int main(int argc, char **argv) init_parse_config_file("/init.rc"); /* pull the kernel commandline and ramdisk properties file in */ - qemu_init(); import_kernel_cmdline(0); - get_hardware_name(); + get_hardware_name(hardware, &revision); snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); init_parse_config_file(tmp); action_for_each_trigger("early-init", action_add_queue_tail); - queue_builtin_action(device_init_action, "device_init"); + queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(property_init_action, "property_init"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); @@ -794,13 +734,6 @@ int main(int argc, char **argv) execute_one_command(); restart_processes(); - if (!device_fd_init && get_device_fd() > 0) { - ufds[fd_count].fd = get_device_fd(); - ufds[fd_count].events = POLLIN; - ufds[fd_count].revents = 0; - fd_count++; - device_fd_init = 1; - } if (!property_set_fd_init && get_property_set_fd() > 0) { ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; @@ -849,9 +782,7 @@ int main(int argc, char **argv) for (i = 0; i < fd_count; i++) { if (ufds[i].revents == POLLIN) { - if (ufds[i].fd == get_device_fd()) - handle_device_fd(); - else if (ufds[i].fd == get_property_set_fd()) + if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) handle_keychord(); diff --git a/init/keywords.h b/init/keywords.h index 1f4a77d0d..25315d835 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -27,7 +27,6 @@ int do_copy(int nargs, char **args); int do_chown(int nargs, char **args); int do_chmod(int nargs, char **args); int do_loglevel(int nargs, char **args); -int do_device(int nargs, char **args); int do_wait(int nargs, char **args); #define __MAKE_KEYWORD_ENUM__ #define KEYWORD(symbol, flags, nargs, func) K_##symbol, @@ -76,7 +75,6 @@ enum { KEYWORD(chown, COMMAND, 2, do_chown) KEYWORD(chmod, COMMAND, 2, do_chmod) KEYWORD(loglevel, COMMAND, 1, do_loglevel) - KEYWORD(device, COMMAND, 4, do_device) KEYWORD(ioprio, OPTION, 0, 0) #ifdef __MAKE_KEYWORD_ENUM__ KEYWORD_COUNT, diff --git a/init/ueventd.c b/init/ueventd.c new file mode 100644 index 000000000..5a2222aad --- /dev/null +++ b/init/ueventd.c @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#include + +#include "ueventd.h" +#include "log.h" +#include "util.h" +#include "devices.h" + +int ueventd_main(int argc, char **argv) +{ + struct pollfd ufd; + int nr; + + open_devnull_stdio(); + log_init(); + + INFO("starting ueventd\n"); + + device_init(); + + ufd.events = POLLIN; + ufd.fd = get_device_fd(); + + while(1) { + ufd.revents = 0; + nr = poll(&ufd, 1, -1); + if (nr <= 0) + continue; + if (ufd.revents == POLLIN) + handle_device_fd(); + } +} diff --git a/init/ueventd.h b/init/ueventd.h new file mode 100644 index 000000000..9066e4780 --- /dev/null +++ b/init/ueventd.h @@ -0,0 +1,22 @@ +/* + * 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_UEVENTD_H_ +#define _INIT_UEVENTD_H_ + +int ueventd_main(int argc, char **argv); + +#endif diff --git a/init/util.c b/init/util.c index 761c51b38..377754b79 100644 --- a/init/util.c +++ b/init/util.c @@ -35,6 +35,7 @@ #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. */ @@ -390,3 +391,67 @@ int wait_for_file(const char *filename, int timeout) return ret; } + +void open_devnull_stdio(void) +{ + int fd; + static const char *name = "/dev/__null__"; + if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) { + fd = open(name, O_RDWR); + unlink(name); + if (fd >= 0) { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + if (fd > 2) { + close(fd); + } + return; + } + } + + exit(1); +} + +void get_hardware_name(char *hardware, unsigned int *revision) +{ + char data[1024]; + int fd, n; + char *x, *hw, *rev; + + /* Hardware string was provided on kernel command line */ + if (hardware[0]) + return; + + fd = open("/proc/cpuinfo", O_RDONLY); + if (fd < 0) return; + + n = read(fd, data, 1023); + close(fd); + if (n < 0) return; + + data[n] = 0; + hw = strstr(data, "\nHardware"); + rev = strstr(data, "\nRevision"); + + if (hw) { + x = strstr(hw, ": "); + if (x) { + x += 2; + n = 0; + while (*x && !isspace(*x)) { + hardware[n++] = tolower(*x); + x++; + if (n == 31) break; + } + hardware[n] = 0; + } + } + + if (rev) { + x = strstr(rev, ": "); + if (x) { + *revision = strtoul(x + 2, 0, 16); + } + } +} diff --git a/init/util.h b/init/util.h index bf7928d3d..5fcd2ec33 100644 --- a/init/util.h +++ b/init/util.h @@ -17,6 +17,11 @@ #ifndef _INIT_UTIL_H_ #define _INIT_UTIL_H_ +#include +#include + +static const char *coldboot_done = "/dev/.coldboot_done"; + int mtd_name_to_number(const char *name); int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid); @@ -29,4 +34,6 @@ void sanitize(char *p); void make_link(const char *oldpath, const char *newpath); 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); #endif diff --git a/rootdir/init.rc b/rootdir/init.rc index 04e396093..8d8955b6f 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -1,3 +1,5 @@ +on early-init + start ueventd on init @@ -259,6 +261,9 @@ on boot service console /system/bin/sh console +service ueventd /sbin/ueventd + critical + # adbd is controlled by the persist.service.adb.enable system property service adbd /sbin/adbd disabled