feature (drivers): implemented an infrastructure to link drivers into the kernel

This commit is contained in:
antifallobst 2023-06-01 00:10:15 +02:00
parent 3d4cea2060
commit 7d33377806
7 changed files with 123 additions and 18 deletions

View File

@ -31,6 +31,7 @@ typedef struct {
int64_t addend; int64_t addend;
} elf_relocation_a_T; } 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 #endif //NOXOS_RELOCATION_H

View File

@ -16,6 +16,9 @@ typedef enum {
ELF_SECTION_DYNAMIC, ELF_SECTION_DYNAMIC,
ELF_SECTION_NOTE, ELF_SECTION_NOTE,
ELF_SECTION_NOBITS, ELF_SECTION_NOBITS,
ELF_SECTION_REL,
ELF_SECTION_SHLIB,
ELF_SECTION_DYNAMIC_SYMBOL_TABLE,
ELF_SECTION_ENUM_END ELF_SECTION_ENUM_END
} elf_section_type_E; } elf_section_type_E;

View File

@ -88,9 +88,14 @@ void kmain(boot_info_T boot_info) {
// //
// syscall_perform(SYSCALL_PROCESS_SIGNAL, pid, PROCESS_SIGNAL_START, 0, 0); // 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); 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 CORE_HALT_FOREVER
} }

7
src/drivers/api.c Normal file
View File

@ -0,0 +1,7 @@
// This file is part of noxos and licensed under the MIT open source license
#include <utils/logger.h>
void nx_drv_init() {
DEBUG("hello from the driver api");
}

View File

@ -1,26 +1,106 @@
// This file is part of noxos and licensed under the MIT open source license // This file is part of noxos and licensed under the MIT open source license
#include <drivers/builtin/elf/relocation.h> #include <drivers/builtin/elf/relocation.h>
#include <drivers/builtin/elf/dynamic.h>
#include <drivers/builtin/elf/symbol.h>
#include <utils/logger.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) { //void elf_relocate(elf_executable_T* executable, uint8_t* buffer, void* address) {
// elf_section_T* sections = (elf_section_T*)&buffer[executable->header.offset_section_header];
// elf_section_T* section_dynamic = NULL;
// for (uint32_t i = 0; i < executable->header.num_section_header_entries; i++) {
// if (sections[i].type != ELF_SECTION_DYNAMIC) continue;
// section_dynamic = &sections[i];
// DEBUG("Found DYNAMIC section %d", i);
// break;
// }
// if (section_dynamic == NULL) {
// log(LOG_ERROR, "Failed to relocate ELF executable (no .dynamic section found)");
// return;
// }
// uint32_t num_dynamic_entries = section_dynamic->length / section_dynamic->entry_size;
// elf_dynamic_T* dynamic_entries = (elf_dynamic_T*)&buffer[section_dynamic->offset];
// uint32_t num_needed_libraries = 0;
//
// for (int i = 0; i < num_dynamic_entries; i++) {
// switch (dynamic_entries[i].tag) {
// case ELF_DYNAMIC_TAG_NEEDED: {
// num_needed_libraries++;
// break;
// }
// }
// }
//
// log(LOG_ERROR, "Failed to relocate executable (not implemented)");
//
//}
bool elf_relocate_driver(elf_executable_T* executable, uint8_t* buffer, void* load_address) {
elf_section_T* sections = (elf_section_T*)&buffer[executable->header.offset_section_header]; 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_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++) { for (uint32_t i = 0; i < executable->header.num_section_header_entries; i++) {
if (sections[i].type != ELF_SECTION_DYNAMIC) continue; switch (sections[i].type) {
case ELF_SECTION_DYNAMIC: {
section_dynamic = &sections[i]; section_dynamic = &sections[i];
DEBUG("Found DYNAMIC section %d", i);
break; break;
} }
case ELF_SECTION_STRING_TABLE: {
if (!string_compare(".dynstr", &section_names[sections[i].name_offset])) break;
section_dynstr = &sections[i];
break;
}
case ELF_SECTION_DYNAMIC_SYMBOL_TABLE: {
section_dynsym = &sections[i];
break;
}
}
}
if (section_dynamic == NULL) { if (section_dynamic == NULL) {
log(LOG_ERROR, "Failed to relocate ELF executable (no .dynamic section found)"); log(LOG_ERROR, "Failed to relocate driver executable (no .dynamic section found)");
return; 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 = ; for (uint32_t i = 0; i < executable->header.num_section_header_entries; i++) {
// if (sections[i].type != ELF_SECTION_RELOCATION_A) continue;
// uint32_t num_relocations = sections[i].length / sections[i].entry_size;
// elf_section_T* related_section = &sections[sections[i].info];
// 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;
} }

View File

@ -12,6 +12,9 @@ string_t g_elf_section_type_strings[ELF_SECTION_ENUM_END+1] = {
"Dynamic Linker Info", "Dynamic Linker Info",
"Note", "Note",
"No Bits", "No Bits",
"Relocation",
"Unspecified Semantics (Not ABI Conform)",
"Symbol Table (Dynamic)",
"Unknown" "Unknown"
}; };

View File

@ -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_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) { void driver_init(driver_T* driver, driver_config_header_T* conf) {