diff --git a/Makefile b/Makefile index 318f1cb..d90341e 100644 --- a/Makefile +++ b/Makefile @@ -213,6 +213,12 @@ $(BUILD_DIR)/initrd.tar: $(KERNEL_ELF) mkdir -p $(BUILD_DIR)/initrd/root/Pictures mkdir -p $(BUILD_DIR)/initrd/root/Documents mkdir -p $(BUILD_DIR)/initrd/root/Downloads + mkdir -p $(BUILD_DIR)/initrd/etc + mkdir -p $(BUILD_DIR)/initrd/usr/lib/tcc/include + mkdir -p $(BUILD_DIR)/initrd/usr/local/include + mkdir -p $(BUILD_DIR)/initrd/usr/include/sys + mkdir -p $(BUILD_DIR)/initrd/usr/include/libc + mkdir -p $(BUILD_DIR)/initrd/usr/lib @printf "$(YELLOW)[COPY]$(RESET) Limine binaries + kernel for installer..." @if [ -f limine/BOOTX64.EFI ]; then cp limine/BOOTX64.EFI $(BUILD_DIR)/initrd/boot/; fi @@ -228,6 +234,22 @@ $(BUILD_DIR)/initrd.tar: $(KERNEL_ELF) fi \ done + @printf "$(YELLOW)[COPY]$(RESET) TCC support files..." + @cp $(SRC_DIR)/userland/cli/third_party/tcc/libtcc1.a $(BUILD_DIR)/initrd/usr/lib/tcc/ + @cp $(SRC_DIR)/userland/cli/third_party/tcc/libtcc1.a $(BUILD_DIR)/initrd/usr/lib/ + @cp $(SRC_DIR)/userland/cli/third_party/tcc/include/*.h $(BUILD_DIR)/initrd/usr/lib/tcc/include/ + @cp $(SRC_DIR)/userland/sdk/lib/libboredos.a $(BUILD_DIR)/initrd/usr/lib/ + @cp $(SRC_DIR)/userland/sdk/lib/libc.a $(BUILD_DIR)/initrd/usr/lib/ + @cp $(SRC_DIR)/userland/sdk/lib/libm.a $(BUILD_DIR)/initrd/usr/lib/ + @cp $(SRC_DIR)/userland/bin/crt0.o $(BUILD_DIR)/initrd/usr/lib/crt0.o + @cp $(SRC_DIR)/userland/bin/crt0.o $(BUILD_DIR)/initrd/usr/lib/crt1.o + @cp $(SRC_DIR)/userland/bin/empty.o $(BUILD_DIR)/initrd/usr/lib/crti.o + @cp $(SRC_DIR)/userland/bin/empty.o $(BUILD_DIR)/initrd/usr/lib/crtn.o + @cp $(SRC_DIR)/userland/libc/*.h $(BUILD_DIR)/initrd/usr/include/ + @cp $(SRC_DIR)/userland/libc/sys/*.h $(BUILD_DIR)/initrd/usr/include/sys/ + @cp $(SRC_DIR)/userland/libc/*.h $(BUILD_DIR)/initrd/usr/include/libc/ + @cp $(SRC_DIR)/userland/libc/*.h $(BUILD_DIR)/initrd/usr/local/include/ + @printf "$(YELLOW)[COPY]$(RESET) Wallpapers..." @for f in $(SRC_DIR)/images/wallpapers/*; do \ if [ -f "$$f" ]; then \ @@ -291,6 +313,7 @@ $(BUILD_DIR)/initrd.tar: $(KERNEL_ELF) @if [ -f README.md ]; then printf " -> README.md"; cp README.md $(BUILD_DIR)/initrd/; fi @if [ -f LICENSE ]; then printf " -> LICENSE"; cp LICENSE $(BUILD_DIR)/initrd/; fi @if [ -f limine.conf ]; then printf " -> limine.conf"; cp limine.conf $(BUILD_DIR)/initrd/; fi + @if [ -f $(SRC_DIR)/userland/gui/about.c ]; then printf " -> about.c"; cp $(SRC_DIR)/userland/gui/about.c $(BUILD_DIR)/initrd/; fi @printf "$(YELLOW)[TAR]$(RESET) Creating initrd.tar..." cd $(BUILD_DIR)/initrd && COPYFILE_DISABLE=1 tar --exclude="._*" -cf ../initrd.tar * diff --git a/src/fs/fat32.c b/src/fs/fat32.c index c66c51f..daaee95 100644 --- a/src/fs/fat32.c +++ b/src/fs/fat32.c @@ -15,7 +15,7 @@ static spinlock_t ramfs_lock = SPINLOCK_INIT; // Protects the RAM-based filesystem (/) -#define MAX_CLUSTERS 8192 +#define MAX_CLUSTERS 32768 #define MAX_OPEN_HANDLES 32 // In-memory FAT table diff --git a/src/userland/Makefile b/src/userland/Makefile index 41822b1..c4b8179 100644 --- a/src/userland/Makefile +++ b/src/userland/Makefile @@ -16,7 +16,7 @@ APP_METADATA_SOURCE_LUA = cli/third_party/lua/boredos_onelua.c APP_SOURCE_DIRS = . cli gui sys games net cli/third_party define app_source_for -$(if $(filter doom,$1),$(APP_METADATA_SOURCE_DOOM),$(if $(filter lua,$1),$(APP_METADATA_SOURCE_LUA),$(firstword $(foreach d,$(APP_SOURCE_DIRS),$(wildcard $(d)/$1.c))))) +$(if $(filter doom,$1),$(APP_METADATA_SOURCE_DOOM),$(if $(filter lua,$1),$(APP_METADATA_SOURCE_LUA),$(if $(filter tcc,$1),cli/third_party/tcc/tcc.c,$(firstword $(foreach d,$(APP_SOURCE_DIRS),$(wildcard $(d)/$1.c)))))) endef LIBC_SOURCES = $(wildcard libc/*.c) @@ -38,7 +38,7 @@ DOOM_OBJS = $(patsubst games/doom/%.c, $(BIN_DIR)/%.o, $(DOOM_SOURCES)) LUA_DIR = cli/third_party/lua LUA_CFLAGS = -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-red-zone -isystem $(LUA_DIR)/sysinclude -I. -Ilibc -I$(LUA_DIR) -DLUA_USE_C89 -Wno-conversion -Wno-sign-conversion -Wno-double-promotion -Wno-unused-parameter -Wno-missing-declarations -Wno-shadow -Wno-undef -Wno-redundant-decls -Wno-old-style-definition -Wno-missing-prototypes -Wno-implicit-fallthrough -Wno-type-limits -all: $(BIN_DIR) $(APP_ELFS) $(BIN_DIR)/doom.elf $(BIN_DIR)/lua.elf +all: $(BIN_DIR) $(APP_ELFS) $(BIN_DIR)/doom.elf $(BIN_DIR)/lua.elf $(BIN_DIR)/tcc.elf $(BIN_DIR)/empty.o $(BIN_DIR): mkdir -p $(BIN_DIR) @@ -55,6 +55,11 @@ $(BIN_DIR)/libwidget.o: ../wm/libwidget.c | $(BIN_DIR) $(BIN_DIR)/stb_image.o: stb_image.c | $(BIN_DIR) $(CC) $(CFLAGS) -c $< -o $@ +$(BIN_DIR)/empty.o: | $(BIN_DIR) + echo "section .text" > $(BIN_DIR)/empty.asm + $(AS) -f elf64 $(BIN_DIR)/empty.asm -o $@ + rm $(BIN_DIR)/empty.asm + $(BIN_DIR)/%.note.c: $(APP_METADATA_TOOL) | $(BIN_DIR) src="$(call app_source_for,$*)"; \ if [ -z "$$src" ] || [ ! -f "$$src" ]; then \ @@ -97,5 +102,23 @@ $(BIN_DIR)/lua_onelua.o: $(LUA_DIR)/boredos_onelua.c | $(BIN_DIR) $(BIN_DIR)/lua.elf: $(LIBC_OBJS) $(BIN_DIR)/lua_onelua.o $(BIN_DIR)/lua.note.o $(LD) $(LDFLAGS) $^ -o $@ +# TCC - Tiny C Compiler +TCC_DIR = cli/third_party/tcc +$(BIN_DIR)/tcc.elf: $(LIBC_OBJS) $(BIN_DIR)/tcc.note.o sdk $(TCC_DIR)/tcc.c $(TCC_DIR)/config.h $(TCC_DIR)/tcc.h + cd $(TCC_DIR) && x86_64-elf-gcc -O2 -m64 -march=x86-64 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -ffreestanding -nostdlib -static -no-pie -DONE_SOURCE=1 -DTARGETOS_BoredOS=1 -I. -I../../../sdk/include -Ttext=0x40000000 tcc.c -o tcc.elf ../../../sdk/lib/libboredos.a + cp $(TCC_DIR)/tcc.elf $(BIN_DIR)/tcc.elf + cd $(TCC_DIR) && sh build_libtcc1.sh + +# SDK target +SDK_DIR = sdk +sdk: $(LIBC_OBJS) $(BIN_DIR)/libui.o + mkdir -p $(SDK_DIR)/lib $(SDK_DIR)/include/sys + cp libc/*.h $(SDK_DIR)/include/ + cp libc/sys/*.h $(SDK_DIR)/include/sys/ + x86_64-elf-ar rcs $(SDK_DIR)/lib/libboredos.a $(LIBC_OBJS) + cp $(SDK_DIR)/lib/libboredos.a $(SDK_DIR)/lib/libc.a + cp $(SDK_DIR)/lib/libboredos.a $(SDK_DIR)/lib/libm.a + x86_64-elf-ar rcs $(SDK_DIR)/lib/libui.a $(BIN_DIR)/libui.o + clean: - rm -rf $(BIN_DIR) + rm -rf $(BIN_DIR) $(SDK_DIR) diff --git a/src/userland/cli/boredos_install.c b/src/userland/cli/boredos_install.c index f7af24b..d843923 100644 --- a/src/userland/cli/boredos_install.c +++ b/src/userland/cli/boredos_install.c @@ -337,6 +337,8 @@ int main(int argc, char **argv) { if (copy_tree("/Library", "/mnt/Library") != 0) { serial_printf("[ERROR] copy /Library failed\n"); return 1; } if (copy_tree("/docs", "/mnt/docs") != 0) { serial_printf("[ERROR] copy /docs failed\n"); return 1; } if (copy_tree("/root", "/mnt/root") != 0) { serial_printf("[ERROR] copy /root failed\n"); return 1; } + if (copy_tree("/usr", "/mnt/usr") != 0) { serial_printf("[ERROR] copy /usr failed\n"); return 1; } + if (copy_tree("/etc", "/mnt/etc") != 0) { serial_printf("[ERROR] copy /etc failed\n"); return 1; } serial_printf("Copying kernel and initrd...\n"); if (copy_file("/boot/boredos.elf", "/mnt/boot/boredos.elf") != 0) { @@ -357,8 +359,9 @@ int main(int argc, char **argv) { serial_printf("[WARNING] initrd.tar not found in live system (checked /boot/ and /)!\n"); } - copy_file_optional("README.md", "/mnt/README.md"); - copy_file_optional("LICENSE", "/mnt/LICENSE"); + copy_file_optional("/README.md", "/mnt/README.md"); + copy_file_optional("/LICENSE", "/mnt/LICENSE"); + copy_file_optional("/about.c", "/mnt/about.c"); uint64_t t1 = get_ticks(); serial_printf("Files copied (%llu ticks).\n", (unsigned long long)(t1 - t0)); } diff --git a/src/userland/crt1.asm b/src/userland/crt1.asm new file mode 100644 index 0000000..f77284b --- /dev/null +++ b/src/userland/crt1.asm @@ -0,0 +1,26 @@ +; Copyright (c) 2023-2026 Chris (boreddevnl) +; This software is released under the GNU General Public License v3.0. See LICENSE file for details. +; This header needs to maintain in any file it is present in, as per the GPL license terms. +; userland/crt0.asm +global _start +extern main +extern sys_exit + +section .text +_start: + ; The kernel loads the ELF and jumps here. + ; RSP should point to the 0x800000 stack. + + ; Align the stack to 16 bytes for C functions (System V ABI) + and rsp, -16 + + ; Call main(argc, argv) + call main + + ; If main returns, call exit(status) + mov rdi, rax ; Pass main's return value to exit syscall + call sys_exit + + ; Fallback halt if exit miraculously returns +.hang: + jmp .hang diff --git a/src/userland/crti.asm b/src/userland/crti.asm new file mode 100644 index 0000000..16eaa3b --- /dev/null +++ b/src/userland/crti.asm @@ -0,0 +1,3 @@ +global _init +section .init +_init: diff --git a/src/userland/crtn.asm b/src/userland/crtn.asm new file mode 100644 index 0000000..a84d4e1 --- /dev/null +++ b/src/userland/crtn.asm @@ -0,0 +1,3 @@ +global _fini +section .fini +_fini: diff --git a/src/userland/gui/browser.c b/src/userland/gui/browser.c index 60d20af..1a73daa 100644 --- a/src/userland/gui/browser.c +++ b/src/userland/gui/browser.c @@ -52,26 +52,6 @@ static char* str_istrstr(const char* haystack, const char* needle) { return NULL; } -static long strtol(const char* nptr, char** endptr, int base) { - long res = 0; - while (*nptr == ' ' || *nptr == '\t' || *nptr == '\n' || *nptr == '\r') nptr++; - bool neg = false; - if (*nptr == '-') { neg = true; nptr++; } - else if (*nptr == '+') nptr++; - - while (*nptr) { - int v = -1; - if (*nptr >= '0' && *nptr <= '9') v = *nptr - '0'; - else if (*nptr >= 'a' && *nptr <= 'z') v = *nptr - 'a' + 10; - else if (*nptr >= 'A' && *nptr <= 'Z') v = *nptr - 'A' + 10; - if (v < 0 || v >= base) break; - res = res * base + v; - nptr++; - } - if (endptr) *endptr = (char*)nptr; - return neg ? -res : res; -} - #define TAG_NONE 0 #define TAG_IMG 1 #define TAG_INPUT 2 diff --git a/src/userland/libc/assert.h b/src/userland/libc/assert.h new file mode 100644 index 0000000..e26808b --- /dev/null +++ b/src/userland/libc/assert.h @@ -0,0 +1,4 @@ +#ifndef _ASSERT_H +#define _ASSERT_H +#define assert(x) ((void)0) +#endif diff --git a/src/userland/libc/dlfcn.h b/src/userland/libc/dlfcn.h new file mode 100644 index 0000000..a4532b8 --- /dev/null +++ b/src/userland/libc/dlfcn.h @@ -0,0 +1,9 @@ +#ifndef _DLFCN_H +#define _DLFCN_H +#define RTLD_LAZY 0x00001 +#define RTLD_NOW 0x00002 +void *dlopen(const char *filename, int flag); +char *dlerror(void); +void *dlsym(void *handle, const char *symbol); +int dlclose(void *handle); +#endif diff --git a/src/userland/libc/empty.asm b/src/userland/libc/empty.asm new file mode 100644 index 0000000..e007d42 --- /dev/null +++ b/src/userland/libc/empty.asm @@ -0,0 +1 @@ +section .text diff --git a/src/userland/libc/inttypes.h b/src/userland/libc/inttypes.h new file mode 100644 index 0000000..112de7e --- /dev/null +++ b/src/userland/libc/inttypes.h @@ -0,0 +1,7 @@ +#ifndef _INTTYPES_H +#define _INTTYPES_H +#include +#define PRId64 "lld" +#define PRIu64 "llu" +#define PRIx64 "llx" +#endif diff --git a/src/userland/libc/libmath.c b/src/userland/libc/libmath.c index ac19b40..f404979 100644 --- a/src/userland/libc/libmath.c +++ b/src/userland/libc/libmath.c @@ -157,3 +157,15 @@ double fclamp(double x, double lo, double hi) { if (x > hi) return hi; return x; } + +double ldexp(double x, int exp) { + if (exp >= 0) { while (exp--) x *= 2.0; } + else { while (exp++) x /= 2.0; } + return x; +} + +long double ldexpl(long double x, int exp) { + if (exp >= 0) { while (exp--) x *= 2.0L; } + else { while (exp++) x /= 2.0L; } + return x; +} diff --git a/src/userland/libc/math.h b/src/userland/libc/math.h index 25d91ab..b5a6945 100644 --- a/src/userland/libc/math.h +++ b/src/userland/libc/math.h @@ -29,6 +29,7 @@ double log2(double x); double log10(double x); double exp(double x); double ldexp(double x, int expn); +long double ldexpl(long double x, int expn); double frexp(double x, int *expn); double pow(double base, double exponent); double atan2(double y, double x); diff --git a/src/userland/libc/posix_io.c b/src/userland/libc/posix_io.c index d970590..b71065d 100644 --- a/src/userland/libc/posix_io.c +++ b/src/userland/libc/posix_io.c @@ -3,6 +3,25 @@ #include #include "errno.h" +#include "sys/mman.h" + +void *mmap(void *addr, unsigned long length, int prot, int flags, int fd, long offset) { + (void)addr; (void)length; (void)prot; (void)flags; (void)fd; (void)offset; + errno = ENOSYS; + return MAP_FAILED; +} + +int munmap(void *addr, unsigned long length) { + (void)addr; (void)length; + errno = ENOSYS; + return -1; +} + +int mprotect(void *addr, unsigned long length, int prot) { + (void)addr; (void)length; (void)prot; + errno = ENOSYS; + return -1; +} #include "fcntl.h" #include "stdlib.h" #include "string.h" diff --git a/src/userland/libc/runtime.c b/src/userland/libc/runtime.c index 9d21b32..0a17cde 100644 --- a/src/userland/libc/runtime.c +++ b/src/userland/libc/runtime.c @@ -1,4 +1,5 @@ #include "stdlib.h" +char **environ = 0; #include "string.h" #include "errno.h" #include "syscall.h" @@ -176,3 +177,11 @@ __attribute__((weak)) double strtod(const char *nptr, char **endptr) { } return sign * value; } + +__attribute__((weak)) float strtof(const char *nptr, char **endptr) { + return (float)strtod(nptr, endptr); +} + +__attribute__((weak)) long double strtold(const char *nptr, char **endptr) { + return (long double)strtod(nptr, endptr); +} diff --git a/src/userland/libc/stdint.h b/src/userland/libc/stdint.h new file mode 100644 index 0000000..d6b9125 --- /dev/null +++ b/src/userland/libc/stdint.h @@ -0,0 +1,22 @@ +#ifndef _STDINT_H +#define _STDINT_H +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long int64_t; +typedef unsigned long uint64_t; + +#ifndef _INTPTR_T +#define _INTPTR_T +typedef long intptr_t; +#endif + +#ifndef _UINTPTR_T +#define _UINTPTR_T +typedef unsigned long uintptr_t; +#endif + +#endif diff --git a/src/userland/libc/stdio.c b/src/userland/libc/stdio.c index 9003df9..96020ef 100644 --- a/src/userland/libc/stdio.c +++ b/src/userland/libc/stdio.c @@ -76,6 +76,19 @@ FILE *fopen(const char *path, const char *mode) { return f; } +FILE *fdopen(int fd, const char *mode) { + (void)mode; + if (fd < 0) return NULL; + FILE *f = (FILE *)malloc(sizeof(FILE)); + if (!f) return NULL; + f->fd = fd; + f->eof = 0; + f->err = 0; + f->has_ungetc = 0; + f->ungetc_char = 0; + return f; +} + FILE *freopen(const char *path, const char *mode, FILE *stream) { int fd; if (!stream) { @@ -193,6 +206,10 @@ int getc(FILE *stream) { return (int)ch; } +int fgetc(FILE *stream) { + return getc(stream); +} + int ungetc(int c, FILE *stream) { if (!stream || c == EOF) { return EOF; diff --git a/src/userland/libc/stdio.h b/src/userland/libc/stdio.h index 9c4b9b0..114e6ad 100644 --- a/src/userland/libc/stdio.h +++ b/src/userland/libc/stdio.h @@ -25,8 +25,10 @@ extern FILE *stderr; #define TMP_MAX 32 FILE *fopen(const char *path, const char *mode); +FILE *fdopen(int fd, const char *mode); FILE *freopen(const char *path, const char *mode, FILE *stream); int fclose(FILE *stream); +int fgetc(FILE *stream); size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); int fseek(FILE *stream, long offset, int whence); diff --git a/src/userland/libc/stdlib.c b/src/userland/libc/stdlib.c index c3d317b..68b747b 100644 --- a/src/userland/libc/stdlib.c +++ b/src/userland/libc/stdlib.c @@ -234,6 +234,70 @@ int atoi(const char *nptr) { return sign * res; } +long strtol(const char *nptr, char **endptr, int base) { + long res = 0; + int sign = 1; + while (*nptr == ' ' || *nptr == '\t' || *nptr == '\n' || *nptr == '\r') nptr++; + if (*nptr == '-') { sign = -1; nptr++; } + else if (*nptr == '+') nptr++; + + if (base == 0) { + if (*nptr == '0') { + if (*(nptr+1) == 'x' || *(nptr+1) == 'X') { base = 16; nptr += 2; } + else base = 8; + } else base = 10; + } else if (base == 16) { + if (*nptr == '0' && (*(nptr+1) == 'x' || *(nptr+1) == 'X')) nptr += 2; + } + + while (1) { + int val = -1; + if (*nptr >= '0' && *nptr <= '9') val = *nptr - '0'; + else if (*nptr >= 'a' && *nptr <= 'f') val = *nptr - 'a' + 10; + else if (*nptr >= 'A' && *nptr <= 'F') val = *nptr - 'A' + 10; + + if (val == -1 || val >= base) break; + res = res * base + val; + nptr++; + } + if (endptr) *endptr = (char *)nptr; + return sign * res; +} + +unsigned long strtoul(const char *nptr, char **endptr, int base) { + return (unsigned long)strtol(nptr, endptr, base); +} + +unsigned long long strtoull(const char *nptr, char **endptr, int base) { + return (unsigned long long)strtol(nptr, endptr, base); +} + +static void swap(void *a, void *b, size_t size) { + char *ca = a, *cb = b; + while (size--) { char t = *ca; *ca++ = *cb; *cb++ = t; } +} + +void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { + if (nmemb < 2) return; + char *pivot = (char *)base + (nmemb / 2) * size; + char *left = base; + char *right = (char *)base + (nmemb - 1) * size; + + while (left <= right) { + while (compar(left, pivot) < 0) left += size; + while (compar(right, pivot) > 0) right -= size; + if (left <= right) { + swap(left, right, size); + if (pivot == left) pivot = right; + else if (pivot == right) pivot = left; + left += size; + right -= size; + } + } + if (base < (void*)right) qsort(base, (right - (char *)base) / size + 1, size, compar); + if ((void*)left < (char *)base + nmemb * size) qsort(left, ((char *)base + nmemb * size - left) / size, size, compar); +} + void itoa(int n, char *buf) { if (n == 0) { buf[0] = '0'; buf[1] = 0; return; @@ -265,6 +329,13 @@ char* getcwd(char *buf, int size) { return NULL; } +char *realpath(const char *path, char *resolved_path) { + if (!resolved_path) resolved_path = malloc(1024); + if (!resolved_path) return NULL; + strcpy(resolved_path, path); + return resolved_path; +} + void sleep(int ms) { sys_system(SYSTEM_CMD_SLEEP, ms, 0, 0, 0); } diff --git a/src/userland/libc/stdlib.h b/src/userland/libc/stdlib.h index 8e87f46..fa4065d 100644 --- a/src/userland/libc/stdlib.h +++ b/src/userland/libc/stdlib.h @@ -3,6 +3,7 @@ #include #include +extern char **environ; void* malloc(size_t size); void free(void* ptr); @@ -18,6 +19,12 @@ int atoi(const char *nptr); void itoa(int n, char *buf); int abs(int x); double strtod(const char *nptr, char **endptr); +float strtof(const char *nptr, char **endptr); +long double strtold(const char *nptr, char **endptr); +long strtol(const char *nptr, char **endptr, int base); +unsigned long strtoul(const char *nptr, char **endptr, int base); +unsigned long long strtoull(const char *nptr, char **endptr, int base); +void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); // IO functions void puts(const char *s); @@ -31,6 +38,7 @@ void abort(void); // System/Process functions int chdir(const char *path); char* getcwd(char *buf, int size); +char *realpath(const char *path, char *resolved_path); int access(const char *pathname, int mode); void sleep(int ms); void exit(int status); diff --git a/src/userland/libc/sys/mman.h b/src/userland/libc/sys/mman.h new file mode 100644 index 0000000..b5027ed --- /dev/null +++ b/src/userland/libc/sys/mman.h @@ -0,0 +1,14 @@ +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_FAILED ((void *)-1) +void *mmap(void *addr, unsigned long length, int prot, int flags, int fd, long offset); +int munmap(void *addr, unsigned long length); +int mprotect(void *addr, unsigned long length, int prot); +#endif diff --git a/src/userland/libc/sys/time.h b/src/userland/libc/sys/time.h new file mode 100644 index 0000000..86e1e4b --- /dev/null +++ b/src/userland/libc/sys/time.h @@ -0,0 +1,6 @@ +#ifndef _SYS_TIME_H +#define _SYS_TIME_H +struct timeval { long tv_sec; long tv_usec; }; +struct timezone { int tz_minuteswest; int tz_dsttime; }; +int gettimeofday(struct timeval *tv, void *tz); +#endif diff --git a/src/userland/libc/sys/ucontext.h b/src/userland/libc/sys/ucontext.h new file mode 100644 index 0000000..03a085a --- /dev/null +++ b/src/userland/libc/sys/ucontext.h @@ -0,0 +1,3 @@ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H +#endif diff --git a/src/userland/libc/time.c b/src/userland/libc/time.c index 6bb1248..00ade94 100644 --- a/src/userland/libc/time.c +++ b/src/userland/libc/time.c @@ -3,6 +3,7 @@ #include "time.h" #include "stdio.h" #include "syscall.h" +#include "sys/time.h" static int _b_is_leap(int year) { return ((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0); @@ -164,3 +165,13 @@ __attribute__((weak)) time_t mktime(struct tm *tm) { tm->tm_min, tm->tm_sec); } + +int gettimeofday(struct timeval *tv, void *tz) { + (void)tz; + if (tv) { + time_t t = time(NULL); + tv->tv_sec = (long)t; + tv->tv_usec = 0; + } + return 0; +} diff --git a/src/userland/sdk/include/assert.h b/src/userland/sdk/include/assert.h new file mode 100644 index 0000000..e26808b --- /dev/null +++ b/src/userland/sdk/include/assert.h @@ -0,0 +1,4 @@ +#ifndef _ASSERT_H +#define _ASSERT_H +#define assert(x) ((void)0) +#endif diff --git a/src/userland/sdk/include/ctype.h b/src/userland/sdk/include/ctype.h new file mode 100644 index 0000000..4960be3 --- /dev/null +++ b/src/userland/sdk/include/ctype.h @@ -0,0 +1,18 @@ +#ifndef BOREDOS_LIBC_CTYPE_H +#define BOREDOS_LIBC_CTYPE_H + +int isdigit(int c); +int isalpha(int c); +int isalnum(int c); +int isspace(int c); +int isupper(int c); +int islower(int c); +int isxdigit(int c); +int iscntrl(int c); +int ispunct(int c); +int isprint(int c); +int isgraph(int c); +int tolower(int c); +int toupper(int c); + +#endif diff --git a/src/userland/sdk/include/dlfcn.h b/src/userland/sdk/include/dlfcn.h new file mode 100644 index 0000000..a4532b8 --- /dev/null +++ b/src/userland/sdk/include/dlfcn.h @@ -0,0 +1,9 @@ +#ifndef _DLFCN_H +#define _DLFCN_H +#define RTLD_LAZY 0x00001 +#define RTLD_NOW 0x00002 +void *dlopen(const char *filename, int flag); +char *dlerror(void); +void *dlsym(void *handle, const char *symbol); +int dlclose(void *handle); +#endif diff --git a/src/userland/sdk/include/errno.h b/src/userland/sdk/include/errno.h new file mode 100644 index 0000000..396ca00 --- /dev/null +++ b/src/userland/sdk/include/errno.h @@ -0,0 +1,27 @@ +#ifndef BOREDOS_LIBC_ERRNO_H +#define BOREDOS_LIBC_ERRNO_H + +extern int errno; + +#define EDOM 33 +#define E2BIG 7 +#define ERANGE 34 +#define EINVAL 22 +#define EISDIR 21 +#define ENOENT 2 +#define ENOMEM 12 +#define EACCES 13 +#define EBADF 9 +#define EIO 5 +#define EEXIST 17 +#define EAGAIN 11 +#define EINTR 4 +#define ECHILD 10 +#define ENOTSUP 95 +#define EPIPE 32 +#define ENOTDIR 20 +#define EBUSY 16 +#define ESPIPE 29 +#define ENOSYS 38 + +#endif diff --git a/src/userland/sdk/include/fcntl.h b/src/userland/sdk/include/fcntl.h new file mode 100644 index 0000000..6bb56c1 --- /dev/null +++ b/src/userland/sdk/include/fcntl.h @@ -0,0 +1,27 @@ +#ifndef BOREDOS_LIBC_FCNTL_H +#define BOREDOS_LIBC_FCNTL_H + +#include "sys/types.h" + +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_ACCMODE 0x0003 +#define O_CREAT 0x0040 +#define O_EXCL 0x0080 +#define O_TRUNC 0x0200 +#define O_APPEND 0x0400 +#define O_NONBLOCK 0x0800 + +#define F_GETFL 3 +#define F_SETFL 4 + +#define FD_CLOEXEC 1 + +int open(const char *pathname, int flags, ...); +int fcntl(int fd, int cmd, ...); +int dup(int oldfd); +int dup2(int oldfd, int newfd); +int pipe(int pipefd[2]); + +#endif diff --git a/src/userland/sdk/include/input.h b/src/userland/sdk/include/input.h new file mode 100644 index 0000000..e5c05b6 --- /dev/null +++ b/src/userland/sdk/include/input.h @@ -0,0 +1,19 @@ +#ifndef INPUT_H +#define INPUT_H + +// Arrow keys +#define KEY_UP 17 +#define KEY_DOWN 18 +#define KEY_LEFT 19 +#define KEY_RIGHT 20 + +// controls +#define KEY_ENTER 10 +#define KEY_BACKSPACE 8 +#define KEY_ESCAPE 27 +#define KEY_SPACE 32 +#define KEY_ALT 22 +#define KEY_CTRL_L 21 +#define KEY_TAB 9 + +#endif diff --git a/src/userland/sdk/include/inttypes.h b/src/userland/sdk/include/inttypes.h new file mode 100644 index 0000000..112de7e --- /dev/null +++ b/src/userland/sdk/include/inttypes.h @@ -0,0 +1,7 @@ +#ifndef _INTTYPES_H +#define _INTTYPES_H +#include +#define PRId64 "lld" +#define PRIu64 "llu" +#define PRIx64 "llx" +#endif diff --git a/src/userland/sdk/include/libui.h b/src/userland/sdk/include/libui.h new file mode 100644 index 0000000..38d92e4 --- /dev/null +++ b/src/userland/sdk/include/libui.h @@ -0,0 +1,78 @@ +#ifndef LIBUI_H +#define LIBUI_H + +#include +#include + +// GUI Command IDs +#define GUI_CMD_WINDOW_CREATE 1 +#define GUI_CMD_DRAW_RECT 2 +#define GUI_CMD_DRAW_STRING 3 +#define GUI_CMD_MARK_DIRTY 4 +#define GUI_CMD_GET_EVENT 5 +#define GUI_CMD_DRAW_ROUNDED_RECT_FILLED 6 +#define GUI_CMD_DRAW_IMAGE 7 +#define GUI_CMD_GET_STRING_WIDTH 8 +#define GUI_CMD_GET_FONT_HEIGHT 9 +#define GUI_CMD_WINDOW_SET_RESIZABLE 14 +#define GUI_CMD_DRAW_STRING_BITMAP 10 +#define GUI_CMD_DRAW_STRING_SCALED 11 +#define GUI_CMD_GET_STRING_WIDTH_SCALED 12 +#define GUI_CMD_GET_FONT_HEIGHT_SCALED 13 +#define GUI_CMD_WINDOW_SET_TITLE 15 +#define GUI_CMD_SET_FONT 16 +#define GUI_CMD_DRAW_STRING_SCALED_SLOPED 18 +#define GUI_CMD_GET_SCREEN_SIZE 50 +#define GUI_CMD_GET_SCREENBUFFER 51 +#define GUI_CMD_SHOW_NOTIFICATION 52 +#define GUI_CMD_GET_DATETIME 53 + +// Event Types +#define GUI_EVENT_NONE 0 +#define GUI_EVENT_PAINT 1 +#define GUI_EVENT_CLICK 2 +#define GUI_EVENT_RIGHT_CLICK 3 +#define GUI_EVENT_CLOSE 4 +#define GUI_EVENT_KEY 5 +#define GUI_EVENT_KEYUP 10 + +#define GUI_EVENT_MOUSE_DOWN 6 +#define GUI_EVENT_MOUSE_UP 7 +#define GUI_EVENT_MOUSE_MOVE 8 +#define GUI_EVENT_MOUSE_WHEEL 9 +#define GUI_EVENT_RESIZE 11 + +typedef struct { + int type; + int arg1; // CLICK: x / KEY: legacy char-or-compat key + int arg2; // CLICK: y / KEY: keycode + int arg3; // CLICK: button state / KEY: modifier mask + int arg4; // KEY: Unicode codepoint (0 if none) +} gui_event_t; + +// Window Handle +typedef uint64_t ui_window_t; + +// libui API +ui_window_t ui_window_create(const char *title, int x, int y, int w, int h); +bool ui_get_event(ui_window_t win, gui_event_t *ev); + +void ui_draw_rect(ui_window_t win, int x, int y, int w, int h, uint32_t color); +void ui_draw_rounded_rect_filled(ui_window_t win, int x, int y, int w, int h, int radius, uint32_t color); +void ui_draw_string(ui_window_t win, int x, int y, const char *str, uint32_t color); +void ui_mark_dirty(ui_window_t win, int x, int y, int w, int h); +void ui_draw_image(ui_window_t win, int x, int y, int w, int h, uint32_t *image_data); +uint32_t ui_get_string_width(const char *str); +uint32_t ui_get_font_height(void); +void ui_get_screen_size(uint64_t *out_w, uint64_t *out_h); +void ui_draw_string_bitmap(ui_window_t win, int x, int y, const char *str, uint32_t color); + +void ui_draw_string_scaled(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale); +void ui_draw_string_scaled_sloped(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale, float slope); +uint32_t ui_get_string_width_scaled(const char *str, float scale); +uint32_t ui_get_font_height_scaled(float scale); +void ui_window_set_title(ui_window_t win, const char *title); +void ui_window_set_resizable(ui_window_t win, bool resizable); +void ui_set_font(ui_window_t win, const char *path); + +#endif diff --git a/src/userland/sdk/include/limits.h b/src/userland/sdk/include/limits.h new file mode 100644 index 0000000..760f213 --- /dev/null +++ b/src/userland/sdk/include/limits.h @@ -0,0 +1,22 @@ +#ifndef BOREDOS_LIBC_LIMITS_H +#define BOREDOS_LIBC_LIMITS_H + +#define CHAR_BIT 8 +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 +#define USHRT_MAX 65535 +#define INT_MIN (-2147483647 - 1) +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295U +#define LONG_MIN (-9223372036854775807L - 1) +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL +#define LLONG_MIN (-9223372036854775807LL - 1) +#define LLONG_MAX 9223372036854775807LL +#define ULLONG_MAX 18446744073709551615ULL +#define DBL_MAX 1.7976931348623157e+308 + +#endif diff --git a/src/userland/sdk/include/locale.h b/src/userland/sdk/include/locale.h new file mode 100644 index 0000000..46158da --- /dev/null +++ b/src/userland/sdk/include/locale.h @@ -0,0 +1,30 @@ +#ifndef BOREDOS_LIBC_LOCALE_H +#define BOREDOS_LIBC_LOCALE_H + +struct lconv { + char *decimal_point; + char *thousands_sep; + char *grouping; + char *int_curr_symbol; + char *currency_symbol; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; +}; + +#define LC_ALL 0 + +char *setlocale(int category, const char *locale); +struct lconv *localeconv(void); + +#endif diff --git a/src/userland/sdk/include/math.h b/src/userland/sdk/include/math.h new file mode 100644 index 0000000..b5a6945 --- /dev/null +++ b/src/userland/sdk/include/math.h @@ -0,0 +1,46 @@ +// Copyright (c) 2023-2026 Chris (boreddevnl) +// This software is released under the GNU General Public License v3.0. See LICENSE file for details. +// This header needs to maintain in any file it is present in, as per the GPL license terms. + +#ifndef MATH_H +#define MATH_H + +#define M_PI 3.14159265358979323846 +#define M_E 2.71828182845904523536 +#define M_LN2 0.69314718055994530942 +#define M_SQRT2 1.41421356237309504880 +#define HUGE_VAL (1e300 * 1e300) + +double fabs(double x); + +double fmod(double x, double y); + +double floor(double x); + +double ceil(double x); + +double sin(double x); +double cos(double x); +double tan(double x); +double sqrt(double x); + +double log(double x); +double log2(double x); +double log10(double x); +double exp(double x); +double ldexp(double x, int expn); +long double ldexpl(long double x, int expn); +double frexp(double x, int *expn); +double pow(double base, double exponent); +double atan2(double y, double x); +double asin(double x); +double acos(double x); +double sinh(double x); +double cosh(double x); +double tanh(double x); +double hypot(double x, double y); +double fmin(double a, double b); +double fmax(double a, double b); +double fclamp(double x, double lo, double hi); + +#endif /* MATH_H */ diff --git a/src/userland/sdk/include/setjmp.h b/src/userland/sdk/include/setjmp.h new file mode 100644 index 0000000..4bbc400 --- /dev/null +++ b/src/userland/sdk/include/setjmp.h @@ -0,0 +1,20 @@ +#ifndef BOREDOS_LIBC_SETJMP_H +#define BOREDOS_LIBC_SETJMP_H + +#include + +typedef struct boredos_jmp_buf_s { + uint64_t rbx; + uint64_t rbp; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rsp; + uint64_t rip; +} jmp_buf[1]; + +int setjmp(jmp_buf env) __attribute__((returns_twice, noinline)); +void longjmp(jmp_buf env, int val) __attribute__((noreturn, noinline)); + +#endif diff --git a/src/userland/sdk/include/signal.h b/src/userland/sdk/include/signal.h new file mode 100644 index 0000000..671f8c1 --- /dev/null +++ b/src/userland/sdk/include/signal.h @@ -0,0 +1,37 @@ +#ifndef BOREDOS_LIBC_SIGNAL_H +#define BOREDOS_LIBC_SIGNAL_H + +#include "sys/types.h" + +typedef void (*sighandler_t)(int); +typedef unsigned long sigset_t; + +struct sigaction { + sighandler_t sa_handler; + sigset_t sa_mask; + int sa_flags; +}; + +#define SIG_DFL ((sighandler_t)0) +#define SIG_IGN ((sighandler_t)1) +#define SIG_ERR ((sighandler_t)-1) +#define SIGKILL 9 +#define SIGTERM 15 +#define SIGINT 2 + +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 + +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 + +sighandler_t signal(int sig, sighandler_t handler); +int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact); +int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); +int sigpending(sigset_t *set); +int raise(int sig); +int kill(pid_t pid, int sig); + +#endif diff --git a/src/userland/sdk/include/stdint.h b/src/userland/sdk/include/stdint.h new file mode 100644 index 0000000..d6b9125 --- /dev/null +++ b/src/userland/sdk/include/stdint.h @@ -0,0 +1,22 @@ +#ifndef _STDINT_H +#define _STDINT_H +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long int64_t; +typedef unsigned long uint64_t; + +#ifndef _INTPTR_T +#define _INTPTR_T +typedef long intptr_t; +#endif + +#ifndef _UINTPTR_T +#define _UINTPTR_T +typedef unsigned long uintptr_t; +#endif + +#endif diff --git a/src/userland/sdk/include/stdio.h b/src/userland/sdk/include/stdio.h new file mode 100644 index 0000000..114e6ad --- /dev/null +++ b/src/userland/sdk/include/stdio.h @@ -0,0 +1,61 @@ +#ifndef BOREDOS_LIBC_STDIO_H +#define BOREDOS_LIBC_STDIO_H + +#include +#include + +typedef struct BOREDOS_FILE { + int fd; + int eof; + int err; + int has_ungetc; + int ungetc_char; +} FILE; + +extern FILE *stdin; +extern FILE *stdout; +extern FILE *stderr; + +#define EOF (-1) +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#define BUFSIZ 1024 +#define FILENAME_MAX 260 +#define TMP_MAX 32 + +FILE *fopen(const char *path, const char *mode); +FILE *fdopen(int fd, const char *mode); +FILE *freopen(const char *path, const char *mode, FILE *stream); +int fclose(FILE *stream); +int fgetc(FILE *stream); +size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); +int fseek(FILE *stream, long offset, int whence); +long ftell(FILE *stream); +int getc(FILE *stream); +int ungetc(int c, FILE *stream); +char *fgets(char *s, int n, FILE *stream); +int fputs(const char *s, FILE *stream); +int feof(FILE *stream); +int ferror(FILE *stream); +void clearerr(FILE *stream); +int fflush(FILE *stream); +int fputc(int c, FILE *stream); +int putchar(int c); +int fprintf(FILE *stream, const char *fmt, ...); +int vfprintf(FILE *stream, const char *fmt, va_list ap); +long filelength(FILE *f); +int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); +int snprintf(char *str, size_t size, const char *fmt, ...); +int sprintf(char *str, const char *fmt, ...); +int sscanf(const char *str, const char *fmt, ...); +int remove(const char *path); +int rename(const char *oldpath, const char *newpath); +FILE *tmpfile(void); +char *tmpnam(char *s); + +void puts(const char *s); +void printf(const char *fmt, ...); + +#endif diff --git a/src/userland/sdk/include/stdlib.h b/src/userland/sdk/include/stdlib.h new file mode 100644 index 0000000..fa4065d --- /dev/null +++ b/src/userland/sdk/include/stdlib.h @@ -0,0 +1,47 @@ +#ifndef STDLIB_H +#define STDLIB_H + +#include +#include +extern char **environ; + +void* malloc(size_t size); +void free(void* ptr); +void* calloc(size_t nmemb, size_t size); +void* realloc(void* ptr, size_t size); +void *memset(void *s, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t n); + +#include "string.h" + +// Math/Utility functions +int atoi(const char *nptr); +void itoa(int n, char *buf); +int abs(int x); +double strtod(const char *nptr, char **endptr); +float strtof(const char *nptr, char **endptr); +long double strtold(const char *nptr, char **endptr); +long strtol(const char *nptr, char **endptr, int base); +unsigned long strtoul(const char *nptr, char **endptr, int base); +unsigned long long strtoull(const char *nptr, char **endptr, int base); +void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); + +// IO functions +void puts(const char *s); +void printf(const char *fmt, ...); + +// Runtime stubs +int system(const char *command); +char *getenv(const char *name); +void abort(void); + +// System/Process functions +int chdir(const char *path); +char* getcwd(char *buf, int size); +char *realpath(const char *path, char *resolved_path); +int access(const char *pathname, int mode); +void sleep(int ms); +void exit(int status); +void _exit(int status); + +#endif diff --git a/src/userland/sdk/include/string.h b/src/userland/sdk/include/string.h new file mode 100644 index 0000000..a5eab52 --- /dev/null +++ b/src/userland/sdk/include/string.h @@ -0,0 +1,28 @@ +#ifndef BOREDOS_LIBC_STRING_H +#define BOREDOS_LIBC_STRING_H + +#include + +void *memmove(void *dest, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +void *memcpy(void *dest, const void *src, size_t n); +void *memset(void *s, int c, size_t n); +void *memchr(const void *s, int c, size_t n); +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +char *strpbrk(const char *s, const char *accept); +char *strstr(const char *haystack, const char *needle); +size_t strspn(const char *s, const char *accept); +size_t strcspn(const char *s, const char *reject); +size_t strlen(const char *s); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +int strncasecmp(const char *s1, const char *s2, size_t n); +int strcasecmp(const char *s1, const char *s2); +int strcoll(const char *s1, const char *s2); +char* strcpy(char *dest, const char *src); +char* strcat(char *dest, const char *src); +char *strdup(const char *s); +char *strerror(int errnum); + +#endif diff --git a/src/userland/sdk/include/sys/mman.h b/src/userland/sdk/include/sys/mman.h new file mode 100644 index 0000000..b5027ed --- /dev/null +++ b/src/userland/sdk/include/sys/mman.h @@ -0,0 +1,14 @@ +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_FAILED ((void *)-1) +void *mmap(void *addr, unsigned long length, int prot, int flags, int fd, long offset); +int munmap(void *addr, unsigned long length); +int mprotect(void *addr, unsigned long length, int prot); +#endif diff --git a/src/userland/sdk/include/sys/stat.h b/src/userland/sdk/include/sys/stat.h new file mode 100644 index 0000000..e3cfdb8 --- /dev/null +++ b/src/userland/sdk/include/sys/stat.h @@ -0,0 +1,47 @@ +#ifndef BOREDOS_LIBC_SYS_STAT_H +#define BOREDOS_LIBC_SYS_STAT_H + +#include "types.h" + +typedef long time_t; + +struct stat { + unsigned long st_dev; + unsigned long st_ino; + mode_t st_mode; + unsigned long st_nlink; + uid_t st_uid; + gid_t st_gid; + unsigned long st_rdev; + int st_size; + long st_blksize; + long st_blocks; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; + +#define S_IFMT 0170000 +#define S_IFIFO 0010000 +#define S_IFCHR 0020000 +#define S_IFDIR 0040000 +#define S_IFREG 0100000 + +#define S_IRUSR 0400 +#define S_IWUSR 0200 +#define S_IXUSR 0100 +#define S_IRGRP 0040 +#define S_IWGRP 0020 +#define S_IXGRP 0010 +#define S_IROTH 0004 +#define S_IWOTH 0002 +#define S_IXOTH 0001 + +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) + +int stat(const char *pathname, struct stat *statbuf); +int fstat(int fd, struct stat *statbuf); +int mkdir(const char *pathname, int mode); + +#endif diff --git a/src/userland/sdk/include/sys/time.h b/src/userland/sdk/include/sys/time.h new file mode 100644 index 0000000..86e1e4b --- /dev/null +++ b/src/userland/sdk/include/sys/time.h @@ -0,0 +1,6 @@ +#ifndef _SYS_TIME_H +#define _SYS_TIME_H +struct timeval { long tv_sec; long tv_usec; }; +struct timezone { int tz_minuteswest; int tz_dsttime; }; +int gettimeofday(struct timeval *tv, void *tz); +#endif diff --git a/src/userland/sdk/include/sys/types.h b/src/userland/sdk/include/sys/types.h new file mode 100644 index 0000000..da5815b --- /dev/null +++ b/src/userland/sdk/include/sys/types.h @@ -0,0 +1,11 @@ +#ifndef BOREDOS_LIBC_SYS_TYPES_H +#define BOREDOS_LIBC_SYS_TYPES_H + +typedef long ssize_t; +typedef long off_t; +typedef unsigned int mode_t; +typedef int pid_t; +typedef unsigned int uid_t; +typedef unsigned int gid_t; + +#endif diff --git a/src/userland/sdk/include/sys/ucontext.h b/src/userland/sdk/include/sys/ucontext.h new file mode 100644 index 0000000..03a085a --- /dev/null +++ b/src/userland/sdk/include/sys/ucontext.h @@ -0,0 +1,3 @@ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H +#endif diff --git a/src/userland/sdk/include/sys/wait.h b/src/userland/sdk/include/sys/wait.h new file mode 100644 index 0000000..6e0133c --- /dev/null +++ b/src/userland/sdk/include/sys/wait.h @@ -0,0 +1,15 @@ +#ifndef BOREDOS_LIBC_SYS_WAIT_H +#define BOREDOS_LIBC_SYS_WAIT_H + +#include "../sys/types.h" + +#define WNOHANG 1 + +#define WEXITSTATUS(status) (((status) >> 8) & 0xff) +#define WIFEXITED(status) ((((status) & 0x7f) == 0) ? 1 : 0) +#define WTERMSIG(status) ((status) & 0x7f) +#define WIFSIGNALED(status) (((status) & 0x7f) != 0) + +pid_t waitpid(pid_t pid, int *status, int options); + +#endif diff --git a/src/userland/sdk/include/syscall.h b/src/userland/sdk/include/syscall.h new file mode 100644 index 0000000..135f2f0 --- /dev/null +++ b/src/userland/sdk/include/syscall.h @@ -0,0 +1,292 @@ +#ifndef SYSCALL_H +#define SYSCALL_H + +#include +#include +#include + +// Standard syscalls available from Kernel mode +#define SYS_EXIT 0 +#define SYS_WRITE 1 +#define SYS_GUI 3 +#define SYS_FS 4 +#define SYS_SYSTEM 5 +#define SYS_KILL 10 +#define SYS_SBRK 9 + +// FS Commands +#define FS_CMD_OPEN 1 +#define FS_CMD_READ 2 +#define FS_CMD_WRITE 3 +#define FS_CMD_CLOSE 4 +#define FS_CMD_SEEK 5 +#define FS_CMD_TELL 6 +#define FS_CMD_LIST 7 +#define FS_CMD_DELETE 8 +#define FS_CMD_SIZE 9 +#define FS_CMD_MKDIR 10 +#define FS_CMD_EXISTS 11 +#define FS_CMD_GETCWD 12 +#define FS_CMD_CHDIR 13 +#define FS_CMD_GET_INFO 14 +#define FS_CMD_DUP 15 +#define FS_CMD_DUP2 16 +#define FS_CMD_PIPE 17 +#define FS_CMD_FCNTL 18 + +// System Commands (via SYS_SYSTEM) +#define SYSTEM_CMD_SET_BG_COLOR 1 +#define SYSTEM_CMD_SET_BG_PATTERN 2 +#define SYSTEM_CMD_SET_WALLPAPER 3 +#define SYSTEM_CMD_SET_DESKTOP_PROP 4 +#define SYSTEM_CMD_SET_MOUSE_SPEED 5 +#define SYSTEM_CMD_NETWORK_INIT 6 +#define SYSTEM_CMD_GET_DESKTOP_PROP 7 +#define SYSTEM_CMD_GET_MOUSE_SPEED 8 +#define SYSTEM_CMD_GET_WALLPAPER_THUMB 9 +#define SYSTEM_CMD_CLEAR_SCREEN 10 +#define SYSTEM_CMD_RTC_GET 11 +#define SYSTEM_CMD_REBOOT 12 +#define SYSTEM_CMD_SHUTDOWN 13 +#define SYSTEM_CMD_BEEP 14 +#define SYSTEM_CMD_GET_MEM_INFO 15 +#define SYSTEM_CMD_GET_TICKS 16 +#define SYSTEM_CMD_PCI_LIST 17 +#define SYSTEM_CMD_NETWORK_DHCP 18 +#define SYSTEM_CMD_NETWORK_GET_MAC 19 +#define SYSTEM_CMD_NETWORK_GET_IP 20 +#define SYSTEM_CMD_NETWORK_SET_IP 21 +#define SYSTEM_CMD_UDP_SEND 22 +#define SYSTEM_CMD_NETWORK_GET_STATS 23 +#define SYSTEM_CMD_NETWORK_GET_GATEWAY 24 +#define SYSTEM_CMD_NETWORK_GET_DNS 25 +#define SYSTEM_CMD_ICMP_PING 26 +#define SYSTEM_CMD_NETWORK_IS_INIT 27 +#define SYSTEM_CMD_NETWORK_HAS_IP 30 +#define SYSTEM_CMD_GET_SHELL_CONFIG 28 +#define SYSTEM_CMD_NETWORK_GET_NIC_NAME 48 +#define SYSTEM_CMD_SET_KEYBOARD_LAYOUT 49 +#define SYSTEM_CMD_GET_KEYBOARD_LAYOUT 51 +#define SYSTEM_CMD_SET_TEXT_COLOR 29 +#define SYSTEM_CMD_SET_WALLPAPER_PATH 31 +#define SYSTEM_CMD_RTC_SET 32 +#define SYSTEM_CMD_TCP_CONNECT 33 +#define SYSTEM_CMD_TCP_SEND 34 +#define SYSTEM_CMD_TCP_RECV 35 +#define SYSTEM_CMD_TCP_CLOSE 36 +#define SYSTEM_CMD_DNS_LOOKUP 37 +#define SYSTEM_CMD_SET_DNS 38 +#define SYSTEM_CMD_NET_UNLOCK 39 +#define SYSTEM_CMD_SET_FONT 40 +#define SYSTEM_CMD_SLEEP 46 +#define SYSTEM_CMD_SET_RAW_MODE 41 +#define SYSTEM_CMD_TCP_RECV_NB 42 +#define SYSTEM_CMD_YIELD 43 +#define SYSTEM_CMD_SET_RESOLUTION 47 +#define SYSTEM_CMD_PARALLEL_RUN 50 +#define SYSTEM_CMD_TTY_CREATE 60 +#define SYSTEM_CMD_TTY_READ_OUT 61 +#define SYSTEM_CMD_TTY_WRITE_IN 62 +#define SYSTEM_CMD_TTY_READ_IN 63 +#define SYSTEM_CMD_SPAWN 64 +#define SYSTEM_CMD_TTY_SET_FG 65 +#define SYSTEM_CMD_TTY_GET_FG 66 +#define SYSTEM_CMD_TTY_KILL_FG 67 +#define SYSTEM_CMD_TTY_KILL_ALL 68 +#define SYSTEM_CMD_TTY_DESTROY 69 +#define SYSTEM_CMD_EXEC 70 +#define SYSTEM_CMD_WAITPID 71 +#define SYSTEM_CMD_KILL_SIGNAL 72 +#define SYSTEM_CMD_SIGACTION 73 +#define SYSTEM_CMD_SIGPROCMASK 74 +#define SYSTEM_CMD_SIGPENDING 75 +#define SYSTEM_CMD_GET_ELF_METADATA 76 +#define SYSTEM_CMD_GET_ELF_PRIMARY_IMAGE 77 + +#define SPAWN_FLAG_TERMINAL 0x1 +#define SPAWN_FLAG_INHERIT_TTY 0x2 +#define SPAWN_FLAG_TTY_ID 0x4 +#define SPAWN_FLAG_BACKGROUND 0x8 + +// ELF app metadata (mirrors src/sys/elf.h, kept in sync manually) +#define BOREDOS_APP_METADATA_MAX_APP_NAME 64 +#define BOREDOS_APP_METADATA_MAX_DESCRIPTION 192 +#define BOREDOS_APP_METADATA_MAX_IMAGES 4 +#define BOREDOS_APP_METADATA_MAX_IMAGE_PATH 160 + +typedef struct __attribute__((packed)) { + uint32_t magic; + uint16_t version; + uint16_t image_count; + uint16_t reserved; + char app_name[BOREDOS_APP_METADATA_MAX_APP_NAME]; + char description[BOREDOS_APP_METADATA_MAX_DESCRIPTION]; + char images[BOREDOS_APP_METADATA_MAX_IMAGES][BOREDOS_APP_METADATA_MAX_IMAGE_PATH]; +} boredos_app_metadata_t; + +// Internal assembly entry into Ring 0 +extern uint64_t syscall0(uint64_t sys_num); +extern uint64_t syscall1(uint64_t sys_num, uint64_t arg1); +extern uint64_t syscall2(uint64_t sys_num, uint64_t arg1, uint64_t arg2); +extern uint64_t syscall3(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3); +extern uint64_t syscall4(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4); +extern uint64_t syscall5(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5); + +// Public API +void sys_exit(int status); +int sys_write(int fd, const char *buf, int len); +void *sys_sbrk(int incr); +void sys_kill(int pid); +int sys_system(int cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4); + +typedef struct { + char os_name[64]; + char os_version[64]; + char os_codename[64]; + char kernel_name[64]; + char kernel_version[64]; + char build_date[64]; + char build_time[64]; + char build_arch[64]; +} os_info_t; + +int sys_get_os_info(os_info_t *info); + +// FS API +int sys_open(const char *path, const char *mode); +int sys_read(int fd, void *buf, uint32_t len); +int sys_write_fs(int fd, const void *buf, uint32_t len); +void sys_close(int fd); +int sys_seek(int fd, int offset, int whence); +uint32_t sys_tell(int fd); +uint32_t sys_size(int fd); +int sys_delete(const char *path); +int sys_mkdir(const char *path); +int sys_exists(const char *path); +int sys_getcwd(char *buf, int size); +int sys_chdir(const char *path); +int sys_dup(int oldfd); +int sys_dup2(int oldfd, int newfd); +int sys_pipe(int pipefd[2]); +int sys_fcntl(int fd, int cmd, int val); + +int sys_tty_create(void); +int sys_tty_read_out(int tty_id, char *buf, int len); +int sys_tty_write_in(int tty_id, const char *buf, int len); +int sys_tty_read_in(char *buf, int len); +int sys_spawn(const char *path, const char *args, uint64_t flags, uint64_t tty_id); +int sys_exec(const char *path, const char *args); +int sys_waitpid(int pid, int *status, int options); +int sys_kill_signal(int pid, int sig); +int sys_sigaction(int sig, const void *act, void *oldact); +int sys_sigprocmask(int how, const unsigned long *set, unsigned long *oldset); +int sys_sigpending(unsigned long *set); +int sys_tty_set_fg(int tty_id, int pid); +int sys_tty_get_fg(int tty_id); +int sys_tty_kill_fg(int tty_id); +int sys_tty_kill_all(int tty_id); +int sys_tty_destroy(int tty_id); + +typedef struct { + char name[256]; + uint32_t size; + uint8_t is_directory; + uint32_t start_cluster; + uint16_t write_date; + uint16_t write_time; +} FAT32_FileInfo; + +int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries); +int sys_get_file_info(const char *path, FAT32_FileInfo *info); + +typedef struct { + uint32_t pid; + char name[64]; + uint64_t ticks; + size_t used_memory; + uint32_t is_idle; +} ProcessInfo; + +// Network API +typedef struct { uint8_t bytes[6]; } net_mac_address_t; +typedef struct { uint8_t bytes[4]; } net_ipv4_address_t; + +int sys_network_init(void); +int sys_network_dhcp_acquire(void); +int sys_network_get_mac(net_mac_address_t *mac); +int sys_network_get_nic_name(char *name_out); +int sys_network_get_ip(net_ipv4_address_t *ip); +int sys_network_set_ip(const net_ipv4_address_t *ip); +int sys_network_get_stat(int stat_type); +int sys_network_get_gateway(net_ipv4_address_t *ip); +int sys_network_get_dns(net_ipv4_address_t *ip); +int sys_get_dns_server(net_ipv4_address_t *ip); +int sys_udp_send(const net_ipv4_address_t *dest_ip, uint16_t dest_port, uint16_t src_port, const void *data, size_t data_len); +int sys_icmp_ping(const net_ipv4_address_t *dest_ip); +int sys_network_is_initialized(void); +int sys_network_has_ip(void); +uint64_t sys_get_shell_config(const char *key); +void sys_set_text_color(uint32_t color); + +int sys_tcp_connect(const net_ipv4_address_t *ip, uint16_t port); +int sys_tcp_send(const void *data, size_t len); +int sys_tcp_recv(void *buf, size_t max_len); +int sys_tcp_recv_nb(void *buf, size_t max_len); +int sys_tcp_close(void); +int sys_dns_lookup(const char *name, net_ipv4_address_t *out_ip); +int sys_set_dns_server(const net_ipv4_address_t *ip); +void sys_network_force_unlock(void); +void sys_yield(void); + +// ELF metadata API +int sys_get_elf_metadata(const char *path, boredos_app_metadata_t *out_metadata); +int sys_get_elf_primary_image(const char *path, char *out_path, size_t out_path_size); + +// Disk Management Syscalls + +#define SYSTEM_CMD_DISK_GET_COUNT 100 +#define SYSTEM_CMD_DISK_GET_INFO 101 +#define SYSTEM_CMD_DISK_MOUNT 105 +#define SYSTEM_CMD_DISK_UMOUNT 106 +#define SYSTEM_CMD_DISK_RESCAN 107 +#define SYSTEM_CMD_DISK_SYNC 109 + +#define SYSTEM_CMD_DISK_WRITE_GPT 102 +#define SYSTEM_CMD_DISK_WRITE_MBR 103 +#define SYSTEM_CMD_DISK_MKFS_FAT32 104 +#define SYSTEM_CMD_DISK_REPLACE_KERNEL 108 + +typedef struct { + char devname[16]; + char label[32]; + uint32_t type; + uint32_t total_sectors; + bool is_partition; + bool is_fat32; + bool is_esp; + uint32_t lba_offset; +} disk_info_t; + +typedef struct { + uint32_t lba_start; + uint32_t sector_count; + uint8_t part_type; + uint8_t flags; + char label[36]; +} partition_spec_t; + +#define PART_FLAG_ESP 0x01 +#define MIN_INSTALL_SECTORS 2097152 + +int sys_disk_get_count(void); +int sys_disk_get_info(int index, disk_info_t *out); +int sys_disk_write_gpt(const char *devname, partition_spec_t *parts, int count); +int sys_disk_write_mbr(const char *devname, partition_spec_t *parts, int count); +int sys_disk_mkfs_fat32(const char *devname, const char *label); +int sys_disk_mount(const char *devname, const char *mountpoint); +int sys_disk_umount(const char *mountpoint); +int sys_disk_sync(const char *mountpoint); +int sys_disk_rescan(const char *devname); +int sys_disk_replace_kernel(const char *src_path, const char *esp_mountpoint); + +#endif diff --git a/src/userland/sdk/include/syscall_user.h b/src/userland/sdk/include/syscall_user.h new file mode 100644 index 0000000..892e4f2 --- /dev/null +++ b/src/userland/sdk/include/syscall_user.h @@ -0,0 +1,11 @@ +#ifndef SYSCALL_USER_H +#define SYSCALL_USER_H + +#include "syscall.h" +#include + +static inline void sys_serial_write(const char *str) { + syscall2(8, 0, (uint64_t)str); +} + +#endif diff --git a/src/userland/sdk/include/time.h b/src/userland/sdk/include/time.h new file mode 100644 index 0000000..b3e7c3c --- /dev/null +++ b/src/userland/sdk/include/time.h @@ -0,0 +1,30 @@ +#ifndef BOREDOS_LIBC_TIME_H +#define BOREDOS_LIBC_TIME_H + +#include + +typedef long long time_t; +typedef unsigned long long clock_t; + +#define CLOCKS_PER_SEC 3000000000ULL + +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +time_t time(time_t *out); +clock_t clock(void); +struct tm *localtime(const time_t *timer); +struct tm *gmtime(const time_t *timer); +size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tm); +time_t mktime(struct tm *tm); + +#endif diff --git a/src/userland/sdk/include/unistd.h b/src/userland/sdk/include/unistd.h new file mode 100644 index 0000000..36d7081 --- /dev/null +++ b/src/userland/sdk/include/unistd.h @@ -0,0 +1,30 @@ +#ifndef BOREDOS_LIBC_UNISTD_H +#define BOREDOS_LIBC_UNISTD_H + +#include +#include "sys/types.h" + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#define F_OK 0 +#define X_OK 1 +#define W_OK 2 +#define R_OK 4 + +int close(int fd); +ssize_t read(int fd, void *buf, size_t count); +ssize_t write(int fd, const void *buf, size_t count); +off_t lseek(int fd, off_t offset, int whence); +int unlink(const char *pathname); +int isatty(int fd); +int execv(const char *path, char *const argv[]); +int execve(const char *path, char *const argv[], char *const envp[]); +int execvp(const char *file, char *const argv[]); +int execl(const char *path, const char *arg, ...); +int execlp(const char *file, const char *arg, ...); +int execle(const char *path, const char *arg, ...); +pid_t waitpid(pid_t pid, int *status, int options); + +#endif diff --git a/src/userland/sdk/include/utf-8.h b/src/userland/sdk/include/utf-8.h new file mode 100644 index 0000000..1af7b36 --- /dev/null +++ b/src/userland/sdk/include/utf-8.h @@ -0,0 +1,25 @@ +#ifndef UTF_8_H +#define UTF_8_H + +#include + +// Decode one UTF-8 codepoint +// s: input string +// advance: number of bytes consumed +uint32_t text_decode_utf8(const char *s, int *advance); + +// Encode one codepoint into UTF-8 +// out must be at least 4 bytes +// return: number of bytes written +int text_encode_utf8(uint32_t cp, char *out); + +// Move to next UTF-8 character +const char* text_next_utf8(const char *s); + +// Move to previous UTF-8 character +const char* text_prev_utf8(const char *start, const char *s); + +// Count characters (not bytes) +int text_strlen_utf8(const char *s); + +#endif \ No newline at end of file diff --git a/src/userland/sdk/lib/libboredos.a b/src/userland/sdk/lib/libboredos.a new file mode 100644 index 0000000..394888f Binary files /dev/null and b/src/userland/sdk/lib/libboredos.a differ diff --git a/src/userland/sdk/lib/libc.a b/src/userland/sdk/lib/libc.a new file mode 100644 index 0000000..394888f Binary files /dev/null and b/src/userland/sdk/lib/libc.a differ diff --git a/src/userland/sdk/lib/libm.a b/src/userland/sdk/lib/libm.a new file mode 100644 index 0000000..394888f Binary files /dev/null and b/src/userland/sdk/lib/libm.a differ diff --git a/src/userland/sdk/lib/libui.a b/src/userland/sdk/lib/libui.a new file mode 100644 index 0000000..57109b1 Binary files /dev/null and b/src/userland/sdk/lib/libui.a differ