From 9c7a1bc253ba4a264e8e3d6ae7983f2fc645f2b3 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Tue, 20 Sep 2022 03:01:18 +0000 Subject: acpi: Convert translator to an emulated mach device This makes acpi usable as a bootstrap translator. Message-Id: <20220920030035.931113-1-damien@zamaudio.com> --- acpi/main.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 145 insertions(+), 10 deletions(-) (limited to 'acpi/main.c') 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 #include #include +#include #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 +#include #include #include @@ -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; -- cgit v1.2.3