Compare commits

..

5 Commits

Author SHA1 Message Date
Eric-Paul Ickhorn 4f5da10be1 Renamed run.sh to run.bash aswell 2023-05-29 23:45:29 +02:00
Eric-Paul Ickhorn 09ed173eef Renamed build.sh to build.bash to more clearly indicate bash 2023-05-29 23:43:36 +02:00
Eric-Paul Ickhorn 3a90af4704 Added cleanup-functionality to build.sh 2023-05-29 23:43:16 +02:00
Eric-Paul Ickhorn 1ad60a7351 Slightly bigger restructuring to get the dependencies into this repo 2023-05-29 22:59:31 +02:00
Eric-Paul Ickhorn 2f9ca93cb1 Basic userspace driver infrastructure 2023-05-29 15:42:56 +02:00
54 changed files with 916 additions and 1156 deletions

1
.gitignore vendored
View File

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

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "libraries/libnoxos"]
path = libraries/libnoxos
url = https://git.nerdcult.net/noxos/libnoxos.git
[submodule "initrd/sources/userland"]
path = initrd/sources/userland
url = https://git.nerdcult.net/noxos/userland.git

View File

@ -3,53 +3,39 @@
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] 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
- [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)
- [ ] 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 [here](https://git.nerdcult.net/noxos/documentation).
Install instructions, Code Documentation and a Contribution guide can be found in the [wiki](https://codeberg.org/antifallobst/noxos/wiki/).
## Copyright / License (MIT)
Copyright 2023 Antifallobst <antifallobst@systemausfall.org>

View File

@ -3,6 +3,21 @@
# This file is part of noxos and licensed under the MIT open source license
set -e
PROJECT_ROOT=$PWD
OVMF_PATH=" "
if [[ -f "/usr/share/ovmf/x64/OVMF.fd" ]]; then
OVMF_PATH="/usr/share/ovmf/x64/OVMF.fd"
elif [[ -f "/usr/share/OVMF/OVMF.fd" ]]; then
OVMF_PATH="/usr/share/OVMF/OVMF.fd"
elif [[ -f "$PROECT_ROOT/build/ovmf/x64/OVMF.fd" ]]; then
OVMF_PATH="$PROECT_ROOT/build/ovmf/x64/OVMF.fd"
else
echo "Could not find OVMF-file! Did search at:"
echo "1) /usr/share/ovmf/x64/OVMF.fd"
echo "2) /usr/share/OVMF/OVMF.fd"
echo "3) $PROECT_ROOT/build/OVMF/x64/OVMF.fd"
exit 255
fi
workspace_setup() {
echo " --> Setting up workspace"
@ -26,13 +41,11 @@ check_toolchain() {
hash qemu-system-x86_64
echo " |--> found qemu"
[ ! -d "/usr/share/ovmf/x64/" ] && echo "OVMF binaries not found!" && exit 255
echo " |--> found ovmf"
echo " --> All checks passed"
}
kernel_build() {
echo " --> Building kernel"
cd build/cmake
@ -42,31 +55,12 @@ kernel_build() {
echo ""
}
libnx_build() {
cd ../libraries/libnx
bash build.sh
cd ../../kernel
libnoxos_build() {
cd libraries/libnoxos/
# bash build.sh
cd $PROJECT_ROOT
}
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() {
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
}
limine_install() {
echo " --> Installing Limine"
cd build
@ -81,7 +75,10 @@ limine_install() {
generate_initial_ramdisk() {
echo " --> Generating initrd"
tar -C ramdisk -cvf build/initrd.tar .
cd initrd
bash build.bash
cd $PROJECT_ROOT
tar -C initrd -cvf build/initrd.tar .
}
generate_image() {
@ -112,19 +109,25 @@ generate_image() {
echo ""
}
echo "!=====[ NoxOS build script ]=====!"
cleanup_files() {
rm -Rf build/
}
echo "!=====[ NOXOS build script ]=====!"
case $1 in
"check")
check_toolchain
;;
"cleanup")
cleanup_files
;;
*)
workspace_setup
kernel_build
[ ! -d "build/limine" ] && limine_install
libnx_build
libnxdrv_build
shell_build
libnoxos_build
generate_initial_ramdisk
generate_image
;;

View File

@ -1,23 +0,0 @@
// 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,7 +10,8 @@
typedef struct {
elf_header_T header;
symbol_table_T symbol_table;
uint64_t num_symbols;
symbol_T* symbols;
uint64_t num_mappings;
elf_mapping_T* mappings;
void* string_table;

View File

@ -1,37 +0,0 @@
// 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,12 +13,9 @@ typedef enum {
ELF_SECTION_STRING_TABLE,
ELF_SECTION_RELOCATION_A,
ELF_SECTION_HASH,
ELF_SECTION_DYNAMIC,
ELF_SECTION_DYNAMIC_LINK,
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,7 +31,6 @@
#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); \
@ -83,9 +82,9 @@ typedef struct {
json_node_T* root_node;
} json_T;
json_T* json_from_string (string_t str);
json_T * json_from_string (string_t str);
void json_destruct (json_T* json);
json_node_T* json_node_alloc (json_node_T* parent, json_node_type_E type, json_token_T* token);
json_node_T * json_node_alloc (json_node_T* parent, json_node_type_E type, json_token_T* token);
void json_node_destruct (json_node_T* node);
void json_node_dump (json_node_T* node, uint32_t indent);
string_t json_node_type_to_string (json_node_type_E type);
@ -94,5 +93,7 @@ bool json_parse (json_T* json);
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);
bool json_parse_array (json_T* json, uint32_t* token_id, json_node_T* node);
json_node_T * json_resolve_path (json_node_T *base, char *path);
#endif //NOXOS_JSON_H

View File

@ -0,0 +1,79 @@
#ifndef NOXOS_DEVICE_H
#define NOXOS_DEVICE_H
#include <utils/stdtypes.h>
#include <drivers/driver_manager.h>
typedef enum {
DEVICE_PCI = 1,
DEVICE_USB = 2,
DEVICE_VIRTUAL = 255
} device_category_E;
typedef enum {
DEVICE_CAPABILITY_TRANSMISSION,
DEVICE_CAPABILITY_STORAGE,
DEVICE_CAPABILITY_GRAPHICS,
DEVICE_CAPABILITY_AUDIO
} device_top_level_capability_E;
typedef struct device_capabilities_t {
device_top_level_capability_E *top_level;
struct device_transmission_capability_t {
// TODO
} transmission;
struct device_storage_capability_t {
char uuid[32];
uint64_t size;
} storage;
struct device_graphics_capability_t {
uint32_t fb_width;
uint32_t fb_height;
uint16_t bits_per_pixel;
} graphics;
struct device_audio_capability_t {
// TODO
} audio;
} device_capabilities_T;
typedef struct device_t {
uint32_t id;
device_category_E category;
void *specific;
driver_T *driver;
} device_T;
typedef struct device_manager_t {
uint32_t num_devices;
device_T *devices;
} device_manager_T;
extern device_manager_T g_device_manager;
void device_manager_init ();
void device_remove (device_T *device);
device_T * device_find (device_capabilities_T capabilities, uint32_t index, uint32_t *out_count);
#endif

View File

@ -1,115 +0,0 @@
// 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

@ -0,0 +1,117 @@
#ifndef NOXOS_DRIVER_H
#define NOXOS_DRIVER_H
#include "utils/stdtypes.h"
#define DRIVER_COMMAND_SIZE 32
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_NVME_DEVICE = 0x0205,
DRIVER_BLUETOOTH = 0x0206,
DRIVER_ETHERNET = 0x0207,
// MISCELLANEOUS
DRIVER_EMULATION = 0x7fff
} driver_category_E;
typedef struct driver_mass_storage_t {
} driver_mass_storage_T;
typedef struct driver_configuration_t
{
uint16_t category;
uint16_t max_command_buffers;
uint16_t category_dependencies[16];
uint8_t reserved[220];
} driver_configuration_T;
typedef struct driver_command_buffer_config_t
{
uint64_t num_commands;
void *mapping_address;
uint8_t reserved[240];
} driver_command_buffer_config_T;
typedef struct driver_command_buffer_t
{
uint64_t command_capacity;
void *mapping_address;
} driver_command_buffer_T;
typedef struct driver_t // TODO: Accesses must be thread-safe
{
driver_category_E category;
uint32_t id;
uint16_t max_command_buffers;
driver_command_buffer_T *command_buffers;
} driver_T;
typedef struct driver_manager_t {
uint32_t max_drivers;
uint32_t num_drivers;
driver_T *drivers;
} driver_manager_T;
extern driver_manager_T g_driver_manager;
void driver_manager_init ();
void driver_manager_load_single_driver (char *driver_config_path);
void driver_manager_load_drivers (char *main_config_path);
uint32_t driver_manager_register_driver (driver_configuration_T *configuration);
driver_T * driver_manager_resolve_driver_id (uint32_t id);
// driver_add_command_buffer: Adds a command buffer to the 'command_buffers'-array in the given driver.
void driver_add_command_buffer (driver_T *driver, driver_command_buffer_config_T *configuration);
// driver_flush_command_buffer: Flushes the command buffer that 'buffer' points to,
// meaning that it executes all commands stored in it. 'buffer' doesn't need to be the first
// byte; the function will execute from the first command in a buffer even if some byte in the
// middle of the buffer is given into this function.
void driver_flush_command_buffer (driver_T *driver, void *buffer);
#endif

View File

@ -16,11 +16,10 @@
#define MEM_REGION_PROCESS_USABLE 0x0000080000000000
#define MEM_REGION_KERNEL 0x0000800000000000
#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
#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
extern uint64_t _kernel_start;
extern uint64_t _kernel_end;

View File

@ -11,6 +11,4 @@
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

32
inc/modules/loader.h Normal file
View File

@ -0,0 +1,32 @@
// 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

16
inc/modules/module.h Normal file
View File

@ -0,0 +1,16 @@
// 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

@ -9,38 +9,53 @@
typedef enum {
SYSCALLS_FILES = 0x00,
SYSCALLS_MEMORY = 0x01,
SYSCALLS_PROC = 0x02,
SYSCALLS_DRIVERS = 0x03,
SYSCALLS_PROCESS = 0x02,
SYSCALLS_DRIVER = 0x03,
SYSCALLS_RUNTIME_LINKER = 0x04,
SYSCALLS_COMPATABILITY = 0x05,
SYSCALLS_KERNEL = 0xFF
}syscall_group_E;
typedef enum {
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_FILES_OPEN = 0x0001,
SYSCALL_FILES_CLOSE = 0x0002,
SYSCALL_FILES_READ = 0x0003,
SYSCALL_FILES_WRITE = 0x0004,
SYSCALL_FILES_DELETE = 0x0005,
SYSCALL_FILES_LIST = 0x0006,
SYSCALL_FILES_INFO = 0x0007,
SYSCALL_NX_MEM_ALLOC = 0x0101,
SYSCALL_NX_MEM_FREE = 0x0102,
SYSCALL_NX_MEM_LABEL = 0x0103,
SYSCALL_NX_MEM_UNLABEL = 0x0104,
SYSCALL_MEMORY_MAP = 0x0101,
SYSCALL_MEMORY_UNMAP = 0x0102,
SYSCALL_MEMORY_LABEL = 0x0103,
SYSCALL_MEMORY_RANGE = 0x0104,
SYSCALL_MEMORY_ACCESS = 0x0105,
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_PROCESS_CREATE = 0x0201,
SYSCALL_PROCESS_ENV = 0x0202,
SYSCALL_PROCESS_SIGNAL = 0x0203,
SYSCALL_PROCESS_THREAD_CREATE = 0x0204,
SYSCALL_PROCESS_THREAD_START = 0x0205,
SYSCALL_PROCESS_THREAD_PAUSE = 0x0206,
SYSCALL_PROCESS_THREAD_KILL = 0x0207,
SYSCALL_NX_DRV_REGISTER = 0x0301,
SYSCALL_DRIVER_REGISTER = 0x0301,
SYSCALL_DRIVER_CREATE_COMMAND_BUFFER = 0x0302,
SYSCALL_DRIVER_FLUSH_COMMAND_BUFFER = 0x0303,
SYSCALL_NX_KERNEL_SCHEDULER_START = 0xFF00,
SYSCALL_NX_KERNEL_PANIC = 0xFF01
SYSCALL_RUNTIME_LINKER_OPEN = 0x7f01,
SYSCALL_RUNTIME_LINKER_CLOSE = 0x7f02,
SYSCALL_RUNTIME_LINKER_LOAD_SYMBOL = 0x7f03,
SYSCALL_RUNTIME_LINKER_STATUS = 0x7f04,
SYSCALL_RUNTIME_LINKER_STANDARD_MOD = 0x7f05,
SYSCALL_COMPATABILITY_ABI_TYPE = 0x0501,
SYSCALL_COMPATABILITY_ABI_VERSION = 0x0502,
SYSCALL_COMPATABILITY_ACTION = 0x0503,
SYSCALL_KERNEL_SCHEDULER_START = 0xFF00,
SYSCALL_KERNEL_PANIC = 0xFF01
} syscall_E;
typedef enum {

View File

@ -32,23 +32,9 @@ typedef enum {
PROCESS_SIGNAL_START, // SIGSTART
PROCESS_SIGNAL_PAUSE, // SIGPAUSE
PROCESS_SIGNAL_KILL, // SIGKILL
PROCESS_SIGNAL_PAGEFAULT, // SIGPAGEFAULT
PROCESS_SIGNAL_MATHFAULT, // SIGMATHFAULT
PROCESS_SIGNAL_PFAULT, // SIGPFAULT
} 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];
@ -60,6 +46,10 @@ struct process_T {
elf_executable_T* executable;
file_descriptor_array_T* fd_array;
// driver: If this process is a driver, this tells the ID
// of that driver within the driver management system.
uint32_t driver;
pipe_T* stdout;
pipe_T stdin;
pipe_T* stderr;
@ -71,7 +61,7 @@ struct process_T {
bitmap_T thread_ids;
process_T* parent;
process_T* childs;
process_T* childs; // TODO: Must be 'children'
process_T* prev;
process_T* next;
};

11
inc/utils/file.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef NOXOS_FILE_UTILS_H
#define NOXOS_FILE_UTILS_H
#include <utils/stdtypes.h>
uint64_t file_get_length (char *path);
uint64_t file_read_into_buffer (char *path, void *buffer, uint64_t offset, uint64_t num_bytes);
#endif

View File

@ -1,28 +0,0 @@
// 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,6 +57,4 @@ 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,7 +4,6 @@
#define NOX_SYMBOLS_H
#include "utils/string.h"
#include "utils/hashmap.h"
typedef enum {
SYMBOL_FUNCTION,
@ -18,17 +17,7 @@ typedef struct {
uint64_t address;
} symbol_T;
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);
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);
#endif //NOX_SYMBOLS_H

3
initrd/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
build/

5
initrd/build.bash Normal file
View File

@ -0,0 +1,5 @@
#!/bin/bash
cd sources/userland/
# bash build.bash

@ -0,0 +1 @@
Subproject commit 9999b292ac52afd0ff629b566b372aeb5db978cf

1
libraries/libnoxos Submodule

@ -0,0 +1 @@
Subproject commit d5ed088f54751dd1874aaf2c2678cc5ab292434a

View File

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

View File

@ -1,4 +0,0 @@
{
"PS2_ACPI_VALIDATION": true,
"LOG_GRAPHICAL": true
}

View File

@ -1,11 +0,0 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Proin molestie porta erat eu interdum.
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Cras semper porta ligula quis condimentum.
Aliquam sed bibendum diam, sit amet gravida orci.
Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Proin vitae urna vel magna luctus pulvinar.
Etiam diam diam, vulputate nec eros a, bibendum tristique velit.
Donec interdum consectetur vehicula.
Vestibulum gravida varius nisi non fringilla.
Nam eu accumsan erat, ac condimentum massa.

View File

@ -5,6 +5,11 @@ EMUFLAGS="-no-reboot -machine type=q35,accel=kvm -cpu max -m 256M \
-drive file=build/noxos.iso \
-chardev stdio,id=log,logfile=noxos.log -serial chardev:log"
OVMF_PATH="/usr/share/ovmf/x64/OVMF.fd"
if [[ -f "/usr/share/OVMF/OVMF.fd" ]]; then
OVMF_PATH="/usr/share/OVMF/OVMF.fd"
fi
emulate_bios() {
echo "<=====| Emulating |=====>"
qemu-system-x86_64 $EMUFLAGS
@ -12,13 +17,13 @@ emulate_bios() {
emulate_uefi() {
echo "<=====| Emulating in UEFI mode |=====>"
qemu-system-x86_64 -bios /usr/share/ovmf/x64/OVMF.fd $EMUFLAGS
qemu-system-x86_64 -bios $OVMF_PATH $EMUFLAGS
}
# qemu will wait for gdb to connect, before booting
emulate_debug() {
echo "<=====| Emulating in debug mode |=====>"
qemu-system-x86_64 -s -S -bios /usr/share/ovmf/x64/OVMF.fd $EMUFLAGS
qemu-system-x86_64 -s -S -bios $OVMF_PATH $EMUFLAGS
}
case $1 in

63
shell.c
View File

@ -1,63 +0,0 @@
#include "nox/stdio.h"
#include "nox/memory.h"
#include "nox/math.h"
#define COMMAND_BUFFER_SIZE 512
int read_command(char* command_buffer) {
char chr = 0;
int pos = 0;
while (chr != '\n') {
chr = getc();
switch (chr) {
case '\b': {
if (pos > 0) pos--;
break;
}
default: {
if (pos < COMMAND_BUFFER_SIZE) {
command_buffer[pos] = chr;
pos++;
}
break;
}
}
}
command_buffer[--pos] = '\0';
return pos;
}
bool handle_command(char* command_buffer) {
int command_length = strlen(command_buffer);
if (command_length < 2) return true;
if (memcmp(command_buffer, "help", min(4, command_length))) {
printf("Commands:\n");
printf(" help | shows this help message\n");
printf(" exit | exit noxsh\n");
} else if (memcmp(command_buffer, "exit", min(4, command_length))) {
printf("exiting noxsh\n");
return false;
} else {
printf("Unknown command: '");
printf(command_buffer);
printf("'\n");
}
return true;
}
void _start() {
printf("Welcome to the nox shell.\ntype 'help' for a list of commands\n");
bool running = true;
while(running) {
printf("\n[/]=> ");
char command_buffer[COMMAND_BUFFER_SIZE];
read_command(command_buffer);
running = handle_command(command_buffer);
}
}

View File

@ -3,6 +3,7 @@
#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"
@ -19,8 +20,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));
@ -50,14 +51,16 @@ void kernel_init(boot_info_T* boot_info) {
scheduler_init(boot_info);
driver_manager_init();
acpi_init(boot_info);
module_manager_init();
drive_manager_init();
pci_init();
driver_manager_init();
tty_init();
ps2_controller_init();
@ -65,26 +68,15 @@ void kernel_init(boot_info_T* boot_info) {
void kmain(boot_info_T boot_info) {
limine_terminal_print(&boot_info, "Booting NoxOS...\n");
log(LOG_DEBUG, "Booting NoxOS");
limine_terminal_print(&boot_info, "Booting NOXOS...\n");
log(LOG_DEBUG, "Booting NOXOS");
kernel_init(&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;
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);
syscall_perform(SYSCALL_PROCESS_CREATE, (uint64_t)"/initrd/shell.elf", 0, (uint64_t)&pid, 0);
process_T* process = scheduler_get_process(pid);
@ -93,8 +85,10 @@ void kmain(boot_info_T boot_info) {
g_tty->output = &process->stdin;
process->stdout = &g_tty->input;
syscall_perform(SYSCALL_NX_PROC_SIGNAL_SEND, pid, PROCESS_SIGNAL_START, 0, 0);
syscall_perform(SYSCALL_PROCESS_SIGNAL, pid, PROCESS_SIGNAL_START, 0, 0);
uint8_t digest[20];
sha1_hash(digest, "test", 4);
CORE_HALT_FOREVER
}

View File

@ -1,30 +0,0 @@
// 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,33 +36,31 @@ bool elf_executable_validate(elf_executable_T* executable) {
}
void elf_executable_extract_symbols(elf_executable_temp_T* executable_temp) {
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);
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));
for (int i = 0; i < num_symbols; i++) {
symbol_T symbol;
for (int i = 0; i < executable_temp->executable->num_symbols; i++) {
symbol_T* symbol = &executable_temp->executable->symbols[i];
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);
}
}
@ -155,7 +153,7 @@ elf_executable_T* elf_executable_create(uint8_t* buffer) {
void elf_executable_destruct(elf_executable_T* executable) {
memory_free(executable->string_table);
symbol_table_destruct(&executable->symbol_table);
memory_free(executable->symbols);
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 + (mapping->offset_virtual % PFRAME_SIZE), PFRAME_SIZE) / PFRAME_SIZE;
uint64_t num_pages = CEIL_TO(mapping->length_virtual, 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,11 +28,9 @@ 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

@ -1,109 +0,0 @@
// 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,9 +12,6 @@ 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+1];
char name[length];
memory_copy((void*)path, name, length);
name[length] = '\0';

View File

@ -9,8 +9,6 @@ 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);
@ -272,8 +270,6 @@ 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);
@ -318,6 +314,7 @@ 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;
@ -326,6 +323,7 @@ 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;
@ -345,13 +343,12 @@ 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;
@ -381,14 +378,15 @@ 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]);
@ -423,6 +421,7 @@ 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;
@ -431,6 +430,7 @@ 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,8 +453,11 @@ 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
}
}
@ -466,6 +469,11 @@ 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);
}

View File

@ -0,0 +1,28 @@
#include <drivers/device_manager.h>
#include <drivers/builtin/fs/vfs.h>
device_manager_T g_device_manager;
void device_manager_init() {
}
void device_remove(device_T *device) {
}
device_T * device_find(device_capabilities_T capabilities, uint32_t index, uint32_t *out_count) {
}

View File

@ -1,285 +0,0 @@
// 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

@ -0,0 +1,140 @@
#include <drivers/driver_manager.h>
#include <drivers/builtin/json.h>
#include <utils/file.h>
#include <utils/memory.h>
#include <utils/logger.h>
driver_manager_T g_driver_manager;
void driver_manager_init()
{
log(LOG_INFO, "Starting Driver Manager!");
driver_manager_T manager;
manager.max_drivers = 1024;
manager.num_drivers = 0;
manager.drivers = memory_allocate(sizeof(driver_T) * manager.max_drivers);
g_driver_manager = manager;
}
void driver_manager_load_single_driver(char *driver_config_path)
{ // TODO
uint64_t len_file = file_get_length(driver_config_path);
void *content = memory_allocate(len_file+1);
file_read_into_buffer(driver_config_path, content, 0, len_file);
((uint8_t *) content)[len_file] = 0x00; // End it with a NULL-terminator
json_T *config_json = json_from_string(content);
// config_json->root_node->
}
void driver_manager_load_drivers(char *main_config_path)
{
}
driver_T * driver_manager_find_free_driver_slot()
{
driver_T *drivers = g_driver_manager.drivers;
uint32_t index = 0;
while(index < g_driver_manager.max_drivers)
{
if(drivers[index].category == DRIVER_UNKNOWN) return &drivers[index];
++index;
}
return NULL; // TODO: Resize array
}
uint32_t driver_manager_find_unused_driver_id()
{
driver_T *drivers = g_driver_manager.drivers;
uint32_t index = 0;
uint32_t id = 0;
while(id < 131072)
{
while(index < g_driver_manager.max_drivers)
{
if(drivers[index].id == id) break;
++index;
}
++id;
}
return id;
}
bool driver_is_configuration_valid(driver_configuration_T *configuration)
{
if(configuration->max_command_buffers == 0) return false;
if(configuration->max_command_buffers > 32) return false;
return true;
}
uint32_t driver_manager_register_driver(driver_configuration_T *configuration)
{
if(!driver_is_configuration_valid(configuration)) return 0; // TODO: Log
driver_T *driver = driver_manager_find_free_driver_slot();
driver->category = DRIVER_RESERVED;
driver->max_command_buffers = configuration->max_command_buffers;
driver->command_buffers = memory_allocate(sizeof(driver_T) * driver->max_command_buffers);
driver->id = driver_manager_find_unused_driver_id();
driver->category = configuration->category; // Activate the entry
return driver->id;
}
driver_T * driver_manager_resolve_driver_id(uint32_t id)
{
driver_T *drivers = g_driver_manager.drivers;
uint32_t index = 0;
while(index < g_driver_manager.max_drivers)
{
if(drivers[index].id == id) return &drivers[index];
++index;
}
return NULL;
}
driver_command_buffer_T * driver_find_free_command_buffer_slot(driver_T *driver)
{
driver_command_buffer_T *buffers = driver->command_buffers;
uint32_t index = 0;
while(index < driver->max_command_buffers)
{
if(buffers[index].mapping_address == NULL) return &buffers[index];
++index;
}
return NULL;
}
void driver_add_command_buffer(driver_T *driver, driver_command_buffer_config_T *configuration)
{
driver_command_buffer_T *buffer = driver_find_free_command_buffer_slot(driver);
buffer->command_capacity = configuration->num_commands;
buffer->mapping_address = configuration->mapping_address;
}
void driver_flush_command_buffer(driver_T *driver, void *buffer)
{
}

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->symbol_table, rip);
symbol_T* symbol = symbol_resolve_from_rip(process->executable->symbols, process->executable->num_symbols, rip);
if (symbol == NULL) {
log(LOG_NONE, " 0x%x -> <failed to resolve symbol> (symbol NULL reference)", rip);

53
src/modules/loader.c Normal file
View File

@ -0,0 +1,53 @@
// 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) {
}

3
src/modules/module.c Normal file
View File

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

View File

@ -6,11 +6,12 @@
#include "utils/memory.h"
#include "proc/scheduler.h"
#include "drivers/builtin/fs/vfs.h"
#include "drivers/driver.h"
#include <drivers/driver_manager.h>
#include "mm/page_frame.h"
#include "mm/region.h"
void syscall_handle_nx_fs_open(cpu_state_T* state) {
void syscall_handle_nx_fopen(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
@ -24,7 +25,7 @@ void syscall_handle_nx_fs_open(cpu_state_T* state) {
*fd_ptr = file_descriptor_request(scheduler_get_current_process()->fd_array, node);
}
void syscall_handle_nx_fs_close(cpu_state_T* state) {
void syscall_handle_nx_fclose(cpu_state_T* state) {
file_descriptor_t fd = (file_descriptor_t)state->rdi; // arg1
file_descriptor_free(scheduler_get_current_process()->fd_array, fd);
@ -32,7 +33,7 @@ void syscall_handle_nx_fs_close(cpu_state_T* state) {
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_fs_read(cpu_state_T* state) {
void syscall_handle_nx_fread(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
@ -64,7 +65,7 @@ void syscall_handle_nx_fs_read(cpu_state_T* state) {
state->rax = read_bytes;
}
void syscall_handle_nx_fs_write(cpu_state_T* state) {
void syscall_handle_nx_fwrite(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
@ -104,7 +105,7 @@ void syscall_handle_nx_fs_write(cpu_state_T* state) {
state->rax = written_bytes;
}
void syscall_handle_nx_fs_delete(cpu_state_T* state) {
void syscall_handle_nx_fdelete(cpu_state_T* state) {
string_t path = (string_t)state->rdi; // arg1
string_t len = (string_t)state->rsi; // arg2
@ -119,7 +120,7 @@ void syscall_handle_nx_fs_delete(cpu_state_T* state) {
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_fs_list(cpu_state_T* state) {
void syscall_handle_nx_flist(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
@ -154,7 +155,7 @@ void syscall_handle_nx_fs_list(cpu_state_T* state) {
}
void syscall_handle_nx_mem_alloc(cpu_state_T* state) {
void syscall_handle_nx_mmap(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
@ -188,12 +189,14 @@ void syscall_handle_nx_mem_alloc(cpu_state_T* state) {
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_mem_free(cpu_state_T* state) {
void* addr = (void*)state->rdi; // arg1
void syscall_handle_nx_munmap(cpu_state_T* state) {
void *addr = (void *) state->rdi; // arg1
uint64_t n = state->rsi; // arg2
if ((uint64_t)&addr[n * PFRAME_SIZE] > MEM_REGION_KERNEL ||
(uint64_t)addr < MEM_REGION_PROCESS_USABLE) {
if(
((uint64_t) &addr[n * PFRAME_SIZE] > MEM_REGION_KERNEL) ||
((uint64_t) addr < MEM_REGION_PROCESS_USABLE)
) {
state->rax = STATUS_PERMISSION_DENIED;
return;
}
@ -208,14 +211,13 @@ void syscall_handle_nx_mem_free(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
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);
vfs_node_T* node = vfs_resolve_path(&g_root_fs, path);
if (node == NULL || node->type != VFS_NODE_FILE) {
state->rax = STATUS_RESOURCE_NOT_AVAILABLE;
return;
@ -231,19 +233,23 @@ void syscall_handle_nx_proc_create(cpu_state_T* state) {
return;
}
*pid_ptr = process_spawn(parent->id, conf->name, exec, buffer);
if (*pid_ptr == PROCESS_NONE) {
if (name == NULL) {
name = path;
}
*pid = process_spawn(scheduler_get_current_process()->id, name, exec, buffer);
if (*pid == PROCESS_NONE) {
state->rax = STATUS_GENERIC_ERROR;
return;
}
void* entry = (void*)(symbol_resolve_from_name(&exec->symbol_table, "_start")->address + MEM_REGION_PROCESS_EXEC);
void* entry = (void*)(symbol_resolve_from_name(exec->symbols, exec->num_symbols, "_start")->address + MEM_REGION_PROCESS_EXEC);
thread_spawn(*pid_ptr, entry);
thread_spawn(*pid, entry);
state->rax = STATUS_SUCCESS;
}
void syscall_handle_nx_proc_signal_send(cpu_state_T* state) {
void syscall_handle_nx_psignal(cpu_state_T* state) {
pid_t pid = (pid_t)state->rdi; // arg1
uint64_t signal = state->rsi; // arg2
@ -263,41 +269,121 @@ void syscall_handle_nx_proc_signal_send(cpu_state_T* state) {
}
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)");
uint64_t ceil_to(uint64_t base, uint64_t factor)
{
return base + (base % factor);
}
uint64_t floor_to(uint64_t base, uint64_t factor)
{
return (base + (base % factor)) - factor;
}
bool are_process_pages_unused(process_T *process, void *address, uint64_t num_pages)
{
page_map_T *process_page_map = process->page_map;
uint64_t page_index = 0;
while(page_index < num_pages)
{
if(page_map_check_memory(
process_page_map,
&address[page_index * PFRAME_SIZE])
) {
return false;
}
++page_index;
}
return true;
}
bool are_process_memory_bytes_unused(process_T *process, void *address, uint64_t num_bytes)
{
uint64_t first_full_page_address = floor_to(address, PFRAME_SIZE);
uint64_t num_pages = ceil_to(address+num_bytes, PFRAME_SIZE) / PFRAME_SIZE;
return are_process_pages_unused(process, first_full_page_address, num_pages);
}
void mark_memory_region_for_process(process_T *process,
void *address, uint64_t num_pages,
bool read_write, bool executable)
{
uint64_t map_flags = 0;
if(read_write) map_flags |= PM_FLAG_READ_WRITE;
if(!executable) map_flags |= PM_FLAG_NO_EXECUTE;
page_map_T *process_page_map = process->page_map;
uint64_t page_index = 0;
while(page_index < num_pages)
{
page_map_map_memory(process_page_map, &address[page_index * PFRAME_SIZE], pframe_request(), map_flags);
++page_index;
}
}
// map_memory_for_user: Returns FALSE if the action failed and TRUE otherwise.
bool map_memory_for_process(process_T *process,void *address, uint64_t num_pages, bool read_write, bool executable)
{
if(address == NULL)
{
return false;
}
if(!are_process_pages_unused(process, address, num_pages))
{
return false;
}
mark_memory_region_for_process(process, address, num_pages, read_write, executable);
return true;
}
void syscall_handle_nx_drv_register_driver(cpu_state_T* state)
{
void *configuration = state->rdi;
process_T *caller = scheduler_get_current_process();
// Check permissions
if(are_process_memory_bytes_unused(caller, configuration, 256))
{
state->rax = STATUS_RESOURCE_NOT_AVAILABLE;
return;
}
caller->driver = driver_manager_register_driver(configuration);
}
uint8_t* buffer = memory_allocate(node->size);
vfs_file_read(node, 0, node->size, buffer);
void syscall_handle_nx_drv_create_command_buffer(cpu_state_T* state)
{
void *address = (void *) state->rdi;
uint64_t wanted_commands = state->rsi;
uint64_t num_pages = ceil_to(wanted_commands * DRIVER_COMMAND_SIZE, PFRAME_SIZE) / PFRAME_SIZE;
process_T *caller = scheduler_get_current_process();
driver_T *driver = driver_manager_resolve_driver_id(caller->driver);
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;
if(map_memory_for_process(caller, address, num_pages, true, false))
{
driver_command_buffer_config_T buffer_config;
buffer_config.num_commands = num_pages;
buffer_config.mapping_address = address;
driver_add_command_buffer(driver, &buffer_config);
state->rax = address;
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;
}
// TODO: Select an address for the process and re-run map_memory_for_process.
void (*drv_init)() = drv->base + symbol_resolve_from_name(&exec->symbol_table, "_init")->address;;
drv_init();
state->rax = STATUS_RESOURCE_NOT_AVAILABLE;
}
*id_ptr = drv->id;
state->rax = STATUS_SUCCESS;
void syscall_handle_nx_drv_flush_command_buffer(cpu_state_T* state)
{
void *command_buffer = state->rsi;
process_T *caller = scheduler_get_current_process();
driver_T *driver = driver_manager_resolve_driver_id(caller->driver);
driver_flush_command_buffer(driver, command_buffer);
}
cpu_state_T* syscall_handle(cpu_state_T* state) {
@ -309,28 +395,28 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
case SYSCALLS_FILES: {
switch (state->rax) {
case SYSCALL_NX_FS_OPEN: {
syscall_handle_nx_fs_open(state);
case SYSCALL_FILES_OPEN: {
syscall_handle_nx_fopen(state);
break;
}
case SYSCALL_NX_FS_CLOSE: {
syscall_handle_nx_fs_close(state);
case SYSCALL_FILES_CLOSE: {
syscall_handle_nx_fclose(state);
break;
}
case SYSCALL_NX_FS_READ: {
syscall_handle_nx_fs_read(state);
case SYSCALL_FILES_READ: {
syscall_handle_nx_fread(state);
break;
}
case SYSCALL_NX_FS_WRITE: {
syscall_handle_nx_fs_write(state);
case SYSCALL_FILES_WRITE: {
syscall_handle_nx_fwrite(state);
break;
}
case SYSCALL_NX_FS_DELETE: {
syscall_handle_nx_fs_delete(state);
case SYSCALL_FILES_DELETE: {
syscall_handle_nx_fdelete(state);
break;
}
case SYSCALL_NX_FS_LIST: {
syscall_handle_nx_fs_list(state);
case SYSCALL_FILES_LIST: {
syscall_handle_nx_flist(state);
break;
}
}
@ -339,39 +425,53 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
case SYSCALLS_MEMORY: {
switch (state->rax) {
case SYSCALL_NX_MEM_ALLOC: {
syscall_handle_nx_mem_alloc(state);
case SYSCALL_MEMORY_MAP: {
syscall_handle_nx_mmap(state);
break;
}
case SYSCALL_NX_MEM_FREE: {
syscall_handle_nx_mem_free(state);
case SYSCALL_MEMORY_UNMAP: {
syscall_handle_nx_munmap(state);
break;
}
}
break;
}
case SYSCALLS_PROC: {
case SYSCALLS_PROCESS: {
switch (state->rax) {
case SYSCALL_NX_PROC_CREATE: {
syscall_handle_nx_proc_create(state);
case SYSCALL_PROCESS_CREATE: {
syscall_handle_nx_pcreate(state);
break;
}
case SYSCALL_NX_PROC_SIGNAL_SEND: {
syscall_handle_nx_proc_signal_send(state);
case SYSCALL_PROCESS_SIGNAL: {
syscall_handle_nx_psignal(state);
break;
}
}
break;
}
case SYSCALLS_DRIVERS: {
switch (state->rax) {
case SYSCALL_NX_DRV_REGISTER: {
syscall_handle_nx_drv_register(state);
case SYSCALLS_DRIVER: {
switch(state->rax) {
case SYSCALL_DRIVER_REGISTER: {
syscall_handle_nx_drv_register_driver(state);
} break;
case SYSCALL_DRIVER_CREATE_COMMAND_BUFFER: {
syscall_handle_nx_drv_create_command_buffer(state);
} break;
case SYSCALL_DRIVER_FLUSH_COMMAND_BUFFER: {
syscall_handle_nx_drv_flush_command_buffer(state);
} break;
}
}
case SYSCALLS_RUNTIME_LINKER: {
break;
}
}
case SYSCALLS_COMPATABILITY: {
break;
}
@ -387,12 +487,12 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
}
switch (state->rax) {
case SYSCALL_NX_KERNEL_SCHEDULER_START: {
case SYSCALL_KERNEL_SCHEDULER_START: {
return_state = scheduler_start(state);
break;
}
case SYSCALL_NX_KERNEL_PANIC: {
case SYSCALL_KERNEL_PANIC: {
panic(state, (string_t)arg1);
break;
}

View File

@ -1,7 +0,0 @@
; 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_NX_KERNEL_SCHEDULER_START, 0, 0, 0, 0);
syscall_perform(SYSCALL_KERNEL_SCHEDULER_START, 0, 0, 0, 0);
}
cpu_state_T* scheduler_start(cpu_state_T* state) {

20
src/utils/file.c Normal file
View File

@ -0,0 +1,20 @@
#include <utils/file.h>
#include <drivers/builtin/fs/vfs.h>
uint64_t file_get_length(char *path)
{
vfs_node_T *file = vfs_resolve_path(&g_root_fs, path);
if(file == NULL) return 0;
return file->size;
}
uint64_t file_read_into_buffer(char *path, void *buffer, uint64_t offset, uint64_t num_bytes)
{
vfs_node_T *file = vfs_resolve_path(&g_root_fs, path);
if(file == NULL) return 0;
uint64_t actual_read_bytes = vfs_file_read(file, offset, num_bytes, buffer);
vfs_node_destruct(file);
return actual_read_bytes;
}

View File

@ -1,87 +0,0 @@
// 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->symbol_table, state->rip);
symbol_T* symbol = symbol_resolve_from_rip(process->executable->symbols, process->executable->num_symbols,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,13 +463,3 @@ 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,47 +1,25 @@
// This file is part of noxos and licensed under the MIT open source license
#include "utils/symbol.h"
#include "utils/memory.h"
#include "utils/logger.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];
}
}
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;
return NULL;
}
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_resolve_from_rip(symbol_T* symbols, uint64_t num_symbols, uint64_t rip) {
symbol_T* symbol = NULL;
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))
for (uint64_t i = 0; i < num_symbols; i++) {
if (symbols[i].address <= rip &&
(symbol == NULL || symbols[i].address > symbol->address))
{
symbol = &symbol_table->symbols[i];
symbol = &symbols[i];
}
}

5
update.bash Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
git submodule update libraries/libnoxos/
git submodule update initrd/sources/userland/