summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2022-09-20 03:01:18 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2022-09-20 23:39:29 +0200
commit9c7a1bc253ba4a264e8e3d6ae7983f2fc645f2b3 (patch)
tree07892fe8350ec6defec702790b158ee8bbc038fa
parent432ecc4bed0ef5341d8dc7637d7631fe05ffd717 (diff)
acpi: Convert translator to an emulated mach device
This makes acpi usable as a bootstrap translator. Message-Id: <20220920030035.931113-1-damien@zamaudio.com>
-rw-r--r--acpi/Makefile6
-rw-r--r--acpi/acpifs.c37
-rw-r--r--acpi/acpifs.h6
-rw-r--r--acpi/main.c155
-rw-r--r--acpi/options.c20
-rw-r--r--acpi/options.h8
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}
};