Compare commits
5 Commits
master
...
modulariza
Author | SHA1 | Date |
---|---|---|
Eric-Paul Ickhorn | 4f5da10be1 | |
Eric-Paul Ickhorn | 09ed173eef | |
Eric-Paul Ickhorn | 3a90af4704 | |
Eric-Paul Ickhorn | 1ad60a7351 | |
Eric-Paul Ickhorn | 2f9ca93cb1 |
|
@ -1,5 +1,4 @@
|
|||
build
|
||||
cmake-build-debug
|
||||
noxos.log
|
||||
ramdisk/shell.elf
|
||||
*.nxkm
|
||||
ramdisk/shell.elf
|
|
@ -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
|
64
README.md
64
README.md
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
@ -25,14 +40,12 @@ check_toolchain() {
|
|||
echo " |--> found xorriso"
|
||||
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
|
||||
;;
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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,16 +82,18 @@ typedef struct {
|
|||
json_node_T* root_node;
|
||||
} json_T;
|
||||
|
||||
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);
|
||||
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);
|
||||
void json_tokenize (json_T* json, string_t str);
|
||||
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_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);
|
||||
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);
|
||||
void json_tokenize (json_T* json, string_t str);
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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_DRIVER_REGISTER = 0x0301,
|
||||
SYSCALL_DRIVER_CREATE_COMMAND_BUFFER = 0x0302,
|
||||
SYSCALL_DRIVER_FLUSH_COMMAND_BUFFER = 0x0303,
|
||||
|
||||
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_NX_DRV_REGISTER = 0x0301,
|
||||
SYSCALL_COMPATABILITY_ABI_TYPE = 0x0501,
|
||||
SYSCALL_COMPATABILITY_ABI_VERSION = 0x0502,
|
||||
SYSCALL_COMPATABILITY_ACTION = 0x0503,
|
||||
|
||||
SYSCALL_NX_KERNEL_SCHEDULER_START = 0xFF00,
|
||||
SYSCALL_NX_KERNEL_PANIC = 0xFF01
|
||||
SYSCALL_KERNEL_SCHEDULER_START = 0xFF00,
|
||||
SYSCALL_KERNEL_PANIC = 0xFF01
|
||||
} syscall_E;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -29,26 +29,12 @@ typedef enum {
|
|||
} process_blockers_E;
|
||||
|
||||
typedef enum {
|
||||
PROCESS_SIGNAL_START, // SIGSTART
|
||||
PROCESS_SIGNAL_PAUSE, // SIGPAUSE
|
||||
PROCESS_SIGNAL_KILL, // SIGKILL
|
||||
PROCESS_SIGNAL_PAGEFAULT, // SIGPAGEFAULT
|
||||
PROCESS_SIGNAL_MATHFAULT, // SIGMATHFAULT
|
||||
PROCESS_SIGNAL_START, // SIGSTART
|
||||
PROCESS_SIGNAL_PAUSE, // SIGPAUSE
|
||||
PROCESS_SIGNAL_KILL, // SIGKILL
|
||||
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];
|
||||
|
@ -59,6 +45,10 @@ struct process_T {
|
|||
page_map_T* page_map;
|
||||
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;
|
||||
|
@ -66,12 +56,12 @@ struct process_T {
|
|||
|
||||
bitmap_T waiting;
|
||||
|
||||
uint32_t num_threads;
|
||||
uint32_t num_threads;
|
||||
void* threads;
|
||||
bitmap_T thread_ids;
|
||||
|
||||
process_T* parent;
|
||||
process_T* childs;
|
||||
process_T* childs; // TODO: Must be 'children'
|
||||
process_T* prev;
|
||||
process_T* next;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
build/
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd sources/userland/
|
||||
# bash build.bash
|
||||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 9999b292ac52afd0ff629b566b372aeb5db978cf
|
|
@ -0,0 +1 @@
|
|||
Subproject commit d5ed088f54751dd1874aaf2c2678cc5ab292434a
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"BOOT": [
|
||||
"/initrd/drv/test.nxkm"
|
||||
]
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"PS2_ACPI_VALIDATION": true,
|
||||
"LOG_GRAPHICAL": true
|
||||
}
|
|
@ -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.
|
|
@ -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
63
shell.c
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
|
@ -34,57 +35,48 @@ void kernel_init(boot_info_T* boot_info) {
|
|||
idt_init();
|
||||
pic_init();
|
||||
pit_set_divisor(PIT_DIVISOR);
|
||||
|
||||
|
||||
paging_init();
|
||||
CORE_INTERRUPTS_ENABLE
|
||||
|
||||
|
||||
memory_allocator_init((void*)MEM_REGION_KERNEL_HEAP);
|
||||
|
||||
|
||||
graphics_renderer_init(boot_info);
|
||||
|
||||
|
||||
vfs_init(boot_info);
|
||||
|
||||
|
||||
sysconfig_init();
|
||||
|
||||
|
||||
if (g_sysconfig->log_graphical) graphical_log_init();
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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,10 +28,8 @@ 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));
|
||||
}
|
||||
for (uint64_t i = 0; i < num_pages; i++) {
|
||||
page_map_unmap_memory(g_kernel_page_map, virtual_address + (PFRAME_SIZE * i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = §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,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"
|
||||
};
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#include <modules/module.h>
|
|
@ -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,15 +25,15 @@ 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);
|
||||
|
||||
|
||||
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,9 +105,9 @@ 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
|
||||
string_t len = (string_t)state->rsi; // arg2
|
||||
|
||||
vfs_node_T* node = vfs_resolve_path(&g_root_fs, path);
|
||||
if (node == NULL) {
|
||||
|
@ -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
|
||||
uint64_t n = state->rsi; // arg2
|
||||
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)");
|
||||
state->rax = STATUS_RESOURCE_NOT_AVAILABLE;
|
||||
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);
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// TODO: Select an address for the process and re-run map_memory_for_process.
|
||||
|
||||
state->rax = STATUS_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -407,4 +507,4 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
|
|||
}
|
||||
|
||||
return return_state;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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,14 +462,4 @@ 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,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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
git submodule update libraries/libnoxos/
|
||||
git submodule update initrd/sources/userland/
|
||||
|
Loading…
Reference in New Issue