Update kernel args to be module-based

- The old kernel_args structure is now mostly represented as a series of
  'modules' or memory ranges, tagged with a type. An arbitrary number
  can be passed to the kernel
- Update bootloader to allocate space for the args header and 10 module
  descriptors
This commit is contained in:
Justin C. Miller
2020-02-23 00:07:50 -08:00
parent ec563ea8e4
commit 6f5a2a3d3f
3 changed files with 115 additions and 68 deletions

View File

@@ -10,9 +10,10 @@
#include "console.h" #include "console.h"
#include "error.h" #include "error.h"
#include "memory.h" #include "memory.h"
#include "kernel_args.h"
/* /*
#include "guids.h" #include "guids.h"
#include "kernel_args.h"
#include "loader.h" #include "loader.h"
#include "utility.h" #include "utility.h"
@@ -40,14 +41,9 @@ using kernel_entry = void (*)(kernel_args *);
namespace boot { namespace boot {
constexpr int max_modules = 10; // Max modules to allocate room for
/* /*
static void
type_to_wchar(wchar_t *into, uint32_t type)
{
for (int j=0; j<4; ++j)
into[j] = static_cast<wchar_t>(reinterpret_cast<char *>(&type)[j]);
}
EFI_STATUS EFI_STATUS
detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) { detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) {
@@ -87,6 +83,29 @@ detect_debug_mode(EFI_RUNTIME_SERVICES *run, kernel_args *header) {
} }
*/ */
uintptr_t
find_acpi_table(uefi::system_table *st)
{
// Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found.
uintptr_t acpi1_table = 0;
for (size_t i = 0; i < st->number_of_table_entries; ++i) {
uefi::configuration_table *table = &st->configuration_table[i];
// If we find an ACPI 2.0 table, return it immediately
if (table->vendor_guid == uefi::vendor_guids::acpi2)
return reinterpret_cast<uintptr_t>(table->vendor_table);
if (table->vendor_guid == uefi::vendor_guids::acpi1) {
// Mark a v1 table with the LSB high
acpi1_table = reinterpret_cast<uintptr_t>(table->vendor_table);
acpi1_table |= 1;
}
}
return acpi1_table;
}
uefi::status uefi::status
bootloader_main_uefi(uefi::system_table *st, console &con) bootloader_main_uefi(uefi::system_table *st, console &con)
{ {
@@ -95,40 +114,12 @@ bootloader_main_uefi(uefi::system_table *st, console &con)
uefi::boot_services *bs = st->boot_services; uefi::boot_services *bs = st->boot_services;
uefi::runtime_services *rs = st->runtime_services; uefi::runtime_services *rs = st->runtime_services;
/*
con.status_begin(L"Trying to do a harder thing...");
con.status_warn(L"First warning");
con.status_warn(L"Second warning");
con.status_begin(L"Trying to do the impossible...");
con.status_warn(L"we're not going to make it");
error::raise(uefi::status::unsupported, L"OH NO");
*/
con.status_begin(L"Initializing pointer fixup for virtualization"); con.status_begin(L"Initializing pointer fixup for virtualization");
memory::init_pointer_fixup(bs, rs); memory::init_pointer_fixup(bs, rs);
con.status_end(); con.status_end();
// Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found.
//
con.status_begin(L"Searching for ACPI table"); con.status_begin(L"Searching for ACPI table");
uintptr_t acpi_table = 0; uintptr_t acpi_table = find_acpi_table(st);
for (size_t i = 0; i < st->number_of_table_entries; ++i) {
uefi::configuration_table *table = &st->configuration_table[i];
if (table->vendor_guid == uefi::vendor_guids::acpi2) {
acpi_table = reinterpret_cast<uintptr_t>(table->vendor_table);
break;
}
if (table->vendor_guid == uefi::vendor_guids::acpi1) {
// Mark a v1 table with the LSB high
acpi_table = reinterpret_cast<uintptr_t>(table->vendor_table);
acpi_table |= 1;
}
}
if (!acpi_table) { if (!acpi_table) {
error::raise(uefi::status::not_found, L"Could not find ACPI table"); error::raise(uefi::status::not_found, L"Could not find ACPI table");
} else if (acpi_table & 1) { } else if (acpi_table & 1) {
@@ -136,11 +127,44 @@ bootloader_main_uefi(uefi::system_table *st, console &con)
} }
con.status_end(); con.status_end();
con.status_begin(L"Setting up kernel args memory");
kernel::args::header *args = nullptr;
size_t args_size =
sizeof(kernel::args::header) + // The header itself
max_modules * sizeof(kernel::args::module); // The module structures
try_or_raise(
bs->allocate_pool(
uefi::memory_type::loader_data,
args_size,
reinterpret_cast<void**>(&args)),
L"Could not allocate argument memory");
kernel::args::module *modules =
reinterpret_cast<kernel::args::module*>(args + 1);
args->magic = kernel::args::magic;
args->version = kernel::args::version;
args->runtime_services = rs;
args->acpi_table = reinterpret_cast<void*>(acpi_table);
args->modules = modules;
args->num_modules = 0;
con.status_end();
con.status_begin(L"Loading initrd into memory");
kernel::args::module &initrd = modules[args->num_modules++];
initrd.type = kernel::args::type::initrd;
con.status_end();
while(1); while(1);
return uefi::status::success; return uefi::status::success;
} }
/*
/*
// Compute necessary number of data pages // Compute necessary number of data pages
// //
size_t data_length = 0; size_t data_length = 0;

View File

@@ -4,44 +4,59 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#define DATA_HEADER_MAGIC 0x600dda7a namespace kernel {
#define DATA_HEADER_VERSION 1 namespace args {
#define JSIX_FLAG_DEBUG 0x00000001 constexpr uint32_t magic = 0x600dda7a;
constexpr uint16_t version = 1;
enum class flags : uint32_t
{
debug = 0x00000001
};
enum class type : uint32_t {
unknown,
kernel,
initrd,
memory_map,
framebuffer,
max
};
enum class mode : uint8_t {
normal,
debug
};
#pragma pack(push, 1) #pragma pack(push, 1)
struct kernel_args { struct module {
void *location;
size_t size;
type type;
flags flags;
};
struct header {
uint32_t magic; uint32_t magic;
uint16_t version; uint16_t version;
uint16_t length;
uint16_t _reserved0; mode mode;
uint16_t scratch_pages;
uint32_t flags;
void *initrd; uint8_t _reserved0;
size_t initrd_length;
void *data;
size_t data_length;
void *memory_map;
size_t memory_map_length;
size_t memory_map_desc_size;
void *runtime;
void *acpi_table;
void *frame_buffer;
size_t frame_buffer_length;
uint32_t hres;
uint32_t vres;
uint32_t rmask;
uint32_t gmask;
uint32_t bmask;
uint32_t _reserved1; uint32_t _reserved1;
uint32_t num_modules;
module *modules;
void *runtime_services;
void *acpi_table;
} }
__attribute__((aligned(alignof(max_align_t)))); __attribute__((aligned(alignof(max_align_t))));
#pragma pack(pop) #pragma pack(pop)
} // namespace args
} // namespace kernel

View File

@@ -26,7 +26,7 @@
#include "syscall.h" #include "syscall.h"
extern "C" { extern "C" {
void kernel_main(kernel_args *header); void kernel_main(kernel::args::header *header);
void *__bss_start, *__bss_end; void *__bss_start, *__bss_end;
} }
@@ -69,9 +69,9 @@ init_console()
} }
void void
kernel_main(kernel_args *header) kernel_main(kernel::args::header *header)
{ {
bool waiting = header && (header->flags && JSIX_FLAG_DEBUG); bool waiting = header && (header->mode == kernel::args::mode::debug);
while (waiting); while (waiting);
kutil::assert_set_callback(__kernel_assert); kutil::assert_set_callback(__kernel_assert);
@@ -79,6 +79,7 @@ kernel_main(kernel_args *header)
gdt_init(); gdt_init();
interrupts_init(); interrupts_init();
/*
memory_initialize( memory_initialize(
header->scratch_pages, header->scratch_pages,
header->memory_map, header->memory_map,
@@ -110,16 +111,19 @@ kernel_main(kernel_args *header)
for (auto &f : ird.files()) for (auto &f : ird.files())
log::info(logs::boot, " %s%s (%d bytes).", f.executable() ? "*" : "", f.name(), f.size()); log::info(logs::boot, " %s%s (%d bytes).", f.executable() ? "*" : "", f.name(), f.size());
*/
/* /*
page_manager::get()->dump_pml4(nullptr, 0); page_manager::get()->dump_pml4(nullptr, 0);
page_manager::get()->dump_blocks(true); page_manager::get()->dump_blocks(true);
*/ */
/*
device_manager *devices = device_manager *devices =
new (&device_manager::get()) device_manager(header->acpi_table, heap); new (&device_manager::get()) device_manager(header->acpi_table, heap);
interrupts_enable(); interrupts_enable();
*/
/* /*
auto r = cpu.get(0x15); auto r = cpu.get(0x15);
log::info(logs::boot, "CPU Crystal: %dHz", r.ecx); log::info(logs::boot, "CPU Crystal: %dHz", r.ecx);
@@ -128,9 +132,11 @@ kernel_main(kernel_args *header)
__asm__ __volatile__ ( "mov %%cr4, %0" : "=r" (cr4) ); __asm__ __volatile__ ( "mov %%cr4, %0" : "=r" (cr4) );
log::info(logs::boot, "cr4: %016x", cr4); log::info(logs::boot, "cr4: %016x", cr4);
*/ */
/*
devices->init_drivers(); devices->init_drivers();
*/
/* /*
block_device *disk = devices->get_block_device(0); block_device *disk = devices->get_block_device(0);
if (disk) { if (disk) {
@@ -154,6 +160,7 @@ kernel_main(kernel_args *header)
log::warn(logs::boot, "No block devices present."); log::warn(logs::boot, "No block devices present.");
} }
*/ */
/*
devices->get_lapic()->calibrate_timer(); devices->get_lapic()->calibrate_timer();
@@ -183,4 +190,5 @@ kernel_main(kernel_args *header)
} }
sched->start(); sched->start();
*/
} }