Exemplo n.º 1
0
int do_exec_rc(int nargs, char **args)
{
#ifdef INIT_ENG_BUILD
    init_parse_config_file(args[1]);
    action_for_each_trigger(args[2], action_add_queue_head);
#endif
    return 0;
}
Exemplo n.º 2
0
int do_verity_load_state(int nargs, char **args) {
    int mode = -1;
    int rc = fs_mgr_load_verity_state(&mode);
    if (rc == 0 && mode == VERITY_MODE_LOGGING) {
        action_for_each_trigger("verity-logging", action_add_queue_tail);
    }
    return rc;
}
Exemplo n.º 3
0
int do_class_reset(int nargs, char **args)
{
    char prop[PROP_NAME_MAX];
    snprintf(prop, PROP_NAME_MAX, "class_reset:%s", args[1]);

    service_for_each_class(args[1], service_reset);
    action_for_each_trigger(prop, action_add_queue_tail);
    return 0;
}
Exemplo n.º 4
0
int do_mount_all(int nargs, char **args)
{
    pid_t pid;
    int ret = -1;
    int child_ret = -1;
    int status;
    const char *prop;
    struct fstab *fstab;

    if (nargs != 2) {
        return -1;
    }

    /*
     * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
     * do the call in the child to provide protection to the main init
     * process if anything goes wrong (crash or memory leak), and wait for
     * the child to finish in the parent.
     */
    pid = fork();
    if (pid > 0) {
        /* Parent.  Wait for the child to return */
        waitpid(pid, &status, 0);
        if (WIFEXITED(status)) {
            ret = WEXITSTATUS(status);
        } else {
            ret = -1;
        }
    } else if (pid == 0) {
        /* child, call fs_mgr_mount_all() */
        klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */
        fstab = fs_mgr_read_fstab(args[1]);
        child_ret = fs_mgr_mount_all(fstab);
        fs_mgr_free_fstab(fstab);
        if (child_ret == -1) {
            ERROR("fs_mgr_mount_all returned an error\n");
        }
        exit(child_ret);
    } else {
        /* fork failed, return an error */
        return -1;
    }

    /* ret is 1 if the device is encrypted, 0 if not, and -1 on error */
    if (ret == 1) {
        property_set("ro.crypto.state", "encrypted");
        property_set("vold.decrypt", "1");
    } else if (ret == 0) {
        property_set("ro.crypto.state", "unencrypted");
        /* If fs_mgr determined this is an unencrypted device, then trigger
         * that action.
         */
        action_for_each_trigger("nonencrypted", action_add_queue_tail);
    }

    return ret;
}
Exemplo n.º 5
0
int do_class_start(int nargs, char **args)
{
    char prop[PROP_NAME_MAX];
    snprintf(prop, PROP_NAME_MAX, "class_start:%s", args[1]);

    /* Starting a class does not start services
     * which are explicitly disabled.  They must
     * be started individually.
     */
    service_for_each_class(args[1], service_start_if_not_disabled);
    action_for_each_trigger(prop, action_add_queue_tail);
    return 0;
}
Exemplo n.º 6
0
/******************************************************************************
 * system/core/init/init.c
 * - readme.txt, android init language
 *   http://android.git.kernel.org/?p=platform/system/core.git;a=blob;f=init/readme.txt;hb=HEAD
 *   o action
 *   o service
 *   o command
 *   o options
 */
int main(int argc, char **argv)
{
    /* Get the basic filesystem setup we need put
     * together in the initramdisk on / and then we'll
     * let the rc file figure out the rest.
     */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    // http://www.manpagez.com/man/2/mount/
    //  int mount(const char *source, const char *target,          
    //  const char *filesystemtype,
    //  unsigned long mountflags,          const void *data);
    // 
    // mount() attaches the filesystem specified by source (which is often a device name, 
    // but can also be a directory name or a dummy) to the directory specified by target.
    // 
    // mount device tmpfs under /dev as the type of "tmpfs"
    // "tmpfs" is a device name defined in kernel
    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

    // TODO:
    log_init();

    // parse init.rc
    init_parse_config_file("/init.rc");
    // system/core/init/init_parse.c
    //
    // parse hardware specific init.rc
    get_hardware_name(hardware, &revision);
    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
    init_parse_config_file(tmp);

    // add "early-init" into the action_queue
    action_for_each_trigger("early-init", action_add_queue_tail);

    // add more action into action_queue
    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");
    queue_builtin_action(set_init_properties_action, "set_init_properties");    
}
Exemplo n.º 7
0
int do_trigger(int nargs, char **args)
{
    action_for_each_trigger(args[1], action_add_queue_tail);
    return 0;
}
Exemplo n.º 8
0
/*
 * This function might request a reboot, in which case it will
 * not return.
 */
int do_mount_all(int nargs, char **args)
{
    pid_t pid;
    int ret = -1;
    int child_ret = -1;
    int status;
    struct fstab *fstab;

    if (nargs != 2) {
        return -1;
    }

    /*
     * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
     * do the call in the child to provide protection to the main init
     * process if anything goes wrong (crash or memory leak), and wait for
     * the child to finish in the parent.
     */
    pid = fork();
    if (pid > 0) {
        /* Parent.  Wait for the child to return */
        int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
        if (wp_ret < 0) {
            /* Unexpected error code. We will continue anyway. */
            NOTICE("waitpid failed rc=%d, errno=%d\n", wp_ret, errno);
        }

        if (WIFEXITED(status)) {
            ret = WEXITSTATUS(status);
        } else {
            ret = -1;
        }
    } else if (pid == 0) {
        /* child, call fs_mgr_mount_all() */
        klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */
        fstab = fs_mgr_read_fstab(args[1]);
        child_ret = fs_mgr_mount_all(fstab);
        fs_mgr_free_fstab(fstab);
        if (child_ret == -1) {
            ERROR("fs_mgr_mount_all returned an error\n");
        }
        _exit(child_ret);
    } else {
        /* fork failed, return an error */
        return -1;
    }

    if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
        property_set("vold.decrypt", "trigger_encryption");
    } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
        property_set("ro.crypto.state", "encrypted");
        property_set("vold.decrypt", "trigger_default_encryption");
    } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
        property_set("ro.crypto.state", "unencrypted");
        /* If fs_mgr determined this is an unencrypted device, then trigger
         * that action.
         */
        action_for_each_trigger("nonencrypted", action_add_queue_tail);
    } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
        /* Setup a wipe via recovery, and reboot into recovery */
        ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n");
        ret = wipe_data_via_recovery();
        /* If reboot worked, there is no return. */
    } else if (ret > 0) {
        ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret);
    }
    /* else ... < 0: error */

    return ret;
}
Exemplo n.º 9
0
/* mount <type> <device> <path> <flags ...> <options> */
int do_mount(int nargs, char **args)
{
    char tmp[64];
    char *source, *target, *system;
    char *options = NULL;
    unsigned flags = 0;
    int n, i;
    int wait = 0;

    for (n = 4; n < nargs; n++) {
        for (i = 0; mount_flags[i].name; i++) {
            if (!strcmp(args[n], mount_flags[i].name)) {
                flags |= mount_flags[i].flag;
                break;
            }
        }

        if (!mount_flags[i].name) {
            if (!strcmp(args[n], "wait"))
                wait = 1;
            /* if our last argument isn't a flag, wolf it up as an option string */
            else if (n + 1 == nargs)
                options = args[n];
        }
    }

    system = args[1];
    source = args[2];
    target = args[3];

    if (!strncmp(source, "mtd@", 4)) {
        n = mtd_name_to_number(source + 4);
        if (n < 0) {
            return -1;
        }

        sprintf(tmp, "/dev/block/mtdblock%d", n);

        if (wait)
            wait_for_file(tmp, COMMAND_RETRY_TIMEOUT);
        if (mount(tmp, target, system, flags, options) < 0) {
            return -1;
        }

        goto exit_success;
    } else if (!strncmp(source, "loop@", 5)) {
        int mode, loop, fd;
        struct loop_info info;

        mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
        fd = open(source + 5, mode);
        if (fd < 0) {
            return -1;
        }

        for (n = 0; ; n++) {
            sprintf(tmp, "/dev/block/loop%d", n);
            loop = open(tmp, mode);
            if (loop < 0) {
                return -1;
            }

            /* if it is a blank loop device */
            if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
                /* if it becomes our loop device */
                if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {
                    close(fd);

                    if (mount(tmp, target, system, flags, options) < 0) {
                        ioctl(loop, LOOP_CLR_FD, 0);
                        close(loop);
                        return -1;
                    }

                    close(loop);
                    goto exit_success;
                }
            }

            close(loop);
        }

        close(fd);
        ERROR("out of loopback devices");
        return -1;
    } else {
        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
             * 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.
             * Then save the orig mount parms in properties
             * for vold to query when it mounts the real
             * encrypted /data.
             */
            if (!strcmp(target, DATA_MNT_POINT) && !partition_wiped(source)) {
                const char *tmpfs_options;

                tmpfs_options = property_get("ro.crypto.tmpfs_options");

                if (mount("tmpfs", target, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV,
                    tmpfs_options) < 0) {
                    return -1;
                }

                /* Set the property that triggers the framework to do a minimal
                 * startup and ask the user for a password
                 */
                property_set("ro.crypto.state", "encrypted");
                property_set("vold.decrypt", "1");
            } else {
                return -1;
            }
        }

        if (!strcmp(target, DATA_MNT_POINT)) {
            char fs_flags[32];

            /* Save the original mount options */
            property_set("ro.crypto.fs_type", system);
            property_set("ro.crypto.fs_real_blkdev", source);
            property_set("ro.crypto.fs_mnt_point", target);
            if (options) {
                property_set("ro.crypto.fs_options", options);
            }
            snprintf(fs_flags, sizeof(fs_flags), "0x%8.8x", flags);
            property_set("ro.crypto.fs_flags", fs_flags);
        }
    }

exit_success:
    /* If not running encrypted, then set the property saying we are
     * unencrypted, and also trigger the action for a nonencrypted system.
     */
    if (!strcmp(target, DATA_MNT_POINT)) {
        const char *prop;

        prop = property_get("ro.crypto.state");
        if (! prop) {
            prop = "notset";
        }
        if (strcmp(prop, "encrypted")) {
            property_set("ro.crypto.state", "unencrypted");
            action_for_each_trigger("nonencrypted", action_add_queue_tail);
        }
    }

    return 0;

}
Exemplo n.º 10
0
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    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);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    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.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    klog_init();

    INFO("reading config file\n");

    if (!charging_mode_booting())
       init_parse_config_file("/init.rc");
    else
       init_parse_config_file("/lpm.rc");

    /* pull the kernel commandline and ramdisk properties file in */
    import_kernel_cmdline(0, import_kernel_nv);
    /* don't expose the raw commandline to nonpriv processes */
    chmod("/proc/cmdline", 0440);

    if (!charging_mode_booting()) {
         get_hardware_name(hardware, &revision);
         snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
         init_parse_config_file(tmp);
    }

    /* Check for a target specific initialisation file and read if present */
    if (access("/init.target.rc", R_OK) == 0) {
        INFO("Reading target specific config file");
            init_parse_config_file("/init.target.rc");
    }

    action_for_each_trigger("early-init", action_add_queue_tail);

    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");
    queue_builtin_action(set_init_properties_action, "set_init_properties");

    /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);

    /* skip mounting filesystems in charger mode */
    if (strcmp(bootmode, "charger") != 0 || strcmp(battchg_pause, "true") != 0) {
        action_for_each_trigger("early-fs", action_add_queue_tail);
    if(emmc_boot) {
        action_for_each_trigger("emmc-fs", action_add_queue_tail);
    } else {
        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");

    if (!strcmp(bootmode, "charger") || !strcmp(battchg_pause, "true")) {
        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");


#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init && get_keychord_fd() > 0) {
            ufds[fd_count].fd = get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;

    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(0);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    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.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    klog_init();
    property_init();

    get_hardware_name(hardware, &revision);

    process_kernel_cmdline();

#ifdef HAVE_SELINUX
    union selinux_callback cb;
    cb.func_log = klog_write;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    INFO("loading selinux policy\n");
    if (selinux_enabled) {
        if (selinux_android_load_policy() < 0) {
            selinux_enabled = 0;
            INFO("SELinux: Disabled due to failed policy load\n");
        } else {
            selinux_init_all_handles();
        }
    } else {
        INFO("SELinux:  Disabled by command line option\n");
    }
    /* These directories were necessarily created before initial policy load
     * and therefore need their security context restored to the proper value.
     * This must happen before /dev is populated by ueventd.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
#endif

    is_charger = !strcmp(bootmode, "charger");

    INFO("property init\n");
    if (!is_charger)
        property_load_boot_defaults();

    INFO("reading config file\n");
    init_parse_config_file("/init.rc");

    action_for_each_trigger("early-init", action_add_queue_tail);

    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(keychord_init_action, "keychord_init");
    //queue_builtin_action(console_init_action, "console_init");

    /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);

    /* skip mounting filesystems in charger mode */
    if (!is_charger) {
        action_for_each_trigger("early-fs", action_add_queue_tail);
        queue_builtin_action(console_init_action, "console_init");
        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");

    if (is_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_property_triggers");


#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init && get_keychord_fd() > 0) {
            ufds[fd_count].fd = get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}
Exemplo n.º 12
0
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;

    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(0);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    /* Don't repeat the setup of these filesystems,
     * it creates double mount points with an unknown effect
     * on the system.  This init file is for 2nd-init anyway.
     */
#ifndef NO_DEVFS_SETUP
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    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.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    klog_init();
#endif
    property_init();

    get_hardware_name(hardware, &revision);

    process_kernel_cmdline();

    union selinux_callback cb;
    cb.func_log = klog_write;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    selinux_initialize();
    /* These directories were necessarily created before initial policy load
     * and therefore need their security context restored to the proper value.
     * This must happen before /dev is populated by ueventd.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon_recursive("/sys");

    is_charger = !strcmp(bootmode, "charger");

    INFO("property init\n");
    if (!is_charger)
        property_load_boot_defaults();

    INFO("reading config file\n");

    if (!charging_mode_booting())
       init_parse_config_file("/init.rc");
    else
       init_parse_config_file("/lpm.rc");

    /* Check for an emmc initialisation file and read if present */
    if (emmc_boot && access("/init.emmc.rc", R_OK) == 0) {
        INFO("Reading emmc config file");
            init_parse_config_file("/init.emmc.rc");
    }

    /* Check for a target specific initialisation file and read if present */
    if (access("/init.target.rc", R_OK) == 0) {
        INFO("Reading target specific config file");
            init_parse_config_file("/init.target.rc");
    }

    action_for_each_trigger("early-init", action_add_queue_tail);

    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(keychord_init_action, "keychord_init");
    queue_builtin_action(console_init_action, "console_init");

    /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);

    if (!is_charger) {
        action_for_each_trigger("early-fs", action_add_queue_tail);
        if(emmc_boot) {
            action_for_each_trigger("emmc-fs", action_add_queue_tail);
        } else {
            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);
    } else {
        action_for_each_trigger("charger-fs", action_add_queue_tail);
    }

    /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
     * wasn't ready immediately after wait_for_coldboot_done
     */
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");

    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");

    /* Older bootloaders use non-standard charging modes. Check for
     * those now, after mounting the filesystems */
    if (strcmp(battchg_pause, BOARD_CHARGING_CMDLINE_VALUE) == 0)
        is_charger = 1;

    if (is_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_property_triggers");


#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init && get_keychord_fd() > 0) {
            ufds[fd_count].fd = get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents & POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}
Exemplo n.º 13
0
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;
#ifdef MTK_INIT
    int mt_boot_mode = 0;

    klog_set_level(6);
#endif
    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(0);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

#ifdef INIT_ENG_BUILD
    mount("debugfs", "/sys/kernel/debug", "debugfs", 0, NULL);
#endif
        /* 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.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    klog_init();
    property_init();

    get_hardware_name(hardware, &revision);

    process_kernel_cmdline();

    union selinux_callback cb;
    cb.func_log = log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    selinux_initialize();
    /* These directories were necessarily created before initial policy load
     * and therefore need their security context restored to the proper value.
     * This must happen before /dev is populated by ueventd.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon_recursive("/sys");

    is_charger = !strcmp(bootmode, "charger");

    INFO("property init\n");
    property_load_boot_defaults();
#ifndef INIT_ENG_BUILD
    property_set("ro.mtprof.disable", "1");
#endif


    INFO("reading config file\n");

#ifdef MTK_INIT
/* NEW FEATURE: multi-boot mode */
    mt_boot_mode = get_boot_mode();
    if ( (mt_boot_mode == MT_FACTORY_BOOT) || (mt_boot_mode == MT_ATE_FACTORY_BOOT) ) {
        printf("Factory Mode Booting.....\n");
        property_set("sys.mtk.no.factoryimage","1");
        init_parse_config_file("/factory_init.rc");
        init_parse_config_file("/factory_init.project.rc");
    }
    else if ( mt_boot_mode == MT_META_BOOT ) {
        printf("META Mode Booting.....\n");
        init_parse_config_file("/meta_init.rc");
        init_parse_config_file("/meta_init.project.rc");
    }
	else
     {
#endif // MTK_INIT
        init_parse_config_file("/init.rc");
#ifdef MTK_INIT
    }
#endif

#ifdef MTK_INIT
    if ( (mt_boot_mode == MT_FACTORY_BOOT) || (mt_boot_mode == MT_ATE_FACTORY_BOOT) ) {
    	  NOTICE("No need modem.rc for factory mode\n");
    }
    else if ( mt_boot_mode == MT_META_BOOT ) {
        init_parse_config_file("/meta_init.modem.rc");
    }else {
        init_parse_config_file("/init.modem.rc");
    }
#endif // MTK_INIT
/**** End of Parsing .rc files ****/

    action_for_each_trigger("early-init", action_add_queue_tail);

    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(keychord_init_action, "keychord_init");
    queue_builtin_action(console_init_action, "console_init");

    /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);

    /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
     * wasn't ready immediately after wait_for_coldboot_done
     */
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(property_service_init_action, "property_service_init");
    queue_builtin_action(signal_init_action, "signal_init");

    /* Don't mount filesystems or start core system services if in charger mode. */
    if (is_charger) {
        action_for_each_trigger("charger", action_add_queue_tail);
    }
    else
     {
        action_for_each_trigger("late-init", action_add_queue_tail);
    }

    /* run all property triggers based on current state of the properties */
    queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");

#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init && get_keychord_fd() > 0) {
            ufds[fd_count].fd = get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents & POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}
Exemplo n.º 14
0
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;

    klog_set_level(LOG_DEFAULT_LEVEL);
    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(0);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

#ifdef INIT_ENG_BUILD
    mount("debugfs", "/sys/kernel/debug", "debugfs", 0, NULL);
#endif
        /* 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.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    //open_devnull_stdio();
    klog_init();
    property_init();

    get_hardware_name(hardware, &revision);

    process_kernel_cmdline();

#ifdef HAVE_SELINUX
    union selinux_callback cb;
    cb.func_log = klog_write;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    INFO("loading selinux policy\n");
    if (selinux_enabled) {
        if (selinux_android_load_policy() < 0) {
            selinux_enabled = 0;
            INFO("SELinux: Disabled due to failed policy load\n");
        } else {
            selinux_init_all_handles();
        }
    } else {
        INFO("SELinux:  Disabled by command line option\n");
    }
    /* These directories were necessarily created before initial policy load
     * and therefore need their security context restored to the proper value.
     * This must happen before /dev is populated by ueventd.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
#endif

    is_charger = !strcmp(bootmode, "charger");

    INFO("property init\n");
    if (!is_charger)
        property_load_boot_defaults();

#ifdef HAVE_AEE_FEATURE
    INFO("reading AEE config file\n");
#ifndef PARTIAL_BUILD
	init_parse_config_file("/init.aee.mtk.rc");
#else
	init_parse_config_file("/init.aee.customer.rc");
#endif // PARTIAL_BUILD

#endif // HAVE_AEE_FEATURE
    INFO("reading config file\n");

#ifdef USE_BUILT_IN_FACTORY
    ERROR("USE_BUILT_IN_FACTORY");
    if (is_factory_boot())
    {
        ERROR("This is factory boot");
        property_set("sys.mtk.no.factoryimage","1");
        init_parse_config_file("/factory_init.rc");
            INFO("reading project config file\n");
        init_parse_config_file("/factory_init.project.rc");
    }
    else
    {
        if(is_meta_boot())
        {
            ERROR("Parsing meta_init.rc ...\n");
            init_parse_config_file("/meta_init.rc");
            INFO("reading project config file\n");
            init_parse_config_file("/meta_init.project.rc");
            init_parse_config_file("/meta_init.modem.rc");
        }
        else if(is_advanced_meta_boot())
        {
            ERROR("Parsing advanced_meta_init.rc ...\n");
            init_parse_config_file("/advanced_meta_init.rc");
            INFO("reading project config file\n");
            init_parse_config_file("/advanced_meta_init.project.rc");
#ifdef MTK_FAT_ON_NAND
            printf("reading init.fon.rc file\n");
            init_parse_config_file("/init.fon.rc");
#endif
        }
        #if defined (MTK_KERNEL_POWER_OFF_CHARGING_SUPPORT)
	else if (is_kernel_power_off_charging_boot())
    {
        ERROR("Parsing init.charging.rc ...\n");
        if (init_parse_config_file("/init.charging.rc") < 0)
        {
            init_parse_config_file("/init.rc");
            INFO("reading project config file\n");
            init_parse_config_file("/init.project.rc");
            init_parse_config_file("/init.modem.rc");
	    }
	}
	#endif
        else
        {
            printf("Parsing init.rc ...\n");
            init_parse_config_file("/init.rc");
            INFO("reading project config file\n");
            init_parse_config_file("/init.project.rc");
            init_parse_config_file("/init.modem.rc");
#ifdef MTK_FAT_ON_NAND
            printf("reading init.fon.rc file\n");
            init_parse_config_file("/init.fon.rc");
#endif
        }
    }
#else
    if(is_meta_boot())
    {
        ERROR("Parsing meta_init.rc ...\n");
        init_parse_config_file("/meta_init.rc");
        INFO("reading project config file\n");
        init_parse_config_file("/meta_init.project.rc");
        init_parse_config_file("/meta_init.modem.rc");
    }
    else if(is_advanced_meta_boot())
    {
        ERROR("Parsing advanced_meta_init.rc ...\n");
        init_parse_config_file("/advanced_meta_init.rc");
        INFO("reading project config file\n");
        init_parse_config_file("/advanced_meta_init.project.rc");
    }
    else
    {
        printf("Parsing init.rc ...\n");
        init_parse_config_file("/init.rc");
        INFO("reading project config file\n");
        init_parse_config_file("/init.project.rc");
        init_parse_config_file("/init.modem.rc");
    }
#endif
#ifdef MTK_SHARED_SDCARD
    if(is_support_sdcard_share_boot())
    {
#ifdef MTK_2SDCARD_SWAP
        printf("Parsing init.ssd_sdswap.rc ...\n");
        init_parse_config_file("/init.ssd_nomuser.rc");
#else
        printf("Parsing init.ssd.rc ...\n");
        init_parse_config_file("/init.ssd.rc");
#endif
    }
    else 
    {
        printf("Parsing init.no_ssd.rc ...\n");
        init_parse_config_file("/init.no_ssd.rc");
    }
#else 
    printf("Parsing init.no_ssd.rc ...\n");
    init_parse_config_file("/init.no_ssd.rc");
#endif

#ifndef INIT_ENG_BUILD
    property_set("ro.mtprof.disable", "1");
#endif

    if(is_support_protected_data_boot())
    {       	    
	printf("Parsing init.protect.rc ...\n");  
        init_parse_config_file("/init.protect.rc");
    }
    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(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(keychord_init_action, "keychord_init");
    queue_builtin_action(console_init_action, "console_init");

    /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);

    /* skip mounting filesystems in charger mode */
    if (!is_charger) {
        queue_builtin_action(queue_fs_property_triggers_action, "queue_fs_propety_triggers");
        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");

    queue_builtin_action(queue_early_property_triggers_action, "queue_early_propety_triggers");
    if (is_charger) {
        action_for_each_trigger("charger", action_add_queue_tail);
    }
#if defined (MTK_KERNEL_POWER_OFF_CHARGING_SUPPORT)
    else if (is_kernel_power_off_charging_boot()){
	action_for_each_trigger("ipo", action_add_queue_tail);
    } 
#endif
    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_property_triggers");

    /* change USB function by meta_com_id */
#ifdef USE_BUILT_IN_FACTORY
    if (is_meta_boot() || is_factory_boot()) {
        queue_builtin_action(queue_com_triggers_action, "queue_com_triggers");
    }
#else
    if (is_meta_boot()) {
        queue_builtin_action(queue_com_triggers_action, "queue_com_triggers");
    }
#endif


#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init && get_keychord_fd() > 0) {
            ufds[fd_count].fd = get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}
Exemplo n.º 15
0
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;

    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(0);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    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.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();
    klog_init();
    property_init();

    get_hardware_name(hardware, &revision);

    process_kernel_cmdline();

    union selinux_callback cb;
    cb.func_log = log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    selinux_initialize();
    /* These directories were necessarily created before initial policy load
     * and therefore need their security context restored to the proper value.
     * This must happen before /dev is populated by ueventd.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon_recursive("/sys");

    is_charger = !strcmp(bootmode, "charger");

    INFO("property init\n");
    property_load_boot_defaults();

    INFO("reading config file\n");
    init_parse_config_file("/init.rc");

    action_for_each_trigger("early-init", action_add_queue_tail);

    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(keychord_init_action, "keychord_init");
    queue_builtin_action(console_init_action, "console_init");

    /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);

    /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
     * wasn't ready immediately after wait_for_coldboot_done
     */
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(property_service_init_action, "property_service_init");
    queue_builtin_action(signal_init_action, "signal_init");

    /* Don't mount filesystems or start core system services if in charger mode. */
    if (is_charger) {
        action_for_each_trigger("charger", action_add_queue_tail);
    } else {
        action_for_each_trigger("late-init", action_add_queue_tail);
    }

    /* run all property triggers based on current state of the properties */
    queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");


#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init && get_keychord_fd() > 0) {
            ufds[fd_count].fd = get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            long long current_time;
            int elapsed_time, remaining_time;

            current_time = bootchart_gettime();
            elapsed_time = current_time - bootchart_time;

            if (elapsed_time >= BOOTCHART_POLLING_MS) {
                /* count missed samples */
                while (elapsed_time >= BOOTCHART_POLLING_MS) {
                    elapsed_time -= BOOTCHART_POLLING_MS;
                    bootchart_count--;
                }
                /* count may be negative, take a sample anyway */
                bootchart_time = current_time;
                if (bootchart_step() < 0 || bootchart_count <= 0) {
                    bootchart_finish();
                    bootchart_count = 0;
                }
            }
            if (bootchart_count > 0) {
                remaining_time = BOOTCHART_POLLING_MS - elapsed_time;
                if (timeout < 0 || timeout > remaining_time)
                    timeout = remaining_time;
            }
        }
#endif

        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents & POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}
Exemplo n.º 16
0
/*
 * This function might request a reboot, in which case it will
 * not return.
 */
int do_mount_all(int nargs, char **args)
{
    pid_t pid;
    int ret = -1;
    int child_ret = -1;
    int status;
    char boot_mode[PROP_VALUE_MAX] = {0};
    struct fstab *fstab;

    if (nargs != 2) {
        return -1;
    }

    /*
     * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
     * do the call in the child to provide protection to the main init
     * process if anything goes wrong (crash or memory leak), and wait for
     * the child to finish in the parent.
     */
    pid = fork();
    if (pid > 0) {
        /* Parent.  Wait for the child to return */
        int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
        if (wp_ret < 0) {
            /* Unexpected error code. We will continue anyway. */
            NOTICE("waitpid failed rc=%d: %s\n", wp_ret, strerror(errno));
        }

        if (WIFEXITED(status)) {
            ret = WEXITSTATUS(status);
        } else {
            ret = -1;
        }
    } else if (pid == 0) {
        /* child, call fs_mgr_mount_all() */
        klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */
        fstab = fs_mgr_read_fstab(args[1]);
        child_ret = fs_mgr_mount_all(fstab);
        fs_mgr_free_fstab(fstab);
        if (child_ret == -1) {
            ERROR("fs_mgr_mount_all returned an error\n");
        }
        _exit(child_ret);
    } else {
        /* fork failed, return an error */
        return -1;
    }

    if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
        property_set("vold.decrypt", "trigger_encryption");
    } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "block");
        property_set("vold.decrypt", "trigger_default_encryption");
    } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
        property_set("ro.crypto.state", "unencrypted");
        /* If fs_mgr determined this is an unencrypted device and we are
         * not booting into ffbm(fast factory boot mode),then trigger
	 * that action.
         */
        property_get("ro.bootmode", boot_mode);
        if (strncmp(boot_mode, "ffbm", 4))
            action_for_each_trigger("nonencrypted", action_add_queue_tail);
    } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
        /* Setup a wipe via recovery, and reboot into recovery */
        ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n");
        ret = wipe_data_via_recovery();
        /* If reboot worked, there is no return. */
    } else if (ret == FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED) {
        if (e4crypt_install_keyring()) {
            return -1;
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "file");

        // Although encrypted, we have device key, so we do not need to
        // do anything different from the nonencrypted case.
        property_get("ro.bootmode", boot_mode);
        if (strncmp(boot_mode, "ffbm", 4))
            action_for_each_trigger("nonencrypted", action_add_queue_tail);
    } else if (ret == FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED) {
        if (e4crypt_install_keyring()) {
            return -1;
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "file");
        property_set("vold.decrypt", "trigger_restart_min_framework");
    } else if (ret > 0) {
        ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret);
    }
    /* else ... < 0: error */

    return ret;
}
Exemplo n.º 17
0
/* mount <type> <device> <path> <flags ...> <options> */
int do_mount(int nargs, char **args)
{
    char tmp[64];
    char *source, *target, *type;
    char *options = NULL;
    unsigned flags = 0;
    int n, i;
    int wait = 0;
    //add for power loss test
    struct stat stbuf; 

    for (n = 4; n < nargs; n++) {
        for (i = 0; mount_flags[i].name; i++) {
            if (!strcmp(args[n], mount_flags[i].name)) {
                flags |= mount_flags[i].flag;
                break;
            }
        }

        if (!mount_flags[i].name) {
            if (!strcmp(args[n], "wait"))
                wait = 1;
            /* if our last argument isn't a flag, wolf it up as an option string */
            else if (n + 1 == nargs)
                options = args[n];
        }
    }

    type = args[1];
    source = args[2];
    target = args[3];

    if (!strncmp(source, "mtd@", 4)) {
        n = mtd_name_to_number(source + 4);
        if (n < 0) {
            return -1;
        }

        sprintf(tmp, "/dev/block/mtdblock%d", n);

        if (wait)
            wait_for_file(tmp, COMMAND_RETRY_TIMEOUT);
        if (mount(tmp, target, type, flags, options) < 0) {
            return -1;
        }

        goto exit_success;
    } else if (!strncmp(source, "loop@", 5)) {
        int mode, loop, fd;
        struct loop_info info;

        mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
        fd = open(source + 5, mode);
        if (fd < 0) {
            return -1;
        }

        for (n = 0; ; n++) {
            sprintf(tmp, "/dev/block/loop%d", n);
            loop = open(tmp, mode);
            if (loop < 0) {
                return -1;
            }

            /* if it is a blank loop device */
            if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
                /* if it becomes our loop device */
                if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {
                    close(fd);

                    if (mount(tmp, target, type, flags, options) < 0) {
                        ioctl(loop, LOOP_CLR_FD, 0);
                        close(loop);
                        return -1;
                    }

                    close(loop);
                    goto exit_success;
                }
            }

            close(loop);
        }

        close(fd);
        ERROR("out of loopback devices");
        return -1;
    } else {

#ifdef MTK_EMMC_SUPPORT
         struct phone_encrypt_state ps;  
         if (!strcmp(target, DATA_MNT_POINT)) {
             if (misc_get_phone_encrypt_state(&ps) < 0) {
                 printf("Failed to get encrypted status in MISC\n");
             }
             else {
                 printf("Success: get encrypted status: 0x%x in MISC\n", ps.state);
             }  
         }
#endif

        if (wait)
            wait_for_file(source, COMMAND_RETRY_TIMEOUT);
        if (mount(source, target, type, flags, options) < 0) {
            /* 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.
             * Then save the orig mount parms in properties
             * for vold to query when it mounts the real
             * encrypted /data.
             */


            if (!strcmp(target, DATA_MNT_POINT)) {
                int fd;
                if ((fd = open(source, O_RDONLY)) < 0) {
                     printf("Mount /data fail because source(%s) doesn't exist.", source);
                     return -1;
                }
            }

            if (!strcmp(target, DATA_MNT_POINT) && !partition_wiped(source)) {
                const char *tmpfs_options;

                tmpfs_options = property_get("ro.crypto.tmpfs_options");

                if (mount("tmpfs", target, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV,
                    tmpfs_options) < 0) {
                    return -1;
                }

                /* Set the property that triggers the framework to do a minimal
                 * startup and ask the user for a password
                 */
                property_set("ro.crypto.state", "encrypted");
                property_set("vold.decrypt", "1");
            } else {
                return -1;
            }
        }
#ifdef MTK_EMMC_SUPPORT
        else {
             if (!strcmp(target, DATA_MNT_POINT)) {
                    if (ps.state == PHONE_ENCRYPTED) {
                        ps.state = PHONE_UNCRYPTED;
                        if (misc_set_phone_encrypt_state(&ps) < 0) {
                            printf("Failed to set encrypted status to 0x%x in MISC\n", ps.state);
                        }
                        else {
                            printf("Success: Set encrypted status to 0x%x in MISC\n", ps.state);
                        }
                    }
             }
        }
#endif

        if (!strcmp(target, DATA_MNT_POINT)) {
            char fs_flags[32];

            /* Save the original mount options */
            property_set("ro.crypto.fs_type", type);
            property_set("ro.crypto.fs_real_blkdev", source);
            property_set("ro.crypto.fs_mnt_point", target);
            if (options) {
                property_set("ro.crypto.fs_options", options);
            }
            snprintf(fs_flags, sizeof(fs_flags), "0x%8.8x", flags);
            property_set("ro.crypto.fs_flags", fs_flags);
        }
        if (!strncmp(type, "ext4", 4)){
            if (!strncmp(target, "/data", 5)){
               printf("delete lost-found in data dir\n");
               system("/system/bin/rm -r /data/lost+found/*");
               
               if (stat("/data/data", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/data file\n");
                   system("/system/bin/rm -r /data/data");    
               }

               if (stat("/data/system", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/system file\n");
                   system("/system/bin/rm -r /data/system");    
               }

               if (stat("/data/misc", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/misc file\n");
                   system("/system/bin/rm -r /data/misc");    
               }

               if (stat("/data/local", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/local file\n");
                   system("/system/bin/rm -r /data/local");    
               }

               if (stat("/data/app-private", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/app-private file\n");
                   system("/system/bin/rm -r /data/app-private");    
               }

               if (stat("/data/dalvik-cache", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/dalvik-cache file\n");
                   system("/system/bin/rm -r /data/dalvik-cache");    
               }


               if (stat("/data/property", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/property file\n");
                   system("/system/bin/rm -r /data/property");    
               } 

               if (stat("/data/mvg_root", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/mvg_root file\n");
                   system("/system/bin/rm -r /data/mvg_root");    
               }

               if (stat("/data/anr", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/anr file\n");
                   system("/system/bin/rm -r /data/anr");    
               }

               if (stat("/data/app", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/app file\n");
                   system("/system/bin/rm -r /data/app");    
               }

               if (stat("/data/nvram", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/nvram file\n");
                   system("/system/bin/rm -r /data/nvram");    
               }

               if (stat("/data/secure", &stbuf) < 0){
                   printf("stat syscall fail\n");
               }
               if (S_ISREG(stbuf.st_mode)){
                   printf("delete /data/secure file\n");
                   system("/system/bin/rm -r /data/secure");    
               }
            }

            if (!strncmp(target, "/cache", 6)){
               printf("delete lost-found in cache dir\n");
               system("/system/bin/rm -r /cache/lost+found/*");
            }
        }        
    }

exit_success:
    /* If not running encrypted, then set the property saying we are
     * unencrypted, and also trigger the action for a nonencrypted system.
     */
    if (!strcmp(target, DATA_MNT_POINT)) {
        const char *prop;

        prop = property_get("ro.crypto.state");
        if (! prop) {
            prop = "notset";
        }
        if (strcmp(prop, "encrypted")) {
            property_set("ro.crypto.state", "unencrypted");
            action_for_each_trigger("nonencrypted", action_add_queue_tail);
        }
    }

    return 0;

}
Exemplo n.º 18
0
int main(int argc, char **argv)
{
    int fd_count = 0;
    struct pollfd ufds[4];
    char *tmpdev;
    char* debuggable;
    char tmp[32];
    int property_set_fd_init = 0;
    int signal_fd_init = 0;
    int keychord_fd_init = 0;
    bool is_charger = false;        // 判断是否是在充电

    char* args_swapon[2];
    args_swapon[0] = "swapon_all";;
    args_swapon[1] = "/fstab.sun8i";;
        
    char* args_write[3];
    args_write[0] = "write";
    args_write[1] = "/proc/sys/vm/page-cluster";
    args_write[2] = "0";

    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    /* clear the umask */
    umask(0);

        /* Get the basic filesystem setup we need put
         * together in the initramdisk on / and then we'll
         * let the rc file figure out the rest.
         */
    // 创建设备节点
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    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.
         * Now that tmpfs is mounted on /dev, we can actually
         * talk to the outside world.
         */
    open_devnull_stdio();       // stdio/stdout/stderr都指向__null__设备
    klog_init();                // 从这里创建__kmsg__设备
    property_init();            // 1. 完成property的环境变量初始化等动作

    get_hardware_name(hardware, &revision);

    process_kernel_cmdline();   // 属性初始设置

    union selinux_callback cb;
    cb.func_log = klog_write;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    selinux_initialize();
    /* These directories were necessarily created before initial policy load
     * and therefore need their security context restored to the proper value.
     * This must happen before /dev is populated by ueventd.
     */
    restorecon("/dev");
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon_recursive("/sys");

    is_charger = !strcmp(bootmode, "charger");      // 从bootloader中获取是否在充电的信息
    usb_charge_flag = is_charger;

    INFO("property init\n");
    if (!is_charger)
        property_load_boot_defaults();
	get_kernel_cmdline_partitions();
    get_kernel_cmdline_signature();
    INFO("reading config file\n");
    init_parse_config_file("/init.rc");

    action_for_each_trigger("early-init", action_add_queue_tail);

    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    queue_builtin_action(keychord_init_action, "keychord_init");

    /* 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);
    /* skip mounting filesystems in charger mode */
    if (!is_charger) {
        // 显示initlog.rle,也就是android第二张图片
        queue_builtin_action(console_init_action, "console_init");
        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);
        
        //SWAP TO ZRAM if low mem devices
        if (!(get_dram_size() > 512)) {
            char trigger[] = {"early-fs"};
            ERROR("***************************LOW MEM DEVICE DETECT");
            add_command(trigger, 2, args_swapon);
            char trigger2[] = {"post-fs-data"};
            add_command(trigger2, 3, args_write);
        }
    }

    /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
     * wasn't ready immediately after wait_for_coldboot_done
     */
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");

    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");

    if (is_charger) {
        // 如果是charger模式,则调用charger.c
        queue_builtin_action(console_init_action, "console_init");
        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_property_triggers");


#if BOOTCHART
    queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif

    for(;;) {       // 监视事件 事件处理循环
        int nr, i, timeout = -1;

        execute_one_command();
        restart_processes();

        if (!property_set_fd_init && get_property_set_fd() > 0) {       // 通过套接字传递信息
            ufds[fd_count].fd = get_property_set_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            property_set_fd_init = 1;
        }
        if (!signal_fd_init && get_signal_fd() > 0) {
            ufds[fd_count].fd = get_signal_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            signal_fd_init = 1;
        }
        if (!keychord_fd_init && get_keychord_fd() > 0) {
            ufds[fd_count].fd = get_keychord_fd();
            ufds[fd_count].events = POLLIN;
            ufds[fd_count].revents = 0;
            fd_count++;
            keychord_fd_init = 1;
        }

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action)
            timeout = 0;

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif

        nr = poll(ufds, fd_count, timeout);     // 获取事件(热插拔检测)
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {                        // 处理套接字传回的信息
            if (ufds[i].revents & POLLIN) {
                if (ufds[i].fd == get_property_set_fd())        // 处理属性变更
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())         // 处理子进程传回的信息
                    handle_signal();
            }
        }
    }

    return 0;
}