From d1296d7ca780daf7c54520831e6ebb5cbe0a3642 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 9 Oct 2025 17:06:22 -0400 Subject: kern: iotap: Expose I/O taps to userland Expose I/O taps to userland using a tap message interface. An application may construct a tap message to send to the kernel requesting data from a specific tap, if there is data, the buffers will be safely populated, otherwise some error returned. An example is accessing the PS/2 keyboard tap: -- char name[] = "i8042.port.0"; char buf[2] = {0, 0}; struct iotap_msg msg = { .opcode = IOTAP_OPC_READ, .buf = buf, .len = len }; ... /* muxtap() may be used */ ... -- Signed-off-by: Ian Moffett --- src/sys/os/os_iotap.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) (limited to 'src/sys/os/os_iotap.c') diff --git a/src/sys/os/os_iotap.c b/src/sys/os/os_iotap.c index 6eb6ed2..238acfe 100644 --- a/src/sys/os/os_iotap.c +++ b/src/sys/os/os_iotap.c @@ -29,8 +29,11 @@ #include #include +#include #include #include +#include +#include #include #include #include @@ -102,3 +105,101 @@ iotap_lookup(const char *name, struct iotap_desc *dp_res) *dp_res = *tap; return 0; } + +ssize_t +iotap_mux(const char *name, struct iotap_msg *msg) +{ + struct iotap_ops *ops; + struct iotap_desc desc; + int error; + + if (msg == NULL) { + return -EINVAL; + } + + if (msg->buf == NULL || msg->len == 0) { + return -EINVAL; + } + + /* Lookup the tap */ + error = iotap_lookup(name, &desc); + if (error < 0) { + return error; + } + + ops = desc.ops; + switch (msg->opcode) { + case IOTAP_OPC_READ: + return ops->read(&desc, msg->buf, msg->len); + } + + return -EINVAL; +} + +/* + * Get an I/O TAP: + * + * ARG0: Name + * ARG1: Message + * + * RETURNED IN RAX: TAP ID + */ +scret_t +sys_muxtap(struct syscall_args *scargs) +{ + struct iotap_msg msg; + struct iotap_desc desc; + char *u_databuf; + char buf[NAME_MAX], *kbuf; + const char *u_name = SCARG(scargs, const char *, 0); + struct iotap_msg *u_msg = SCARG(scargs, struct iotap_msg *, 1); + int error; + + /* Grab the name */ + error = copyinstr(u_name, buf, sizeof(buf)); + if (error < 0) { + printf("gettap: bad address for name\n"); + return error; + } + + /* Get the message */ + error = copyin(u_msg, &msg, sizeof(msg)); + if (error < 0) { + printf("gettap: bad address for message\n"); + return error; + } + + /* Grab the actual tap */ + error = iotap_lookup(buf, &desc); + if (error < 0) { + printf("gettap: SYS_gettap lookup failure\n"); + return error; + } + + /* Truncate if needed */ + if (msg.len >= IOTAP_MSG_MAX) { + msg.len = IOTAP_MSG_MAX; + } + + /* Allocate a kernel-side buffer */ + kbuf = kalloc(msg.len); + if (kbuf == NULL) { + return -ENOMEM; + } + + /* Perform the operation */ + u_databuf = msg.buf; + msg.buf = kbuf; + error = iotap_mux(buf, &msg); + + /* + * If there are no errors, then we are free to + * copy the results back + */ + if (error > 0) { + copyout(kbuf, u_databuf, msg.len); + } + + kfree(kbuf); + return error; +} -- cgit v1.2.3