summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/Makefile6
-rw-r--r--src/cmd/cat/Makefile16
-rw-r--r--src/cmd/cat/cat.c64
-rw-r--r--src/cmd/echo/Makefile4
-rw-r--r--src/cmd/fetch/Makefile4
-rw-r--r--src/cmd/hush/Makefile4
-rw-r--r--src/cmd/init/Makefile4
-rw-r--r--src/cmd/init/init.c28
-rw-r--r--src/cmd/login/Makefile4
-rw-r--r--src/cmd/lsdisk/Makefile4
-rw-r--r--src/cmd/mex/Makefile18
-rw-r--r--src/cmd/mex/mex.c107
-rw-r--r--src/cmd/reboot/Makefile4
-rw-r--r--src/lib/libc/include/unistd.h10
-rw-r--r--src/lib/libc/src/l5/mmap.c45
-rw-r--r--src/lib/libc/src/unistd/lseek.c47
-rw-r--r--src/sys/arch/amd64/cpu/cpu_conf.c3
-rw-r--r--src/sys/arch/amd64/cpu/trap.c24
-rw-r--r--src/sys/arch/amd64/os/os_panic.c6
-rw-r--r--src/sys/arch/amd64/simd.S75
-rw-r--r--src/sys/fs/devfs.c56
-rw-r--r--src/sys/fs/tmpfs.c375
-rw-r--r--src/sys/include/compat/unix/syscall.h15
-rw-r--r--src/sys/include/fs/devfs.h1
-rw-r--r--src/sys/include/os/filedesc.h34
-rw-r--r--src/sys/include/os/kalloc.h8
-rw-r--r--src/sys/include/os/ucred.h61
-rw-r--r--src/sys/include/os/vnode.h52
-rw-r--r--src/sys/include/sys/fcntl.h1
-rw-r--r--src/sys/include/sys/mman.h9
-rw-r--r--src/sys/include/sys/mount.h5
-rw-r--r--src/sys/include/sys/namei.h2
-rw-r--r--src/sys/include/sys/proc.h2
-rw-r--r--src/sys/include/sys/seek.h37
-rw-r--r--src/sys/include/sys/socket.h83
-rw-r--r--src/sys/include/sys/syscall.h5
-rw-r--r--src/sys/include/sys/types.h1
-rw-r--r--src/sys/include/sys/ucred.h48
-rw-r--r--src/sys/include/vm/map.h6
-rw-r--r--src/sys/io/cons/cons.c20
-rw-r--r--src/sys/io/ic/ahci.c28
-rw-r--r--src/sys/os/os_filedes.c88
-rw-r--r--src/sys/os/os_iotap.c3
-rw-r--r--src/sys/os/os_kalloc.c11
-rw-r--r--src/sys/os/os_null.c2
-rw-r--r--src/sys/os/os_proc.c8
-rw-r--r--src/sys/os/os_socket.c256
-rw-r--r--src/sys/os/os_ucred.c90
-rw-r--r--src/sys/os/vfs_init.c3
-rw-r--r--src/sys/os/vfs_namei.c75
-rw-r--r--src/sys/os/vfs_subr.c43
-rw-r--r--src/sys/vm/vm_map.c61
52 files changed, 1882 insertions, 84 deletions
diff --git a/src/cmd/Makefile b/src/cmd/Makefile
index 1263be8..7c51ebf 100644
--- a/src/cmd/Makefile
+++ b/src/cmd/Makefile
@@ -20,6 +20,10 @@ all:
LIBC_DIR=$(shell pwd)/../$(LIBC_DIR)
cd echo/; make LDSCRIPT=$(LDSCRIPT) CC=$(CC) AS=$(AS) LD=$(LD) SYSROOT=$(SYSROOT) \
LIBC_DIR=$(shell pwd)/../$(LIBC_DIR)
+ cd cat/; make LDSCRIPT=$(LDSCRIPT) CC=$(CC) AS=$(AS) LD=$(LD) SYSROOT=$(SYSROOT) \
+ LIBC_DIR=$(shell pwd)/../$(LIBC_DIR)
+ cd mex/; make LDSCRIPT=$(LDSCRIPT) CC=$(CC) AS=$(AS) LD=$(LD) SYSROOT=$(SYSROOT) \
+ LIBC_DIR=$(shell pwd)/../$(LIBC_DIR)
.PHONY: clean
clean:
@@ -30,3 +34,5 @@ clean:
cd lsdisk/; make clean
cd login/; make clean
cd echo/; make clean
+ cd cat/; make clean
+ cd mex/; make clean
diff --git a/src/cmd/cat/Makefile b/src/cmd/cat/Makefile
new file mode 100644
index 0000000..8ae32ac
--- /dev/null
+++ b/src/cmd/cat/Makefile
@@ -0,0 +1,16 @@
+include ../../data/build/user.mk
+
+CFILES = $(shell find . -name "*.c")
+CFILES = $(shell find . -name "*.c")
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) -L../../lib/libc/ -lc
+OBJECTS = $(CFILES:%.c=%.o)
+
+$(SYSROOT)/usr/bin/cat: $(OBJECTS)
+ $(LD) $(OBJECTS) -o $@ $(CFLAGS)
+
+%.o: %.c
+ $(CC) $(INTERNAL_CFLAGS) -c $(CFLAGS) $< -o $@
+
+.PHONY: clean
+clean:
+ rm -f *.o *.d
diff --git a/src/cmd/cat/cat.c b/src/cmd/cat/cat.c
new file mode 100644
index 0000000..bb5049d
--- /dev/null
+++ b/src/cmd/cat/cat.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <fcntl.h>
+
+static void
+cat(const char *path)
+{
+ char buf[128];
+ ssize_t len;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ printf("error: could not open \"%s\"\n", path);
+ return;
+ }
+
+ /* Read chunk by chunk */
+ while ((len = read(fd, buf, sizeof(buf))) > 0) {
+ printf("%s", buf);
+ }
+
+ close(fd);
+}
+
+int
+main(void)
+{
+ for (int i = 1; i < __argc; ++i) {
+ cat(__argv[i]);
+ }
+
+ return 0;
+}
diff --git a/src/cmd/echo/Makefile b/src/cmd/echo/Makefile
index 40b3d93..0ebf3fd 100644
--- a/src/cmd/echo/Makefile
+++ b/src/cmd/echo/Makefile
@@ -2,9 +2,7 @@ include ../../data/build/user.mk
CFILES = $(shell find . -name "*.c")
CFILES = $(shell find . -name "*.c")
-CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) \
- -L../../lib/libwidget -lwidget -L../../lib/libc/ -lc \
- -I../../lib/libwidget/include/
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) -L../../lib/libc/ -lc
OBJECTS = $(CFILES:%.c=%.o)
$(SYSROOT)/usr/bin/echo: $(OBJECTS)
diff --git a/src/cmd/fetch/Makefile b/src/cmd/fetch/Makefile
index bcc5da2..1f6461f 100644
--- a/src/cmd/fetch/Makefile
+++ b/src/cmd/fetch/Makefile
@@ -2,9 +2,7 @@ include ../../data/build/user.mk
CFILES = $(shell find . -name "*.c")
CFILES = $(shell find . -name "*.c")
-CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) \
- -L../../lib/libwidget -lwidget -L../../lib/libc/ -lc \
- -I../../lib/libwidget/include/
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) -L../../lib/libc/ -lc
OBJECTS = $(CFILES:%.c=%.o)
$(SYSROOT)/usr/bin/fetch: $(OBJECTS)
diff --git a/src/cmd/hush/Makefile b/src/cmd/hush/Makefile
index 29ac3b0..d97efa3 100644
--- a/src/cmd/hush/Makefile
+++ b/src/cmd/hush/Makefile
@@ -2,9 +2,7 @@ include ../../data/build/user.mk
CFILES = $(shell find . -name "*.c")
CFILES = $(shell find . -name "*.c")
-CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) \
- -L../../lib/libwidget -lwidget -L../../lib/libc/ -lc \
- -I../../lib/libwidget/include/
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) -L../../lib/libc/ -lc
OBJECTS = $(CFILES:%.c=%.o)
$(SYSROOT)/usr/bin/hush: $(OBJECTS)
diff --git a/src/cmd/init/Makefile b/src/cmd/init/Makefile
index b58b223..73fefe5 100644
--- a/src/cmd/init/Makefile
+++ b/src/cmd/init/Makefile
@@ -2,9 +2,7 @@ include ../../data/build/user.mk
CFILES = $(shell find . -name "*.c")
CFILES = $(shell find . -name "*.c")
-CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) \
- -L../../lib/libwidget -lwidget -L../../lib/libc/ -lc \
- -I../../lib/libwidget/include/
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) -L../../lib/libc/ -lc
OBJECTS = $(CFILES:%.c=%.o)
$(SYSROOT)/usr/bin/init: $(OBJECTS)
diff --git a/src/cmd/init/init.c b/src/cmd/init/init.c
index 3f39743..7851c9c 100644
--- a/src/cmd/init/init.c
+++ b/src/cmd/init/init.c
@@ -28,13 +28,41 @@
*/
#include <sys/spawn.h>
+#include <sys/mount.h>
#include <stddef.h>
+#include <stdio.h>
void
main(void)
{
char login_path[] = "/usr/sbin/login";
char *argv_dmmy[] = { "/usr/sbin/login", NULL };
+ int error;
+
+ /* Mount tmpfs */
+ error = mount(
+ NULL,
+ "/tmp",
+ MOUNT_TMPFS,
+ 0,
+ NULL
+ );
+
+ if (error < 0) {
+ printf("init: failed to mount tmpfs\n");
+ }
+
+ error = mount(
+ NULL,
+ "/dev",
+ MOUNT_DEVFS,
+ 0,
+ NULL
+ );
+
+ if (error < 0) {
+ printf("init: failed to mount devfs\n");
+ }
spawn(login_path, argv_dmmy);
for (;;);
diff --git a/src/cmd/login/Makefile b/src/cmd/login/Makefile
index f0018e8..f9a9fff 100644
--- a/src/cmd/login/Makefile
+++ b/src/cmd/login/Makefile
@@ -2,9 +2,7 @@ include ../../data/build/user.mk
CFILES = $(shell find . -name "*.c")
CFILES = $(shell find . -name "*.c")
-CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) \
- -L../../lib/libwidget -lwidget -L../../lib/libc/ -lc \
- -I../../lib/libwidget/include/
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) -L../../lib/libc/ -lc
OBJECTS = $(CFILES:%.c=%.o)
$(SYSROOT)/usr/sbin/login: $(OBJECTS)
diff --git a/src/cmd/lsdisk/Makefile b/src/cmd/lsdisk/Makefile
index 721f530..b785bde 100644
--- a/src/cmd/lsdisk/Makefile
+++ b/src/cmd/lsdisk/Makefile
@@ -2,9 +2,7 @@ include ../../data/build/user.mk
CFILES = $(shell find . -name "*.c")
CFILES = $(shell find . -name "*.c")
-CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) \
- -L../../lib/libwidget -lwidget -L../../lib/libc/ -lc \
- -I../../lib/libwidget/include/
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) -L../../lib/libc/ -lc
OBJECTS = $(CFILES:%.c=%.o)
$(SYSROOT)/usr/bin/lsdisk: $(OBJECTS)
diff --git a/src/cmd/mex/Makefile b/src/cmd/mex/Makefile
new file mode 100644
index 0000000..bc88287
--- /dev/null
+++ b/src/cmd/mex/Makefile
@@ -0,0 +1,18 @@
+include ../../data/build/user.mk
+
+CFILES = $(shell find . -name "*.c")
+CFILES = $(shell find . -name "*.c")
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) \
+ -L../../lib/libwidget -lwidget -L../../lib/libc/ -lc \
+ -I../../lib/libwidget/include/
+OBJECTS = $(CFILES:%.c=%.o)
+
+$(SYSROOT)/usr/bin/mex: $(OBJECTS)
+ $(LD) $(OBJECTS) -o $@ $(CFLAGS)
+
+%.o: %.c
+ $(CC) $(INTERNAL_CFLAGS) -c $(CFLAGS) $< -o $@
+
+.PHONY: clean
+clean:
+ rm -f *.o *.d
diff --git a/src/cmd/mex/mex.c b/src/cmd/mex/mex.c
new file mode 100644
index 0000000..da501c3
--- /dev/null
+++ b/src/cmd/mex/mex.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define LINE_LEN 16
+
+static void
+dump_line(const char *line, size_t len)
+{
+ /* The amount of bytes we write */
+ const uint8_t BYTE_COUNT = 2;
+
+ for (size_t i = 0; i < LINE_LEN; ++i) {
+ if (i < len) {
+ printf("%02x", line[i] & 0xFF);
+ } else {
+ printf(" ");
+ }
+
+ /* Put spacing between bytes */
+ if (((i + 1) % BYTE_COUNT) == 0) {
+ printf(" ");
+ }
+ }
+
+ printf(" ");
+ for (size_t i = 0; i < len; ++i) {
+ if (line[i] > 31 && line[i] < 127) {
+ printf("%c", line[i]);
+ } else {
+ printf(".");
+ }
+ }
+
+ printf("\n");
+}
+
+static void
+dump_file(int fd)
+{
+ char buf[LINE_LEN];
+ ssize_t count;
+ size_t offset = 0;
+
+ for (;;) {
+ count = read(fd, buf, sizeof(char) * LINE_LEN);
+ if (count <= 0) {
+ break;
+ }
+
+ printf("%08x: ", offset);
+ offset += LINE_LEN;
+ dump_line(buf, count);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+
+ if (__argc < 2) {
+ printf("mex: usage: mex <filename>\n");
+ return -1;
+ }
+
+ if ((fd = open(__argv[1], O_RDONLY)) < 0) {
+ printf("mex: failed to open input\n");
+ return fd;
+ }
+
+ dump_file(fd);
+ close(fd);
+ return 0;
+}
diff --git a/src/cmd/reboot/Makefile b/src/cmd/reboot/Makefile
index be5c21f..c39fcb9 100644
--- a/src/cmd/reboot/Makefile
+++ b/src/cmd/reboot/Makefile
@@ -2,9 +2,7 @@ include ../../data/build/user.mk
CFILES = $(shell find . -name "*.c")
CFILES = $(shell find . -name "*.c")
-CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) \
- -L../../lib/libwidget -lwidget -L../../lib/libc/ -lc \
- -I../../lib/libwidget/include/
+CFLAGS = -L$(LIBC_DIR) -lc $(INTERNAL_CFLAGS) -L../../lib/libc/ -lc
OBJECTS = $(CFILES:%.c=%.o)
$(SYSROOT)/usr/bin/reboot: $(OBJECTS)
diff --git a/src/lib/libc/include/unistd.h b/src/lib/libc/include/unistd.h
index b668d5b..61b437c 100644
--- a/src/lib/libc/include/unistd.h
+++ b/src/lib/libc/include/unistd.h
@@ -30,6 +30,7 @@
#ifndef _UNISTD_H
#define _UNISTD_H 1
+#include <sys/seek.h>
#include <stddef.h>
/* Standard stream file numbers */
@@ -74,4 +75,13 @@ ssize_t write(int fd, const void *buf, size_t count);
*/
ssize_t read(int fd, void *buf, size_t count);
+/*
+ * Reposition the file offset of a file
+ *
+ * @fd: File descriptor to reposition
+ * @offset: Offset to move `fd' to
+ * @whence: How it should be repositioned
+ */
+off_t lseek(int fd, off_t offset, int whence);
+
#endif /* _UNISTD_H */
diff --git a/src/lib/libc/src/l5/mmap.c b/src/lib/libc/src/l5/mmap.c
new file mode 100644
index 0000000..14471c5
--- /dev/null
+++ b/src/lib/libc/src/l5/mmap.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/syscall.h>
+#include <sys/mman.h>
+
+void *
+mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
+{
+ return (void *)syscall(
+ SYS_mmap,
+ (uintptr_t)addr,
+ (int)len,
+ prot,
+ flags,
+ fildes,
+ off
+ );
+}
diff --git a/src/lib/libc/src/unistd/lseek.c b/src/lib/libc/src/unistd/lseek.c
new file mode 100644
index 0000000..ade0a1e
--- /dev/null
+++ b/src/lib/libc/src/unistd/lseek.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <errno.h>
+
+off_t
+lseek(int fd, off_t offset, int whence)
+{
+ if (fd < 0) {
+ return -EBADF;
+ }
+
+ return syscall(
+ SYS_lseek,
+ fd,
+ offset,
+ whence
+ );
+}
diff --git a/src/sys/arch/amd64/cpu/cpu_conf.c b/src/sys/arch/amd64/cpu/cpu_conf.c
index da2d747..8a3b4e6 100644
--- a/src/sys/arch/amd64/cpu/cpu_conf.c
+++ b/src/sys/arch/amd64/cpu/cpu_conf.c
@@ -44,7 +44,9 @@
extern void syscall_isr(void);
extern void core_halt_isr(void);
+
void core_halt_handler(void);
+int simd_init(void);
void
core_halt_handler(void)
@@ -193,6 +195,7 @@ cpu_conf(struct pcore *pcore)
pcore->self = pcore;
wrmsr(IA32_GS_BASE, (uintptr_t)pcore);
+ simd_init();
init_vectors();
idt_load();
cpu_identify(mdcore);
diff --git a/src/sys/arch/amd64/cpu/trap.c b/src/sys/arch/amd64/cpu/trap.c
index ae3a0cc..94c6e83 100644
--- a/src/sys/arch/amd64/cpu/trap.c
+++ b/src/sys/arch/amd64/cpu/trap.c
@@ -34,6 +34,7 @@
#include <sys/param.h>
#include <sys/cdefs.h>
+#include <sys/errno.h>
#include <sys/panic.h>
#include <sys/cpuvar.h>
#include <sys/syslog.h>
@@ -148,6 +149,26 @@ trapframe_dump(struct trapframe *tf)
tf->rbp, tf->rsp, tf->rip);
}
+/*
+ * Handle user faults
+ */
+static void
+handle_ufault(void)
+{
+ struct proc *self = proc_self();
+
+ if (__unlikely(self == NULL)) {
+ panic("could not get self on fault\n");
+ }
+
+ syslog_toggle(true);
+ printf("** hardware violation **\n");
+ syslog_toggle(false);
+
+ proc_kill(self, -EFAULT);
+ __builtin_unreachable();
+}
+
void
trap_syscall(struct trapframe *tf)
{
@@ -194,7 +215,8 @@ trap_handler(struct trapframe *tf)
{
trapframe_dump(tf);
if (ISSET(tf->cs, 3)) {
- panic("fatal user trap\n");
+ handle_ufault();
+ __builtin_unreachable();
}
panic("fatal trap\n");
diff --git a/src/sys/arch/amd64/os/os_panic.c b/src/sys/arch/amd64/os/os_panic.c
index 88e962e..996ba13 100644
--- a/src/sys/arch/amd64/os/os_panic.c
+++ b/src/sys/arch/amd64/os/os_panic.c
@@ -37,12 +37,16 @@ __dead
void panic(const char *fmt, ...)
{
static va_list ap;
+ struct pcore *core = this_core();
+ uint32_t core_id;
cpu_halt_others();
va_start(ap, fmt);
- printf("lunos panic: ");
+ core_id = (core == NULL) ? 0xFF : core->id;
+ printf("lunos panic[cpu %d]: ", core_id);
vprintf(fmt, &ap);
+
for (;;) {
md_intoff();
md_halt();
diff --git a/src/sys/arch/amd64/simd.S b/src/sys/arch/amd64/simd.S
new file mode 100644
index 0000000..f0673f9
--- /dev/null
+++ b/src/sys/arch/amd64/simd.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ .text
+ .globl simd_init
+simd_init:
+ /*
+ * Enable SIMD, if SSE and AVX is supported,
+ * a value of zero is returned. If SSE is
+ * supported yet AVX is not, a value of one
+ * is returned. However, if none are supported,
+ * this routine returns -1.
+ */
+
+ // Do we support SSE?
+ mov $1, %eax
+ cpuid
+ bt $25, %edx
+ jnc .sse_not_sup
+
+ mov %cr0, %rax // Old CR0 -> EAX
+ and $0xFFFB, %ax // Disable co-processor emulation
+ or $0x02, %ax // Enable co-processor monitoring
+ mov %rax, %cr0 // Update CR0 with new flags
+
+ mov %cr4, %rax // Old CR4 -> EAX
+ or $0x200, %ax // Enable FXSAVE/FXRSTOR
+ or $0x400, %ax // Enable SIMD FP exceptions
+ mov %rax, %cr4 // Update CR4 with new flags
+
+ mov $1, %eax // LEAF 1
+ cpuid // Bit 28 of ECX indicates AVX support
+ mov $3, %eax // We need to check two bits
+ shl $27, %eax // Which are ECX.OSXSAVE and ECX.AVX
+ test %eax, %ecx // Are XSAVE and AVX supported?
+ jnc .avx_not_sup // Nope, just continue
+
+ // Enable AVX
+ xor %rcx, %rcx // Select XCR0
+ xgetbv // Load extended control register
+ or $0x07, %eax // Set AVX + SSE bits
+ xsetbv // Store new flags
+ xor %rax, %rax // Everything is good
+ retq // Return back to caller (RETURN)
+.sse_not_sup:
+ mov $-1, %rax
+ retq
+.avx_not_sup:
+ mov $1, %rax
+ retq
diff --git a/src/sys/fs/devfs.c b/src/sys/fs/devfs.c
index 7553003..0e6b8ef 100644
--- a/src/sys/fs/devfs.c
+++ b/src/sys/fs/devfs.c
@@ -72,12 +72,13 @@ devfs_lookup(struct vop_lookup_args *args)
}
/* Found it! Create a vnode */
- error = vfs_valloc(&vp, VTYPE_FILE, 0);
+ error = vfs_valloc(&vp, VTYPE_CDEV, 0);
if (error < 0) {
return error;
}
vp->data = dnp;
+ vp->vops = &devfs_vops;
*args->vpp = vp;
return 0;
}
@@ -116,6 +117,7 @@ devfs_register(const char *name, dev_type_t type, void *devsw, int flags)
break;
}
+ dnp->dev = devsw;
devname_len = strlen(name);
memcpy(dnp->name, name, devname_len);
TAILQ_INSERT_TAIL(&nodelist, dnp, link);
@@ -123,6 +125,53 @@ devfs_register(const char *name, dev_type_t type, void *devsw, int flags)
}
/*
+ * Read a character device
+ */
+static int
+devfs_cdev_read(struct devfs_node *dnp, struct dev_iobuf *iobuf, int flags)
+{
+ struct cdevsw *cdev;
+
+ if (dnp == NULL || iobuf == NULL) {
+ return -EINVAL;
+ }
+
+ if ((cdev = dnp->cdev) == NULL) {
+ return -EIO;
+ }
+
+ return cdev->read(dnp, iobuf, flags);
+}
+
+/*
+ * VFS read callback for devfs
+ */
+static ssize_t
+devfs_read(struct vop_rw_data *args)
+{
+ struct vnode *vp;
+ struct devfs_node *dnp;
+ struct dev_iobuf iobuf;
+
+ if ((vp = args->vp) == NULL) {
+ return -EIO;
+ }
+
+ if ((dnp = vp->data) == NULL) {
+ return -EIO;
+ }
+
+ iobuf.buf = args->data;
+ iobuf.count = args->len;
+ iobuf.off = args->off;
+ if (dnp->type == DEVFS_CDEV) {
+ return devfs_cdev_read(dnp, &iobuf, 0);
+ }
+
+ return -EIO;
+}
+
+/*
* Initialize the device filesystem
*/
static int
@@ -157,10 +206,11 @@ devfs_mount(struct fs_info *fip, struct mount_args *margs)
}
static struct vop devfs_vops = {
- .lookup = devfs_lookup
+ .lookup = devfs_lookup,
+ .read = devfs_read
};
-struct vfsops g_devfs_vfops = {
+struct vfsops g_devfs_vfsops = {
.init = devfs_init,
.mount = devfs_mount
};
diff --git a/src/sys/fs/tmpfs.c b/src/sys/fs/tmpfs.c
new file mode 100644
index 0000000..3048fb4
--- /dev/null
+++ b/src/sys/fs/tmpfs.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/syslog.h>
+#include <sys/errno.h>
+#include <sys/queue.h>
+#include <sys/param.h>
+#include <os/vnode.h>
+#include <os/kalloc.h>
+#include <string.h>
+
+#define TMPFS_NAMEMAX 128
+#define TMPFS_INIT_SIZE 8
+
+/*
+ * Represents a single tmpfs node
+ */
+struct tmpfs_node {
+ char name[TMPFS_NAMEMAX];
+ char *data;
+ size_t len;
+ size_t real_len;
+ int ref;
+ vtype_t vtype; /* vnode vtype mapping */
+ TAILQ_ENTRY(tmpfs_node) link;
+};
+
+#define tmpfs_ref(TMP_NODEP) \
+ atomic_inc_int(&(TMP_NODEP)->ref)
+
+static TAILQ_HEAD(, tmpfs_node) tmpfs;
+static struct vop tmpfs_vops;
+
+/*
+ * Create a new tmpfs node
+ *
+ * @name: Name of node to create
+ * @type: Type of vnode file should be associated with
+ * @np_res: Result pointer is written here
+ *
+ * Returns zero on success, otherwise a less than
+ * zero value on failure
+ */
+static int
+tmpfs_new(const char *name, vtype_t type, struct tmpfs_node **np_res)
+{
+ struct tmpfs_node *np;
+ size_t name_len;
+
+ if (name == NULL) {
+ return -EINVAL;
+ }
+
+ name_len = strlen(name);
+ if (name_len > sizeof(np->name) - 1) {
+ return -ENAMETOOLONG;
+ }
+
+ np = kalloc(sizeof(*np));
+ if (np == NULL) {
+ return -ENOMEM;
+ }
+
+ memset(np, 0, sizeof(*np));
+ np->data = kalloc(TMPFS_INIT_SIZE);
+ if (np->data == NULL) {
+ kfree(np);
+ return -ENOMEM;
+ }
+
+ np->real_len = 0;
+ np->len = TMPFS_INIT_SIZE;
+ np->ref = 1;
+ np->vtype = type;
+ memset(np->data, 0, TMPFS_INIT_SIZE);
+ memcpy(np->name, name, name_len);
+
+ if (np_res != NULL) {
+ *np_res = np;
+ }
+
+ TAILQ_INSERT_TAIL(&tmpfs, np, link);
+ return 0;
+}
+
+/*
+ * Lookup a tmpfs node by name
+ *
+ * @name: Name to lookup
+ * @np_res: Result is written here
+ */
+static int
+tmpfs_byname(const char *name, struct tmpfs_node **np_res)
+{
+ struct tmpfs_node *npcur;
+ int retval = -ENOENT;
+
+ if (name == NULL || np_res == NULL) {
+ return -EINVAL;
+ }
+
+ TAILQ_FOREACH(npcur, &tmpfs, link) {
+ if (npcur == NULL) {
+ continue;
+ }
+
+ if (strcmp(npcur->name, name) == 0) {
+ retval = 0;
+ *np_res = npcur;
+ break;
+ }
+ }
+
+ return retval;
+}
+
+/*
+ * VFS tmpfs lookup callback
+ */
+static int
+tmpfs_lookup(struct vop_lookup_args *args)
+{
+ struct tmpfs_node *np;
+ struct vnode *vp;
+ int error;
+
+ /* Sanity checks */
+ if (args == NULL)
+ return -EINVAL;
+ if (args->name == NULL)
+ return -EINVAL;
+ if (args->vpp == NULL)
+ return -EINVAL;
+
+ error = tmpfs_byname(args->name, &np);
+ if (error < 0) {
+ return error;
+ }
+
+ error = vfs_valloc(&vp, np->vtype, 0);
+ if (error < 0) {
+ return error;
+ }
+
+ /* Ref that node and give it */
+ tmpfs_ref(np);
+ vp->data = np;
+ vp->vops = &tmpfs_vops;
+ *args->vpp = vp;
+ return 0;
+}
+
+/*
+ * Create a tmpfs node
+ */
+static int
+tmpfs_create(struct vop_create_args *args)
+{
+ struct nameidata *ndp;
+ struct tmpfs_node *np = NULL;
+
+ if (args == NULL) {
+ return -EINVAL;
+ }
+
+ if ((ndp = args->ndp) == NULL) {
+ return -EINVAL;
+ }
+
+ /* Does it already exist? */
+ if (tmpfs_byname(ndp->path, &np) == 0) {
+ return -EEXIST;
+ }
+
+ /* Only accept the types we support */
+ switch (args->vtype) {
+ case VTYPE_FILE:
+ case VTYPE_SOCK:
+ break;
+ default:
+ return -ENOTSUP;
+ }
+
+ return tmpfs_new(ndp->path, args->vtype, NULL);
+}
+
+/*
+ * Initialize the temporary filesystem
+ */
+static int
+tmpfs_init(struct fs_info *fip)
+{
+ TAILQ_INIT(&tmpfs);
+ return 0;
+}
+
+/*
+ * Mount the filesystem
+ */
+static int
+tmpfs_mount(struct fs_info *fip, struct mount_args *margs)
+{
+ int error;
+ struct vnode *vp;
+
+ if (fip == NULL || margs == NULL) {
+ return -1;
+ }
+
+ /* Allocate a vnode for this mountpoint */
+ error = vfs_valloc(&margs->vp_res, VTYPE_DIR, 0);
+ if (error < 0) {
+ return error;
+ }
+
+ vp = margs->vp_res;
+ vp->vops = &tmpfs_vops;
+ return 0;
+}
+
+/*
+ * Write to the filesystem
+ */
+static ssize_t
+tmpfs_write(struct vop_rw_data *data)
+{
+ struct vnode *vp;
+ struct tmpfs_node *np;
+ char *dest;
+ void *p;
+ size_t node_len, len;
+ size_t overflow_window;
+
+ if (data == NULL) {
+ return -EINVAL;
+ }
+
+ if ((vp = data->vp) == NULL) {
+ return -EIO;
+ }
+
+ /* We need the vnode for lengths */
+ if ((np = vp->data) == NULL) {
+ return -EIO;
+ }
+
+ /*
+ * Check if there is going to be any overflows
+ * and if so, get the overflow window and expand
+ * the buffer by it.
+ */
+ len = data->len;
+ if ((len + data->off) > np->len) {
+ overflow_window = (len + data->off) - np->len;
+ np->len += overflow_window + 1;
+
+ p = np->data;
+ np->data = krealloc(np->data, np->len);
+ if (np->data == NULL) {
+ np->data = p;
+ return -ENOMEM;
+ }
+ }
+
+ np->real_len += len;
+ node_len = np->len;
+ dest = np->data + data->off;
+ memcpy(dest, data->data, len);
+ return len;
+}
+
+static ssize_t
+tmpfs_read(struct vop_rw_data *data)
+{
+ struct vnode *vp;
+ struct tmpfs_node *np;
+ size_t len;
+ char *dest, *src;
+
+ if (data == NULL) {
+ return -1;
+ }
+
+ if ((vp = data->vp) == NULL) {
+ return -EIO;
+ }
+
+ if ((np = vp->data) == NULL) {
+ return -EIO;
+ }
+
+ /* Return EOF if the offset is too far */
+ len = data->len;
+ if (data->off >= np->real_len) {
+ return 0; /* EOF */
+ }
+
+ /* Is there any data to read? */
+ if ((len + data->off) > np->len) {
+ len = np->len;
+ }
+ if (len == 0) {
+ return 0;
+ }
+
+ dest = data->data;
+ src = np->data + data->off;
+ memcpy(dest, src, len);
+ return len;
+}
+
+static int
+tmpfs_getattr(struct vnode *vp, struct vattr *res)
+{
+ struct tmpfs_node *np;
+
+ if (vp == NULL || res == NULL) {
+ return -EINVAL;
+ }
+
+ if ((np = vp->data) == NULL) {
+ return -EIO;
+ }
+
+ res->size = np->real_len;
+ return 0;
+}
+
+static int
+tmpfs_reclaim(struct vnode *vp, int flags)
+{
+ return 0;
+}
+
+static struct vop tmpfs_vops = {
+ .lookup = tmpfs_lookup,
+ .create = tmpfs_create,
+ .reclaim = tmpfs_reclaim,
+ .write = tmpfs_write,
+ .read = tmpfs_read,
+ .getattr = tmpfs_getattr
+};
+
+struct vfsops g_tmpfs_vfsops = {
+ .init = tmpfs_init,
+ .mount = tmpfs_mount,
+};
diff --git a/src/sys/include/compat/unix/syscall.h b/src/sys/include/compat/unix/syscall.h
index a031872..5df3c51 100644
--- a/src/sys/include/compat/unix/syscall.h
+++ b/src/sys/include/compat/unix/syscall.h
@@ -31,12 +31,15 @@
#define _UNIX_SYSCALL_H_ 1
#include <sys/proc.h>
+#include <sys/socket.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/syscall.h>
+#include <os/ucred.h>
#include <os/iotap.h>
#include <os/reboot.h>
#include <dms/dms.h>
+#include <vm/map.h>
/*
* Exit the current process - exit(2) syscall
@@ -73,6 +76,11 @@ scret_t sys_read(struct syscall_args *scargs);
*/
scret_t sys_close(struct syscall_args *scargs);
+/*
+ * Seek a file descriptor
+ */
+scret_t sys_lseek(struct syscall_args *scargs);
+
#ifdef _NEED_UNIX_SCTAB
scret_t(*g_unix_sctab[])(struct syscall_args *) = {
[SYS_none] = NULL,
@@ -89,7 +97,12 @@ scret_t(*g_unix_sctab[])(struct syscall_args *) = {
[SYS_waitpid] = sys_waitpid,
[SYS_dmsio] = sys_dmsio,
[SYS_read] = sys_read,
- [SYS_close] = sys_close
+ [SYS_close] = sys_close,
+ [SYS_lseek] = sys_lseek,
+ [SYS_socket] = sys_socket,
+ [SYS_listen] = sys_listen,
+ [SYS_seteuid] = sys_seteuid,
+ [SYS_mmap] = sys_mmap
};
#endif /* !_NEED_UNIX_SCTAB */
diff --git a/src/sys/include/fs/devfs.h b/src/sys/include/fs/devfs.h
index ea96cdd..68c910f 100644
--- a/src/sys/include/fs/devfs.h
+++ b/src/sys/include/fs/devfs.h
@@ -45,6 +45,7 @@ struct devfs_node;
struct dev_iobuf {
void *buf;
size_t count;
+ off_t off;
};
/*
diff --git a/src/sys/include/os/filedesc.h b/src/sys/include/os/filedesc.h
index a6a2ac5..95400ed 100644
--- a/src/sys/include/os/filedesc.h
+++ b/src/sys/include/os/filedesc.h
@@ -30,6 +30,7 @@
#ifndef _OS_FILEDESC_H_
#define _OS_FILEDESC_H_ 1
+#include <sys/seek.h>
#include <sys/types.h>
#include <os/vnode.h>
@@ -51,6 +52,18 @@ struct filedesc {
};
/*
+ * Allocate a file descriptor from a specific process's
+ * file descriptor table
+ *
+ * @procp: Process to allocate fd from
+ * @fd_res: Result pointer is written here
+ *
+ * Returns zero on success, otherwise a less than
+ * zero value upon failure
+ */
+int fd_alloc(struct proc *procp, struct filedesc **fd_res);
+
+/*
* Duplicate a file descriptor
*
* @procp: Process to duplicate from
@@ -62,6 +75,18 @@ struct filedesc {
struct filedesc *fd_dup(struct proc *procp, int fd);
/*
+ * Look up a file descriptor that belongs to a specific
+ * process by using its fd number
+ *
+ * @procp: Process to look up
+ * @fd: File descriptor number
+ *
+ * Returns the file descriptor pointer on success,
+ * otherwise a less than zero value on failure
+ */
+struct filedesc *fd_get(struct proc *procp, int fd);
+
+/*
* Initialize a process file descriptor table
* and set up standard streams
*
@@ -117,4 +142,13 @@ ssize_t write(int fd, const void *buf, size_t count);
*/
ssize_t read(int fd, void *buf, size_t count);
+/*
+ * Reposition the file offset of a file
+ *
+ * @fd: File descriptor to reposition
+ * @offset: Offset to move `fd' to
+ * @whence: How it should be repositioned
+ */
+off_t lseek(int fd, off_t offset, int whence);
+
#endif /* !_OS_FILEDESC_H_ */
diff --git a/src/sys/include/os/kalloc.h b/src/sys/include/os/kalloc.h
index 143c4f9..aaaaa74 100644
--- a/src/sys/include/os/kalloc.h
+++ b/src/sys/include/os/kalloc.h
@@ -48,6 +48,14 @@
void *kalloc(size_t sz);
/*
+ * Reallocates memory pool created by `dynalloc()'
+ *
+ * @old_ptr: Pointer to old pool.
+ * @newsize: Size of new pool.
+ */
+void *krealloc(void *old_ptr, size_t newsize);
+
+/*
* Free a chunk of memory given to by
* `ptr'
*
diff --git a/src/sys/include/os/ucred.h b/src/sys/include/os/ucred.h
new file mode 100644
index 0000000..6e3e4b4
--- /dev/null
+++ b/src/sys/include/os/ucred.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _OS_UCRED_H_
+#define _OS_UCRED_H_ 1
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/ucred.h>
+#include <sys/proc.h>
+
+/*
+ * Initialize user credientials
+ *
+ * @proc: Current process
+ * @cred: credientials to initialize
+ *
+ * XXX: 'proc' being NULL drops the creds to root
+ *
+ * Returns zero on success, otherwise a less
+ * than zero value on failure.
+ */
+int ucred_init(struct proc *proc, struct ucred *cred);
+
+/*
+ * Set effective user ID
+ */
+int seteuid(uid_t euid);
+
+/*
+ * Set EUID system call
+ */
+scret_t sys_seteuid(struct syscall_args *scargs);
+
+#endif /* !_OS_UCRED_H_ */
diff --git a/src/sys/include/os/vnode.h b/src/sys/include/os/vnode.h
index 1bef1e2..9d8a3e6 100644
--- a/src/sys/include/os/vnode.h
+++ b/src/sys/include/os/vnode.h
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/atomic.h>
+#include <sys/namei.h>
/* Forward declarations */
struct vnode;
@@ -43,12 +44,16 @@ struct vop;
* @VTYPE_NONE: Vnode is yet to be assigned a type
* @VTYPE_FILE: Vnode references a file
* @VTYPE_DIR: Vnode references a directory
+ * @VTYPE_SOCK: Vnode references a socket
+ * @VTYPE_CDEV: Vnode references a character device
* @__N_VTYPE: Number of valid nodes on the system
*/
typedef enum {
VTYPE_NONE,
VTYPE_FILE,
VTYPE_DIR,
+ VTYPE_SOCK,
+ VTYPE_CDEV,
__N_VTYPE
} vtype_t;
@@ -83,12 +88,35 @@ struct vop_rw_data {
};
/*
+ * Arguments to create an entry within a
+ * filesystem
+ *
+ * @ndp: Path component to create
+ * @vtype: Vnode type
+ */
+struct vop_create_args {
+ struct nameidata *ndp;
+ vtype_t vtype;
+};
+
+/*
+ * Represents attributes of a vnode
+ *
+ * @size: File size in bytes
+ */
+struct vattr {
+ size_t size;
+};
+
+/*
* Represents operations that can be performed on
* a specific vnode. These are implemented as callbacks
*/
struct vop {
+ int(*getattr)(struct vnode *vp, struct vattr *res);
int(*lookup)(struct vop_lookup_args *args);
int(*reclaim)(struct vnode *vp, int flags);
+ int(*create)(struct vop_create_args *args);
ssize_t(*write)(struct vop_rw_data *data);
ssize_t(*read)(struct vop_rw_data *data);
};
@@ -176,4 +204,28 @@ ssize_t vop_read(struct vnode *vp, char *data, off_t off, size_t len);
*/
int vop_reclaim(struct vnode *vp, int flags);
+/*
+ * Create a node within a specific filesystem or
+ * directory
+ *
+ * @vp: Vnode of parent directory
+ * @ndp: Namei descriptor of path component
+ * @type: Vnode type to create with
+ *
+ * Returns zero on success, otherwise a less than zero
+ * value on failure.
+ */
+int vop_create(struct vnode *vp, struct nameidata *ndp, vtype_t type);
+
+/*
+ * Get the attributes of a file
+ *
+ * @vp: Vnode of file to get attributes of
+ * @res: Result of file to get attr of
+ *
+ * Returns zero on success, otherwise a less than
+ * zero value on failure
+ */
+int vop_getattr(struct vnode *vp, struct vattr *res);
+
#endif /* !_OS_VNODE_H_ */
diff --git a/src/sys/include/sys/fcntl.h b/src/sys/include/sys/fcntl.h
index 30d2ec4..1ab3e71 100644
--- a/src/sys/include/sys/fcntl.h
+++ b/src/sys/include/sys/fcntl.h
@@ -43,6 +43,7 @@
#define O_RDONLY 0x00
#define O_RDWR BIT(1)
#define O_WRONLY BIT(2)
+#define O_CREAT BIT(3)
/* File access mode flags */
#define O_ACCMODE (O_RDWR | O_WRONLY)
diff --git a/src/sys/include/sys/mman.h b/src/sys/include/sys/mman.h
index 7ae1ed2..0ad4959 100644
--- a/src/sys/include/sys/mman.h
+++ b/src/sys/include/sys/mman.h
@@ -30,7 +30,11 @@
#ifndef _SYS_MMAN_H_
#define _SYS_MMAN_H_ 1
+#include <sys/types.h>
#include <sys/param.h>
+#if !defined(_KERNEL)
+#include <stddef.h>
+#endif /* !_KERNEL */
#define PROT_READ BIT(0)
#define PROT_WRITE BIT(1)
@@ -39,4 +43,9 @@
#define PROT_USER BIT(3)
#endif /* _KERNEL */
+/*
+ * Map memory pages
+ */
+void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
+
#endif /* !_SYS_MMAN_H_ */
diff --git a/src/sys/include/sys/mount.h b/src/sys/include/sys/mount.h
index 6d041ee..5f6fa6b 100644
--- a/src/sys/include/sys/mount.h
+++ b/src/sys/include/sys/mount.h
@@ -42,6 +42,7 @@
*/
#define MOUNT_INITRD "initrd" /* Initial ramdisk */
#define MOUNT_DEVFS "devfs" /* Device filesystem */
+#define MOUNT_TMPFS "tmpfs" /* Temporary filesystem */
/*
* The mount system call
@@ -65,7 +66,8 @@ struct mount;
/* Filesystem vfsops */
extern struct vfsops g_omar_vfsops;
-extern struct vfsops g_devfs_vfops;
+extern struct vfsops g_devfs_vfsops;
+extern struct vfsops g_tmpfs_vfsops;
/*
* Represents a mountpoint
@@ -133,7 +135,6 @@ struct fs_info {
*/
#define FS_ATTR_IMAGE BIT(0) /* Is an image kind e.g., OSMORA OMAR */
-
/*
* VFS operations vector
*
diff --git a/src/sys/include/sys/namei.h b/src/sys/include/sys/namei.h
index 58307b1..9e78a4c 100644
--- a/src/sys/include/sys/namei.h
+++ b/src/sys/include/sys/namei.h
@@ -32,6 +32,8 @@
#include <os/vnode.h>
+#define NAMEI_CREATE BIT(0) /* Create as we go */
+
/*
* Represents namei data that can be used for
* looking up files
diff --git a/src/sys/include/sys/proc.h b/src/sys/include/sys/proc.h
index a547233..b188d50 100644
--- a/src/sys/include/sys/proc.h
+++ b/src/sys/include/sys/proc.h
@@ -30,6 +30,7 @@
#ifndef _SYS_PROC_H_
#define _SYS_PROC_H_
+#include <sys/ucred.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/cdefs.h>
@@ -91,6 +92,7 @@ struct proc {
struct penv_blk *envblk;
struct ptrbox *envblk_box;
struct proc *parent;
+ struct ucred cred;
mac_level_t level;
struct spinlock maplist_lock;
sigtab_t sigtab;
diff --git a/src/sys/include/sys/seek.h b/src/sys/include/sys/seek.h
new file mode 100644
index 0000000..1edc50b
--- /dev/null
+++ b/src/sys/include/sys/seek.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_SEEK_H_
+#define _SYS_SEEK_H_ 1
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#endif /* !_SYS_SEEK_H_ */
diff --git a/src/sys/include/sys/socket.h b/src/sys/include/sys/socket.h
new file mode 100644
index 0000000..0ca041f
--- /dev/null
+++ b/src/sys/include/sys/socket.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_SOCKET_H_
+#define _SYS_SOCKET_H_ 1
+
+#include <sys/types.h>
+#include <sys/syscall.h>
+
+/* Address family defines */
+#define AF_UNIX 0x00 /* Local comms / IPC */
+#define AF_LOCAL AF_UNIX /* AF_UNIX alias */
+
+/* Socket type defines */
+#define SOCK_STREAM 0x00
+#define SOCK_DGRAM 0x01
+
+/*
+ * Get a socket as a file descriptor
+ *
+ * @domain: Socket domain (AF_*)
+ * @type: Socket type SOCK_*
+ *
+ * Returns file descriptor on success, otherwise
+ * a less than zero value on failure
+ */
+int socket(int domain, int type, int protocol);
+
+/*
+ * @socket: Socket to listen on
+ * @backlog: Max connections
+ */
+int listen(int socket, int backlog);
+
+#if defined(_KERNEL)
+
+/*
+ * Kernel representation of a socket
+ *
+ * @backlog: Maximum connections (< 0 means socket not active)
+ */
+struct ksocket {
+ int backlog;
+};
+
+/*
+ * Socket syscall
+ */
+scret_t sys_socket(struct syscall_args *scargs);
+
+/*
+ * Listen syscall
+ */
+scret_t sys_listen(struct syscall_args *scargs);
+
+#endif /* _KERNEL */
+#endif /* !_SYS_SOCKET_H_ */
diff --git a/src/sys/include/sys/syscall.h b/src/sys/include/sys/syscall.h
index 77b7505..ee6ef48 100644
--- a/src/sys/include/sys/syscall.h
+++ b/src/sys/include/sys/syscall.h
@@ -58,6 +58,11 @@
#define SYS_dmsio 0x0D /* DMS I/O */
#define SYS_read 0x0E /* read a file descriptor */
#define SYS_close 0x0F /* close a file */
+#define SYS_lseek 0x10 /* seek to end of file */
+#define SYS_socket 0x11 /* get a socket fd */
+#define SYS_listen 0x12 /* listen on a socket */
+#define SYS_seteuid 0x13 /* set effective UID */
+#define SYS_mmap 0x14 /* map a virtual address */
typedef __ssize_t scret_t;
typedef __ssize_t scarg_t;
diff --git a/src/sys/include/sys/types.h b/src/sys/include/sys/types.h
index b1d5994..745eed7 100644
--- a/src/sys/include/sys/types.h
+++ b/src/sys/include/sys/types.h
@@ -96,7 +96,6 @@ typedef __size_t uintptr_t;
typedef __size_t off_t;
typedef int pid_t;
typedef int dev_t;
-typedef __uint32_t uid_t;
typedef __uint32_t mode_t;
typedef __uint32_t ino_t;
typedef __uint32_t nlink_t;
diff --git a/src/sys/include/sys/ucred.h b/src/sys/include/sys/ucred.h
new file mode 100644
index 0000000..ab44b6c
--- /dev/null
+++ b/src/sys/include/sys/ucred.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_UCRED_H_
+#define _SYS_UCRED_H_ 1
+
+#include <sys/types.h>
+
+/*
+ * Represents current user credientials
+ *
+ * @euid: Effective user ID
+ * @ruid: Real user ID
+ * @suid: Saved UID
+ */
+struct ucred {
+ uid_t euid;
+ uid_t ruid;
+ uid_t suid;
+};
+
+#endif /* !_SYS_UCRED_H_ */
diff --git a/src/sys/include/vm/map.h b/src/sys/include/vm/map.h
index 69d7d73..8183b62 100644
--- a/src/sys/include/vm/map.h
+++ b/src/sys/include/vm/map.h
@@ -31,6 +31,7 @@
#define _VM_MAP_H_ 1
#include <sys/types.h>
+#include <sys/syscall.h>
#include <sys/mman.h>
#include <machine/vas.h> /* standard */
#include <vm/mmu.h>
@@ -52,4 +53,9 @@
*/
int vm_map(struct vm_vas *vas, struct mmu_map *spec, size_t len, int prot);
+/*
+ * POSIX mmap syscall
+ */
+scret_t sys_mmap(struct syscall_args *scargs);
+
#endif /* !_VM_MAP_H_ */
diff --git a/src/sys/io/cons/cons.c b/src/sys/io/cons/cons.c
index a80644c..65d1f1b 100644
--- a/src/sys/io/cons/cons.c
+++ b/src/sys/io/cons/cons.c
@@ -37,6 +37,8 @@
#include <stdbool.h>
#include <string.h>
+#define TAB_WIDTH (FONT_WIDTH * 4)
+
/* kconf background color config */
#if defined(__CONS_BG)
#define DEFAULT_BG __CONS_BG
@@ -180,6 +182,21 @@ cons_backspace(struct cons_scr *scr)
cons_draw_cursor(scr, false);
}
+static void
+cons_tab(struct cons_scr *scr)
+{
+ cons_draw_cursor(scr, true);
+ scr->text_x += TAB_WIDTH;
+ scr->cursor_x += TAB_WIDTH;
+
+ /* Wrap to next line if needed */
+ if (scr->cursor_x >= scr->max_col) {
+ cons_newline(scr);
+ }
+
+ cons_draw_cursor(scr, false);
+}
+
/*
* Fill a screen with a desired background
* color
@@ -224,6 +241,9 @@ cons_handle_spec(struct cons_scr *scr, int c)
case ASCII_BS:
cons_backspace(scr);
return c;
+ case ASCII_HT:
+ cons_tab(scr);
+ return c;
}
return -1;
diff --git a/src/sys/io/ic/ahci.c b/src/sys/io/ic/ahci.c
index 383e531..f4b38d2 100644
--- a/src/sys/io/ic/ahci.c
+++ b/src/sys/io/ic/ahci.c
@@ -665,6 +665,7 @@ ahci_init_port(struct ahci_hba *hba, struct ahci_port *port)
const uint16_t BSIZE = 512;
volatile struct hba_port *regs;
struct ahci_cmd_hdr *cmdlist;
+ struct ahci_port *port_cpy;
uint32_t cmd, lo, hi;
size_t clen;
paddr_t pa;
@@ -718,8 +719,14 @@ ahci_init_port(struct ahci_hba *hba, struct ahci_port *port)
return error;
}
- TAILQ_INSERT_TAIL(&portlist, port, link);
- ahci_identify(hba, port);
+ port_cpy = kalloc(sizeof(*port_cpy));
+ if (port_cpy == NULL) {
+ return -ENOMEM;
+ }
+
+ memcpy(port_cpy, port, sizeof(*port_cpy));
+ TAILQ_INSERT_TAIL(&portlist, port_cpy, link);
+ ahci_identify(hba, port_cpy);
return 0;
}
@@ -730,7 +737,7 @@ static int
ahci_init_ports(struct ahci_hba *hba)
{
volatile struct hba_memspace *io = hba->io;
- struct ahci_port *port;
+ struct ahci_port port;
uint32_t pi, nbits;
int error;
@@ -743,20 +750,13 @@ ahci_init_ports(struct ahci_hba *hba)
/* Allocate a new port descriptor */
dtrace("port %d implemented\n", i);
- port = kalloc(sizeof(*port));
- if (port == NULL) {
- dtrace("failed to allocate port\n");
- continue;
- }
-
- port->io = &io->ports[i];
- port->portno = i;
- port->parent = hba;
+ port.io = &io->ports[i];
+ port.portno = i;
+ port.parent = hba;
/* Initialize the port */
- error = ahci_init_port(hba, port);
+ error = ahci_init_port(hba, &port);
if (error < 0) {
- ahci_port_detach(port);
dtrace("port init failed (error=%d)\n", error);
continue;
}
diff --git a/src/sys/os/os_filedes.c b/src/sys/os/os_filedes.c
index 95452af..3eaee0d 100644
--- a/src/sys/os/os_filedes.c
+++ b/src/sys/os/os_filedes.c
@@ -44,16 +44,9 @@
#define STDOUT_FILENO 1
/*
- * Allocate a file descriptor from a specific process's
- * file descriptor table
- *
- * @procp: Process to allocate fd from
- * @fd_res: Result pointer is written here
- *
- * Returns zero on success, otherwise a less than
- * zero value upon failure
+ * Allocate a file descriptor
*/
-static int
+int
fd_alloc(struct proc *procp, struct filedesc **fd_res)
{
struct filedesc *fd;
@@ -91,16 +84,9 @@ fd_alloc(struct proc *procp, struct filedesc **fd_res)
}
/*
- * Look up a file descriptor that belongs to a specific
- * process by using its fd number
- *
- * @procp: Process to look up
- * @fd: File descriptor number
- *
- * Returns the file descriptor pointer on success,
- * otherwise a less than zero value on failure
+ * Get a file descriptor
*/
-static struct filedesc *
+struct filedesc *
fd_get(struct proc *procp, int fd)
{
struct filedesc *fdp;
@@ -160,8 +146,10 @@ fd_open(const char *path, mode_t mode)
{
struct filedesc *fd;
struct nameidata nd;
+ struct vop_create_args creat_args;
struct proc *self = proc_self();
struct vnode *vp;
+ uint32_t namei_flags = 0;
int error;
/* We need the current proc */
@@ -180,12 +168,21 @@ fd_open(const char *path, mode_t mode)
}
/*
+ * If we are creating a new file, we'll need to
+ * get the parent vnode so that we can use the
+ * create vop.
+ */
+ if (ISSET(mode, O_CREAT)) {
+ namei_flags |= NAMEI_CREATE;
+ }
+
+ /*
* Now we try to do the lookup, we'll need
* the vnode for file references to be
* useful
*/
nd.path = path;
- nd.flags = 0;
+ nd.flags = namei_flags;
nd.vp_res = &vp;
error = namei(&nd);
if (error < 0) {
@@ -348,6 +345,44 @@ read(int fd, void *buf, size_t count)
return retval;
}
+off_t
+lseek(int fd, off_t offset, int whence)
+{
+ struct filedesc *fdp;
+ struct proc *self = proc_self();
+ struct vattr attr;
+ int error;
+
+ if (fd < 0) {
+ return -EBADF;
+ }
+
+ fdp = fd_get(self, fd);
+ if (fdp == NULL) {
+ return -EBADF;
+ }
+
+ /* Could not get vnode attributes */
+ error = vop_getattr(fdp->vp, &attr);
+ if (error < 0) {
+ return 0;
+ }
+
+ switch (whence) {
+ case SEEK_SET:
+ fdp->off = offset;
+ break;
+ case SEEK_CUR:
+ fdp->off += offset;
+ break;
+ case SEEK_END:
+ fdp->off = attr.size;
+ break;
+ }
+
+ return fdp->off;
+}
+
/*
* ARG0: Path
* ARG1: Mode
@@ -367,3 +402,18 @@ sys_open(struct syscall_args *scargs)
return fd_open(pathbuf, mode);
}
+
+/*
+ * ARG0: Fd
+ * ARG1: Offset
+ * ARG2: Whence
+ */
+scret_t
+sys_lseek(struct syscall_args *scargs)
+{
+ int fd = SCARG(scargs, int, 0);
+ off_t off = SCARG(scargs, off_t, 1);
+ int whence = SCARG(scargs, int, 2);
+
+ return lseek(fd, off, whence);
+}
diff --git a/src/sys/os/os_iotap.c b/src/sys/os/os_iotap.c
index 238acfe..54d1157 100644
--- a/src/sys/os/os_iotap.c
+++ b/src/sys/os/os_iotap.c
@@ -130,6 +130,9 @@ iotap_mux(const char *name, struct iotap_msg *msg)
ops = desc.ops;
switch (msg->opcode) {
case IOTAP_OPC_READ:
+ if (ops->read == NULL) {
+ return -ENOTSUP;
+ }
return ops->read(&desc, msg->buf, msg->len);
}
diff --git a/src/sys/os/os_kalloc.c b/src/sys/os/os_kalloc.c
index 53e2e13..a5e48e5 100644
--- a/src/sys/os/os_kalloc.c
+++ b/src/sys/os/os_kalloc.c
@@ -64,6 +64,17 @@ kalloc(size_t sz)
return tmp;
}
+void *
+krealloc(void *old_ptr, size_t newsize)
+{
+ void *tmp;
+
+ spinlock_acquire(&lock);
+ tmp = tlsf_realloc(tlsf_ctx, old_ptr, newsize);
+ spinlock_release(&lock);
+ return tmp;
+}
+
/*
* Memory deallocation
*/
diff --git a/src/sys/os/os_null.c b/src/sys/os/os_null.c
index e142c6f..ae0fcf4 100644
--- a/src/sys/os/os_null.c
+++ b/src/sys/os/os_null.c
@@ -41,7 +41,7 @@ static ssize_t
null_read(struct devfs_node *dnp, struct dev_iobuf *io, int flags)
{
/* We give you a whole lot of nothing! */
- return io->count;
+ return 0;
}
/*
diff --git a/src/sys/os/os_proc.c b/src/sys/os/os_proc.c
index a8f49d7..ef6c04c 100644
--- a/src/sys/os/os_proc.c
+++ b/src/sys/os/os_proc.c
@@ -40,6 +40,7 @@
#include <os/systm.h>
#include <vm/vm.h>
#include <vm/physseg.h>
+#include <os/ucred.h>
#include <os/elfload.h>
#include <os/signal.h>
#include <os/kalloc.h>
@@ -386,9 +387,14 @@ proc_spawn(const char *path, struct penv_blk *envbp)
proc->envblk = envbp;
proc->parent = proc_self();
+ error = ucred_init(proc->parent, &proc->cred);
+ if (error < 0) {
+ kfree(proc);
+ return error;
+ }
+
md_set_ip(proc, elf.entrypoint);
sched_enq(&core->scq, proc);
-
TAILQ_INSERT_TAIL(&procq, proc, lup_link);
return proc->pid;
}
diff --git a/src/sys/os/os_socket.c b/src/sys/os/os_socket.c
new file mode 100644
index 0000000..a37d15f
--- /dev/null
+++ b/src/sys/os/os_socket.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/syslog.h>
+#include <sys/errno.h>
+#include <sys/proc.h>
+#include <os/vnode.h>
+#include <os/kalloc.h>
+#include <os/filedesc.h>
+#include <string.h>
+
+static size_t next_sockid = 1;
+
+/*
+ * Allocate a socket file descriptor
+ *
+ * @fdp_res: Result is written here
+ *
+ * XXX: Socket vnodes are never deallocated until explicitly
+ * closed
+ *
+ * Returns file descriptor on success, otherwise a
+ * less than zero value on faulure
+ */
+static int
+get_sock_fd(struct filedesc **fdp_res)
+{
+ char namebuf[256];
+ struct ksocket *sock;
+ struct mount *mp;
+ struct nameidata nd;
+ struct filedesc *fdp;
+ struct proc *self = proc_self();
+ struct vnode *vp;
+ int error;
+
+ if (fdp_res == NULL) {
+ return -EINVAL;
+ }
+
+ if (self == NULL) {
+ return -EIO;
+ }
+
+ error = mount_lookup("/tmp", &mp);
+ if (error < 0) {
+ printf("socket: could not get /tmp mountpoint\n");
+ return error;
+ }
+
+ error = fd_alloc(self, &fdp);
+ if (error < 0) {
+ printf("socket: could not allocate fd\n");
+ return error;
+ }
+
+ sock = kalloc(sizeof(*sock));
+ if (sock == NULL) {
+ fd_close(fdp->fdno);
+ return -EINVAL;
+ }
+
+ /* Format the name */
+ snprintf(
+ namebuf,
+ sizeof(namebuf),
+ "sock.%d",
+ next_sockid++
+ );
+
+ /* Allocate a persistent vnode */
+ error = vfs_valloc(&vp, VTYPE_SOCK, 0);
+ if (error < 0) {
+ printf("socket: could not allocate vnode\n");
+ fd_close(fdp->fdno);
+ kfree(sock);
+ return error;
+ }
+
+ /* Create the backing file */
+ nd.path = namebuf;
+ error = vop_create(mp->vp, &nd, VTYPE_SOCK);
+ if (error < 0) {
+ printf("socket: failed to create /tmp entry\n");
+ fd_close(fdp->fdno);
+ kfree(sock);
+ return error;
+ }
+
+ /* Mark the socket as inactive */
+ memset(sock, 0, sizeof(*sock));
+ sock->backlog = -1;
+
+ fdp->vp = vp;
+ vp->data = sock;
+ printf("socket: socket created @ /tmp/%s\n", namebuf);
+ return fdp->fdno;
+}
+
+/*
+ * Get a socket descriptor from a fd
+ *
+ * @fd: File descriptor to look up
+ * @sock_res: Result pointer is written here
+ *
+ * Returns zero on success, otherwise a less
+ * than zero value on failure
+ */
+static int
+get_sock(int fd, struct ksocket **sock_res)
+{
+ struct filedesc *fdp;
+ struct proc *self = proc_self();
+ struct vnode *vp;
+
+ if (fd < 0) {
+ return -EBADF;
+ }
+
+ if (sock_res == NULL) {
+ return -1;
+ }
+
+ if (self == NULL) {
+ return -EINVAL;
+ }
+
+ /* Get the file descriptor */
+ fdp = fd_get(
+ self,
+ fd
+ );
+
+ if (fdp == NULL) {
+ return -EBADF;
+ }
+
+ /* We need the vnode */
+ if ((vp = fdp->vp) == NULL) {
+ return -EIO;
+ }
+
+ *sock_res = vp->data;
+ return 0;
+}
+
+/*
+ * Any backlog value > 0 marks the socket
+ * as accepting connections
+ */
+int
+listen(int socket, int backlog)
+{
+ struct ksocket *ksock = NULL;
+ int error;
+
+ if (socket < 0) {
+ return -EBADF;
+ }
+
+ if (backlog < 0) {
+ backlog = 0;
+ }
+
+ error = get_sock(socket, &ksock);
+ if (error < 0) {
+ printf("listen: failed to get socket descriptor\n");
+ return error;
+ }
+
+ /* Set the backlog */
+ ksock->backlog = backlog;
+ return 0;
+}
+
+/*
+ * Handles the AF_UNIX domain
+ */
+static int
+af_unix(int type, int protocol)
+{
+ struct filedesc *desc;
+
+ return get_sock_fd(&desc);
+}
+
+int
+socket(int domain, int type, int protocol)
+{
+ if (domain < 0 || type < 0) {
+ return -EINVAL;
+ }
+
+ switch (domain) {
+ case AF_UNIX:
+ return af_unix(type, protocol);
+ }
+
+ return -1;
+}
+
+/*
+ * ARG0: Domain
+ * ARG1: Type
+ * ARG2: Protocol
+ */
+scret_t
+sys_socket(struct syscall_args *scargs)
+{
+ int domain = SCARG(scargs, int, 0);
+ int type = SCARG(scargs, int, 1);
+ int protocol = SCARG(scargs, int, 2);
+
+ return socket(domain, type, protocol);
+}
+
+/*
+ * ARG0: Socket fd
+ * @backlog: Maximum connections
+ */
+scret_t
+sys_listen(struct syscall_args *scargs)
+{
+ int sockfd = SCARG(scargs, int, 0);
+ int backlog = SCARG(scargs, int, 1);
+
+ return listen(sockfd, backlog);
+}
diff --git a/src/sys/os/os_ucred.c b/src/sys/os/os_ucred.c
new file mode 100644
index 0000000..bf46308
--- /dev/null
+++ b/src/sys/os/os_ucred.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/errno.h>
+#include <os/ucred.h>
+#include <os/ucred.h>
+
+int
+ucred_init(struct proc *proc, struct ucred *cred)
+{
+ struct ucred *curcred;
+
+ if (cred == NULL) {
+ return -EINVAL;
+ }
+
+ if (proc != NULL) {
+ curcred = &proc->cred;
+ cred->ruid = curcred->ruid;
+ } else {
+ cred->ruid = 0;
+ }
+
+ cred->euid = cred->ruid;
+ cred->suid = cred->ruid;
+ return 0;
+}
+
+int
+seteuid(uid_t euid)
+{
+ struct proc *self = proc_self();
+ struct ucred *cred;
+ int retval = -EPERM;
+
+ if (__unlikely(self == NULL)) {
+ return -ESRCH;
+ }
+
+ /* Verify against current creds */
+ cred = &self->cred;
+ if (euid == cred->euid || euid == cred->ruid) {
+ cred->euid = euid;
+ retval = 0;
+ } else if (euid == cred->suid || cred->euid == 0) {
+ cred->euid = euid;
+ retval = 0;
+ }
+
+ return retval;
+}
+
+/*
+ * ARG0: EUID
+ */
+scret_t
+sys_seteuid(struct syscall_args *scargs)
+{
+ uid_t euid = SCARG(scargs, int, 0);
+
+ return seteuid(euid);
+}
diff --git a/src/sys/os/vfs_init.c b/src/sys/os/vfs_init.c
index 80d8559..1b6f815 100644
--- a/src/sys/os/vfs_init.c
+++ b/src/sys/os/vfs_init.c
@@ -39,7 +39,8 @@
*/
static struct fs_info fstab[] = {
{ MOUNT_INITRD, &g_omar_vfsops, 0 },
- { MOUNT_DEVFS, &g_devfs_vfops, 0 }
+ { MOUNT_DEVFS, &g_devfs_vfsops, 0 },
+ { MOUNT_TMPFS, &g_tmpfs_vfsops, 0 }
};
/*
diff --git a/src/sys/os/vfs_namei.c b/src/sys/os/vfs_namei.c
index 1425c30..013c0ea 100644
--- a/src/sys/os/vfs_namei.c
+++ b/src/sys/os/vfs_namei.c
@@ -46,10 +46,13 @@ namei(struct nameidata *ndp)
struct vnode *vp;
struct vop *vops;
struct vop_lookup_args lookup;
+ struct vop_create_args create;
+ struct nameidata nd_create;
struct fs_info *fip;
char namebuf[NAME_MAX];
+ size_t root_len;
const char *p, *pcur;
- size_t len, i = 0;
+ size_t i = 0;
int error;
if (ndp == NULL) {
@@ -61,23 +64,35 @@ namei(struct nameidata *ndp)
return -EINVAL;
}
- error = mount_lookup("/", &mp);
+ /* Get rid of leading slashes */
+ pcur = p;
+ while (*pcur == '/') {
+ ++pcur;
+ }
+
+ /* Wait until we get the '/' */
+ while (*pcur != '/' && *pcur != '\0') {
+ ++pcur;
+ }
+
+ /* Copy the root path e.g., /tmp */
+ root_len = (size_t)(pcur - p);
+ memcpy(namebuf, p, root_len);
+ error = mount_lookup(namebuf, &mp);
+
if (error < 0) {
- printf("namei: failed to get rootfs\n");
+ error = mount_lookup("/", &mp);
+ }
+ if (error < 0) {
+ printf("namei: could not get mount %s\n", namebuf);
return error;
}
- vp = mp->vp;
fip = mp->fs;
-
- if ((vops = vp->vops) == NULL) {
- printf("namei: failed to get vops\n");
+ if ((vp = mp->vp) == NULL) {
return -EIO;
}
-
- /* We need vops->lookup() */
- if (vops->lookup == NULL) {
- printf("namei: vops does not have lookup op\n");
+ if ((vops = vp->vops) == NULL) {
return -EIO;
}
@@ -99,12 +114,11 @@ namei(struct nameidata *ndp)
if (error == 0) {
return 0;
}
+
+ return -ENOENT;
}
- printf("namei: f: %s\n", ndp->path);
- printf("namei: d: /\n", ndp->path);
- pcur = p;
while (*pcur != '\0') {
/* Get out of the slashes */
while (*pcur == '/')
@@ -123,7 +137,36 @@ namei(struct nameidata *ndp)
}
i = 0;
- printf("namei: n %s\n", namebuf);
+
+ /* Get the vops */
+ vp = mp->vp;
+ if ((vops = vp->vops) == NULL) {
+ return -EIO;
+ }
+
+ /* Create as we go? */
+ if (ISSET(ndp->flags, NAMEI_CREATE)) {
+ if (vops->create == NULL)
+ return -EIO;
+
+ nd_create.path = namebuf;
+ create.ndp = &nd_create;
+ create.vtype = VTYPE_FILE;
+ error = vops->create(&create);
+ if (error < 0)
+ return error;
+ }
+
+ /* Do the lookup */
+ lookup.dirvp = vp;
+ lookup.vpp = &vp;
+ lookup.name = namebuf;
+ error = vops->lookup(&lookup);
+ if (error < 0) {
+ return -ENOENT;
+ }
}
- return -ENOENT;
+
+ *ndp->vp_res = vp;
+ return 0;
}
diff --git a/src/sys/os/vfs_subr.c b/src/sys/os/vfs_subr.c
index 6cb7767..0e8c605 100644
--- a/src/sys/os/vfs_subr.c
+++ b/src/sys/os/vfs_subr.c
@@ -224,3 +224,46 @@ vop_reclaim(struct vnode *vp, int flags)
return vops->reclaim(vp, flags);
}
+
+int
+vop_create(struct vnode *vp, struct nameidata *ndp, vtype_t type)
+{
+ struct vop *vops;
+ struct vop_create_args args;
+
+ if (vp == NULL || ndp == NULL) {
+ return -EINVAL;
+ }
+
+ if ((vops = vp->vops) == NULL) {
+ return -EIO;
+ }
+
+ if (vops->create == NULL) {
+ return -EIO;
+ }
+
+ args.ndp = ndp;
+ args.vtype = type;
+ return vops->create(&args);
+}
+
+int
+vop_getattr(struct vnode *vp, struct vattr *res)
+{
+ struct vop *vops;
+
+ if (vp == NULL || res == NULL) {
+ return -EINVAL;
+ }
+
+ if ((vops = vp->vops) == NULL) {
+ return -EIO;
+ }
+
+ if (vops->getattr == NULL) {
+ return -EIO;
+ }
+
+ return vops->getattr(vp, res);
+}
diff --git a/src/sys/vm/vm_map.c b/src/sys/vm/vm_map.c
index 6748348..1d801af 100644
--- a/src/sys/vm/vm_map.c
+++ b/src/sys/vm/vm_map.c
@@ -30,12 +30,16 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
+#include <sys/param.h>
#include <sys/syslog.h>
#include <vm/physseg.h>
#include <vm/mmu.h>
#include <vm/map.h>
#include <vm/vm.h>
+#define MMAP_START 0x6F3C8E0C0000
+#define MMAP_END 0x6F3C90000000
+
/*
* Create a virtual to physical memory
* mapping
@@ -133,7 +137,60 @@ vm_map(struct vm_vas *vas, struct mmu_map *spec, size_t len, int prot)
}
/* Place a guard page at the end */
- spec->va = spec_cpy.va + len;
- __vm_map(vas, spec, DEFAULT_PAGESIZE, 0);
+ spec_cpy.va = spec_cpy.va + len;
+ __vm_map(vas, &spec_cpy, DEFAULT_PAGESIZE, 0);
return 0;
}
+
+void *
+mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
+{
+ struct mmu_map spec;
+ struct vm_vas vas;
+ paddr_t pa;
+ int error;
+
+ /* TODO: Support address allocation */
+ if (len == 0 || addr == NULL) {
+ return NULL;
+ }
+
+ spec.va = (uintptr_t)addr;
+ spec.pa = 0;
+ error = mmu_this_vas(&vas);
+ if (error < 0) {
+ return NULL;
+ }
+
+ /* Create the mapping */
+ error = vm_map(&vas, &spec, len, prot);
+ if (error < 0) {
+ return NULL;
+ }
+
+ return (void *)spec.va;
+}
+
+/*
+ * ARG0: Address
+ * ARG1: Length
+ * ARG2: Protection flags
+ * ARG3: Flags
+ * ARG4: Fildes
+ * ARG5: Offset
+ */
+scret_t
+sys_mmap(struct syscall_args *scargs)
+{
+ void *address = SCARG(scargs, void *, 0);
+ size_t length = SCARG(scargs, size_t, 1);
+ int prot = SCARG(scargs, int, 2);
+
+ prot |= PROT_USER;
+ if (address != NULL) {
+ address = PTR_OFFSET(address, MMAP_START);
+ }
+
+ /* XXX: Should use rest of the args */
+ return (uintptr_t)mmap(address, length, prot, 0, 0, 0);
+}