Compare commits
27 Commits
modulariza
...
master
Author | SHA1 | Date |
---|---|---|
antifallobst | f0bf8ac3f5 | |
antifallobst | b498cb2c98 | |
antifallobst | 81fc9ca9fc | |
antifallobst | 91f7aa4009 | |
antifallobst | d7c79e1bdf | |
antifallobst | ae0ef5c85d | |
antifallobst | 8c273f4dc7 | |
antifallobst | b00b57b180 | |
antifallobst | 4070959736 | |
antifallobst | 3fbc9dc274 | |
antifallobst | 83f5e77d52 | |
antifallobst | e69065f889 | |
antifallobst | 2902215904 | |
antifallobst | e85621ec55 | |
antifallobst | b50750653d | |
antifallobst | 78ea65ec75 | |
antifallobst | 74aa1a4e4d | |
antifallobst | a904629abd | |
antifallobst | 263e7305cf | |
antifallobst | 7d33377806 | |
antifallobst | 3d4cea2060 | |
antifallobst | bb19ff02e1 | |
antifallobst | 82af1f195b | |
antifallobst | 7e53ab9e7c | |
antifallobst | 0732a19f8a | |
antifallobst | 713ffbc089 | |
antifallobst | cd5737dba7 |
|
@ -1,4 +1,5 @@
|
|||
build
|
||||
cmake-build-debug
|
||||
noxos.log
|
||||
ramdisk/shell.elf
|
||||
ramdisk/shell.elf
|
||||
*.nxkm
|
64
README.md
64
README.md
|
@ -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>
|
||||
|
|
21
build.sh
21
build.sh
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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); \
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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 {
|
||||
|
|
|
@ -29,12 +29,26 @@ typedef enum {
|
|||
} process_blockers_E;
|
||||
|
||||
typedef enum {
|
||||
PROCESS_SIGNAL_START, // SIGSTART
|
||||
PROCESS_SIGNAL_PAUSE, // SIGPAUSE
|
||||
PROCESS_SIGNAL_KILL, // SIGKILL
|
||||
PROCESS_SIGNAL_PFAULT, // SIGPFAULT
|
||||
PROCESS_SIGNAL_START, // SIGSTART
|
||||
PROCESS_SIGNAL_PAUSE, // SIGPAUSE
|
||||
PROCESS_SIGNAL_KILL, // SIGKILL
|
||||
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];
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"BOOT": [
|
||||
"/initrd/drv/test.nxkm"
|
||||
]
|
||||
}
|
|
@ -1,8 +1,4 @@
|
|||
{
|
||||
"PS2_ACPI_VALIDATION": true,
|
||||
"LOG_GRAPHICAL": false,
|
||||
|
||||
"modules": {
|
||||
"FAT32": "/initrd/modules/fat32.nxkm"
|
||||
}
|
||||
"LOG_GRAPHICAL": true
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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,8 +28,10 @@ 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);
|
||||
|
||||
for (uint64_t i = 0; i < num_pages; i++) {
|
||||
page_map_unmap_memory(g_kernel_page_map, virtual_address + (PFRAME_SIZE * i));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = §ions[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 = §ions[i];
|
||||
break;
|
||||
}
|
||||
case ELF_SECTION_STRING_TABLE: {
|
||||
if (!string_compare(".dynstr", §ion_names[sections[i].name_offset])) break;
|
||||
section_dynstr = §ions[i];
|
||||
break;
|
||||
}
|
||||
case ELF_SECTION_DYNAMIC_SYMBOL_TABLE: {
|
||||
section_dynsym = §ions[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;
|
||||
}
|
|
@ -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"
|
||||
};
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#include <modules/module.h>
|
|
@ -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,9 +104,9 @@ 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
|
||||
string_t len = (string_t)state->rsi; // arg2
|
||||
|
||||
vfs_node_T* node = vfs_resolve_path(&g_root_fs, path);
|
||||
if (node == NULL) {
|
||||
|
@ -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: {
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSCALLS_COMPATABILITY: {
|
||||
case SYSCALLS_DRIVERS: {
|
||||
switch (state->rax) {
|
||||
case SYSCALL_NX_DRV_REGISTER: {
|
||||
syscall_handle_nx_drv_register(state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -462,4 +462,14 @@ bool string_is_char_lowercase (char chr) {
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t string_hash_djb(string_t str) {
|
||||
uint32_t hash = 5381;
|
||||
|
||||
while (*(++str) != '\0') {
|
||||
hash = ((hash << 5) + hash) + (*str);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue