diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 3e4ada4..b1e7ad6 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,7 +4,9 @@ "name": "Linux", "includePath": [ "${workspaceFolder}/libc/include/**", - "${workspaceFolder}/out/system/include/**" + "${workspaceFolder}/out/system/include/**", + "${workspaceFolder}/libs/include/**", + "${workspaceFolder}/libs/include" ], "defines": [ "__debug_vscode__", @@ -19,6 +21,10 @@ "configurationProvider": "ms-vscode.makefile-tools", "compilerArgs": [ "-pipe", + "-nostdinc++", + "-nostdinc", + "-fno-builtin", + "-ffreestanding" ] } ], diff --git a/apps/system/init/Makefile b/apps/system/init/Makefile index f16f0ee..dac3584 100644 --- a/apps/system/init/Makefile +++ b/apps/system/init/Makefile @@ -53,7 +53,7 @@ build: $(FILENAME) mv $(FILENAME) ../../../out/system/$(FILENAME) $(FILENAME): $(OBJ) - $(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -lssp -linit -o $@ + $(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -lssp -linit -lsys -lgraph -o $@ %.o: %.c $(HEADERS) $(info Compiling $<) diff --git a/apps/system/init/init.c b/apps/system/init/init.c index 083c979..038ae65 100644 --- a/apps/system/init/init.c +++ b/apps/system/init/init.c @@ -1,13 +1,24 @@ #include -#include #include -#include + +#include +#include +#include + +void PutCharToKernelConsole(char c) +{ + __asm__ __volatile__("syscall" + : + : "a"(1), "D"(c), "S"(0) + : "rcx", "r11", "memory"); +} #define print(m, ...) init_log(m, ##__VA_ARGS__) int main(int argc, char *argv[], char *envp[]) { - print("Hello World!\n"); + for (int i = 0; i < 14; i++) + PutCharToKernelConsole("\nHello World!\n"[i]); print("%p %p %p\n", (void *)(uint64_t)&argc, (void *)&argv, (void *)&envp); print("I have %d arguments\n", argc); for (int i = 0; i < argc; i++) @@ -30,5 +41,17 @@ int main(int argc, char *argv[], char *envp[]) for (auxv = (Elf64_auxv_t *)e; auxv->a_type != AT_NULL; auxv++) print("auxv: %ld %#lx\n", auxv->a_type, auxv->a_un.a_val); + File *test = FileOpen("/Test.txt", FILE_READ); + if (test == NULL) + { + print("Failed to open file\n"); + return 1; + } + + char buf[1024]; + uint64_t read = FileRead(test, (uint8_t *)buf, 1024); + print("Read %ld bytes from file\n", read); + print("File contents: %s\n", buf); + FileClose(test); return 0; } diff --git a/libc/Interpreter/Makefile b/libc/Interpreter/Makefile new file mode 100644 index 0000000..69040a7 --- /dev/null +++ b/libc/Interpreter/Makefile @@ -0,0 +1,53 @@ +# Config file +include ../../../Makefile.conf + +NAME=ld + +OBJECT_NAME=$(NAME).so +SO_NAME=$(OBJECT_NAME) + +OUTPUT_DIR=../../out/system/ +SYSROOT = --sysroot=../../out/system/ + +CC = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)gcc +AS = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)as +AR = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)ar +OBJDUMP = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)objdump +NASM = /usr/bin/nasm + +C_SOURCES = $(shell find ./ -type f -name '*.c') +CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') +S_SOURCES = $(shell find ./ -type f -name '*.S') +ASM_SOURCES = $(shell find ./ -type f -name '*.asm') +OBJ = ${C_SOURCES:.c=.o} ${CPP_SOURCES:.cpp=.o} ${ASM_SOURCES:.asm=.o} ${S_SOURCES:.S=.o} + +INCLUDE = ../include + +ifeq ($(OSARCH), amd64) +ASM_ARCH := elf64 +else ifeq ($(OSARCH), i686) +ASM_ARCH := elf32 +endif + +CFLAGS := -fPIC -I$(INCLUDE) + +build: $(OBJECT_NAME) + +$(OBJECT_NAME): $(OBJ) + $(CC) -nostdlib -static -fPIC -fPIE -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ + $(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map + +%.o: %.c + $(CC) $(CFLAGS) -std=c17 -c $< -o $@ + +%.o: %.cpp + $(CC) $(CFLAGS) -std=c++20 -c $< -o $@ + +%.o: %.S + $(AS) -c $< -o $@ + +%.o: %.asm + $(NASM) $< -f $(ASM_ARCH) -o $@ + +clean: + rm -f file_dump.map $(OBJ) diff --git a/libc/Interpreter/hash.c b/libc/Interpreter/hash.c new file mode 100644 index 0000000..805f177 --- /dev/null +++ b/libc/Interpreter/hash.c @@ -0,0 +1,14 @@ +#include "ld.h" + +uint32_t ElfHash(const unsigned char *Name) +{ + uint32_t i = 0, j; + while (*Name) + { + i = (i << 4) + *Name++; + if ((j = i & 0xF0000000) != 0) + i ^= j >> 24; + i &= ~j; + } + return i; +} diff --git a/libc/Interpreter/ld.c b/libc/Interpreter/ld.c new file mode 100644 index 0000000..51de090 --- /dev/null +++ b/libc/Interpreter/ld.c @@ -0,0 +1,12 @@ +#include "ld.h" + +int main(int argc, char *argv[], char *envp[]) +{ + if (argc < 2) + return -1; + + int envc = 0; + while (envp[envc] != NULL) + envc++; + return -0xD0D0; +} diff --git a/libc/Interpreter/ld.h b/libc/Interpreter/ld.h new file mode 100644 index 0000000..8012f84 --- /dev/null +++ b/libc/Interpreter/ld.h @@ -0,0 +1,8 @@ +#ifndef __FENNIX_LIBC_LD_H__ +#define __FENNIX_LIBC_LD_H__ + +#include + +uint32_t ElfHash(const unsigned char *Name); + +#endif // !__FENNIX_LIBC_LD_H__ diff --git a/libc/Makefile b/libc/Makefile index 5a8426d..a38ca15 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -3,7 +3,9 @@ build: cp ../../Kernel/syscalls.h ../out/system/include/sys make --quiet -C runtime build make --quiet -C src build + make --quiet -C Interpreter build clean: make -C runtime clean make -C src clean + make -C Interpreter clean diff --git a/libc/include/string.h b/libc/include/string.h index db62164..c0eafe7 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -12,6 +12,7 @@ extern "C" void *memset(void *, int, size_t); char *strcpy(char *, const char *); size_t strlen(const char *); + int strncmp(const char *s1, const char *s2, size_t n); #ifdef __cplusplus } diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h index 2373096..34c1b65 100644 --- a/libc/include/sys/types.h +++ b/libc/include/sys/types.h @@ -3,4 +3,4 @@ typedef int pid_t; -#endif \ No newline at end of file +#endif diff --git a/libc/src/std/lib.c b/libc/src/std/lib.c index 4272064..482ec45 100644 --- a/libc/src/std/lib.c +++ b/libc/src/std/lib.c @@ -1,5 +1,6 @@ #include #include +#include #include "../mem/liballoc_1_1.h" @@ -37,10 +38,20 @@ int atoi(const char *nptr) return OutBuffer; } +char **environ = NULL; + char *getenv(const char *name) { - static char *env = "PATH=/bin"; - return env; + char **env = environ; + if (env == NULL) + return NULL; + size_t len = strlen(name); + while (*env != NULL) + { + if ((strncmp(*env, name, len) == 0) && ((*env)[len] == '=')) + return &(*env)[len + 1]; + ++env; + } } void *malloc(size_t Size) { return PREFIX(malloc)(Size); } diff --git a/libc/src/string.c b/libc/src/string.c new file mode 100644 index 0000000..3ae0908 --- /dev/null +++ b/libc/src/string.c @@ -0,0 +1,14 @@ +#include + +int strncmp(const char *s1, const char *s2, size_t n) +{ + for (size_t i = 0; i < n; i++) + { + char c1 = s1[i], c2 = s2[i]; + if (c1 != c2) + return c1 - c2; + if (!c1) + return 0; + } + return 0; +} diff --git a/libs/Makefile b/libs/Makefile index 837a8a3..19be317 100644 --- a/libs/Makefile +++ b/libs/Makefile @@ -4,9 +4,11 @@ build: make --quiet -C libinit build make --quiet -C libssp build make --quiet -C libsys build + make --quiet -C libgraph build clean: make -C libgcc clean make -C libinit clean make -C libssp clean make -C libsys clean + make -C libgraph clean diff --git a/libs/include/sysbase.h b/libs/include/sysbase.h new file mode 100644 index 0000000..a63639b --- /dev/null +++ b/libs/include/sysbase.h @@ -0,0 +1,21 @@ +#ifndef __FENNIX_LIBS_BASE_H__ +#define __FENNIX_LIBS_BASE_H__ + +#include + +enum KCtl +{ + KCTL_NULL, + KCTL_GET_PID, + KCTL_GET_TID, + KCTL_GET_UID, + KCTL_GET_GID, + KCTL_GET_PAGE_SIZE, +}; + +long DoCtl(uint64_t Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4); + +uintptr_t KrnlRequestPages(size_t Count); +void KrnlFreePages(uintptr_t Address, size_t Count); + +#endif // !__FENNIX_LIBS_BASE_H__ diff --git a/libs/include/sysfile.h b/libs/include/sysfile.h new file mode 100644 index 0000000..eee5f72 --- /dev/null +++ b/libs/include/sysfile.h @@ -0,0 +1,32 @@ +#ifndef __FENNIX_LIBS_SYS_FILE_H__ +#define __FENNIX_LIBS_SYS_FILE_H__ + +#include + +typedef struct +{ + void *KernelPrivate; +} File; + +enum FileFlags +{ + FILE_READ = 1, + FILE_WRITE = 2, + FILE_APPEND = 4, + FILE_CREATE = 8, + FILE_TRUNCATE = 16, + FILE_EXCLUSIVE = 32, + FILE_DIRECTORY = 64, + FILE_SYMLINK = 128, + FILE_NONBLOCK = 256, + FILE_CLOEXEC = 512, +}; + +File *FileOpen(const char *Path, uint64_t Flags); +void FileClose(File *File); +uint64_t FileRead(File *File, uint8_t *Buffer, uint64_t Size); +uint64_t FileWrite(File *File, uint8_t *Buffer, uint64_t Size); +uint64_t FileSeek(File *File, uint64_t Offset, uint64_t Whence); +uint64_t FileStatus(File *File); + +#endif // !__FENNIX_LIBS_SYS_FILE_H__ diff --git a/libs/include/syslib.h b/libs/include/syslib.h deleted file mode 100644 index 9d11604..0000000 --- a/libs/include/syslib.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __FENNIX_LIBS_SYS_H__ -#define __FENNIX_LIBS_SYS_H__ - -#include - -enum KCtl -{ - KCTL_NULL, - KCTL_GETPID, - KCTL_GETTID, - KCTL_GETUID, - KCTL_GETGID, -}; - -long DoCtl(uint64_t Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4); - -#endif // !__FENNIX_LIBS_SYS_H__ diff --git a/libs/include/sysproc.h b/libs/include/sysproc.h new file mode 100644 index 0000000..731803d --- /dev/null +++ b/libs/include/sysproc.h @@ -0,0 +1,122 @@ +#ifndef __FENNIX_LIBS_SYS_PROC_H__ +#define __FENNIX_LIBS_SYS_PROC_H__ + +#include + +enum ProcessState +{ + PROCESS_STATE_READY, + PROCESS_STATE_RUNNING, + PROCESS_STATE_SLEEPING, + PROCESS_STATE_WAITING, + PROCESS_STATE_STOPPED, + PROCESS_STATE_TERMINATED +}; + +typedef struct +{ + char Name[256]; + unsigned long ID; + enum ProcessState State; + void *KernelPrivate; +} Process; + +typedef struct +{ + char Name[256]; + unsigned long ID; + enum ProcessState State; + void *KernelPrivate; +} Thread; + +/** + * @brief Create a new process from a path + * + * @param Path Path to the executable + * @return Process* Pointer to the process structure + */ +Process *Spawn(const char *Path); + +/** + * @brief Create a new thread + * + * @param EntryPoint Entry point of the thread + * @return Thread* Pointer to the thread structure + */ +Thread *SpawnThread(uintptr_t EntryPoint); + +/** + * @brief Get list of threads + * + * @param Process Process to get the threads from + * @return Thread** Pointer to the thread list (NULL terminated) + */ +Thread **GetThreadList(Process *Process); + +/** + * @brief Get process by ID + * + * @param ID Process ID + * @return Process* Pointer to the process structure + */ +Process *GetProcessByID(unsigned long ID); + +/** + * @brief Get thread by ID + * + * @param ID Thread ID + * @return Thread* Pointer to the thread structure + */ +Thread *GetThreadByID(unsigned long ID); + +/** + * @brief Get current process + * + * @return Process* Pointer to the process structure + */ +Process *GetCurrentProcess(); + +/** + * @brief Get current thread + * + * @return Thread* Pointer to the thread structure + */ +Thread *GetCurrentThread(); + +/** + * @brief [SYSTEM] Create a new empty process + * + * @param KernelPrivate Process parent + * @param Name Process name + * @param TrustLevel Process trust level [RESERVED FOR TRUSTED PROCESSES] + * @param Image Process file image already loaded in memory + * @return Process* Pointer to the process structure + */ +Process *KrnlCreateProcess(void *KernelPrivate, + const char *Name, + long TrustLevel, + void *Image); + +/** + * @brief [SYSTEM] Create a new thread + * + * @param KernelPrivate Process parent + * @param EntryPoint Entry point of the thread + * @param argv Arguments + * @param envp Environment variables + * @param auxv Auxiliary variables + * @param Offset Offset of the entry point + * @param Architecture Architecture of the thread + * @param Compatibility Compatibility of the thread + * @return Thread* Pointer to the thread structure + */ +Thread *KrnlCreateThread(void *KernelPrivate, + unsigned long EntryPoint, + const char **argv, + const char **envp, + void *auxv, + unsigned long Offset, + long Architecture, + long Compatibility); + +#endif // !__FENNIX_LIBS_SYS_PROC_H__ diff --git a/libs/libgraph/Graphics.c b/libs/libgraph/Graphics.c new file mode 100644 index 0000000..fcfd9c1 --- /dev/null +++ b/libs/libgraph/Graphics.c @@ -0,0 +1,18 @@ +#include + +#include "../../../Kernel/syscalls.h" + +long DoCtl(uint64_t Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) +{ + return syscall5(_KernelCTL, Command, Arg1, Arg2, Arg3, Arg4); +} + +uintptr_t KrnlRequestPages(size_t Count) +{ + return syscall1(_RequestPages, Count); +} + +void KrnlFreePages(uintptr_t Address, size_t Count) +{ + syscall2(_FreePages, Address, Count); +} diff --git a/libs/libgraph/Makefile b/libs/libgraph/Makefile new file mode 100644 index 0000000..e516b83 --- /dev/null +++ b/libs/libgraph/Makefile @@ -0,0 +1,51 @@ +# Config file +include ../../../Makefile.conf + +NAME=graph + +OBJECT_NAME=lib$(NAME).so +SO_NAME=$(OBJECT_NAME) + +OUTPUT_DIR=../../out/system/lib/ +SYSROOT = --sysroot=../../out/system/ + +CC = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)gcc +AS = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)as +AR = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)ar +OBJDUMP = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)objdump +NASM = /usr/bin/nasm + +C_SOURCES = $(shell find ./ -type f -name '*.c') +CPP_SOURCES = $(shell find ./ -type f -name '*.cpp') +S_SOURCES = $(shell find ./ -type f -name '*.S') +ASM_SOURCES = $(shell find ./ -type f -name '*.asm') +OBJ = ${C_SOURCES:.c=.o} ${CPP_SOURCES:.cpp=.o} ${ASM_SOURCES:.asm=.o} ${S_SOURCES:.S=.o} + +ifeq ($(OSARCH), amd64) +ASM_ARCH := elf64 +else ifeq ($(OSARCH), i686) +ASM_ARCH := elf32 +endif + +CFLAGS := -fPIC -I../include -I../../libc/include + +build: $(OBJECT_NAME) + +$(OBJECT_NAME): $(OBJ) + $(CC) -nostdlib -shared -fPIC -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ + $(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map + +%.o: %.c + $(CC) $(CFLAGS) -std=c17 -c $< -o $@ + +%.o: %.cpp + $(CC) $(CFLAGS) -std=c++20 -c $< -o $@ + +%.o: %.S + $(AS) -c $< -o $@ + +%.o: %.asm + $(NASM) $< -f $(ASM_ARCH) -o $@ + +clean: + rm -f file_dump.map $(OBJ) diff --git a/libs/libinit/Makefile b/libs/libinit/Makefile index 28800f8..6382ff0 100644 --- a/libs/libinit/Makefile +++ b/libs/libinit/Makefile @@ -3,9 +3,11 @@ include ../../../Makefile.conf NAME=init -OBJECT_NAME=lib$(NAME).a +OBJECT_NAME=lib$(NAME).so +SO_NAME=$(OBJECT_NAME) OUTPUT_DIR=../../out/system/lib/ +SYSROOT = --sysroot=../../out/system/ CC = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)gcc AS = ../../../$(TC_COMPILER_PATH)/$(TC_COMPILER_ARCH)as @@ -30,7 +32,7 @@ CFLAGS := -fPIC -I../include -I../../libc/include build: $(OBJECT_NAME) $(OBJECT_NAME): $(OBJ) - $(AR) rcs $(OUTPUT_DIR)$@ $(OBJ) + $(CC) -nostdlib -shared -fPIC -Wl,-soname,$(SO_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@ $(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map %.o: %.c diff --git a/libs/libsys/Base.c b/libs/libsys/Base.c new file mode 100644 index 0000000..fcfd9c1 --- /dev/null +++ b/libs/libsys/Base.c @@ -0,0 +1,18 @@ +#include + +#include "../../../Kernel/syscalls.h" + +long DoCtl(uint64_t Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) +{ + return syscall5(_KernelCTL, Command, Arg1, Arg2, Arg3, Arg4); +} + +uintptr_t KrnlRequestPages(size_t Count) +{ + return syscall1(_RequestPages, Count); +} + +void KrnlFreePages(uintptr_t Address, size_t Count) +{ + syscall2(_FreePages, Address, Count); +} diff --git a/libs/libsys/File.c b/libs/libsys/File.c new file mode 100644 index 0000000..66bc45f --- /dev/null +++ b/libs/libsys/File.c @@ -0,0 +1,45 @@ +#include +#include + +#include "../../../Kernel/syscalls.h" + +long __FILE_GetPageSize() +{ + static long PageSize = 0; + if (PageSize == 0) + PageSize = DoCtl(KCTL_GET_PAGE_SIZE, 0, 0, 0, 0); + return PageSize; +} + +File *FileOpen(const char *Path, uint64_t Flags) +{ + File *FilePtr = (File *)KrnlRequestPages(sizeof(File) / __FILE_GetPageSize() + 1); + FilePtr->KernelPrivate = (void *)syscall2(_FileOpen, (uint64_t)Path, Flags); + return FilePtr; +} + +void FileClose(File *File) +{ + syscall1(_FileClose, (uint64_t)File->KernelPrivate); + KrnlFreePages((uintptr_t)File, sizeof(File) / __FILE_GetPageSize() + 1); +} + +uint64_t FileRead(File *File, uint8_t *Buffer, uint64_t Size) +{ + return syscall3(_FileRead, (uint64_t)File->KernelPrivate, (uint64_t)Buffer, Size); +} + +uint64_t FileWrite(File *File, uint8_t *Buffer, uint64_t Size) +{ + return syscall3(_FileWrite, (uint64_t)File->KernelPrivate, (uint64_t)Buffer, Size); +} + +uint64_t FileSeek(File *File, uint64_t Offset, uint64_t Whence) +{ + return syscall3(_FileSeek, (uint64_t)File->KernelPrivate, Offset, Whence); +} + +uint64_t FileStatus(File *File) +{ + return syscall1(_FileStatus, (uint64_t)File->KernelPrivate); +} diff --git a/libs/libsys/Makefile b/libs/libsys/Makefile index a5669a7..bac6051 100644 --- a/libs/libsys/Makefile +++ b/libs/libsys/Makefile @@ -4,7 +4,7 @@ include ../../../Makefile.conf NAME=sys OBJECT_NAME=lib$(NAME).so -SO_NAME=libsys +SO_NAME=$(OBJECT_NAME) OUTPUT_DIR=../../out/system/lib/ SYSROOT = --sysroot=../../out/system/ diff --git a/libs/libsys/Process.c b/libs/libsys/Process.c new file mode 100644 index 0000000..dcacdcc --- /dev/null +++ b/libs/libsys/Process.c @@ -0,0 +1,6 @@ +#include +#include + +#include "../../../Kernel/syscalls.h" + + diff --git a/libs/libsys/kcall.c b/libs/libsys/kcall.c deleted file mode 100644 index 412f017..0000000 --- a/libs/libsys/kcall.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#include "../../../Kernel/syscalls.h" - -long DoCtl(uint64_t Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) -{ - return syscall5(_KernelCTL, Command, Arg1, Arg2, Arg3, Arg4); -}