Basic userspace driver infrastructure
This commit is contained in:
parent
6ddd4587cf
commit
2f9ca93cb1
|
@ -82,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);
|
||||
|
@ -93,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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -7,9 +7,10 @@
|
|||
#include "utils/status.h"
|
||||
|
||||
typedef enum {
|
||||
SYSCALLS_FILES = 0x01,
|
||||
SYSCALLS_MEMORY = 0x02,
|
||||
SYSCALLS_PROC = 0x03,
|
||||
SYSCALLS_FILES = 0x00,
|
||||
SYSCALLS_MEMORY = 0x01,
|
||||
SYSCALLS_PROCESS = 0x02,
|
||||
SYSCALLS_DRIVER = 0x03,
|
||||
SYSCALLS_RUNTIME_LINKER = 0x04,
|
||||
SYSCALLS_COMPATABILITY = 0x05,
|
||||
|
||||
|
@ -17,33 +18,37 @@ typedef enum {
|
|||
}syscall_group_E;
|
||||
|
||||
typedef enum {
|
||||
SYSCALL_FILES_OPEN = 0x0101,
|
||||
SYSCALL_FILES_CLOSE = 0x0102,
|
||||
SYSCALL_FILES_READ = 0x0103,
|
||||
SYSCALL_FILES_WRITE = 0x0104,
|
||||
SYSCALL_FILES_DELETE = 0x0105,
|
||||
SYSCALL_FILES_LIST = 0x0106,
|
||||
SYSCALL_FILES_INFO = 0x0107,
|
||||
SYSCALL_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_MEMORY_MAP = 0x0201,
|
||||
SYSCALL_MEMORY_UNMAP = 0x0202,
|
||||
SYSCALL_MEMORY_LABEL = 0x0203,
|
||||
SYSCALL_MEMORY_RANGE = 0x0204,
|
||||
SYSCALL_MEMORY_ACCESS = 0x0205,
|
||||
SYSCALL_MEMORY_MAP = 0x0101,
|
||||
SYSCALL_MEMORY_UNMAP = 0x0102,
|
||||
SYSCALL_MEMORY_LABEL = 0x0103,
|
||||
SYSCALL_MEMORY_RANGE = 0x0104,
|
||||
SYSCALL_MEMORY_ACCESS = 0x0105,
|
||||
|
||||
SYSCALL_PROCESS_CREATE = 0x0301,
|
||||
SYSCALL_PROCESS_ENV = 0x0302,
|
||||
SYSCALL_PROCESS_SIGNAL = 0x0303,
|
||||
SYSCALL_PROCESS_THREAD_CREATE = 0x0304,
|
||||
SYSCALL_PROCESS_THREAD_START = 0x0305,
|
||||
SYSCALL_PROCESS_THREAD_PAUSE = 0x0306,
|
||||
SYSCALL_PROCESS_THREAD_KILL = 0x0307,
|
||||
SYSCALL_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_RUNTIME_LINKER_OPEN = 0x0401,
|
||||
SYSCALL_RUNTIME_LINKER_CLOSE = 0x0402,
|
||||
SYSCALL_RUNTIME_LINKER_LOAD_SYMBOL = 0x0403,
|
||||
SYSCALL_RUNTIME_LINKER_STATUS = 0x0404,
|
||||
SYSCALL_RUNTIME_LINKER_STANDARD_MOD = 0x0405,
|
||||
SYSCALL_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_COMPATABILITY_ABI_TYPE = 0x0501,
|
||||
SYSCALL_COMPATABILITY_ABI_VERSION = 0x0502,
|
||||
|
|
|
@ -46,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;
|
||||
|
@ -57,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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"drivers":
|
||||
[
|
||||
{
|
||||
"name": "nxFAT32",
|
||||
"author": "NOXOS Authors",
|
||||
"category": "filesystem",
|
||||
"type": "fat32",
|
||||
|
||||
"definition-path": "/modules/fat32/definition.json",
|
||||
"binary-path": "/modules/fat32/driver.so"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"PS2_ACPI_VALIDATION": true,
|
||||
"LOG_GRAPHICAL": false,
|
||||
"LOG_GRAPHICAL": true,
|
||||
|
||||
"modules": {
|
||||
"FAT32": "/initrd/modules/fat32.nxkm"
|
||||
|
|
9
run.sh
9
run.sh
|
@ -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
|
||||
|
|
|
@ -59,6 +59,8 @@ void kernel_init(boot_info_T* boot_info) {
|
|||
|
||||
pci_init();
|
||||
|
||||
driver_manager_init();
|
||||
|
||||
tty_init();
|
||||
|
||||
ps2_controller_init();
|
||||
|
@ -66,8 +68,8 @@ 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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@
|
|||
#include "utils/memory.h"
|
||||
#include "proc/scheduler.h"
|
||||
#include "drivers/builtin/fs/vfs.h"
|
||||
#include <drivers/driver_manager.h>
|
||||
|
||||
#include "mm/page_frame.h"
|
||||
#include "mm/region.h"
|
||||
|
||||
|
@ -188,11 +190,13 @@ void syscall_handle_nx_mmap(cpu_state_T* state) {
|
|||
}
|
||||
|
||||
void syscall_handle_nx_munmap(cpu_state_T* state) {
|
||||
void* addr = (void*)state->rdi; // arg1
|
||||
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;
|
||||
}
|
||||
|
@ -264,6 +268,124 @@ void syscall_handle_nx_psignal(cpu_state_T* state) {
|
|||
state->rax = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
cpu_state_T* return_state = state;
|
||||
syscall_group_E group_id = (state->rax & 0xFF00) >> 8;
|
||||
|
@ -315,7 +437,7 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
|
|||
break;
|
||||
}
|
||||
|
||||
case SYSCALLS_PROC: {
|
||||
case SYSCALLS_PROCESS: {
|
||||
switch (state->rax) {
|
||||
case SYSCALL_PROCESS_CREATE: {
|
||||
syscall_handle_nx_pcreate(state);
|
||||
|
@ -329,6 +451,22 @@ cpu_state_T* syscall_handle(cpu_state_T* 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue