init: Move uevent handling to an external ueventd process
Change-Id: Iea6c56013062ade633a1754f7bcf8cf09b3dedc1
This commit is contained in:
parent
6310a8261c
commit
f83d0b9af5
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
#ifndef _INIT_DEVICES_H
|
||||
#define _INIT_DEVICES_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
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 */
|
||||
|
|
103
init/init.c
103
init/init.c
|
@ -31,9 +31,11 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <cutils/sockets.h>
|
||||
#include <cutils/iosched_policy.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sys/system_properties.h>
|
||||
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <poll.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
|
@ -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
|
65
init/util.c
65
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
#ifndef _INIT_UTIL_H_
|
||||
#define _INIT_UTIL_H_
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue