feature (drivers): implemented an infrastructure to link drivers into the kernel
This commit is contained in:
parent
3d4cea2060
commit
7d33377806
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
|
@ -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 = §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];
|
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 = §ions[i];
|
section_dynamic = §ions[i];
|
||||||
DEBUG("Found DYNAMIC section %d", i);
|
|
||||||
break;
|
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) {
|
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 = §ions[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;
|
||||||
}
|
}
|
|
@ -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"
|
||||||
};
|
};
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue