diff --git a/inc/drivers/builtin/elf/relocation.h b/inc/drivers/builtin/elf/relocation.h index 4f6190c..7bbe3ed 100644 --- a/inc/drivers/builtin/elf/relocation.h +++ b/inc/drivers/builtin/elf/relocation.h @@ -31,6 +31,7 @@ typedef struct { int64_t addend; } elf_relocation_a_T; -void elf_relocate(elf_executable_T* executable, uint8_t* buffer, void* address); +//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 diff --git a/inc/drivers/builtin/elf/section.h b/inc/drivers/builtin/elf/section.h index 14af740..21d1e61 100644 --- a/inc/drivers/builtin/elf/section.h +++ b/inc/drivers/builtin/elf/section.h @@ -16,6 +16,9 @@ typedef enum { ELF_SECTION_DYNAMIC, ELF_SECTION_NOTE, ELF_SECTION_NOBITS, + ELF_SECTION_REL, + ELF_SECTION_SHLIB, + ELF_SECTION_DYNAMIC_SYMBOL_TABLE, ELF_SECTION_ENUM_END } elf_section_type_E; diff --git a/src/boot/kmain.c b/src/boot/kmain.c index 7b286bc..91559d6 100644 --- a/src/boot/kmain.c +++ b/src/boot/kmain.c @@ -88,9 +88,14 @@ void kmain(boot_info_T boot_info) { // // syscall_perform(SYSCALL_PROCESS_SIGNAL, pid, PROCESS_SIGNAL_START, 0, 0); - vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/test_driver.nxkm"); + vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/test.nxkm"); elf_executable_T* executable = elf_executable_create(node->cache->buffer); - driver_register(executable, node->cache->buffer); + driver_T* drv = driver_register(executable, node->cache->buffer); + + void* entry = drv->base + symbol_resolve_from_name(executable->symbols, executable->num_symbols, "_start")->address; + + void (*drv_test)() = entry; + drv_test(); CORE_HALT_FOREVER } diff --git a/src/drivers/api.c b/src/drivers/api.c new file mode 100644 index 0000000..80fff93 --- /dev/null +++ b/src/drivers/api.c @@ -0,0 +1,7 @@ +// This file is part of noxos and licensed under the MIT open source license + +#include + +void nx_drv_init() { + DEBUG("hello from the driver api"); +} \ No newline at end of file diff --git a/src/drivers/builtin/elf/relocation.c b/src/drivers/builtin/elf/relocation.c index 47ed718..09e5e52 100644 --- a/src/drivers/builtin/elf/relocation.c +++ b/src/drivers/builtin/elf/relocation.c @@ -1,26 +1,106 @@ // This file is part of noxos and licensed under the MIT open source license #include +#include +#include #include +#include +#include -void elf_relocate(elf_executable_T* executable, uint8_t* buffer, void* address) { +//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++) { - if (sections[i].type != ELF_SECTION_DYNAMIC) continue; - section_dynamic = §ions[i]; - DEBUG("Found DYNAMIC section %d", i); - break; + 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 ELF executable (no .dynamic section found)"); - return; + 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; } -// elf_section_T* section_rela = ; -// -// uint32_t num_relocations = sections[i].length / sections[i].entry_size; -// elf_section_T* related_section = §ions[sections[i].info]; + for (uint32_t i = 0; i < executable->header.num_section_header_entries; i++) { + if (sections[i].type != ELF_SECTION_RELOCATION_A) continue; -// DEBUG("Found RELA section -> relocations: %d section: 0x%x", num_relocations, related_section); -} + symbol_T* symbols = scheduler_get_process(PROCESS_KERNEL)->executable->symbols; + uint64_t num_symbols = scheduler_get_process(PROCESS_KERNEL)->executable->num_symbols; + + uint32_t num_relocations = sections[i].length / sections[i].entry_size; + 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(symbols, num_symbols, 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; + } + + switch (relocation_type) { + case ELF_REL_JUMP_SLOT: { + *relocation_offset = k_symbol->address; + break; + } + } + } + } + + return true; +} \ No newline at end of file diff --git a/src/drivers/builtin/elf/section.c b/src/drivers/builtin/elf/section.c index 7b2b35d..7b7a6af 100644 --- a/src/drivers/builtin/elf/section.c +++ b/src/drivers/builtin/elf/section.c @@ -12,6 +12,9 @@ string_t g_elf_section_type_strings[ELF_SECTION_ENUM_END+1] = { "Dynamic Linker Info", "Note", "No Bits", + "Relocation", + "Unspecified Semantics (Not ABI Conform)", + "Symbol Table (Dynamic)", "Unknown" }; \ No newline at end of file diff --git a/src/drivers/driver.c b/src/drivers/driver.c index 0fa4be6..2863373 100644 --- a/src/drivers/driver.c +++ b/src/drivers/driver.c @@ -74,9 +74,15 @@ driver_T* driver_register(elf_executable_T* executable, uint8_t* buffer) { elf_mappings_apply(executable->mappings, executable->num_mappings, buffer, driver->base, g_kernel_page_map); - elf_relocate(executable, buffer, driver->base); + 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 NULL; + + return driver; } void driver_init(driver_T* driver, driver_config_header_T* conf) {