boot: Add EFISTUB and refactor boot protocols
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
|
||||
#include "loader.h"
|
||||
#include <string.h>
|
||||
#include "loader_arch.h"
|
||||
|
||||
extern const uint8_t __kernel_start[];
|
||||
extern const uint8_t __kernel_end[];
|
||||
|
||||
bool loader_load_kernel(struct kernel_image* out, const char* name) {
|
||||
if (!elf_load(__kernel_start, __kernel_end - __kernel_start, out))
|
||||
return false;
|
||||
|
||||
struct boot_info* info = out->info;
|
||||
memcpy(info->loader, name, MIN(strlen(name), sizeof(info->loader) - 1));
|
||||
info->hhdm_base = ARCH_HHDM_BASE;
|
||||
info->phys_base = out->phys;
|
||||
info->virt_base = out->virt;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loader_add_file(const struct kernel_image* kernel, const char* path, uint64_t base, uint64_t length) {
|
||||
struct boot_info* info = kernel->info;
|
||||
if (info->num_files == ARRAY_SIZE(info->files))
|
||||
return false;
|
||||
|
||||
struct boot_file* file = &info->files[info->num_files++];
|
||||
file->data = base;
|
||||
file->length = length;
|
||||
const size_t path_len = MIN(strlen(path), sizeof(file->path) - 1);
|
||||
memcpy(file->path, path, path_len);
|
||||
file->path[path_len] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void loader_set_mem_map(const struct kernel_image* kernel, struct phys_mem* map, size_t len) {
|
||||
for (size_t i = 1; i < len; i++) {
|
||||
const struct phys_mem entry = map[i];
|
||||
size_t j = i;
|
||||
while (j > 0 && map[j - 1].address > entry.address) {
|
||||
map[j] = map[j - 1];
|
||||
j--;
|
||||
}
|
||||
map[j] = entry;
|
||||
}
|
||||
|
||||
size_t merged = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (!map[i].length)
|
||||
continue;
|
||||
struct phys_mem* prev = merged ? &map[merged - 1] : nullptr;
|
||||
if (prev && prev->usage == map[i].usage && prev->address + prev->length == map[i].address)
|
||||
prev->length += map[i].length;
|
||||
else
|
||||
map[merged++] = map[i];
|
||||
}
|
||||
|
||||
struct boot_info* info = kernel->info;
|
||||
info->num_mem_maps = MIN(merged, ARRAY_SIZE(info->mem_map));
|
||||
memcpy(info->mem_map, map, info->num_mem_maps * sizeof(*map));
|
||||
}
|
||||
|
||||
bool loader_page_tables(
|
||||
const struct kernel_image* kernel,
|
||||
uint64_t mem_top,
|
||||
uint64_t trampoline_phys,
|
||||
uint64_t* out_root
|
||||
) {
|
||||
uint64_t root;
|
||||
if (!loader_alloc(PHYS_RECLAIMABLE, PAGE_SIZE, &root))
|
||||
return false;
|
||||
|
||||
const uint64_t trampoline_virt = ALIGN_DOWN((uint64_t)arch_enter_kernel, PAGE_SIZE);
|
||||
if (!arch_paging_map(root, ARCH_HHDM_BASE, 0, ALIGN_UP(mem_top, ARCH_HUGE_PAGE_SIZE), ARCH_HUGE_PAGE_SIZE) ||
|
||||
!arch_paging_map(root, kernel->virt, kernel->phys, kernel->size, PAGE_SIZE) ||
|
||||
!arch_paging_map(root, trampoline_virt, ALIGN_DOWN(trampoline_phys, PAGE_SIZE), 2 * PAGE_SIZE, PAGE_SIZE))
|
||||
return false;
|
||||
|
||||
*out_root = root;
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user