From ea6ec785a9df21cb3f5e78472af8dd2cd2d45290 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 10 Mar 2026 19:15:59 +0000 Subject: [PATCH] lib: c: re-organise into separate static modules, plus a single shared library --- lib/libc/CMakeLists.txt | 4 +-- lib/libc/core/CMakeLists.txt | 4 ++- lib/libc/core/errno/errno.c | 54 ++++++++++++++++++++++++++++++++ lib/libc/include/errno.h | 3 ++ lib/libc/include/string.h | 2 ++ lib/libc/include/unistd.h | 5 ++- lib/libc/io/CMakeLists.txt | 33 +++++++++++++++++++ lib/libc/io/fs.c | 2 ++ lib/libc/io/include/sys/mman.h | 43 +++++++++++++++++++++++++ lib/libc/io/include/sys/remote.h | 18 +++++++++++ lib/libc/io/remote.c | 45 ++++++++++++++++++++++++++ lib/libc/io/unistd/close.c | 0 lib/libc/io/unistd/mmap.c | 6 ++++ lib/libc/io/unistd/open.c | 40 +++++++++++++++++++++++ lib/libc/io/unistd/read.c | 21 +++++++++++++ lib/libc/io/unistd/write.c | 0 lib/libc/malloc/CMakeLists.txt | 2 +- lib/libc/malloc/string/strdup.c | 14 +++++++++ 18 files changed, 291 insertions(+), 5 deletions(-) create mode 100644 lib/libc/core/errno/errno.c create mode 100644 lib/libc/io/CMakeLists.txt create mode 100644 lib/libc/io/fs.c create mode 100644 lib/libc/io/include/sys/mman.h create mode 100644 lib/libc/io/include/sys/remote.h create mode 100644 lib/libc/io/remote.c create mode 100644 lib/libc/io/unistd/close.c create mode 100644 lib/libc/io/unistd/mmap.c create mode 100644 lib/libc/io/unistd/open.c create mode 100644 lib/libc/io/unistd/read.c create mode 100644 lib/libc/io/unistd/write.c create mode 100644 lib/libc/malloc/string/strdup.c diff --git a/lib/libc/CMakeLists.txt b/lib/libc/CMakeLists.txt index 0c10129..de4a2f3 100644 --- a/lib/libc/CMakeLists.txt +++ b/lib/libc/CMakeLists.txt @@ -1,4 +1,4 @@ -set(source_dirs core malloc) +set(source_dirs core malloc io) set(public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include) @@ -26,5 +26,5 @@ bsp_add_library( NAME libc LIB_DIR /usr/lib) -target_link_libraries(libc libmango) +target_link_libraries(libc libmango libxpc-static interface::fs) target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1) diff --git a/lib/libc/core/CMakeLists.txt b/lib/libc/core/CMakeLists.txt index bbb61d4..a26774c 100644 --- a/lib/libc/core/CMakeLists.txt +++ b/lib/libc/core/CMakeLists.txt @@ -1,4 +1,4 @@ -set(source_dirs stdio string) +set(source_dirs stdio string errno) foreach (dir ${source_dirs}) file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c) @@ -21,3 +21,5 @@ sysroot_add_library( NAME libc-core HEADER_DIR /usr/include LIB_DIR /usr/lib) + +target_link_libraries(libc-core libmango) diff --git a/lib/libc/core/errno/errno.c b/lib/libc/core/errno/errno.c new file mode 100644 index 0000000..2e5989c --- /dev/null +++ b/lib/libc/core/errno/errno.c @@ -0,0 +1,54 @@ +#include +#include + +#if defined(BUILD_STATIC) +int __set_errno(int err) +{ + return -err; +} +#endif + +#if defined(BUILD_SHARED) +int __set_errno(int err) +{ + /* TODO */ + return -1; +} +#endif + +int __errno_from_kern_status(unsigned int err) +{ + switch (err) { + case KERN_OK: + return SUCCESS; + case KERN_UNIMPLEMENTED: + return ENOSYS; + case KERN_NAME_EXISTS: + return EEXIST; + case KERN_INVALID_ARGUMENT: + return EINVAL; + case KERN_UNSUPPORTED: + return ENOTSUP; + case KERN_NO_MEMORY: + return ENOMEM; + case KERN_NO_ENTRY: + return ENOENT; + case KERN_WOULD_BLOCK: + return EWOULDBLOCK; + case KERN_NO_DEVICE: + return ENODEV; + case KERN_DEVICE_STUCK: + case KERN_IO_ERROR: + return EIO; + case KERN_FATAL_ERROR: + return ENXIO; + case KERN_BAD_STATE: + return EPERM; + case KERN_MEMORY_FAULT: + return EFAULT; + case KERN_ACCESS_DENIED: + return EACCES; + default: + return EINVAL; + } +} diff --git a/lib/libc/include/errno.h b/lib/libc/include/errno.h index 03c2d7d..5379f80 100644 --- a/lib/libc/include/errno.h +++ b/lib/libc/include/errno.h @@ -139,4 +139,7 @@ #define EQFULL 106 /* Interface output queue is full */ #define ELAST 106 /* Must be equal largest errno */ +extern int __set_errno(int err); +extern int __errno_from_kern_status(unsigned int err); + #endif diff --git a/lib/libc/include/string.h b/lib/libc/include/string.h index a9c8e87..3103848 100644 --- a/lib/libc/include/string.h +++ b/lib/libc/include/string.h @@ -14,4 +14,6 @@ extern int strncmp(const char *s1, const char *s2, unsigned long n); extern void *memset(void *str, int c, size_t n); extern void *memcpy(void *dst, const void *src, size_t len); +extern char *strdup(char *s); + #endif diff --git a/lib/libc/include/unistd.h b/lib/libc/include/unistd.h index e0dce84..fc07165 100644 --- a/lib/libc/include/unistd.h +++ b/lib/libc/include/unistd.h @@ -1,9 +1,12 @@ #ifndef UNISTD_H_ #define UNISTD_H_ -#include +#include extern int open(const char *path, int flags); extern int close(int fd); +extern int read(int fd, void *buf, size_t count); +extern int write(int fd, const void *buf, size_t count); + #endif diff --git a/lib/libc/io/CMakeLists.txt b/lib/libc/io/CMakeLists.txt new file mode 100644 index 0000000..8293e77 --- /dev/null +++ b/lib/libc/io/CMakeLists.txt @@ -0,0 +1,33 @@ +set(source_dirs unistd stdio) + +file(GLOB sources *.c *.h) + +foreach (dir ${source_dirs}) + file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c) + file(GLOB dir_headers ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.h) + + set(sources ${sources} ${dir_sources}) + set(headers ${headers} ${dir_headers}) +endforeach (dir) + +file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) +set(headers ${headers} ${sub_headers}) + +set(component_sources ${sources} PARENT_SCOPE) +set(component_headers ${headers} PARENT_SCOPE) +set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE) + +rosetta_add_library(STATIC + NAME libc-io + PUBLIC_INCLUDE_DIRS + ${public_include_dirs} + ${CMAKE_CURRENT_SOURCE_DIR}/include + SOURCES ${sources} + HEADERS ${headers}) + +sysroot_add_library( + NAME libc-io + HEADER_DIR /usr/include + LIB_DIR /usr/lib) + +target_link_libraries(libc-io libc-core interface::fs libxpc-static libmango) diff --git a/lib/libc/io/fs.c b/lib/libc/io/fs.c new file mode 100644 index 0000000..2c82cc4 --- /dev/null +++ b/lib/libc/io/fs.c @@ -0,0 +1,2 @@ +#define MSG_IMPLEMENTATION +#include diff --git a/lib/libc/io/include/sys/mman.h b/lib/libc/io/include/sys/mman.h new file mode 100644 index 0000000..e01bc30 --- /dev/null +++ b/lib/libc/io/include/sys/mman.h @@ -0,0 +1,43 @@ +#ifndef SYS_MMAN_H_ +#define SYS_MMAN_H_ + +#include +#include + +#define PROT_NONE 0x00u +#define PROT_EXEC 0x01u +#define PROT_READ 0x02u +#define PROT_WRITE 0x04u + +#define MAP_SHARED 0x01u +#define MAP_SHARED_VALIDATE 0x03u +#define MAP_PRIVATE 0x04u +#define MAP_32BIT 0x08u +#define MAP_ANON MAP_ANONYMOUS +#define MAP_ANONYMOUS 0x10u +#define MAP_DENYWRITE 0x20u +#define MAP_EXECUTABLE 0x40u +#define MAP_FILE 0x80u +#define MAP_FIXED 0x100u +#define MAP_FIXED_NOREPLACE 0x300u +#define MAP_GROWSDOWN 0x400u +#define MAP_HUGETLB 0x800u +#define MAP_HUGE_2MB 0x1000u +#define MAP_HUGE_1GB 0x2000u +#define MAP_LOCKED 0x4000u +#define MAP_NONBLOCK 0x8000u +#define MAP_NORESERVE 0x10000u +#define MAP_POPULATE 0x20000u +#define MAP_STACK 0x40000u +#define MAP_SYNC 0x80000u +#define MAP_UNINITIALIZED 0x100000u + +extern void *mmap( + void *addr, + size_t length, + int prot, + int flags, + int fd, + off_t offset); + +#endif diff --git a/lib/libc/io/include/sys/remote.h b/lib/libc/io/include/sys/remote.h new file mode 100644 index 0000000..390cfff --- /dev/null +++ b/lib/libc/io/include/sys/remote.h @@ -0,0 +1,18 @@ +#ifndef SYS_REMOTE_H_ +#define SYS_REMOTE_H_ + +#include +#include + +enum sys_remote_id { + SYS_REMOTE_NONE, + SYS_REMOTE_NSD, +}; + +extern bool sys_remote_get( + enum sys_remote_id id, + tid_t *out_tid, + unsigned int *out_chid); +extern void sys_remote_set(enum sys_remote_id id, tid_t tid, unsigned int chid); + +#endif diff --git a/lib/libc/io/remote.c b/lib/libc/io/remote.c new file mode 100644 index 0000000..fd0b26f --- /dev/null +++ b/lib/libc/io/remote.c @@ -0,0 +1,45 @@ +#include + +#define TID_INVALID ((tid_t) - 1) +#define CHID_INVALID ((unsigned int)-1) + +struct remote { + tid_t tid; + unsigned int chid; +}; + +static struct remote remotes[] = { + [SYS_REMOTE_NONE] = {.tid = TID_INVALID, .chid = CHID_INVALID}, + [SYS_REMOTE_NSD] = {.tid = TID_INVALID, .chid = CHID_INVALID}, +}; +static const size_t nr_remotes = sizeof remotes / sizeof remotes[0]; + +bool sys_remote_get( + enum sys_remote_id id, + tid_t *out_tid, + unsigned int *out_chid) +{ + if (id < 0 || id >= nr_remotes) { + return false; + } + + const struct remote *remote = &remotes[id]; + if (remote->tid == TID_INVALID || remote->chid == CHID_INVALID) { + return false; + } + + *out_tid = remote->tid; + *out_chid = remote->chid; + return true; +} + +void sys_remote_set(enum sys_remote_id id, tid_t tid, unsigned int chid) +{ + if (id < 0 || id >= nr_remotes) { + return; + } + + struct remote *remote = &remotes[id]; + remote->tid = tid; + remote->chid = chid; +} diff --git a/lib/libc/io/unistd/close.c b/lib/libc/io/unistd/close.c new file mode 100644 index 0000000..e69de29 diff --git a/lib/libc/io/unistd/mmap.c b/lib/libc/io/unistd/mmap.c new file mode 100644 index 0000000..e75fb6b --- /dev/null +++ b/lib/libc/io/unistd/mmap.c @@ -0,0 +1,6 @@ +#include + +void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) +{ + return NULL; +} diff --git a/lib/libc/io/unistd/open.c b/lib/libc/io/unistd/open.c new file mode 100644 index 0000000..6b343eb --- /dev/null +++ b/lib/libc/io/unistd/open.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +int open(const char *path, int flags) +{ + tid_t remote_tid; + unsigned int remote_chid; + if (!sys_remote_get(SYS_REMOTE_NSD, &remote_tid, &remote_chid)) { + return __set_errno(ENXIO); + } + + kern_handle_t port; + kern_status_t status = port_create(&port); + if (status != KERN_OK) { + return __set_errno(__errno_from_kern_status(status)); + } + + status = port_connect(port, remote_tid, remote_chid); + if (status != KERN_OK) { + kern_handle_close(port); + return __set_errno(__errno_from_kern_status(status)); + } + + int err = SUCCESS; + status = fs_open(port, path, flags, &err); + if (status != KERN_OK) { + kern_handle_close(port); + return __set_errno(__errno_from_kern_status(status)); + } + + if (err != SUCCESS) { + kern_handle_close(port); + return __set_errno(err); + } + + return (int)port; +} diff --git a/lib/libc/io/unistd/read.c b/lib/libc/io/unistd/read.c new file mode 100644 index 0000000..04e0351 --- /dev/null +++ b/lib/libc/io/unistd/read.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include + +int read(int fd, void *buf, size_t count) +{ + int err; + size_t nr_read; + kern_status_t status = fs_read(fd, count, &err, &nr_read, buf, count); + if (status != KERN_OK) { + return __set_errno(__errno_from_kern_status(status)); + } + + if (err != SUCCESS) { + return __set_errno(err); + } + + return nr_read; +} diff --git a/lib/libc/io/unistd/write.c b/lib/libc/io/unistd/write.c new file mode 100644 index 0000000..e69de29 diff --git a/lib/libc/malloc/CMakeLists.txt b/lib/libc/malloc/CMakeLists.txt index 3b28814..a040db7 100644 --- a/lib/libc/malloc/CMakeLists.txt +++ b/lib/libc/malloc/CMakeLists.txt @@ -1,4 +1,4 @@ -set(source_dirs stdlib) +set(source_dirs stdlib string) file(GLOB sources *.c *.h) diff --git a/lib/libc/malloc/string/strdup.c b/lib/libc/malloc/string/strdup.c new file mode 100644 index 0000000..9f6f0a9 --- /dev/null +++ b/lib/libc/malloc/string/strdup.c @@ -0,0 +1,14 @@ +#include +#include + +char *strdup(char *s) +{ + size_t len = strlen(s); + char *out = malloc(len + 1); + if (!out) { + return NULL; + } + + memcpy(out, s, len + 1); + return out; +}