Compare commits

...

27 Commits

Author SHA1 Message Date
antifallobst f0bf8ac3f5 docs (README): fixed documentation reference 2023-06-10 15:35:14 +02:00
antifallobst b498cb2c98 docs (roadmap): updated progress 2023-06-10 15:30:31 +02:00
antifallobst 81fc9ca9fc feature (syscalls): implemented 'nx_proc_create' 2023-06-10 15:08:31 +02:00
antifallobst 91f7aa4009 feature (drivers): created infrastructure to config drivers to load on startup 2023-06-06 23:22:08 +02:00
antifallobst d7c79e1bdf feature (symbol tables): upgraded symbol tables from static lists to hashmaps 2023-06-06 22:28:47 +02:00
antifallobst ae0ef5c85d fix (hashmaps): fixed bug that caused PFs and GPFs while handling collisions 2023-06-06 22:27:43 +02:00
antifallobst 8c273f4dc7 refactor (kernel): removed unused and unfinished modules system. The new drivers system performs the same task 2023-06-06 22:05:14 +02:00
antifallobst b00b57b180 feature (syscalls): implemented 'nx_drv_register' 2023-06-06 21:43:23 +02:00
antifallobst 4070959736 refactor (syscalls): refactored syscalls to match the documented SysABI 2023-06-06 21:20:29 +02:00
antifallobst 3fbc9dc274 fix (JSON): fixed array parsing 2023-06-06 20:32:30 +02:00
antifallobst 83f5e77d52 feature (strings): implemented DJB string hashing function 2023-06-05 17:51:10 +02:00
antifallobst e69065f889 feature (drivers API): implemented 'nx_drv_log' 2023-06-01 19:40:52 +02:00
antifallobst 2902215904 docs (readme): removed second roadmap header 2023-06-01 17:09:17 +02:00
antifallobst e85621ec55 docs (readme): updated and extended roadmap 2023-06-01 17:04:21 +02:00
antifallobst b50750653d fix (drivers): applied the fix for PCI to USB too 🤦 2023-06-01 13:52:42 +02:00
antifallobst 78ea65ec75 fix (drivers): pushing without testing was a bad idea ^^ 2023-06-01 13:50:51 +02:00
antifallobst 74aa1a4e4d feature (drivers): implemented driver registration and lookup 2023-06-01 13:12:34 +02:00
antifallobst a904629abd feature (drivers): implemented a function for API functions to determine the calling driver 2023-06-01 11:59:39 +02:00
antifallobst 263e7305cf feature (memory management): implemented a function to read the caller from the stack 2023-06-01 11:40:12 +02:00
antifallobst 7d33377806 feature (drivers): implemented an infrastructure to link drivers into the kernel 2023-06-01 00:10:15 +02:00
antifallobst 3d4cea2060 refactor (drivers): moved test driver to drivers repository 2023-06-01 00:03:36 +02:00
antifallobst bb19ff02e1 feature (ELF): defined structs to parse dynamic section 2023-05-31 00:16:25 +02:00
antifallobst 82af1f195b feature (drivers): started work on a driver handler / loader 2023-05-30 22:26:58 +02:00
antifallobst 7e53ab9e7c feature (drivers): setup a small driver to test stuff 2023-05-30 22:26:20 +02:00
antifallobst 0732a19f8a fix (VFS): fixed path resolving bug, that caused random strings to be resolved as part of the path 2023-05-30 20:47:44 +02:00
antifallobst 713ffbc089 feature (hashmaps): implemented hashmaps (NOT TESTED YET) 2023-05-29 16:23:03 +02:00
antifallobst cd5737dba7 feature (drivers): started work on a generic driver interface / driver manager 2023-05-29 14:40:37 +02:00
39 changed files with 1040 additions and 292 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ build
cmake-build-debug
noxos.log
ramdisk/shell.elf
*.nxkm

View File

@ -3,39 +3,53 @@
NoxOS is a small x86 operating system (currently just a kernel).
The kernel is booted using the limine boot protocol and is fully documented.
## Roadmap
# Roadmap
- [x] Bootable system
- [x] Logger
- [X] Page frame manager
- [X] Interrupts
- [X] Page maps
- [X] Heap
- [X] Format strings
- [X] Graphics Renderer
- [X] Text
- [X] Double buffering
- [X] Buffer requests
- [X] Panic Screen
- [X] Register dump
- [X] Stack tracing
- [X] Scheduler
- [X] (Kernel) Threads
- [X] Ramdisk
- [X] USTAR
- [X] RAMFS
- [X] VFS
- [X] ELF loading
- [X] Processes
- [X] Keyboard input (ps/2 int)
- [x] Page frame manager
- [x] Interrupts
- [x] Page maps
- [x] Heap
- [x] Format strings
- [x] Graphics Renderer
- [x] Text
- [x] Double buffering
- [x] Buffer requests
- [x] Panic Screen
- [x] Register dump
- [x] Stack tracing
- [x] Scheduler
- [x] Threads
- [x] Processes
- [x] Ramdisk
- [x] USTAR
- [x] RAMFS
- [x] VFS
- [x] ELF loading
- [x] Keyboard input (ps/2 int)
- [x] JSON parser for system config
- [ ] Drivers
- [X] Loading / Linking into kernel
- [X] Driver Device assignment (PCI / USB / FS)
- [ ] API
- [ ] Syscalls
- [x] Filesystem
- [x] Memory
- [ ] Processing
- [x] Drivers
- [X] Kernel
- [ ] FAT32 (driver)
- [ ] TUI framework
- [ ] Shell
- [X] JSON parser for system config
- [ ] FAT32
- [ ] Text Editor
- [ ] TCC
- [ ] Tetris
- [ ] Init System
## Contribution Welcome :D
Install instructions, Code Documentation and a Contribution guide can be found in the [wiki](https://codeberg.org/antifallobst/noxos/wiki/).
Install instructions, Code Documentation and a Contribution guide can be found [here](https://git.nerdcult.net/noxos/documentation).
## Copyright / License (MIT)
Copyright 2023 Antifallobst <antifallobst@systemausfall.org>

View File

@ -43,13 +43,27 @@ kernel_build() {
}
libnx_build() {
cd ../libnx
cd ../libraries/libnx
bash build.sh
cd ../kernel
cd ../../kernel
}
libnxdrv_build() {
cd ../libraries/libnxdrv
bash build.sh
cd ../../kernel
cd ../drivers/test
bash build.sh
cd ../../kernel
mkdir -pv ramdisk/drv/
cp ../drivers/build/test.nxkm ramdisk/drv/test.nxkm
}
shell_build() {
gcc shell.c -o ramdisk/shell.elf -nostdlib -nolibc -fno-stack-protector -I../libnx/inc ../libnx/build/cmake/libnx.so
echo " --> Building shell"
# gcc shell.c -o ramdisk/shell.elf -nostdlib -nolibc -fno-stack-protector -I../libraries/libnx/inc/public ../libraries/libnx/build/cmake/libnx.so
}
@ -109,6 +123,7 @@ case $1 in
kernel_build
[ ! -d "build/limine" ] && limine_install
libnx_build
libnxdrv_build
shell_build
generate_initial_ramdisk
generate_image

View File

@ -0,0 +1,23 @@
// This file is part of noxos and licensed under the MIT open source license
#ifndef NOXOS_DYNAMIC_H
#define NOXOS_DYNAMIC_H
#include <utils/stdtypes.h>
typedef enum {
ELF_DYNAMIC_TAG_NULL,
ELF_DYNAMIC_TAG_NEEDED,
ELF_DYNAMIC_TAG_PLT_REL_SIZE,
ELF_DYNAMIC_TAG_HASH,
ELF_DYNAMIC_TAG_STRTAB,
ELF_DYNAMIC_TAG_RELA,
ELF_DYNAMIC_TAG_RELA_SIZE
} elf_dynamic_tag_E;
typedef struct {
uint32_t tag;
uint64_t value;
} elf_dynamic_T;
#endif //NOXOS_DYNAMIC_H

View File

@ -10,8 +10,7 @@
typedef struct {
elf_header_T header;
uint64_t num_symbols;
symbol_T* symbols;
symbol_table_T symbol_table;
uint64_t num_mappings;
elf_mapping_T* mappings;
void* string_table;

View File

@ -0,0 +1,37 @@
// This file is part of noxos and licensed under the MIT open source license
#ifndef NOXOS_RELOCATION_H
#define NOXOS_RELOCATION_H
#include <utils/stdtypes.h>
#include <drivers/builtin/elf/elf.h>
#define ELF_RELOCATION_SYMBOL(i) ((i) >> 32)
#define ELF_RELOCATION_TYPE(i) ((i) & 0xFFFFFFFFL)
#define ELF_RELOCATION_INFO(s,t) (((s) << 32) + ((t) & 0xFFFFFFFFL))
#define ELF_RELOCATION_X86_64_PC32(s,a,p) (s + a - p)
#define ELF_RELOCATION_X86_64_PLT32(l,a,p) (l + a - p)
typedef enum {
ELF_REL_NONE,
ELF_REL_64,
ELF_REL_PC32,
ELF_REL_GOT32,
ELF_REL_PLT32,
ELF_REL_COPY,
ELF_REL_GLOB_DAT,
ELF_REL_JUMP_SLOT,
ELF_REL_RELATIVE
} elf_relocation_type_E;
typedef struct {
uint64_t offset;
uint64_t info;
int64_t addend;
} elf_relocation_a_T;
//void elf_relocate (elf_executable_T* executable, uint8_t* buffer, void* address);
bool elf_relocate_driver(elf_executable_T* executable, uint8_t* buffer, void* load_address);
#endif //NOXOS_RELOCATION_H

View File

@ -13,9 +13,12 @@ typedef enum {
ELF_SECTION_STRING_TABLE,
ELF_SECTION_RELOCATION_A,
ELF_SECTION_HASH,
ELF_SECTION_DYNAMIC_LINK,
ELF_SECTION_DYNAMIC,
ELF_SECTION_NOTE,
ELF_SECTION_NOBITS,
ELF_SECTION_REL,
ELF_SECTION_SHLIB,
ELF_SECTION_DYNAMIC_SYMBOL_TABLE,
ELF_SECTION_ENUM_END
} elf_section_type_E;

View File

@ -31,6 +31,7 @@
#define JSON_INCREMENT_TOKEN_ID \
*token_id += 1; \
/* DEBUG("token: %d - %s", *token_id, json->tokens[*token_id].string);*/ \
if (*token_id >= json->num_tokens) { \
log(LOG_ERROR, "failed to parse json -> unexpected EOF"); \
json_node_dump(json->root_node, 0); \

115
inc/drivers/driver.h Normal file
View File

@ -0,0 +1,115 @@
// This file is part of noxos and licensed under the MIT open source license
#ifndef NOXOS_DRIVER_H
#define NOXOS_DRIVER_H
#include <utils/stdtypes.h>
#include <utils/bitmap.h>
#include <utils/hashmap.h>
#include <drivers/builtin/elf/elf.h>
#define DRIVER_MANAGER_CHUNK_SIZE 64
#define DRIVER_MANAGER_HASHMAP_SIZE 128
#define DRIVER_MEMORY_REGION_SIZE 0x100000000 // 4 GB
typedef enum {
DRIVER_TRANSPORT_PCI,
DRIVER_TRANSPORT_USB,
DRIVER_TRANSPORT_FS
} __attribute__((packed)) driver_transport_protocol_E;
typedef enum {
DRIVER_UNKNOWN = 0x0000,
DRIVER_RESERVED = 0x0001,
// Specific Driver
DRIVER_MASS_STORAGE = 0x0101,
DRIVER_FILESYSTEM = 0x0102,
DRIVER_GRAPHICS = 0x0103,
DRIVER_AUDIO = 0x0104,
// Drivers which define the transmission of data but have multiple
// intended usages, such as USB for mass storage, input, etc..
DRIVER_TRANSMISSION = 0x0201,
DRIVER_USB_DEVICE = 0x0202,
DRIVER_PCI_DEVICE = 0x0203,
DRIVER_PCIE_DEVICE = 0x0204,
DRIVER_BLUETOOTH = 0x0205,
DRIVER_ETHERNET = 0x0206,
// MISCELLANEOUS
DRIVER_EMULATION = 0x7fff
} driver_category_E;
typedef struct {
uint16_t vendor_id;
uint16_t device_id;
} __attribute__((packed)) driver_config_device_id_T;
typedef struct {
bool enable_progif;
uint8_t class;
uint8_t subclass;
uint8_t progif;
uint16_t num_device_ids;
driver_config_device_id_T device_ids[];
} __attribute__((packed)) driver_config_pci_T;
typedef struct {
uint8_t min_version;
uint16_t num_device_ids;
driver_config_device_id_T device_ids[];
} __attribute__((packed)) driver_config_usb_T;
typedef struct {
uint8_t gpt_guid[16];
uint8_t mbr_type;
} __attribute__((packed)) driver_config_fs_T;
typedef union {
driver_config_pci_T* pci;
driver_config_usb_T* usb;
driver_config_fs_T* fs;
} conf_U;
typedef struct {
uint64_t id;
void* base;
elf_executable_T* executable;
} driver_T;
typedef struct driver_manager_chunk_T driver_manager_chunk_T;
struct driver_manager_chunk_T {
driver_T drivers [DRIVER_MANAGER_CHUNK_SIZE];
bitmap_T drivers_bitmap;
uint32_t free_slots;
driver_manager_chunk_T* prev;
driver_manager_chunk_T* next;
};
typedef struct {
driver_manager_chunk_T* driver_pool;
hashmap_T lookup_table_pci;
hashmap_T lookup_table_usb;
hashmap_T lookup_table_fs_gpt;
hashmap_T lookup_table_fs_mbr;
} driver_manager_T;
void driver_manager_init ();
driver_manager_chunk_T* driver_manager_chunk_alloc(driver_manager_chunk_T* prev);
driver_T* driver_register (elf_executable_T* executable, uint8_t* buffer);
void driver_init (driver_T* driver, driver_transport_protocol_E protocol, conf_U conf);
driver_T* driver_lookup_pci_device (uint16_t vendor_id, uint16_t device_id);
driver_T* driver_lookup_usb_device (uint16_t vendor_id, uint16_t device_id);
driver_T* driver_lookup_fs_gpt (uint8_t guid[16]);
driver_T* driver_lookup_fs_mbr (uint8_t type);
driver_T* driver_lookup_by_address (void* address);
#endif //NOXOS_DRIVER_H

View File

@ -16,10 +16,11 @@
#define MEM_REGION_PROCESS_USABLE 0x0000080000000000
#define MEM_REGION_KERNEL 0x0000800000000000
#define MEM_REGION_KERNEL_STACK_DUMMY 0xFFFFF00000000000 // size 0x4000
#define MEM_REGION_KERNEL_HEAP 0xFFFFF80000000000
#define MEM_REGION_KERNEL_THREAD_BASE 0xFFFFFF0000000000
#define MEM_REGION_KERNEL_EXEC 0xFFFFFFFF80000000
#define MEM_REGION_KERNEL_DRIVERS 0xFFFFE80000000000 // size: up to 8 TB
#define MEM_REGION_KERNEL_STACK_DUMMY 0xFFFFF00000000000 // size: 4 KB
#define MEM_REGION_KERNEL_HEAP 0xFFFFF80000000000 // size: up to 8 TB
#define MEM_REGION_KERNEL_THREAD_BASE 0xFFFFFF0000000000 // size: up to 1022 GB
#define MEM_REGION_KERNEL_EXEC 0xFFFFFFFF80000000 // size: up to 2 GB
extern uint64_t _kernel_start;
extern uint64_t _kernel_end;

View File

@ -11,4 +11,6 @@
void stack_dump_call_info (uint64_t rip, symbol_T* symbol);
void stack_trace_call_stack (uint64_t rbp);
extern uint64_t stack_get_caller();
#endif //NOX_STACK_H

View File

@ -1,32 +0,0 @@
// This file is part of noxos and licensed under the MIT open source license
#ifndef NOXOS_MODULES_LOADER_H
#define NOXOS_MODULES_LOADER_H
#include <modules/module.h>
#include <utils/bitmap.h>
#define MODULE_MANAGER_CHUNK_SIZE 16
typedef struct module_manager_chunk_T module_manager_chunk_T;
struct module_manager_chunk_T {
module_T* modules [MODULE_MANAGER_CHUNK_SIZE];
bitmap_T modules_bitmap;
uint32_t num_modules;
module_manager_chunk_T* prev;
module_manager_chunk_T* next;
};
typedef struct {
module_manager_chunk_T* chunks;
} module_manager_T;
void module_manager_init ();
module_manager_chunk_T* module_manager_chunk_alloc (module_manager_chunk_T* prev);
module_T* module_load (string_t name, string_t path);
void module_unload (module_T* module);
#endif //NOXOS_MODULES_LOADER_H

View File

@ -1,16 +0,0 @@
// This file is part of noxos and licensed under the MIT open source license
#ifndef NOXOS_MODULE_H
#define NOXOS_MODULE_H
#include <utils/stdtypes.h>
#include <utils/string.h>
#include <drivers/builtin/elf/elf.h>
typedef struct {
string_t name;
string_t path;
elf_executable_T* executable;
} module_T;
#endif //NOXOS_MODULE_H

View File

@ -7,50 +7,40 @@
#include "utils/status.h"
typedef enum {
SYSCALLS_FILES = 0x01,
SYSCALLS_MEMORY = 0x02,
SYSCALLS_PROC = 0x03,
SYSCALLS_RUNTIME_LINKER = 0x04,
SYSCALLS_COMPATABILITY = 0x05,
SYSCALLS_FILES = 0x00,
SYSCALLS_MEMORY = 0x01,
SYSCALLS_PROC = 0x02,
SYSCALLS_DRIVERS = 0x03,
SYSCALLS_KERNEL = 0xFF
}syscall_group_E;
typedef enum {
SYSCALL_FILES_OPEN = 0x0101,
SYSCALL_FILES_CLOSE = 0x0102,
SYSCALL_FILES_READ = 0x0103,
SYSCALL_FILES_WRITE = 0x0104,
SYSCALL_FILES_DELETE = 0x0105,
SYSCALL_FILES_LIST = 0x0106,
SYSCALL_FILES_INFO = 0x0107,
SYSCALL_NX_FS_OPEN = 0x0001,
SYSCALL_NX_FS_CLOSE = 0x0002,
SYSCALL_NX_FS_READ = 0x0003,
SYSCALL_NX_FS_WRITE = 0x0004,
SYSCALL_NX_FS_DELETE = 0x0005,
SYSCALL_NX_FS_LIST = 0x0006,
SYSCALL_NX_FS_INFO = 0x0007,
SYSCALL_MEMORY_MAP = 0x0201,
SYSCALL_MEMORY_UNMAP = 0x0202,
SYSCALL_MEMORY_LABEL = 0x0203,
SYSCALL_MEMORY_RANGE = 0x0204,
SYSCALL_MEMORY_ACCESS = 0x0205,
SYSCALL_NX_MEM_ALLOC = 0x0101,
SYSCALL_NX_MEM_FREE = 0x0102,
SYSCALL_NX_MEM_LABEL = 0x0103,
SYSCALL_NX_MEM_UNLABEL = 0x0104,
SYSCALL_PROCESS_CREATE = 0x0301,
SYSCALL_PROCESS_ENV = 0x0302,
SYSCALL_PROCESS_SIGNAL = 0x0303,
SYSCALL_PROCESS_THREAD_CREATE = 0x0304,
SYSCALL_PROCESS_THREAD_START = 0x0305,
SYSCALL_PROCESS_THREAD_PAUSE = 0x0306,
SYSCALL_PROCESS_THREAD_KILL = 0x0307,
SYSCALL_NX_PROC_CREATE = 0x0201,
SYSCALL_NX_PROC_SIGNAL_SEND = 0x0202,
SYSCALL_NX_PROC_SIGNAL_SET_HANDLER = 0x0203,
SYSCALL_NX_PROC_THREAD_CREATE = 0x0204,
SYSCALL_NX_PROC_THREAD_START = 0x0205,
SYSCALL_NX_PROC_THREAD_PAUSE = 0x0206,
SYSCALL_NX_PROC_THREAD_KILL = 0x0207,
SYSCALL_RUNTIME_LINKER_OPEN = 0x0401,
SYSCALL_RUNTIME_LINKER_CLOSE = 0x0402,
SYSCALL_RUNTIME_LINKER_LOAD_SYMBOL = 0x0403,
SYSCALL_RUNTIME_LINKER_STATUS = 0x0404,
SYSCALL_RUNTIME_LINKER_STANDARD_MOD = 0x0405,
SYSCALL_NX_DRV_REGISTER = 0x0301,
SYSCALL_COMPATABILITY_ABI_TYPE = 0x0501,
SYSCALL_COMPATABILITY_ABI_VERSION = 0x0502,
SYSCALL_COMPATABILITY_ACTION = 0x0503,
SYSCALL_KERNEL_SCHEDULER_START = 0xFF00,
SYSCALL_KERNEL_PANIC = 0xFF01
SYSCALL_NX_KERNEL_SCHEDULER_START = 0xFF00,
SYSCALL_NX_KERNEL_PANIC = 0xFF01
} syscall_E;
typedef enum {

View File

@ -32,9 +32,23 @@ typedef enum {
PROCESS_SIGNAL_START, // SIGSTART
PROCESS_SIGNAL_PAUSE, // SIGPAUSE
PROCESS_SIGNAL_KILL, // SIGKILL
PROCESS_SIGNAL_PFAULT, // SIGPFAULT
PROCESS_SIGNAL_PAGEFAULT, // SIGPAGEFAULT
PROCESS_SIGNAL_MATHFAULT, // SIGMATHFAULT
} process_signals_E;
typedef struct {
file_descriptor_t at_parent;
file_descriptor_t at_child;
}__attribute__((packed)) process_inherit_fd_T;
typedef struct {
uint8_t privilege_level;
char name[80];
file_descriptor_t executable;
uint16_t num_inherit_fds;
process_inherit_fd_T inherit_fds[];
}__attribute__((packed)) process_config_T;
typedef struct process_T process_T;
struct process_T {
char name [128];

28
inc/utils/hashmap.h Normal file
View File

@ -0,0 +1,28 @@
// This file is part of noxos and licensed under the MIT open source license
#ifndef NOXOS_HASHMAP_H
#define NOXOS_HASHMAP_H
#include <utils/stdtypes.h>
typedef struct hashmap_entry_T hashmap_entry_T;
struct hashmap_entry_T {
bool in_use;
uint64_t key;
void* value;
hashmap_entry_T* prev;
hashmap_entry_T* next;
};
typedef struct {
uint64_t size;
hashmap_entry_T* entries;
} hashmap_T;
hashmap_T hashmap_create (uint64_t size);
void hashmap_destruct (hashmap_T* hashmap);
void hashmap_insert (hashmap_T* hashmap, uint64_t key, void* value);
void hashmap_delete (hashmap_T* hashmap, uint64_t key);
void* hashmap_lookup (hashmap_T* hashmap, uint64_t key);
#endif //NOXOS_HASHMAP_H

View File

@ -57,4 +57,6 @@ bool string_is_char_alpha (char chr);
bool string_is_char_uppercase (char chr);
bool string_is_char_lowercase (char chr);
uint32_t string_hash_djb (string_t str);
#endif //NOX_STRING_H

View File

@ -4,6 +4,7 @@
#define NOX_SYMBOLS_H
#include "utils/string.h"
#include "utils/hashmap.h"
typedef enum {
SYMBOL_FUNCTION,
@ -17,7 +18,17 @@ typedef struct {
uint64_t address;
} symbol_T;
symbol_T* symbol_resolve_from_name (symbol_T* symbols, uint64_t num_symbols, string_t name);
symbol_T* symbol_resolve_from_rip (symbol_T* symbols, uint64_t num_symbols, uint64_t rip);
typedef struct {
hashmap_T hashmap;
uint64_t num_symbols;
symbol_T* symbols;
uint64_t symbols_index;
} symbol_table_T;
symbol_table_T symbol_table_init (uint64_t num_symbols);
void symbol_table_destruct (symbol_table_T* symbol_table);
void symbol_table_insert (symbol_table_T* symbol_table, symbol_T symbol);
symbol_T* symbol_resolve_from_name (symbol_table_T* symbol_table, string_t name);
symbol_T* symbol_resolve_from_rip (symbol_table_T* symbol_table, uint64_t rip);
#endif //NOX_SYMBOLS_H

5
ramdisk/drivers.json Normal file
View File

@ -0,0 +1,5 @@
{
"BOOT": [
"/initrd/drv/test.nxkm"
]
}

View File

@ -1,8 +1,4 @@
{
"PS2_ACPI_VALIDATION": true,
"LOG_GRAPHICAL": false,
"modules": {
"FAT32": "/initrd/modules/fat32.nxkm"
}
"LOG_GRAPHICAL": true
}

View File

@ -3,7 +3,6 @@
#include "utils/logger.h"
#include "utils/core.h"
#include "utils/memory.h"
#include "utils/crypto/sha1.h"
#include "boot/boot_info.h"
#include "boot/config.h"
#include "platform/interrupts.h"
@ -20,8 +19,8 @@
#include "drivers/builtin/pci.h"
#include "drivers/builtin/ps2/controller.h"
#include "drivers/builtin/tty.h"
#include "drivers/driver.h"
#include "proc/scheduler.h"
#include "modules/loader.h"
void limine_terminal_print(boot_info_T* boot_info, string_t string) {
boot_info->terminal->write(boot_info->terminal->terminals[0], string, string_length(string));
@ -51,9 +50,9 @@ void kernel_init(boot_info_T* boot_info) {
scheduler_init(boot_info);
acpi_init(boot_info);
driver_manager_init();
module_manager_init();
acpi_init(boot_info);
drive_manager_init();
@ -73,8 +72,19 @@ void kmain(boot_info_T boot_info) {
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
file_descriptor_t fd;
syscall_perform(SYSCALL_NX_FS_OPEN, (uint64_t)"/initrd/test.elf", 0, &fd, 0);
pid_t pid;
syscall_perform(SYSCALL_PROCESS_CREATE, (uint64_t)"/initrd/shell.elf", 0, (uint64_t)&pid, 0);
process_config_T conf = {
.privilege_level = 0,
.executable = fd,
.num_inherit_fds = 0
};
memory_copy("test", conf.name, 5);
syscall_perform(SYSCALL_NX_PROC_CREATE, (uint64_t)&conf, (uint64_t)&pid, 0, 0);
process_T* process = scheduler_get_process(pid);
@ -83,10 +93,8 @@ void kmain(boot_info_T boot_info) {
g_tty->output = &process->stdin;
process->stdout = &g_tty->input;
syscall_perform(SYSCALL_PROCESS_SIGNAL, pid, PROCESS_SIGNAL_START, 0, 0);
syscall_perform(SYSCALL_NX_PROC_SIGNAL_SEND, pid, PROCESS_SIGNAL_START, 0, 0);
uint8_t digest[20];
sha1_hash(digest, "test", 4);
CORE_HALT_FOREVER
}

30
src/drivers/api.c Normal file
View File

@ -0,0 +1,30 @@
// This file is part of noxos and licensed under the MIT open source license
#include <drivers/driver.h>
#include <utils/logger.h>
#include <mm/stack.h>
void nx_drv_pci_config(driver_config_pci_T* config) {
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
if (driver == NULL) return;
driver_init(driver, DRIVER_TRANSPORT_PCI, (conf_U)config);
}
void nx_drv_usb_config(driver_config_usb_T* config) {
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
if (driver == NULL) return;
driver_init(driver, DRIVER_TRANSPORT_USB, (conf_U)config);
}
void nx_drv_fs_config(driver_config_fs_T* config) {
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
if (driver == NULL) return;
driver_init(driver, DRIVER_TRANSPORT_FS, (conf_U)config);
}
void nx_drv_log(string_t string) {
log(LOG_INFO, "DRIVER -> %s", string);
}

View File

@ -36,31 +36,33 @@ bool elf_executable_validate(elf_executable_T* executable) {
}
void elf_executable_extract_symbols(elf_executable_temp_T* executable_temp) {
executable_temp->executable->num_symbols = executable_temp->symbol_table->length / executable_temp->symbol_table->entry_size;
executable_temp->executable->symbols = memory_allocate(executable_temp->executable->num_symbols * sizeof(symbol_T));
uint64_t num_symbols = executable_temp->symbol_table->length / executable_temp->symbol_table->entry_size;
executable_temp->executable->symbol_table = symbol_table_init(num_symbols);
for (int i = 0; i < executable_temp->executable->num_symbols; i++) {
symbol_T* symbol = &executable_temp->executable->symbols[i];
for (int i = 0; i < num_symbols; i++) {
symbol_T symbol;
elf_symbol_T* symbol_elf = &((elf_symbol_T*)&executable_temp->buffer[executable_temp->symbol_table->offset])[i];
elf_symbol_type_E type = ELF_SYMBOL_TYPE(symbol_elf->info);
symbol->name = &executable_temp->executable->string_table[symbol_elf->name_offset];
symbol->address = symbol_elf->value;
symbol.name = &executable_temp->executable->string_table[symbol_elf->name_offset];
symbol.address = symbol_elf->value;
switch (type) {
case ELF_SYMBOL_FUNC: {
symbol->type = SYMBOL_FUNCTION;
symbol.type = SYMBOL_FUNCTION;
break;
}
case ELF_SYMBOL_OBJECT: {
symbol->type = SYMBOL_VARIABLE;
symbol.type = SYMBOL_VARIABLE;
break;
}
default: {
symbol->type = SYMBOL_UNKNOWN;
symbol.type = SYMBOL_UNKNOWN;
break;
}
}
symbol_table_insert(&executable_temp->executable->symbol_table, symbol);
}
}
@ -153,7 +155,7 @@ elf_executable_T* elf_executable_create(uint8_t* buffer) {
void elf_executable_destruct(elf_executable_T* executable) {
memory_free(executable->string_table);
memory_free(executable->symbols);
symbol_table_destruct(&executable->symbol_table);
memory_free(executable->mappings);
memory_free(executable);
}

View File

@ -7,7 +7,7 @@
#include "utils/memory.h"
void elf_mapping_apply(elf_mapping_T* mapping, uint8_t* buffer, void* base, page_map_T* page_map) {
uint64_t num_pages = CEIL_TO(mapping->length_virtual, PFRAME_SIZE) / PFRAME_SIZE;
uint64_t num_pages = CEIL_TO(mapping->length_virtual + (mapping->offset_virtual % PFRAME_SIZE), PFRAME_SIZE) / PFRAME_SIZE;
log(LOG_INFO, "Mapping: 0x%x -> 0x%x PAGES[%d]", mapping->offset_file, base + mapping->offset_virtual, num_pages);
void* virtual_address = base + mapping->offset_virtual;
@ -28,9 +28,11 @@ void elf_mapping_apply(elf_mapping_T* mapping, uint8_t* buffer, void* base, page
memory_copy(&buffer[mapping->offset_file], virtual_address, mapping->length_file);
if (page_map != g_kernel_page_map) {
for (uint64_t i = 0; i < num_pages; i++) {
page_map_unmap_memory(g_kernel_page_map, virtual_address + (PFRAME_SIZE * i));
}
}
}
void elf_mappings_apply(elf_mapping_T* mappings, uint64_t num_mappings, uint8_t* buffer, void* base, page_map_T* page_map) {

View File

@ -0,0 +1,109 @@
// This file is part of noxos and licensed under the MIT open source license
#include <drivers/builtin/elf/relocation.h>
#include <drivers/builtin/elf/dynamic.h>
#include <drivers/builtin/elf/symbol.h>
#include <utils/logger.h>
#include <utils/memory.h>
#include <proc/scheduler.h>
//void elf_relocate(elf_executable_T* executable, uint8_t* buffer, void* address) {
// elf_section_T* sections = (elf_section_T*)&buffer[executable->header.offset_section_header];
// elf_section_T* section_dynamic = NULL;
// for (uint32_t i = 0; i < executable->header.num_section_header_entries; i++) {
// if (sections[i].type != ELF_SECTION_DYNAMIC) continue;
// section_dynamic = &sections[i];
// DEBUG("Found DYNAMIC section %d", i);
// break;
// }
// if (section_dynamic == NULL) {
// log(LOG_ERROR, "Failed to relocate ELF executable (no .dynamic section found)");
// return;
// }
// uint32_t num_dynamic_entries = section_dynamic->length / section_dynamic->entry_size;
// elf_dynamic_T* dynamic_entries = (elf_dynamic_T*)&buffer[section_dynamic->offset];
// uint32_t num_needed_libraries = 0;
//
// for (int i = 0; i < num_dynamic_entries; i++) {
// switch (dynamic_entries[i].tag) {
// case ELF_DYNAMIC_TAG_NEEDED: {
// num_needed_libraries++;
// break;
// }
// }
// }
//
// log(LOG_ERROR, "Failed to relocate executable (not implemented)");
//
//}
bool elf_relocate_driver(elf_executable_T* executable, uint8_t* buffer, void* load_address) {
elf_section_T* sections = (elf_section_T*)&buffer[executable->header.offset_section_header];
string_t section_names = (string_t)&buffer[sections[executable->header.string_section_index].offset];
elf_section_T* section_dynamic = NULL;
elf_section_T* section_dynstr = NULL;
elf_section_T* section_dynsym = NULL;
for (uint32_t i = 0; i < executable->header.num_section_header_entries; i++) {
switch (sections[i].type) {
case ELF_SECTION_DYNAMIC: {
section_dynamic = &sections[i];
break;
}
case ELF_SECTION_STRING_TABLE: {
if (!string_compare(".dynstr", &section_names[sections[i].name_offset])) break;
section_dynstr = &sections[i];
break;
}
case ELF_SECTION_DYNAMIC_SYMBOL_TABLE: {
section_dynsym = &sections[i];
break;
}
}
}
if (section_dynamic == NULL) {
log(LOG_ERROR, "Failed to relocate driver executable (no .dynamic section found)");
return false;
}
if (section_dynstr == NULL) {
log(LOG_ERROR, "Failed to relocate driver executable (no .dynstr section found)");
return false;
}
if (section_dynsym == NULL) {
log(LOG_ERROR, "Failed to relocate driver executable (no .dynsym section found)");
return false;
}
for (uint32_t i = 0; i < executable->header.num_section_header_entries; i++) {
if (sections[i].type != ELF_SECTION_RELOCATION_A) continue;
process_T* kernel_process = scheduler_get_process(PROCESS_KERNEL);
symbol_table_T* symbol_table = &kernel_process->executable->symbol_table;
uint32_t num_relocations = sections[i].length / sections[i].entry_size;
log(LOG_INFO, "Found RELA section with %d relocations", num_relocations);
for (int j = 0; j < num_relocations; j++) {
elf_relocation_a_T* relocation = &((elf_relocation_a_T*)&buffer[sections[i].offset])[j];
uint64_t* relocation_offset = (uint64_t*)&((uint8_t*)load_address)[relocation->offset];
elf_relocation_type_E relocation_type = ELF_RELOCATION_TYPE(relocation->info);
elf_symbol_T* drv_symbol = &((elf_symbol_T*)&buffer[section_dynsym->offset])[ELF_RELOCATION_SYMBOL(relocation->info)];
string_t drv_symbol_name = (string_t)&buffer[section_dynstr->offset + drv_symbol->name_offset];
symbol_T* k_symbol = symbol_resolve_from_name(symbol_table, drv_symbol_name);
if (k_symbol == NULL) {
log(LOG_ERROR, "Failed to relocate driver (symbol '%s' not found in kernel)", drv_symbol_name);
return false;
}
log(LOG_INFO, "relocating '%s(0x%x)' -> PLT_ENTRY[0x%x]", drv_symbol_name, k_symbol, relocation_offset);
switch (relocation_type) {
case ELF_REL_JUMP_SLOT: {
*relocation_offset = k_symbol->address;
break;
}
}
}
}
return true;
}

View File

@ -12,6 +12,9 @@ string_t g_elf_section_type_strings[ELF_SECTION_ENUM_END+1] = {
"Dynamic Linker Info",
"Note",
"No Bits",
"Relocation",
"Unspecified Semantics (Not ABI Conform)",
"Symbol Table (Dynamic)",
"Unknown"
};

View File

@ -309,7 +309,7 @@ vfs_node_T* vfs_resolve_path(fs_T* filesystem, string_t path) {
length = string_find_next(path, '/');
char name[length];
char name[length+1];
memory_copy((void*)path, name, length);
name[length] = '\0';

View File

@ -9,6 +9,8 @@ json_T* json_from_string(string_t str) {
json_tokenize(json, str);
// DEBUG("TOKENS:");ss
bool status = json_parse(json);
if (!status) {
json_destruct(json);
@ -270,6 +272,8 @@ void json_tokenize(json_T* json, string_t str) {
}
bool json_parse_assignment(json_T* json, uint32_t* token_id, json_node_T* node) {
// DEBUG("parsing assignment");
JSON_INCREMENT_TOKEN_ID
if (json->tokens[*token_id].type != JSON_TOKEN_SPECIAL || json->tokens[*token_id].string[0] != ':') {
log(LOG_ERROR, "failed to parse json at position %d:%d -> expected : got \"%s\"",
json->tokens[*token_id].line, json->tokens[*token_id].column, json->tokens[*token_id].string);
@ -314,7 +318,6 @@ bool json_parse_assignment(json_T* json, uint32_t* token_id, json_node_T* node)
case '{': {
json_node_T* object_node = json_node_alloc(node, JSON_NODE_OBJECT, &json->tokens[*token_id]);
JSON_INCREMENT_TOKEN_ID
bool status = json_parse_object(json, token_id, object_node);
if (!status) return false;
break;
@ -323,7 +326,6 @@ bool json_parse_assignment(json_T* json, uint32_t* token_id, json_node_T* node)
case '[': {
json_node_T* array_node = json_node_alloc(node, JSON_NODE_ARRAY, &json->tokens[*token_id]);
JSON_INCREMENT_TOKEN_ID
bool status = json_parse_array(json, token_id, array_node);
if (!status) return false;
break;
@ -343,12 +345,13 @@ bool json_parse_assignment(json_T* json, uint32_t* token_id, json_node_T* node)
}
bool json_parse_object(json_T* json, uint32_t* token_id, json_node_T* node) {
// DEBUG("parsing object");
while (true) {
JSON_INCREMENT_TOKEN_ID
switch (json->tokens[*token_id].type) {
case JSON_TOKEN_STRING: {
json_node_T* string_node = json_node_alloc(node, JSON_NODE_STRING, &json->tokens[*token_id]);
JSON_INCREMENT_TOKEN_ID
bool status = json_parse_assignment(json, token_id, string_node);
if (!status) return false;
break;
@ -378,15 +381,14 @@ bool json_parse_object(json_T* json, uint32_t* token_id, json_node_T* node) {
return false;
}
return true;
} else {
JSON_INCREMENT_TOKEN_ID
}
}
}
bool json_parse_array(json_T* json, uint32_t* token_id, json_node_T* node) {
// DEBUG("parsing array");
while (true) {
JSON_INCREMENT_TOKEN_ID
switch (json->tokens[*token_id].type) {
case JSON_TOKEN_STRING: {
json_node_alloc(node, JSON_NODE_STRING, &json->tokens[*token_id]);
@ -421,7 +423,6 @@ bool json_parse_array(json_T* json, uint32_t* token_id, json_node_T* node) {
case '{': {
json_node_T* object_node = json_node_alloc(node, JSON_NODE_OBJECT, &json->tokens[*token_id]);
JSON_INCREMENT_TOKEN_ID
bool status = json_parse_object(json, token_id, object_node);
if (!status) return false;
break;
@ -430,7 +431,6 @@ bool json_parse_array(json_T* json, uint32_t* token_id, json_node_T* node) {
case '[': {
json_node_T* array_node = json_node_alloc(node, JSON_NODE_ARRAY, &json->tokens[*token_id]);
JSON_INCREMENT_TOKEN_ID
bool status = json_parse_array(json, token_id, array_node);
if (!status) return false;
break;
@ -453,11 +453,8 @@ bool json_parse_array(json_T* json, uint32_t* token_id, json_node_T* node) {
json->tokens[*token_id].line, json->tokens[*token_id].column, json->tokens[*token_id].string);
return false;
}
JSON_INCREMENT_TOKEN_ID
return true;
}
JSON_INCREMENT_TOKEN_ID
}
}
@ -469,11 +466,6 @@ bool json_parse(json_T* json) {
log(LOG_ERROR, "failed to parse json at position %d:%d -> expected { got \"%s\"", json->tokens[0].line, json->tokens[0].column, json->tokens[0].string);
return false;
}
token_id++;
if (token_id >= json->num_tokens) { \
log(LOG_ERROR, "failed to parse json -> unexpected EOF");
return false;
}
return json_parse_object(json, &token_id, json->root_node);
}

285
src/drivers/driver.c Normal file
View File

@ -0,0 +1,285 @@
// This file is part of noxos and licensed under the MIT open source license
#include <drivers/driver.h>
#include <drivers/builtin/elf/relocation.h>
#include <drivers/builtin/json.h>
#include <utils/logger.h>
#include <utils/memory.h>
#include <proc/scheduler.h>
#include <platform/syscall.h>
#include <mm/region.h>
driver_manager_T g_driver_manager;
void driver_manager_init() {
g_driver_manager.driver_pool = driver_manager_chunk_alloc(NULL);
g_driver_manager.lookup_table_pci = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
g_driver_manager.lookup_table_usb = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
g_driver_manager.lookup_table_fs_gpt = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
g_driver_manager.lookup_table_fs_mbr = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/drivers.json");
if (node == NULL || node->type != VFS_NODE_FILE) {
log(LOG_WARNING, "No drivers config file found. !!! THIS WILL VERY LIKELY CAUSE THE OS TO NOT WORK!!!");
return;
}
char* buffer = memory_allocate(node->size + 1);
vfs_file_read(node, 0, node->size, buffer);
buffer[node->size] = 0;
json_T* json = json_from_string(buffer);
json_node_T* child = json->root_node->childs_start;
while (child != NULL) {
if (string_compare("BOOT", child->string)) {
if (&child->childs_start[0] == NULL || child->childs_start[0].type != JSON_NODE_ARRAY) {
log(LOG_WARNING, "sysconfig -> failed to parse field 'BOOT' (expected array)");
} else {
log(LOG_INFO, "Loading drivers for level 'BOOT':");
json_node_T* array_child = child->childs_start[0].childs_start;
while (array_child != NULL) {
uint64_t drv_id, fd;
log(LOG_INFO, " > %s", array_child->string);
syscall_perform(SYSCALL_NX_FS_OPEN, (uint64_t)array_child->string, 0, (uint64_t)&fd, 0);
syscall_perform(SYSCALL_NX_DRV_REGISTER, fd, (uint64_t)&drv_id, 0, 0);
syscall_perform(SYSCALL_NX_FS_CLOSE, fd, 0, 0, 0);
array_child = array_child->next;
}
}
} else {
log(LOG_WARNING, "sysconfig -> skipping field '%s' (unknown identifier)", child->string);
}
child = child->next;
}
json_destruct(json);
memory_free(buffer);
}
driver_manager_chunk_T* driver_manager_chunk_alloc(driver_manager_chunk_T* prev) {
driver_manager_chunk_T* chunk = memory_allocate(sizeof(driver_manager_chunk_T));
chunk->drivers_bitmap = bitmap_init(DRIVER_MANAGER_CHUNK_SIZE);
chunk->free_slots = DRIVER_MANAGER_CHUNK_SIZE;
chunk->prev = prev;
if (chunk->prev != NULL) {
chunk->prev->next = chunk;
}
return chunk;
}
driver_T* driver_find_pci_device(uint16_t vendor_id, uint16_t device_id) {
log(LOG_WARNING, "driver manager -> pci driver lookup on disk is not implemented yet");
return NULL;
}
driver_T* driver_find_usb_device(uint16_t vendor_id, uint16_t device_id) {
log(LOG_WARNING, "driver manager -> usb driver lookup on disk is not implemented yet");
return NULL;
}
driver_T* driver_find_fs_gpt(uint8_t guid[16]) {
log(LOG_WARNING, "driver manager -> gpt driver lookup on disk is not implemented yet");
return NULL;
}
driver_T* driver_find_fs_mbr(uint8_t type) {
log(LOG_WARNING, "driver manager -> mbr driver lookup on disk is not implemented yet");
return NULL;
}
void driver_init_pci(driver_T* driver, driver_config_pci_T* conf) {
for (int i = 0; i < conf->num_device_ids; i++) {
driver_config_device_id_T* device_id = &conf->device_ids[i];
hashmap_T* level_2 = hashmap_lookup(&g_driver_manager.lookup_table_pci, device_id->vendor_id);
if (level_2 == NULL) {
level_2 = memory_allocate(sizeof(hashmap_T));
*level_2 = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
hashmap_insert(&g_driver_manager.lookup_table_pci, device_id->vendor_id, level_2);
}
void* entry = hashmap_lookup(level_2, device_id->device_id);
if (entry != NULL) {
log(LOG_WARNING, "Failed to register driver for pci device %xw:%xw (there is already a driver registered)", device_id->vendor_id, device_id->device_id);
continue;
}
hashmap_insert(level_2, device_id->device_id, driver);
log(LOG_INFO, "Registered driver for pci device %xw:%xw", device_id->vendor_id, device_id->device_id);
}
}
void driver_init_usb(driver_T* driver, driver_config_usb_T* conf) {
for (int i = 0; i < conf->num_device_ids; i++) {
driver_config_device_id_T* device_id = &conf->device_ids[i];
hashmap_T* level_2 = hashmap_lookup(&g_driver_manager.lookup_table_usb, device_id->vendor_id);
if (level_2 == NULL) {
level_2 = memory_allocate(sizeof(hashmap_T));
*level_2 = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
hashmap_insert(&g_driver_manager.lookup_table_usb, device_id->vendor_id, level_2);
}
void* entry = hashmap_lookup(level_2, device_id->device_id);
if (entry != NULL) {
log(LOG_WARNING, "Failed to register driver for usb device %xw:%xw (there is already a driver registered)", device_id->vendor_id, device_id->device_id);
continue;
}
hashmap_insert(level_2, device_id->device_id, driver);
log(LOG_INFO, "Registered driver for usb device %xw:%xw", device_id->vendor_id, device_id->device_id);
}
}
void driver_init_fs_gpt(driver_T* driver, uint8_t gpt_guid[16]) {
uint64_t gpt_hash = ((uint64_t*)gpt_guid)[0] ^ ((uint64_t*)gpt_guid)[1];
if (hashmap_lookup(&g_driver_manager.lookup_table_fs_gpt, gpt_hash) != NULL) {
log(LOG_WARNING, "Failed to register driver for gpt file system: %xb%xb%xb%xb-%xb%xb-%xb%xb-%xb%xb-%xb%xb%xb%xb%xb%xb (there is already a driver registered)",
gpt_guid[0x0], gpt_guid[0x1], gpt_guid[0x2], gpt_guid[0x3],
gpt_guid[0x4], gpt_guid[0x5], gpt_guid[0x6], gpt_guid[0x7],
gpt_guid[0x8], gpt_guid[0x9], gpt_guid[0xA], gpt_guid[0xB],
gpt_guid[0xC], gpt_guid[0xD], gpt_guid[0xE], gpt_guid[0xF]);
return;
}
hashmap_insert(&g_driver_manager.lookup_table_fs_gpt, gpt_hash, driver);
log(LOG_INFO, "Registered driver for gpt file system: %xb%xb%xb%xb-%xb%xb-%xb%xb-%xb%xb-%xb%xb%xb%xb%xb%xb",
gpt_guid[0x0], gpt_guid[0x1], gpt_guid[0x2], gpt_guid[0x3],
gpt_guid[0x4], gpt_guid[0x5], gpt_guid[0x6], gpt_guid[0x7],
gpt_guid[0x8], gpt_guid[0x9], gpt_guid[0xA], gpt_guid[0xB],
gpt_guid[0xC], gpt_guid[0xD], gpt_guid[0xE], gpt_guid[0xF]);
}
void driver_init_fs_mbr(driver_T* driver, uint8_t type) {
if (hashmap_lookup(&g_driver_manager.lookup_table_fs_gpt, type) != NULL) {
log(LOG_WARNING, "Failed to register driver for mbr file system: %xb (there is already a driver registered)", type);
return;
}
hashmap_insert(&g_driver_manager.lookup_table_fs_gpt, type, driver);
log(LOG_INFO, "Registered driver for mbr file system: %xb", type);
}
void driver_init_fs(driver_T* driver, driver_config_fs_T* conf) {
driver_init_fs_gpt(driver, conf->gpt_guid);
driver_init_fs_mbr(driver, conf->mbr_type);
}
void driver_init(driver_T* driver, driver_transport_protocol_E protocol, conf_U conf) {
switch (protocol) {
case DRIVER_TRANSPORT_PCI: {
driver_init_pci(driver, conf.pci);
break;
}
case DRIVER_TRANSPORT_USB: {
driver_init_usb(driver, conf.usb);
break;
}
case DRIVER_TRANSPORT_FS: {
driver_init_fs(driver, conf.fs);
break;
}
}
}
driver_T* driver_register(elf_executable_T* executable, uint8_t* buffer) {
uint64_t chunk_id = 0;
driver_manager_chunk_T* chunk = g_driver_manager.driver_pool;
while (chunk->free_slots == 0) {
if (chunk->next == NULL) {
driver_manager_chunk_alloc(chunk);
}
chunk = chunk->next;
chunk_id++;
}
driver_T* driver;
for (uint64_t i = 0; i < DRIVER_MANAGER_CHUNK_SIZE; i++) {
if (bitmap_get(&chunk->drivers_bitmap, i)) continue;
bitmap_set(&chunk->drivers_bitmap, i, true);
chunk->free_slots -= 1;
driver = &chunk->drivers[i];
driver->id = (chunk_id * DRIVER_MANAGER_CHUNK_SIZE) + i;
break;
}
driver->base = (void*)(MEM_REGION_KERNEL_DRIVERS + (driver->id * DRIVER_MEMORY_REGION_SIZE));
driver->executable = executable;
elf_mappings_apply(executable->mappings, executable->num_mappings, buffer, driver->base, g_kernel_page_map);
bool status = elf_relocate_driver(executable, buffer, driver->base);
if (!status) {
bitmap_set(&chunk->drivers_bitmap, driver->id % DRIVER_MANAGER_CHUNK_SIZE, false);
chunk->free_slots += 1;
return NULL;
}
return driver;
}
driver_T* driver_lookup_pci_device(uint16_t vendor_id, uint16_t device_id) {
hashmap_T* level_2 = hashmap_lookup(&g_driver_manager.lookup_table_pci, vendor_id);
if (level_2 == NULL) return driver_find_pci_device(vendor_id, device_id);
driver_T* driver = hashmap_lookup(level_2, device_id);
if (driver == NULL) return driver_find_pci_device(vendor_id, device_id);
return driver;
}
driver_T* driver_lookup_usb_device(uint16_t vendor_id, uint16_t device_id) {
hashmap_T* level_2 = hashmap_lookup(&g_driver_manager.lookup_table_usb, vendor_id);
if (level_2 == NULL) return driver_find_usb_device(vendor_id, device_id);
driver_T* driver = hashmap_lookup(level_2, device_id);
if (driver == NULL) return driver_find_usb_device(vendor_id, device_id);
return driver;
}
driver_T* driver_lookup_fs_gpt(uint8_t guid[16]) {
uint64_t gpt_hash = ((uint64_t*)guid)[0] ^ ((uint64_t*)guid)[1];
driver_T* driver = hashmap_lookup(&g_driver_manager.lookup_table_fs_gpt, gpt_hash);
if (driver == NULL) return driver_find_fs_gpt(guid);
return driver;
}
driver_T* driver_lookup_fs_mbr(uint8_t type) {
driver_T* driver = hashmap_lookup(&g_driver_manager.lookup_table_fs_gpt, type);
if (driver == NULL) return driver_find_fs_mbr(type);
return driver;
}
driver_T* driver_lookup_by_address(void* address) {
uint64_t value = (uint64_t)address;
value &= 0xFFFFFFFF00000000;
value -= MEM_REGION_KERNEL_DRIVERS;
value >>= 32;
uint64_t chunk_id = value / DRIVER_MANAGER_CHUNK_SIZE;
uint64_t local_id = value % DRIVER_MANAGER_CHUNK_SIZE;
driver_manager_chunk_T* chunk = g_driver_manager.driver_pool;
for (uint64_t i = 0; i < chunk_id; i++) {
if (chunk->next == NULL) return NULL;
chunk = chunk->next;
}
if (!bitmap_get(&chunk->drivers_bitmap, local_id)) return NULL;
return &chunk->drivers[local_id];
}

View File

@ -16,7 +16,7 @@ void stack_trace_call_stack(uint64_t rbp) {
log(LOG_NONE, " 0x%x -> <failed to resolve symbol> (process NULL reference)", rip);
return;
}
symbol_T* symbol = symbol_resolve_from_rip(process->executable->symbols, process->executable->num_symbols, rip);
symbol_T* symbol = symbol_resolve_from_rip(&process->executable->symbol_table, rip);
if (symbol == NULL) {
log(LOG_NONE, " 0x%x -> <failed to resolve symbol> (symbol NULL reference)", rip);

View File

@ -1,53 +0,0 @@
// This file is part of noxos and licensed under the MIT open source license
#include <modules/loader.h>
#include <utils/memory.h>
#include <utils/logger.h>
#include <drivers/builtin/fs/vfs.h>
module_manager_T g_module_manager;
void module_manager_init() {
g_module_manager.chunks = module_manager_chunk_alloc(NULL);
}
module_manager_chunk_T* module_manager_chunk_alloc(module_manager_chunk_T* prev) {
module_manager_chunk_T* chunk = memory_allocate(sizeof(module_manager_chunk_T));
chunk->modules_bitmap = bitmap_init(MODULE_MANAGER_CHUNK_SIZE);
chunk->num_modules = 0;
chunk->next = NULL;
chunk->prev = prev;
if (prev != NULL) {
prev->next = chunk;
}
return chunk;
}
module_T* module_load(string_t name, string_t path) {
module_T* module = memory_allocate(sizeof(module_T));
module->name = name;
module->path = path;
vfs_node_T* node = vfs_resolve_path(&g_root_fs, path);
if (node == NULL || node->type != VFS_NODE_FILE) {
memory_free(module);
log(LOG_ERROR, "failed to load module '%s' from '%s' (file not found)", name, path);
return NULL;
}
void* buffer = memory_allocate(node->size);
vfs_file_read(node, 0, node->size, buffer);
module->executable = elf_executable_create(buffer);
log(LOG_INFO, "loaded module '%s' from '%s'", name, path);
return module;
}
void module_unload(module_T* module) {
}

View File

@ -1,3 +0,0 @@
// This file is part of noxos and licensed under the MIT open source license
#include <modules/module.h>

View File

@ -6,10 +6,11 @@
#include "utils/memory.h"
#include "proc/scheduler.h"
#include "drivers/builtin/fs/vfs.h"
#include "drivers/driver.h"
#include "mm/page_frame.h"
#include "mm/region.h"
void syscall_handle_nx_fopen(cpu_state_T* state) {
void syscall_handle_nx_fs_open(cpu_state_T* state) {
string_t path = (string_t)state->rdi; // arg1
uint64_t len = state->rsi; // arg2
file_descriptor_t* fd_ptr = (file_descriptor_t*)state->rdx; // arg3
@ -23,7 +24,7 @@ void syscall_handle_nx_fopen(cpu_state_T* state) {
*fd_ptr = file_descriptor_request(scheduler_get_current_process()->fd_array, node);
}
void syscall_handle_nx_fclose(cpu_state_T* state) {
void syscall_handle_nx_fs_close(cpu_state_T* state) {
file_descriptor_t fd = (file_descriptor_t)state->rdi; // arg1
file_descriptor_free(scheduler_get_current_process()->fd_array, fd);
@ -31,7 +32,7 @@ void syscall_handle_nx_fclose(cpu_state_T* state) {
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_fread(cpu_state_T* state) {
void syscall_handle_nx_fs_read(cpu_state_T* state) {
file_descriptor_t fd = (file_descriptor_t)state->rdi; // arg1
uint64_t offset = state->rsi; // arg2
uint8_t* mem = (uint8_t*)state->rdx; // arg3
@ -63,7 +64,7 @@ void syscall_handle_nx_fread(cpu_state_T* state) {
state->rax = read_bytes;
}
void syscall_handle_nx_fwrite(cpu_state_T* state) {
void syscall_handle_nx_fs_write(cpu_state_T* state) {
file_descriptor_t fd = (file_descriptor_t)state->rdi; // arg1
uint64_t offset = state->rsi; // arg2
uint8_t* mem = (uint8_t*)state->rdx; // arg3
@ -103,7 +104,7 @@ void syscall_handle_nx_fwrite(cpu_state_T* state) {
state->rax = written_bytes;
}
void syscall_handle_nx_fdelete(cpu_state_T* state) {
void syscall_handle_nx_fs_delete(cpu_state_T* state) {
string_t path = (string_t)state->rdi; // arg1
string_t len = (string_t)state->rsi; // arg2
@ -118,7 +119,7 @@ void syscall_handle_nx_fdelete(cpu_state_T* state) {
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_flist(cpu_state_T* state) {
void syscall_handle_nx_fs_list(cpu_state_T* state) {
string_t path = (string_t)state->rdi; // arg1
uint64_t len = state->rsi; // arg2
uint8_t* mem = (uint8_t*)state->rdx; // arg3
@ -153,7 +154,7 @@ void syscall_handle_nx_flist(cpu_state_T* state) {
}
void syscall_handle_nx_mmap(cpu_state_T* state) {
void syscall_handle_nx_mem_alloc(cpu_state_T* state) {
uint8_t* addr = (uint8_t*)state->rdi; // arg1
uint64_t n = state->rsi; // arg2
uint64_t flags = (uint64_t)state->rdx; // arg3
@ -187,7 +188,7 @@ void syscall_handle_nx_mmap(cpu_state_T* state) {
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_munmap(cpu_state_T* state) {
void syscall_handle_nx_mem_free(cpu_state_T* state) {
void* addr = (void*)state->rdi; // arg1
uint64_t n = state->rsi; // arg2
@ -207,13 +208,14 @@ void syscall_handle_nx_munmap(cpu_state_T* state) {
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_pcreate(cpu_state_T* state) {
string_t path = (string_t)state->rdi; // arg1
uint64_t len = state->rsi; // arg2
pid_t* pid = (pid_t*)state->rdx; // arg3
string_t name = (string_t)state->rcx; // arg4
vfs_node_T* node = vfs_resolve_path(&g_root_fs, path);
void syscall_handle_nx_proc_create(cpu_state_T* state) {
process_config_T* conf = (process_config_T*)state->rdi; // arg1
pid_t* pid_ptr = (pid_t*)state->rsi; // arg2
process_T* parent = scheduler_get_current_process();
vfs_node_T* node = file_descriptor_resolve(parent->fd_array, conf->executable);
if (node == NULL || node->type != VFS_NODE_FILE) {
state->rax = STATUS_RESOURCE_NOT_AVAILABLE;
return;
@ -229,23 +231,19 @@ void syscall_handle_nx_pcreate(cpu_state_T* state) {
return;
}
if (name == NULL) {
name = path;
}
*pid = process_spawn(scheduler_get_current_process()->id, name, exec, buffer);
if (*pid == PROCESS_NONE) {
*pid_ptr = process_spawn(parent->id, conf->name, exec, buffer);
if (*pid_ptr == PROCESS_NONE) {
state->rax = STATUS_GENERIC_ERROR;
return;
}
void* entry = (void*)(symbol_resolve_from_name(exec->symbols, exec->num_symbols, "_start")->address + MEM_REGION_PROCESS_EXEC);
void* entry = (void*)(symbol_resolve_from_name(&exec->symbol_table, "_start")->address + MEM_REGION_PROCESS_EXEC);
thread_spawn(*pid, entry);
thread_spawn(*pid_ptr, entry);
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_psignal(cpu_state_T* state) {
void syscall_handle_nx_proc_signal_send(cpu_state_T* state) {
pid_t pid = (pid_t)state->rdi; // arg1
uint64_t signal = state->rsi; // arg2
@ -264,6 +262,44 @@ void syscall_handle_nx_psignal(cpu_state_T* state) {
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_drv_register(cpu_state_T* state) {
file_descriptor_t fd = (file_descriptor_t)state->rdi; // arg1
uint64_t* id_ptr = (uint64_t*)state->rsi; // arg2
process_T* process = scheduler_get_current_process();
vfs_node_T* node = file_descriptor_resolve(process->fd_array, fd);
if (node == NULL) {
log(LOG_ERROR, "failed to register driver (file descriptor error)");
state->rax = STATUS_RESOURCE_NOT_AVAILABLE;
return;
}
uint8_t* buffer = memory_allocate(node->size);
vfs_file_read(node, 0, node->size, buffer);
elf_executable_T* exec = elf_executable_create(buffer);
if (exec == NULL) {
memory_free(buffer);
log(LOG_ERROR, "failed to register driver (elf parsing error)");
state->rax = STATUS_NOT_SUPPORTED;
return;
}
driver_T* drv = driver_register(exec, buffer);
if (drv == NULL) {
log(LOG_ERROR, "failed to register driver (registration error)");
state->rax = STATUS_GENERIC_ERROR;
return;
}
void (*drv_init)() = drv->base + symbol_resolve_from_name(&exec->symbol_table, "_init")->address;;
drv_init();
*id_ptr = drv->id;
state->rax = STATUS_SUCCESS;
}
cpu_state_T* syscall_handle(cpu_state_T* state) {
cpu_state_T* return_state = state;
syscall_group_E group_id = (state->rax & 0xFF00) >> 8;
@ -273,28 +309,28 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
case SYSCALLS_FILES: {
switch (state->rax) {
case SYSCALL_FILES_OPEN: {
syscall_handle_nx_fopen(state);
case SYSCALL_NX_FS_OPEN: {
syscall_handle_nx_fs_open(state);
break;
}
case SYSCALL_FILES_CLOSE: {
syscall_handle_nx_fclose(state);
case SYSCALL_NX_FS_CLOSE: {
syscall_handle_nx_fs_close(state);
break;
}
case SYSCALL_FILES_READ: {
syscall_handle_nx_fread(state);
case SYSCALL_NX_FS_READ: {
syscall_handle_nx_fs_read(state);
break;
}
case SYSCALL_FILES_WRITE: {
syscall_handle_nx_fwrite(state);
case SYSCALL_NX_FS_WRITE: {
syscall_handle_nx_fs_write(state);
break;
}
case SYSCALL_FILES_DELETE: {
syscall_handle_nx_fdelete(state);
case SYSCALL_NX_FS_DELETE: {
syscall_handle_nx_fs_delete(state);
break;
}
case SYSCALL_FILES_LIST: {
syscall_handle_nx_flist(state);
case SYSCALL_NX_FS_LIST: {
syscall_handle_nx_fs_list(state);
break;
}
}
@ -303,12 +339,12 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
case SYSCALLS_MEMORY: {
switch (state->rax) {
case SYSCALL_MEMORY_MAP: {
syscall_handle_nx_mmap(state);
case SYSCALL_NX_MEM_ALLOC: {
syscall_handle_nx_mem_alloc(state);
break;
}
case SYSCALL_MEMORY_UNMAP: {
syscall_handle_nx_munmap(state);
case SYSCALL_NX_MEM_FREE: {
syscall_handle_nx_mem_free(state);
break;
}
}
@ -317,23 +353,25 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
case SYSCALLS_PROC: {
switch (state->rax) {
case SYSCALL_PROCESS_CREATE: {
syscall_handle_nx_pcreate(state);
case SYSCALL_NX_PROC_CREATE: {
syscall_handle_nx_proc_create(state);
break;
}
case SYSCALL_PROCESS_SIGNAL: {
syscall_handle_nx_psignal(state);
case SYSCALL_NX_PROC_SIGNAL_SEND: {
syscall_handle_nx_proc_signal_send(state);
break;
}
}
break;
}
case SYSCALLS_RUNTIME_LINKER: {
case SYSCALLS_DRIVERS: {
switch (state->rax) {
case SYSCALL_NX_DRV_REGISTER: {
syscall_handle_nx_drv_register(state);
break;
}
case SYSCALLS_COMPATABILITY: {
}
break;
}
@ -349,12 +387,12 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
}
switch (state->rax) {
case SYSCALL_KERNEL_SCHEDULER_START: {
case SYSCALL_NX_KERNEL_SCHEDULER_START: {
return_state = scheduler_start(state);
break;
}
case SYSCALL_KERNEL_PANIC: {
case SYSCALL_NX_KERNEL_PANIC: {
panic(state, (string_t)arg1);
break;
}

View File

@ -0,0 +1,7 @@
; This file is part of noxos and licensed under the MIT open source license
stack_get_caller:
mov rax, [rbp + 0x8]
ret
GLOBAL stack_get_caller

View File

@ -57,7 +57,7 @@ void scheduler_init(boot_info_T* boot_info) {
process_kernel_spawn(elf_executable_create(boot_info->kernel_file->address));
syscall_perform(SYSCALL_KERNEL_SCHEDULER_START, 0, 0, 0, 0);
syscall_perform(SYSCALL_NX_KERNEL_SCHEDULER_START, 0, 0, 0, 0);
}
cpu_state_T* scheduler_start(cpu_state_T* state) {

87
src/utils/hashmap.c Normal file
View File

@ -0,0 +1,87 @@
// This file is part of noxos and licensed under the MIT open source license
#include <utils/hashmap.h>
#include <utils/memory.h>
hashmap_T hashmap_create(uint64_t size) {
hashmap_T hashmap;
hashmap.size = size;
hashmap.entries = memory_allocate(size * sizeof(hashmap_entry_T));
memory_set(hashmap.entries, 0, size * sizeof(hashmap_entry_T));
return hashmap;
}
void hashmap_destruct (hashmap_T* hashmap) {
for (uint64_t i = 0; i < hashmap->size; i++) {
hashmap_entry_T* entry = hashmap->entries[i].next;
while (entry != NULL) {
hashmap_entry_T* next = entry->next;
memory_free(entry);
entry = next;
}
}
memory_free(hashmap->entries);
}
void hashmap_insert(hashmap_T* hashmap, uint64_t key, void* value) {
uint64_t index = key % hashmap->size;
if (!hashmap->entries[index].in_use) {
hashmap->entries[index].key = key;
hashmap->entries[index].value = value;
hashmap->entries[index].in_use = true;
return;
}
hashmap_entry_T* entry = &hashmap->entries[index];
while (entry->next != NULL) {
entry = entry->next;
}
entry->next = memory_allocate(sizeof(hashmap_entry_T));
entry->next->prev = entry;
entry->next->next = NULL;
entry->next->key = key;
entry->next->value = value;
entry->next->in_use = true;
}
void hashmap_delete(hashmap_T* hashmap, uint64_t key) {
uint64_t index = key % hashmap->size;
hashmap_entry_T* entry = &hashmap->entries[index];
while (entry->key != key) {
if (entry->next == NULL) return;
entry = entry->next;
}
if (entry->prev != NULL) {
entry->prev->next = entry->next;
if (entry->next != NULL) entry->next->prev = entry->prev;
memory_free(entry);
return;
}
entry->key = 0;
entry->value = NULL;
entry->in_use = false;
}
void* hashmap_lookup(hashmap_T* hashmap, uint64_t key) {
uint64_t index = key % hashmap->size;
hashmap_entry_T* entry = &hashmap->entries[index];
while (entry->key != key) {
if (entry->next == NULL) return NULL;
entry = entry->next;
}
if (!entry->in_use) return NULL;
return entry->value;
}

View File

@ -68,7 +68,7 @@ void panic_log_call_stack(cpu_state_T* state) {
log(LOG_NONE, "Call Stack:");
stack_trace_call_stack(state->rbp);
symbol_T* symbol = symbol_resolve_from_rip(process->executable->symbols, process->executable->num_symbols,state->rip);
symbol_T* symbol = symbol_resolve_from_rip(&process->executable->symbol_table, state->rip);
if (symbol == NULL) {
log(LOG_NONE, " 0x%x -> <failed to resolve symbol> (symbol NULL reference)", state->rip);
return;

View File

@ -436,7 +436,7 @@ bool string_is_char_number(char chr) {
bool string_is_char_special(char chr) {
if ((chr >= '!' && chr <= '/') ||
(chr >= ':' && chr <= '@') ||
(chr >= '^' && chr <= '`') ||
(chr >= '[' && chr <= '`') ||
(chr >= '{' && chr <= '~')) {
return true;
}
@ -463,3 +463,13 @@ bool string_is_char_lowercase (char chr) {
}
return false;
}
uint32_t string_hash_djb(string_t str) {
uint32_t hash = 5381;
while (*(++str) != '\0') {
hash = ((hash << 5) + hash) + (*str);
}
return hash;
}

View File

@ -1,25 +1,47 @@
// This file is part of noxos and licensed under the MIT open source license
#include "utils/symbol.h"
#include "utils/memory.h"
symbol_T* symbol_resolve_from_name(symbol_T* symbols, uint64_t num_symbols, string_t name) {
for (uint64_t i = 0; i < num_symbols; i++) {
if (string_compare(name, symbols[i].name)) {
return &symbols[i];
}
}
#include "utils/logger.h"
return NULL;
symbol_table_T symbol_table_init(uint64_t num_symbols) {
symbol_table_T symbol_table;
DEBUG("symbol_table_init -> num_symbols: %d", num_symbols);
symbol_table.symbols = memory_allocate(num_symbols * sizeof(symbol_T));
symbol_table.hashmap = hashmap_create(num_symbols);
symbol_table.num_symbols = num_symbols;
symbol_table.symbols_index = 0;
return symbol_table;
}
symbol_T* symbol_resolve_from_rip(symbol_T* symbols, uint64_t num_symbols, uint64_t rip) {
void symbol_table_destruct(symbol_table_T* symbol_table) {
hashmap_destruct(&symbol_table->hashmap);
memory_free(symbol_table->symbols);
}
void symbol_table_insert(symbol_table_T* symbol_table, symbol_T symbol) {
// DEBUG("symbol_table_insert -> SYMTAB[0x%x] || %s (0x%x)", symbol_table, symbol.name, symbol.address);
symbol_table->symbols[symbol_table->symbols_index] = symbol;
hashmap_insert(&symbol_table->hashmap, string_hash_djb(symbol.name), &symbol_table->symbols[symbol_table->symbols_index]);
symbol_table->symbols_index++;
}
symbol_T* symbol_resolve_from_name(symbol_table_T* symbol_table, string_t name) {
return hashmap_lookup(&symbol_table->hashmap, string_hash_djb(name));
}
symbol_T* symbol_resolve_from_rip(symbol_table_T* symbol_table, uint64_t rip) {
symbol_T* symbol = NULL;
for (uint64_t i = 0; i < num_symbols; i++) {
if (symbols[i].address <= rip &&
(symbol == NULL || symbols[i].address > symbol->address))
for (uint64_t i = 0; i < symbol_table->num_symbols; i++) {
if (symbol_table->symbols[i].address <= rip &&
(symbol == NULL || symbol_table->symbols[i].address > symbol->address))
{
symbol = &symbols[i];
symbol = &symbol_table->symbols[i];
}
}