Basic userspace driver infrastructure
This commit is contained in:
parent
6ddd4587cf
commit
2f9ca93cb1
|
@ -82,16 +82,18 @@ typedef struct {
|
||||||
json_node_T* root_node;
|
json_node_T* root_node;
|
||||||
} json_T;
|
} json_T;
|
||||||
|
|
||||||
json_T* json_from_string (string_t str);
|
json_T * json_from_string (string_t str);
|
||||||
void json_destruct (json_T* json);
|
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_destruct (json_node_T* node);
|
||||||
void json_node_dump (json_node_T* node, uint32_t indent);
|
void json_node_dump (json_node_T* node, uint32_t indent);
|
||||||
string_t json_node_type_to_string (json_node_type_E type);
|
string_t json_node_type_to_string (json_node_type_E type);
|
||||||
void json_tokenize (json_T* json, string_t str);
|
void json_tokenize (json_T* json, string_t str);
|
||||||
bool json_parse (json_T* json);
|
bool json_parse (json_T* json);
|
||||||
bool json_parse_assignment (json_T* json, uint32_t* token_id, json_node_T* node);
|
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_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);
|
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
|
#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"
|
#include "utils/status.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SYSCALLS_FILES = 0x01,
|
SYSCALLS_FILES = 0x00,
|
||||||
SYSCALLS_MEMORY = 0x02,
|
SYSCALLS_MEMORY = 0x01,
|
||||||
SYSCALLS_PROC = 0x03,
|
SYSCALLS_PROCESS = 0x02,
|
||||||
|
SYSCALLS_DRIVER = 0x03,
|
||||||
SYSCALLS_RUNTIME_LINKER = 0x04,
|
SYSCALLS_RUNTIME_LINKER = 0x04,
|
||||||
SYSCALLS_COMPATABILITY = 0x05,
|
SYSCALLS_COMPATABILITY = 0x05,
|
||||||
|
|
||||||
|
@ -17,40 +18,44 @@ typedef enum {
|
||||||
}syscall_group_E;
|
}syscall_group_E;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SYSCALL_FILES_OPEN = 0x0101,
|
SYSCALL_FILES_OPEN = 0x0001,
|
||||||
SYSCALL_FILES_CLOSE = 0x0102,
|
SYSCALL_FILES_CLOSE = 0x0002,
|
||||||
SYSCALL_FILES_READ = 0x0103,
|
SYSCALL_FILES_READ = 0x0003,
|
||||||
SYSCALL_FILES_WRITE = 0x0104,
|
SYSCALL_FILES_WRITE = 0x0004,
|
||||||
SYSCALL_FILES_DELETE = 0x0105,
|
SYSCALL_FILES_DELETE = 0x0005,
|
||||||
SYSCALL_FILES_LIST = 0x0106,
|
SYSCALL_FILES_LIST = 0x0006,
|
||||||
SYSCALL_FILES_INFO = 0x0107,
|
SYSCALL_FILES_INFO = 0x0007,
|
||||||
|
|
||||||
SYSCALL_MEMORY_MAP = 0x0201,
|
SYSCALL_MEMORY_MAP = 0x0101,
|
||||||
SYSCALL_MEMORY_UNMAP = 0x0202,
|
SYSCALL_MEMORY_UNMAP = 0x0102,
|
||||||
SYSCALL_MEMORY_LABEL = 0x0203,
|
SYSCALL_MEMORY_LABEL = 0x0103,
|
||||||
SYSCALL_MEMORY_RANGE = 0x0204,
|
SYSCALL_MEMORY_RANGE = 0x0104,
|
||||||
SYSCALL_MEMORY_ACCESS = 0x0205,
|
SYSCALL_MEMORY_ACCESS = 0x0105,
|
||||||
|
|
||||||
SYSCALL_PROCESS_CREATE = 0x0301,
|
SYSCALL_PROCESS_CREATE = 0x0201,
|
||||||
SYSCALL_PROCESS_ENV = 0x0302,
|
SYSCALL_PROCESS_ENV = 0x0202,
|
||||||
SYSCALL_PROCESS_SIGNAL = 0x0303,
|
SYSCALL_PROCESS_SIGNAL = 0x0203,
|
||||||
SYSCALL_PROCESS_THREAD_CREATE = 0x0304,
|
SYSCALL_PROCESS_THREAD_CREATE = 0x0204,
|
||||||
SYSCALL_PROCESS_THREAD_START = 0x0305,
|
SYSCALL_PROCESS_THREAD_START = 0x0205,
|
||||||
SYSCALL_PROCESS_THREAD_PAUSE = 0x0306,
|
SYSCALL_PROCESS_THREAD_PAUSE = 0x0206,
|
||||||
SYSCALL_PROCESS_THREAD_KILL = 0x0307,
|
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_RUNTIME_LINKER_OPEN = 0x0401,
|
SYSCALL_COMPATABILITY_ABI_TYPE = 0x0501,
|
||||||
SYSCALL_RUNTIME_LINKER_CLOSE = 0x0402,
|
SYSCALL_COMPATABILITY_ABI_VERSION = 0x0502,
|
||||||
SYSCALL_RUNTIME_LINKER_LOAD_SYMBOL = 0x0403,
|
SYSCALL_COMPATABILITY_ACTION = 0x0503,
|
||||||
SYSCALL_RUNTIME_LINKER_STATUS = 0x0404,
|
|
||||||
SYSCALL_RUNTIME_LINKER_STANDARD_MOD = 0x0405,
|
|
||||||
|
|
||||||
SYSCALL_COMPATABILITY_ABI_TYPE = 0x0501,
|
SYSCALL_KERNEL_SCHEDULER_START = 0xFF00,
|
||||||
SYSCALL_COMPATABILITY_ABI_VERSION = 0x0502,
|
SYSCALL_KERNEL_PANIC = 0xFF01
|
||||||
SYSCALL_COMPATABILITY_ACTION = 0x0503,
|
|
||||||
|
|
||||||
SYSCALL_KERNEL_SCHEDULER_START = 0xFF00,
|
|
||||||
SYSCALL_KERNEL_PANIC = 0xFF01
|
|
||||||
} syscall_E;
|
} syscall_E;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -45,6 +45,10 @@ struct process_T {
|
||||||
page_map_T* page_map;
|
page_map_T* page_map;
|
||||||
elf_executable_T* executable;
|
elf_executable_T* executable;
|
||||||
file_descriptor_array_T* fd_array;
|
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* stdout;
|
||||||
pipe_T stdin;
|
pipe_T stdin;
|
||||||
|
@ -52,12 +56,12 @@ struct process_T {
|
||||||
|
|
||||||
bitmap_T waiting;
|
bitmap_T waiting;
|
||||||
|
|
||||||
uint32_t num_threads;
|
uint32_t num_threads;
|
||||||
void* threads;
|
void* threads;
|
||||||
bitmap_T thread_ids;
|
bitmap_T thread_ids;
|
||||||
|
|
||||||
process_T* parent;
|
process_T* parent;
|
||||||
process_T* childs;
|
process_T* childs; // TODO: Must be 'children'
|
||||||
process_T* prev;
|
process_T* prev;
|
||||||
process_T* next;
|
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,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"PS2_ACPI_VALIDATION": true,
|
"PS2_ACPI_VALIDATION": true,
|
||||||
"LOG_GRAPHICAL": false,
|
"LOG_GRAPHICAL": true,
|
||||||
|
|
||||||
"modules": {
|
"modules": {
|
||||||
"FAT32": "/initrd/modules/fat32.nxkm"
|
"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 \
|
-drive file=build/noxos.iso \
|
||||||
-chardev stdio,id=log,logfile=noxos.log -serial chardev:log"
|
-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() {
|
emulate_bios() {
|
||||||
echo "<=====| Emulating |=====>"
|
echo "<=====| Emulating |=====>"
|
||||||
qemu-system-x86_64 $EMUFLAGS
|
qemu-system-x86_64 $EMUFLAGS
|
||||||
|
@ -12,13 +17,13 @@ emulate_bios() {
|
||||||
|
|
||||||
emulate_uefi() {
|
emulate_uefi() {
|
||||||
echo "<=====| Emulating in UEFI mode |=====>"
|
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
|
# qemu will wait for gdb to connect, before booting
|
||||||
emulate_debug() {
|
emulate_debug() {
|
||||||
echo "<=====| Emulating in debug mode |=====>"
|
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
|
case $1 in
|
||||||
|
|
|
@ -35,39 +35,41 @@ void kernel_init(boot_info_T* boot_info) {
|
||||||
idt_init();
|
idt_init();
|
||||||
pic_init();
|
pic_init();
|
||||||
pit_set_divisor(PIT_DIVISOR);
|
pit_set_divisor(PIT_DIVISOR);
|
||||||
|
|
||||||
paging_init();
|
paging_init();
|
||||||
CORE_INTERRUPTS_ENABLE
|
CORE_INTERRUPTS_ENABLE
|
||||||
|
|
||||||
memory_allocator_init((void*)MEM_REGION_KERNEL_HEAP);
|
memory_allocator_init((void*)MEM_REGION_KERNEL_HEAP);
|
||||||
|
|
||||||
graphics_renderer_init(boot_info);
|
graphics_renderer_init(boot_info);
|
||||||
|
|
||||||
vfs_init(boot_info);
|
vfs_init(boot_info);
|
||||||
|
|
||||||
sysconfig_init();
|
sysconfig_init();
|
||||||
|
|
||||||
if (g_sysconfig->log_graphical) graphical_log_init();
|
if (g_sysconfig->log_graphical) graphical_log_init();
|
||||||
|
|
||||||
scheduler_init(boot_info);
|
scheduler_init(boot_info);
|
||||||
|
|
||||||
acpi_init(boot_info);
|
acpi_init(boot_info);
|
||||||
|
|
||||||
module_manager_init();
|
module_manager_init();
|
||||||
|
|
||||||
drive_manager_init();
|
drive_manager_init();
|
||||||
|
|
||||||
pci_init();
|
pci_init();
|
||||||
|
|
||||||
|
driver_manager_init();
|
||||||
|
|
||||||
tty_init();
|
tty_init();
|
||||||
|
|
||||||
ps2_controller_init();
|
ps2_controller_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kmain(boot_info_T boot_info) {
|
void kmain(boot_info_T boot_info) {
|
||||||
|
|
||||||
limine_terminal_print(&boot_info, "Booting NoxOS...\n");
|
limine_terminal_print(&boot_info, "Booting NOXOS...\n");
|
||||||
log(LOG_DEBUG, "Booting NoxOS");
|
log(LOG_DEBUG, "Booting NOXOS");
|
||||||
|
|
||||||
kernel_init(&boot_info);
|
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 "utils/memory.h"
|
||||||
#include "proc/scheduler.h"
|
#include "proc/scheduler.h"
|
||||||
#include "drivers/builtin/fs/vfs.h"
|
#include "drivers/builtin/fs/vfs.h"
|
||||||
|
#include <drivers/driver_manager.h>
|
||||||
|
|
||||||
#include "mm/page_frame.h"
|
#include "mm/page_frame.h"
|
||||||
#include "mm/region.h"
|
#include "mm/region.h"
|
||||||
|
|
||||||
|
@ -25,9 +27,9 @@ void syscall_handle_nx_fopen(cpu_state_T* state) {
|
||||||
|
|
||||||
void syscall_handle_nx_fclose(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_t fd = (file_descriptor_t)state->rdi; // arg1
|
||||||
|
|
||||||
file_descriptor_free(scheduler_get_current_process()->fd_array, fd);
|
file_descriptor_free(scheduler_get_current_process()->fd_array, fd);
|
||||||
|
|
||||||
state->rax = STATUS_SUCCESS;
|
state->rax = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,11 +190,13 @@ void syscall_handle_nx_mmap(cpu_state_T* state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void syscall_handle_nx_munmap(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
|
uint64_t n = state->rsi; // arg2
|
||||||
|
|
||||||
if ((uint64_t)&addr[n * PFRAME_SIZE] > MEM_REGION_KERNEL ||
|
if(
|
||||||
(uint64_t)addr < MEM_REGION_PROCESS_USABLE) {
|
((uint64_t) &addr[n * PFRAME_SIZE] > MEM_REGION_KERNEL) ||
|
||||||
|
((uint64_t) addr < MEM_REGION_PROCESS_USABLE)
|
||||||
|
) {
|
||||||
state->rax = STATUS_PERMISSION_DENIED;
|
state->rax = STATUS_PERMISSION_DENIED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -264,6 +268,124 @@ void syscall_handle_nx_psignal(cpu_state_T* state) {
|
||||||
state->rax = STATUS_SUCCESS;
|
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* syscall_handle(cpu_state_T* state) {
|
||||||
cpu_state_T* return_state = state;
|
cpu_state_T* return_state = state;
|
||||||
syscall_group_E group_id = (state->rax & 0xFF00) >> 8;
|
syscall_group_E group_id = (state->rax & 0xFF00) >> 8;
|
||||||
|
@ -315,7 +437,7 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SYSCALLS_PROC: {
|
case SYSCALLS_PROCESS: {
|
||||||
switch (state->rax) {
|
switch (state->rax) {
|
||||||
case SYSCALL_PROCESS_CREATE: {
|
case SYSCALL_PROCESS_CREATE: {
|
||||||
syscall_handle_nx_pcreate(state);
|
syscall_handle_nx_pcreate(state);
|
||||||
|
@ -328,7 +450,23 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
|
||||||
}
|
}
|
||||||
break;
|
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: {
|
case SYSCALLS_RUNTIME_LINKER: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -369,4 +507,4 @@ cpu_state_T* syscall_handle(cpu_state_T* state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return return_state;
|
return return_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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue