This makes acpi usable as a bootstrap translator. --- acpi/Makefile | 6 +- acpi/acpifs.c | 37 ++++++++---- acpi/acpifs.h | 6 +- acpi/main.c | 155 +++++++++++++++++++++++++++++++++++++++++++++---- acpi/options.c | 20 +++++++ acpi/options.h | 8 +++ 6 files changed, 207 insertions(+), 25 deletions(-)
diff --git a/acpi/Makefile b/acpi/Makefile index 76f27aef..ceccb351 100644 --- a/acpi/Makefile +++ b/acpi/Makefile @@ -22,15 +22,15 @@ PORTDIR = $(srcdir)/port SRCS = main.c netfs_impl.c acpi.c \ acpifs.c ncache.c options.c func_files.c acpi-ops.c \ - acpiServer.c + acpiServer.c startup_notifyServer.c MIGSRCS = OBJS = $(patsubst %.S,%.o,$(patsubst %.c,%.o, $(SRCS) $(MIGSRCS))) -HURDLIBS= fshelp ports shouldbeinlibc netfs iohelp ihash +HURDLIBS= fshelp ports shouldbeinlibc netfs iohelp ihash machdev trivfs LDLIBS = -lpthread $(libacpica_LIBS) -target = acpi +target = acpi acpi.static include ../Makeconf diff --git a/acpi/acpifs.c b/acpi/acpifs.c index 2b5fbc00..1b9fbcf2 100644 --- a/acpi/acpifs.c +++ b/acpi/acpifs.c @@ -81,16 +81,19 @@ alloc_file_system (struct acpifs **fs) } error_t -init_file_system (file_t underlying_node, struct acpifs *fs) +init_root_node (file_t underlying_node) { error_t err; struct node *np; - io_statbuf_t underlying_node_stat; + io_statbuf_t underlying_node_stat = { 0 }; - /* Initialize status from underlying node. */ - err = io_stat (underlying_node, &underlying_node_stat); - if (err) - return err; + if (underlying_node != MACH_PORT_NULL) + { + /* Initialize status from underlying node. */ + err = io_stat (underlying_node, &underlying_node_stat); + if (err) + return err; + } np = netfs_make_node_alloc (sizeof (struct netnode)); if (!np) @@ -106,18 +109,30 @@ init_file_system (file_t underlying_node, struct acpifs *fs) fshelp_touch (&np->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, acpifs_maptime); + netfs_root_node = np; + return 0; +} + +error_t +init_file_system (struct acpifs *fs) +{ + error_t err; + struct node *np = netfs_root_node; + fs->entries = calloc (1, sizeof (struct acpifs_dirent)); if (!fs->entries) - { - free (fs->entries); - return ENOMEM; - } + return ENOMEM; /* Create the root entry */ err = create_dir_entry ("", 0, 0, np->nn_stat, np, fs->entries); + if (err) + { + free(fs->entries); + return err; + } fs->num_entries = 1; - fs->root = netfs_root_node = np; + fs->root = np; fs->root->nn->ln = fs->entries; pthread_mutex_init (&fs->node_cache_lock, 0); diff --git a/acpi/acpifs.h b/acpi/acpifs.h index 4597e1b0..e4ab0d95 100644 --- a/acpi/acpifs.h +++ b/acpi/acpifs.h @@ -97,6 +97,9 @@ struct acpifs size_t node_cache_max; pthread_mutex_t node_cache_lock; + /* Next bootstrap task */ + mach_port_t next_task; + struct acpifs_perm perm; struct acpifs_dirent *entries; @@ -138,7 +141,8 @@ extern volatile struct mapped_time_value *acpifs_maptime; /* FS manipulation functions */ error_t alloc_file_system (struct acpifs **fs); -error_t init_file_system (file_t underlying_node, struct acpifs *fs); +error_t init_file_system (struct acpifs *fs); +error_t init_root_node (file_t underlying_node); error_t create_fs_tree (struct acpifs *fs); error_t fs_set_permissions (struct acpifs *fs); error_t entry_check_perms (struct iouser *user, struct acpifs_dirent *e, diff --git a/acpi/main.c b/acpi/main.c index fc46f4f2..aa153bdb 100644 --- a/acpi/main.c +++ b/acpi/main.c @@ -25,14 +25,19 @@ #include <version.h> #include <argp.h> #include <hurd/netfs.h> +#include <hurd/fsys.h> #include "acpi_S.h" +#include "startup_notify_S.h" #include "libnetfs/io_S.h" #include "libnetfs/fs_S.h" #include "libports/notify_S.h" #include "libnetfs/fsys_S.h" #include "libports/interrupt_S.h" #include "libnetfs/ifsock_S.h" +#include "libmachdev/machdev.h" +#include <device/device.h> +#include <pthread.h> #include <acpi/acpi_init.h> #include <acpifs.h> @@ -45,6 +50,8 @@ volatile struct mapped_time_value *acpifs_maptime; struct acpifs *fs; +static mach_port_t acpi_control_port; + int netfs_demuxer (mach_msg_header_t * inp, mach_msg_header_t * outp) { @@ -56,7 +63,8 @@ netfs_demuxer (mach_msg_header_t * inp, mach_msg_header_t * outp) (routine = netfs_fsys_server_routine (inp)) || (routine = ports_interrupt_server_routine (inp)) || (routine = netfs_ifsock_server_routine (inp)) || - (routine = acpi_server_routine (inp))) + (routine = acpi_server_routine (inp)) || + (routine = startup_notify_server_routine (inp))) { (*routine) (inp, outp); return TRUE; @@ -65,23 +73,126 @@ netfs_demuxer (mach_msg_header_t * inp, mach_msg_header_t * outp) return FALSE; } +static io_return_t +acpi_device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, + dev_mode_t mode, const char *name, device_t * devp, + mach_msg_type_name_t * devicePoly) +{ + io_return_t err = D_SUCCESS; + mach_port_t dev_master, root; + string_t retry_name; + retry_type retry; + uid_t idlist[] = {0, 0, 0}; + + if (strncmp(name, "acpi", 3)) + err = D_NO_SUCH_DEVICE; + + /* Fall back to opening kernel device master */ + if (err) + { + err = get_privileged_ports(NULL, &dev_master); + if (err) + return err; + if (dev_master == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + err = device_open (dev_master, mode, name, devp); + if (err) + return err; + *devicePoly = MACH_MSG_TYPE_MOVE_SEND; + return D_SUCCESS; + } + + err = fsys_getroot(acpi_control_port, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND, + idlist, 3, idlist, 3, 0, + &retry, retry_name, &root); + if (err) + return err; + + *devp = root; + *devicePoly = MACH_MSG_TYPE_COPY_SEND; + return D_SUCCESS; +} + +static struct machdev_device_emulation_ops acpi_emulation_ops = { + NULL, + NULL, + NULL, + NULL, + acpi_device_open, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static mach_port_t +acpifs_startup(mach_port_t bootstrap, int flags) +{ + error_t err; + mach_port_t realnode; + struct port_info *newpi; + + err = ports_create_port (netfs_control_class, netfs_port_bucket, + sizeof (struct port_info), &newpi); + if (err) + error (11, err, "Translator startup failure: acpifs_startup"); + + acpi_control_port = ports_get_send_right (newpi); + + if (bootstrap != MACH_PORT_NULL) + { + err = fsys_startup (bootstrap, flags, acpi_control_port, MACH_MSG_TYPE_COPY_SEND, + &realnode); + assert_perror_backtrace (err); + } + + return realnode; +} + int main (int argc, char **argv) { error_t err; mach_port_t bootstrap; + mach_port_t next_task; + pthread_t t, mt; + file_t underlying_node = MACH_PORT_NULL; /* Parse options */ alloc_file_system (&fs); argp_parse (netfs_runtime_argp, argc, argv, 0, 0, 0); + next_task = fs->next_task; - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "must be started as a translator"); - - /* Initialize ACPI */ - acpi_init(); - + if (next_task != MACH_PORT_NULL) + { + /* We are a bootstrap process */ + + machdev_register (&acpi_emulation_ops); + /* TODO: make libmachdev allow us to also run netfs on the translated path, + * so that we don't need a second acpi to serve /servers/acpi */ + machdev_trivfs_init (argc, argv, next_task, "acpi", NULL /* _SERVERS "acpi" */, &bootstrap); + + machdev_device_init (); + err = pthread_create (&t, NULL, machdev_server, NULL); + if (err) + error (1, err, "creating machdev thread"); + pthread_detach (t); + } + else + { + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (1, 0, "must be started as a translator"); + } /* Initialize netfs and start the translator. */ netfs_init (); @@ -91,8 +202,24 @@ main (int argc, char **argv) if (err) error (1, err, "mapping time"); - /* Create the ACPI filesystem */ - err = init_file_system (netfs_startup (bootstrap, O_READ), fs); + /* Enable ACPI mode of machine */ + acpi_init (); + + if (next_task != MACH_PORT_NULL) + machdev_trivfs_server_startup (bootstrap); + + if (next_task == MACH_PORT_NULL) + underlying_node = netfs_startup (bootstrap, O_READ); + + /* Create the root node first */ + err = init_root_node (underlying_node); + if (err) + error (1, err, "creating the root node"); + + if (next_task != MACH_PORT_NULL) + acpifs_startup (bootstrap, O_READ); + + err = init_file_system (fs); if (err) error (1, err, "creating the ACPI filesystem"); @@ -106,6 +233,14 @@ main (int argc, char **argv) if (err) error (1, err, "setting permissions"); + if (next_task != MACH_PORT_NULL) + { + err = pthread_create (&mt, NULL, machdev_trivfs_server_loop, NULL); + if (err) + error(1, err, "creating machdev_trivfs_server_loop thread"); + pthread_detach (mt); + } + netfs_server_loop (); /* Never returns. */ return 0; diff --git a/acpi/options.c b/acpi/options.c index 8dbcd263..fb348679 100644 --- a/acpi/options.c +++ b/acpi/options.c @@ -64,6 +64,15 @@ parse_opt (int opt, char *arg, struct argp_state *state) case 'G': h->perm.gid = atoi (arg); break; + case 'N': + h->next_task = atoi (arg); + break; + case 'H': + h->host_priv_port = atoi (arg); + break; + case 'P': + h->dev_master_port = atoi (arg); + break; case ARGP_KEY_INIT: /* Initialize our parsing state. */ @@ -74,6 +83,9 @@ parse_opt (int opt, char *arg, struct argp_state *state) h->ncache_len = NODE_CACHE_MAX; h->perm.uid = 0; h->perm.gid = 0; + h->next_task = MACH_PORT_NULL; + h->host_priv_port = MACH_PORT_NULL; + h->dev_master_port = MACH_PORT_NULL; state->hook = h; break; @@ -84,6 +96,11 @@ parse_opt (int opt, char *arg, struct argp_state *state) /* Set cache len */ fs->node_cache_max = h->ncache_len; + /* Set bootstrap ports */ + fs->next_task = h->next_task; + _hurd_host_priv = h->host_priv_port; + _hurd_device_master = h->dev_master_port; + if (fs->root) { /* @@ -140,6 +157,9 @@ netfs_append_args (char **argz, size_t * argz_len) if (p->gid >= 0) ADD_OPT ("--gid=%u", p->gid); + if (fs->next_task != MACH_PORT_NULL) + ADD_OPT ("--next-task=%u", fs->next_task); + #undef ADD_OPT return err; } diff --git a/acpi/options.h b/acpi/options.h index 36ccc48b..53c98ab1 100644 --- a/acpi/options.h +++ b/acpi/options.h @@ -36,6 +36,11 @@ struct parse_hook { struct acpifs_perm perm; size_t ncache_len; + + /* Mach ports */ + mach_port_t next_task; + mach_port_t host_priv_port; + mach_port_t dev_master_port; }; /* ACPI translator options. Used for both startup and runtime. */ @@ -43,6 +48,9 @@ static const struct argp_option options[] = { {0, 0, 0, 0, "These apply to the whole acpi tree:", 1}, {"uid", 'U', "UID", 0, "User ID to give permissions to"}, {"gid", 'G', "GID", 0, "Group ID to give permissions to"}, + {"next-task", 'N', "TASK", 0, "Next bootstrap task"}, + {"host-priv-port", 'H', "PORT", 0, "Port for bootstrapping host"}, + {"device-master-port", 'P', "PORT", 0, "Port for bootstrapping device master"}, {0} }; -- 2.34.1