init.c revision 038862e152b98d0c0f355c6802beaa1ed59cefbe
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <ctype.h>
23#include <signal.h>
24#include <sys/wait.h>
25#include <sys/mount.h>
26#include <sys/stat.h>
27#include <sys/poll.h>
28#include <time.h>
29#include <errno.h>
30#include <stdarg.h>
31#include <mtd/mtd-user.h>
32#include <sys/types.h>
33#include <sys/socket.h>
34#include <sys/un.h>
35#include <sys/reboot.h>
36
37#include <cutils/sockets.h>
38#include <termios.h>
39#include <linux/kd.h>
40#include <linux/keychord.h>
41
42#include <sys/system_properties.h>
43
44#include "devices.h"
45#include "init.h"
46#include "property_service.h"
47#include "bootchart.h"
48
49static int property_triggers_enabled = 0;
50
51#if BOOTCHART
52static int   bootchart_count;
53#endif
54
55static char console[32];
56static char serialno[32];
57static char bootmode[32];
58static char baseband[32];
59static char carrier[32];
60static char bootloader[32];
61static char hardware[32];
62static unsigned revision = 0;
63static char qemu[32];
64static struct input_keychord *keychords = 0;
65static int keychords_count = 0;
66static int keychords_length = 0;
67
68static void drain_action_queue(void);
69
70static void notify_service_state(const char *name, const char *state)
71{
72    char pname[PROP_NAME_MAX];
73    int len = strlen(name);
74    if ((len + 10) > PROP_NAME_MAX)
75        return;
76    snprintf(pname, sizeof(pname), "init.svc.%s", name);
77    property_set(pname, state);
78}
79
80static int have_console;
81static char *console_name = "/dev/console";
82static time_t process_needs_restart;
83
84static const char *ENV[32];
85
86/* add_environment - add "key=value" to the current environment */
87int add_environment(const char *key, const char *val)
88{
89    int n;
90
91    for (n = 0; n < 31; n++) {
92        if (!ENV[n]) {
93            size_t len = strlen(key) + strlen(val) + 2;
94            char *entry = malloc(len);
95            snprintf(entry, len, "%s=%s", key, val);
96            ENV[n] = entry;
97            return 0;
98        }
99    }
100
101    return 1;
102}
103
104static void zap_stdio(void)
105{
106    int fd;
107    fd = open("/dev/null", O_RDWR);
108    dup2(fd, 0);
109    dup2(fd, 1);
110    dup2(fd, 2);
111    close(fd);
112}
113
114static void open_console()
115{
116    int fd;
117    if ((fd = open(console_name, O_RDWR)) < 0) {
118        fd = open("/dev/null", O_RDWR);
119    }
120    dup2(fd, 0);
121    dup2(fd, 1);
122    dup2(fd, 2);
123    close(fd);
124}
125
126/*
127 * gettime() - returns the time in seconds of the system's monotonic clock or
128 * zero on error.
129 */
130static time_t gettime(void)
131{
132    struct timespec ts;
133    int ret;
134
135    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
136    if (ret < 0) {
137        ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
138        return 0;
139    }
140
141    return ts.tv_sec;
142}
143
144static void publish_socket(const char *name, int fd)
145{
146    char key[64] = ANDROID_SOCKET_ENV_PREFIX;
147    char val[64];
148
149    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
150            name,
151            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
152    snprintf(val, sizeof(val), "%d", fd);
153    add_environment(key, val);
154
155    /* make sure we don't close-on-exec */
156    fcntl(fd, F_SETFD, 0);
157}
158
159void service_start(struct service *svc)
160{
161    struct stat s;
162    pid_t pid;
163    int needs_console;
164    int n;
165
166        /* starting a service removes it from the disabled
167         * state and immediately takes it out of the restarting
168         * state if it was in there
169         */
170    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));
171    svc->time_started = 0;
172
173        /* running processes require no additional work -- if
174         * they're in the process of exiting, we've ensured
175         * that they will immediately restart on exit, unless
176         * they are ONESHOT
177         */
178    if (svc->flags & SVC_RUNNING) {
179        return;
180    }
181
182    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
183    if (needs_console && (!have_console)) {
184        ERROR("service '%s' requires console\n", svc->name);
185        svc->flags |= SVC_DISABLED;
186        return;
187    }
188
189    if (stat(svc->args[0], &s) != 0) {
190        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
191        svc->flags |= SVC_DISABLED;
192        return;
193    }
194
195    NOTICE("starting '%s'\n", svc->name);
196
197    pid = fork();
198
199    if (pid == 0) {
200        struct socketinfo *si;
201        struct svcenvinfo *ei;
202        char tmp[32];
203        int fd, sz;
204
205        get_property_workspace(&fd, &sz);
206        sprintf(tmp, "%d,%d", dup(fd), sz);
207        add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
208
209        for (ei = svc->envvars; ei; ei = ei->next)
210            add_environment(ei->name, ei->value);
211
212        for (si = svc->sockets; si; si = si->next) {
213            int s = create_socket(si->name,
214                                  !strcmp(si->type, "dgram") ?
215                                  SOCK_DGRAM : SOCK_STREAM,
216                                  si->perm, si->uid, si->gid);
217            if (s >= 0) {
218                publish_socket(si->name, s);
219            }
220        }
221
222        if (needs_console) {
223            setsid();
224            open_console();
225        } else {
226            zap_stdio();
227        }
228
229#if 0
230        for (n = 0; svc->args[n]; n++) {
231            INFO("args[%d] = '%s'\n", n, svc->args[n]);
232        }
233        for (n = 0; ENV[n]; n++) {
234            INFO("env[%d] = '%s'\n", n, ENV[n]);
235        }
236#endif
237
238        setpgid(0, getpid());
239
240    /* as requested, set our gid, supplemental gids, and uid */
241        if (svc->gid) {
242            setgid(svc->gid);
243        }
244        if (svc->nr_supp_gids) {
245            setgroups(svc->nr_supp_gids, svc->supp_gids);
246        }
247        if (svc->uid) {
248            setuid(svc->uid);
249        }
250
251        if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
252            ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
253        }
254        _exit(127);
255    }
256
257    if (pid < 0) {
258        ERROR("failed to start '%s'\n", svc->name);
259        svc->pid = 0;
260        return;
261    }
262
263    svc->time_started = gettime();
264    svc->pid = pid;
265    svc->flags |= SVC_RUNNING;
266
267    notify_service_state(svc->name, "running");
268}
269
270void service_stop(struct service *svc)
271{
272        /* we are no longer running, nor should we
273         * attempt to restart
274         */
275    svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
276
277        /* if the service has not yet started, prevent
278         * it from auto-starting with its class
279         */
280    svc->flags |= SVC_DISABLED;
281
282    if (svc->pid) {
283        NOTICE("service '%s' is being killed\n", svc->name);
284        kill(-svc->pid, SIGTERM);
285        notify_service_state(svc->name, "stopping");
286    } else {
287        notify_service_state(svc->name, "stopped");
288    }
289}
290
291void property_changed(const char *name, const char *value)
292{
293    if (property_triggers_enabled) {
294        queue_property_triggers(name, value);
295        drain_action_queue();
296    }
297}
298
299#define CRITICAL_CRASH_THRESHOLD    4       /* if we crash >4 times ... */
300#define CRITICAL_CRASH_WINDOW       (4*60)  /* ... in 4 minutes, goto recovery*/
301
302static int wait_for_one_process(int block)
303{
304    pid_t pid;
305    int status;
306    struct service *svc;
307    struct socketinfo *si;
308    time_t now;
309    struct listnode *node;
310    struct command *cmd;
311
312    while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
313    if (pid <= 0) return -1;
314    INFO("waitpid returned pid %d, status = %08x\n", pid, status);
315
316    svc = service_find_by_pid(pid);
317    if (!svc) {
318        ERROR("untracked pid %d exited\n", pid);
319        return 0;
320    }
321
322    NOTICE("process '%s', pid %d exited\n", svc->name, pid);
323
324    if (!(svc->flags & SVC_ONESHOT)) {
325        kill(-pid, SIGKILL);
326        NOTICE("process '%s' killing any children in process group\n", svc->name);
327    }
328
329    /* remove any sockets we may have created */
330    for (si = svc->sockets; si; si = si->next) {
331        char tmp[128];
332        snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
333        unlink(tmp);
334    }
335
336    svc->pid = 0;
337    svc->flags &= (~SVC_RUNNING);
338
339        /* oneshot processes go into the disabled state on exit */
340    if (svc->flags & SVC_ONESHOT) {
341        svc->flags |= SVC_DISABLED;
342    }
343
344        /* disabled processes do not get restarted automatically */
345    if (svc->flags & SVC_DISABLED) {
346        notify_service_state(svc->name, "stopped");
347        return 0;
348    }
349
350    now = gettime();
351    if (svc->flags & SVC_CRITICAL) {
352        if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
353            if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
354                ERROR("critical process '%s' exited %d times in %d minutes; "
355                      "rebooting into recovery mode\n", svc->name,
356                      CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
357                sync();
358                __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
359                         LINUX_REBOOT_CMD_RESTART2, "recovery");
360                return 0;
361            }
362        } else {
363            svc->time_crashed = now;
364            svc->nr_crashed = 1;
365        }
366    }
367
368    /* Execute all onrestart commands for this service. */
369    list_for_each(node, &svc->onrestart.commands) {
370        cmd = node_to_item(node, struct command, clist);
371        cmd->func(cmd->nargs, cmd->args);
372    }
373    svc->flags |= SVC_RESTARTING;
374    notify_service_state(svc->name, "restarting");
375    return 0;
376}
377
378static void restart_service_if_needed(struct service *svc)
379{
380    time_t next_start_time = svc->time_started + 5;
381
382    if (next_start_time <= gettime()) {
383        svc->flags &= (~SVC_RESTARTING);
384        service_start(svc);
385        return;
386    }
387
388    if ((next_start_time < process_needs_restart) ||
389        (process_needs_restart == 0)) {
390        process_needs_restart = next_start_time;
391    }
392}
393
394static void restart_processes()
395{
396    process_needs_restart = 0;
397    service_for_each_flags(SVC_RESTARTING,
398                           restart_service_if_needed);
399}
400
401static int signal_fd = -1;
402
403static void sigchld_handler(int s)
404{
405    write(signal_fd, &s, 1);
406}
407
408static void msg_start(const char *name)
409{
410    struct service *svc = service_find_by_name(name);
411
412    if (svc) {
413        service_start(svc);
414    } else {
415        ERROR("no such service '%s'\n", name);
416    }
417}
418
419static void msg_stop(const char *name)
420{
421    struct service *svc = service_find_by_name(name);
422
423    if (svc) {
424        service_stop(svc);
425    } else {
426        ERROR("no such service '%s'\n");
427    }
428}
429
430void handle_control_message(const char *msg, const char *arg)
431{
432    if (!strcmp(msg,"start")) {
433        msg_start(arg);
434    } else if (!strcmp(msg,"stop")) {
435        msg_stop(arg);
436    } else {
437        ERROR("unknown control msg '%s'\n", msg);
438    }
439}
440
441#define MAX_MTD_PARTITIONS 16
442
443static struct {
444    char name[16];
445    int number;
446} mtd_part_map[MAX_MTD_PARTITIONS];
447
448static int mtd_part_count = -1;
449
450static void find_mtd_partitions(void)
451{
452    int fd;
453    char buf[1024];
454    char *pmtdbufp;
455    ssize_t pmtdsize;
456    int r;
457
458    fd = open("/proc/mtd", O_RDONLY);
459    if (fd < 0)
460        return;
461
462    buf[sizeof(buf) - 1] = '\0';
463    pmtdsize = read(fd, buf, sizeof(buf) - 1);
464    pmtdbufp = buf;
465    while (pmtdsize > 0) {
466        int mtdnum, mtdsize, mtderasesize;
467        char mtdname[16];
468        mtdname[0] = '\0';
469        mtdnum = -1;
470        r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
471                   &mtdnum, &mtdsize, &mtderasesize, mtdname);
472        if ((r == 4) && (mtdname[0] == '"')) {
473            char *x = strchr(mtdname + 1, '"');
474            if (x) {
475                *x = 0;
476            }
477            INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1);
478            if (mtd_part_count < MAX_MTD_PARTITIONS) {
479                strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
480                mtd_part_map[mtd_part_count].number = mtdnum;
481                mtd_part_count++;
482            } else {
483                ERROR("too many mtd partitions\n");
484            }
485        }
486        while (pmtdsize > 0 && *pmtdbufp != '\n') {
487            pmtdbufp++;
488            pmtdsize--;
489        }
490        if (pmtdsize > 0) {
491            pmtdbufp++;
492            pmtdsize--;
493        }
494    }
495    close(fd);
496}
497
498int mtd_name_to_number(const char *name)
499{
500    int n;
501    if (mtd_part_count < 0) {
502        mtd_part_count = 0;
503        find_mtd_partitions();
504    }
505    for (n = 0; n < mtd_part_count; n++) {
506        if (!strcmp(name, mtd_part_map[n].name)) {
507            return mtd_part_map[n].number;
508        }
509    }
510    return -1;
511}
512
513static void import_kernel_nv(char *name, int in_qemu)
514{
515    char *value = strchr(name, '=');
516
517    if (value == 0) return;
518    *value++ = 0;
519    if (*name == 0) return;
520
521    if (!in_qemu)
522    {
523        /* on a real device, white-list the kernel options */
524        if (!strcmp(name,"qemu")) {
525            strlcpy(qemu, value, sizeof(qemu));
526        } else if (!strcmp(name,"androidboot.console")) {
527            strlcpy(console, value, sizeof(console));
528        } else if (!strcmp(name,"androidboot.mode")) {
529            strlcpy(bootmode, value, sizeof(bootmode));
530        } else if (!strcmp(name,"androidboot.serialno")) {
531            strlcpy(serialno, value, sizeof(serialno));
532        } else if (!strcmp(name,"androidboot.baseband")) {
533            strlcpy(baseband, value, sizeof(baseband));
534        } else if (!strcmp(name,"androidboot.carrier")) {
535            strlcpy(carrier, value, sizeof(carrier));
536        } else if (!strcmp(name,"androidboot.bootloader")) {
537            strlcpy(bootloader, value, sizeof(bootloader));
538        } else if (!strcmp(name,"androidboot.hardware")) {
539            strlcpy(hardware, value, sizeof(hardware));
540        } else {
541            qemu_cmdline(name, value);
542        }
543    } else {
544        /* in the emulator, export any kernel option with the
545         * ro.kernel. prefix */
546        char  buff[32];
547        int   len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
548        if (len < (int)sizeof(buff)) {
549            property_set( buff, value );
550        }
551    }
552}
553
554static void import_kernel_cmdline(int in_qemu)
555{
556    char cmdline[1024];
557    char *ptr;
558    int fd;
559
560    fd = open("/proc/cmdline", O_RDONLY);
561    if (fd >= 0) {
562        int n = read(fd, cmdline, 1023);
563        if (n < 0) n = 0;
564
565        /* get rid of trailing newline, it happens */
566        if (n > 0 && cmdline[n-1] == '\n') n--;
567
568        cmdline[n] = 0;
569        close(fd);
570    } else {
571        cmdline[0] = 0;
572    }
573
574    ptr = cmdline;
575    while (ptr && *ptr) {
576        char *x = strchr(ptr, ' ');
577        if (x != 0) *x++ = 0;
578        import_kernel_nv(ptr, in_qemu);
579        ptr = x;
580    }
581
582        /* don't expose the raw commandline to nonpriv processes */
583    chmod("/proc/cmdline", 0440);
584}
585
586static void get_hardware_name(void)
587{
588    char data[1024];
589    int fd, n;
590    char *x, *hw, *rev;
591
592    /* Hardware string was provided on kernel command line */
593    if (hardware[0])
594        return;
595
596    fd = open("/proc/cpuinfo", O_RDONLY);
597    if (fd < 0) return;
598
599    n = read(fd, data, 1023);
600    close(fd);
601    if (n < 0) return;
602
603    data[n] = 0;
604    hw = strstr(data, "\nHardware");
605    rev = strstr(data, "\nRevision");
606
607    if (hw) {
608        x = strstr(hw, ": ");
609        if (x) {
610            x += 2;
611            n = 0;
612            while (*x && !isspace(*x)) {
613                hardware[n++] = tolower(*x);
614                x++;
615                if (n == 31) break;
616            }
617            hardware[n] = 0;
618        }
619    }
620
621    if (rev) {
622        x = strstr(rev, ": ");
623        if (x) {
624            revision = strtoul(x + 2, 0, 16);
625        }
626    }
627}
628
629static void drain_action_queue(void)
630{
631    struct listnode *node;
632    struct command *cmd;
633    struct action *act;
634    int ret;
635
636    while ((act = action_remove_queue_head())) {
637        INFO("processing action %p (%s)\n", act, act->name);
638        list_for_each(node, &act->commands) {
639            cmd = node_to_item(node, struct command, clist);
640            ret = cmd->func(cmd->nargs, cmd->args);
641            INFO("command '%s' r=%d\n", cmd->args[0], ret);
642        }
643    }
644}
645
646void open_devnull_stdio(void)
647{
648    int fd;
649    static const char *name = "/dev/__null__";
650    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
651        fd = open(name, O_RDWR);
652        unlink(name);
653        if (fd >= 0) {
654            dup2(fd, 0);
655            dup2(fd, 1);
656            dup2(fd, 2);
657            if (fd > 2) {
658                close(fd);
659            }
660            return;
661        }
662    }
663
664    exit(1);
665}
666
667void add_service_keycodes(struct service *svc)
668{
669    struct input_keychord *keychord;
670    int i, size;
671
672    if (svc->keycodes) {
673        /* add a new keychord to the list */
674        size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]);
675        keychords = realloc(keychords, keychords_length + size);
676        if (!keychords) {
677            ERROR("could not allocate keychords\n");
678            keychords_length = 0;
679            keychords_count = 0;
680            return;
681        }
682
683        keychord = (struct input_keychord *)((char *)keychords + keychords_length);
684        keychord->version = KEYCHORD_VERSION;
685        keychord->id = keychords_count + 1;
686        keychord->count = svc->nkeycodes;
687        svc->keychord_id = keychord->id;
688
689        for (i = 0; i < svc->nkeycodes; i++) {
690            keychord->keycodes[i] = svc->keycodes[i];
691        }
692        keychords_count++;
693        keychords_length += size;
694    }
695}
696
697int open_keychord()
698{
699    int fd, ret;
700
701    service_for_each(add_service_keycodes);
702
703    /* nothing to do if no services require keychords */
704    if (!keychords)
705        return -1;
706
707    fd = open("/dev/keychord", O_RDWR);
708    if (fd < 0) {
709        ERROR("could not open /dev/keychord\n");
710        return fd;
711    }
712    fcntl(fd, F_SETFD, FD_CLOEXEC);
713
714    ret = write(fd, keychords, keychords_length);
715    if (ret != keychords_length) {
716        ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno);
717        close(fd);
718        fd = -1;
719    }
720
721    free(keychords);
722    keychords = 0;
723
724    return fd;
725}
726
727void handle_keychord(int fd)
728{
729    struct service *svc;
730    int ret;
731    __u16 id;
732
733    ret = read(fd, &id, sizeof(id));
734    if (ret != sizeof(id)) {
735        ERROR("could not read keychord id\n");
736        return;
737    }
738
739    svc = service_find_by_keychord(id);
740    if (svc) {
741        INFO("starting service %s from keychord\n", svc->name);
742        service_start(svc);
743    } else {
744        ERROR("service for keychord %d not found\n", id);
745    }
746}
747
748int main(int argc, char **argv)
749{
750    int device_fd = -1;
751    int property_set_fd = -1;
752    int signal_recv_fd = -1;
753    int keychord_fd = -1;
754    int fd_count;
755    int s[2];
756    int fd;
757    struct sigaction act;
758    char tmp[PROP_VALUE_MAX];
759    struct pollfd ufds[4];
760    char *tmpdev;
761    char* debuggable;
762
763    act.sa_handler = sigchld_handler;
764    act.sa_flags = SA_NOCLDSTOP;
765    act.sa_mask = 0;
766    act.sa_restorer = NULL;
767    sigaction(SIGCHLD, &act, 0);
768
769    /* clear the umask */
770    umask(0);
771
772        /* Get the basic filesystem setup we need put
773         * together in the initramdisk on / and then we'll
774         * let the rc file figure out the rest.
775         */
776    mkdir("/dev", 0755);
777    mkdir("/proc", 0755);
778    mkdir("/sys", 0755);
779
780    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
781    mkdir("/dev/pts", 0755);
782    mkdir("/dev/socket", 0755);
783    mount("devpts", "/dev/pts", "devpts", 0, NULL);
784    mount("proc", "/proc", "proc", 0, NULL);
785    mount("sysfs", "/sys", "sysfs", 0, NULL);
786
787        /* We must have some place other than / to create the
788         * device nodes for kmsg and null, otherwise we won't
789         * be able to remount / read-only later on.
790         * Now that tmpfs is mounted on /dev, we can actually
791         * talk to the outside world.
792         */
793    open_devnull_stdio();
794    log_init();
795
796    INFO("reading config file\n");
797    parse_config_file("/init.rc");
798
799    /* pull the kernel commandline and ramdisk properties file in */
800    qemu_init();
801    import_kernel_cmdline(0);
802
803    get_hardware_name();
804    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
805    parse_config_file(tmp);
806
807    action_for_each_trigger("early-init", action_add_queue_tail);
808    drain_action_queue();
809
810    INFO("device init\n");
811    device_fd = device_init();
812
813    property_init();
814
815    // only listen for keychords if ro.debuggable is true
816    debuggable = property_get("ro.debuggable");
817    if (debuggable && !strcmp(debuggable, "1")) {
818        keychord_fd = open_keychord();
819    }
820
821    if (console[0]) {
822        snprintf(tmp, sizeof(tmp), "/dev/%s", console);
823        console_name = strdup(tmp);
824    }
825
826    fd = open(console_name, O_RDWR);
827    if (fd >= 0)
828        have_console = 1;
829    close(fd);
830
831    if( load_565rle_image(INIT_IMAGE_FILE) ) {
832    fd = open("/dev/tty0", O_WRONLY);
833    if (fd >= 0) {
834        const char *msg;
835            msg = "\n"
836        "\n"
837        "\n"
838        "\n"
839        "\n"
840        "\n"
841        "\n"  // console is 40 cols x 30 lines
842        "\n"
843        "\n"
844        "\n"
845        "\n"
846        "\n"
847        "\n"
848        "\n"
849        "             A N D R O I D ";
850        write(fd, msg, strlen(msg));
851        close(fd);
852    }
853    }
854
855    if (qemu[0])
856        import_kernel_cmdline(1);
857
858    if (!strcmp(bootmode,"factory"))
859        property_set("ro.factorytest", "1");
860    else if (!strcmp(bootmode,"factory2"))
861        property_set("ro.factorytest", "2");
862    else
863        property_set("ro.factorytest", "0");
864
865    property_set("ro.serialno", serialno[0] ? serialno : "");
866    property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
867    property_set("ro.baseband", baseband[0] ? baseband : "unknown");
868    property_set("ro.carrier", carrier[0] ? carrier : "unknown");
869    property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
870
871    property_set("ro.hardware", hardware);
872    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
873    property_set("ro.revision", tmp);
874
875        /* execute all the boot actions to get us started */
876    action_for_each_trigger("init", action_add_queue_tail);
877    drain_action_queue();
878
879        /* read any property files on system or data and
880         * fire up the property service.  This must happen
881         * after the ro.foo properties are set above so
882         * that /data/local.prop cannot interfere with them.
883         */
884    property_set_fd = start_property_service();
885
886    /* create a signalling mechanism for the sigchld handler */
887    if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
888        signal_fd = s[0];
889        signal_recv_fd = s[1];
890        fcntl(s[0], F_SETFD, FD_CLOEXEC);
891        fcntl(s[0], F_SETFL, O_NONBLOCK);
892        fcntl(s[1], F_SETFD, FD_CLOEXEC);
893        fcntl(s[1], F_SETFL, O_NONBLOCK);
894    }
895
896    /* make sure we actually have all the pieces we need */
897    if ((device_fd < 0) ||
898        (property_set_fd < 0) ||
899        (signal_recv_fd < 0)) {
900        ERROR("init startup failure\n");
901        return 1;
902    }
903
904    /* execute all the boot actions to get us started */
905    action_for_each_trigger("early-boot", action_add_queue_tail);
906    action_for_each_trigger("boot", action_add_queue_tail);
907    drain_action_queue();
908
909        /* run all property triggers based on current state of the properties */
910    queue_all_property_triggers();
911    drain_action_queue();
912
913        /* enable property triggers */
914    property_triggers_enabled = 1;
915
916    ufds[0].fd = device_fd;
917    ufds[0].events = POLLIN;
918    ufds[1].fd = property_set_fd;
919    ufds[1].events = POLLIN;
920    ufds[2].fd = signal_recv_fd;
921    ufds[2].events = POLLIN;
922    fd_count = 3;
923
924    if (keychord_fd > 0) {
925        ufds[3].fd = keychord_fd;
926        ufds[3].events = POLLIN;
927        fd_count++;
928    } else {
929        ufds[3].events = 0;
930        ufds[3].revents = 0;
931    }
932
933#if BOOTCHART
934    bootchart_count = bootchart_init();
935    if (bootchart_count < 0) {
936        ERROR("bootcharting init failure\n");
937    } else if (bootchart_count > 0) {
938        NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
939    } else {
940        NOTICE("bootcharting ignored\n");
941    }
942#endif
943
944    for(;;) {
945        int nr, i, timeout = -1;
946
947        for (i = 0; i < fd_count; i++)
948            ufds[i].revents = 0;
949
950        drain_action_queue();
951        restart_processes();
952
953        if (process_needs_restart) {
954            timeout = (process_needs_restart - gettime()) * 1000;
955            if (timeout < 0)
956                timeout = 0;
957        }
958
959#if BOOTCHART
960        if (bootchart_count > 0) {
961            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
962                timeout = BOOTCHART_POLLING_MS;
963            if (bootchart_step() < 0 || --bootchart_count == 0) {
964                bootchart_finish();
965                bootchart_count = 0;
966            }
967        }
968#endif
969        nr = poll(ufds, fd_count, timeout);
970        if (nr <= 0)
971            continue;
972
973        if (ufds[2].revents == POLLIN) {
974            /* we got a SIGCHLD - reap and restart as needed */
975            read(signal_recv_fd, tmp, sizeof(tmp));
976            while (!wait_for_one_process(0))
977                ;
978            continue;
979        }
980
981        if (ufds[0].revents == POLLIN)
982            handle_device_fd(device_fd);
983
984        if (ufds[1].revents == POLLIN)
985            handle_property_set_fd(property_set_fd);
986        if (ufds[3].revents == POLLIN)
987            handle_keychord(keychord_fd);
988    }
989
990    return 0;
991}
992