Skip to content

Commit

Permalink
boot: Split boot info into two parts, put less burden on the protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
marv7000 committed Nov 26, 2024
1 parent dea706e commit 0aded9b
Show file tree
Hide file tree
Showing 15 changed files with 127 additions and 158 deletions.
2 changes: 1 addition & 1 deletion include/menix/system/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ typedef struct Cpu
typedef struct Context Context;

// Initializes the platform for use by the kernel and boot routines.
void arch_early_init(BootInfo* info);
void arch_early_init(EarlyBootInfo* info);

// Initializes the rest of the platform after the boot routines have completed.
void arch_init(BootInfo* info);
Expand Down
47 changes: 22 additions & 25 deletions include/menix/system/boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,49 +18,46 @@ typedef struct
typedef struct Cpu Cpu;

// Information provided to the kernel by the boot protocol.
// Required for `kernel_early_init`.
typedef struct
{
// Required for `kernel_early_init`.
PhysMemory* memory_map; // Physical memory mappings.
usize mm_num; // Amount of memory map entries.
void* kernel_virt; // Virtual address of the kernel.
PhysAddr kernel_phys; // Physical address of the kernel.
void* phys_base; // Virtual base address for an identity mapping of physical memory.

// Required fo `fw_init`.
const char* cmd; // Command line.
void* kernel_file; // Pointer to the ELF of the kernel.
const char* cmd; // Command line.
#ifdef CONFIG_acpi
void* acpi_rsdp; // ACPI RSDP table.
#endif
#ifdef CONFIG_open_firmware
void* fdt_blob; // Device tree blob.
#endif
} EarlyBootInfo;

// Required for `kernel_init`.
usize file_num; // Amount of files loaded.
BootFile* files; // Array of files.
usize cpu_num; // Amount of processors detected.
atomic usize cpu_active; // Amount of processors active.
usize boot_cpu; // Index of the processor that was used to boot.
Cpu* cpus; // Per-CPU information.
} BootInfo;

typedef enum
// Information provided to the kernel by the boot protocol.
// Required for `kernel_init`.
typedef struct
{
ShutdownReason_Normal = 0,
ShutdownReason_Unknown = 1,
ShutdownReason_Abort = 2,
} ShutdownReason;
usize file_num; // Amount of files loaded.
BootFile* files; // Array of files.

// TODO: Handle SMP startup ourselves.
usize cpu_num; // Amount of processors detected.
volatile atomic usize cpu_active; // Amount of processors active.
usize boot_cpu; // Index of the processor that was used to boot.
Cpu* cpus; // Per-CPU information.
} BootInfo;

// Initializes common kernel systems.
// This function can be called as soon as `arch_early_init` has been called and `info` contains a memory map.
void kernel_early_init(BootInfo* info);
// Initializes basic kernel functions.
// This function can be called as soon as `info.early_init` contains data.
void kernel_early_init(EarlyBootInfo* info);

// Initializes the rest of the system after booting has finished.
// After this call, `info` is inaccessible.
// This function can be called as soon as the following functions have been called (in order):
// `kernel_early_init`, `fw_init`, `arch_init`
void kernel_init(BootInfo* info);
// This function can be called as soon as `kernel_early_init` has been called and `info` was filled completely.
// After this call, `info` may be destroyed.
ATTR(noreturn) void kernel_init(BootInfo* info);

// Gets called after platform initialization has finished.
// This is the main kernel function.
Expand Down
4 changes: 2 additions & 2 deletions include/menix/system/fw.h → include/menix/system/dst/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

#include <menix/system/boot.h>

// Initializes firmware.
void fw_init(BootInfo* info);
// Initializes the dynamic system tree.
void dst_init(EarlyBootInfo* info);
3 changes: 1 addition & 2 deletions include/menix/system/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#pragma once

#include <menix/common.h>
#include <menix/system/boot.h>
#include <menix/system/elf.h>
#include <menix/util/log.h>

Expand Down Expand Up @@ -57,7 +56,7 @@ typedef struct
} LoadedModule;

// Initialize all modules and their subsystems.
void module_init(BootInfo* info);
void module_init();

// Clean up all modules, disconnect and disable them all.
void module_fini();
Expand Down
2 changes: 1 addition & 1 deletion include/menix/util/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#define CMDLINE_MAX_LENGTH 1024

// Initializes the command line.
void cmd_init(BootInfo* info);
void cmd_init(const char* data);

// Returns a string from the command line matching the given key.
// If not present, returns `fallback`.
Expand Down
4 changes: 2 additions & 2 deletions kernel/arch/x86_64/system/arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,14 @@ void arch_init_cpu(BootInfo* info, Cpu* cpu, Cpu* boot)
arch_stop();
}

void arch_early_init(BootInfo* info)
void arch_early_init(EarlyBootInfo* info)
{
asm_interrupt_disable();

gdt_init();
idt_init();
serial_init();
pic_disable();
serial_init();
}

void arch_init(BootInfo* info)
Expand Down
155 changes: 60 additions & 95 deletions kernel/boot/boot_protocol_limine/limine_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#include <menix/memory/pm.h>
#include <menix/system/arch.h>
#include <menix/system/boot.h>
#include <menix/system/fw.h>
#include <menix/system/module.h>
#include <menix/system/sch/scheduler.h>
#include <menix/system/video/fb.h>
#include <menix/system/video/fb_default.h>
Expand All @@ -25,45 +23,45 @@
}

ATTR(used, section(".requests_start_marker")) static volatile LIMINE_REQUESTS_START_MARKER; // Start requests
ATTR(used, section(".requests_end_marker")) static volatile LIMINE_REQUESTS_END_MARKER; // End requests
ATTR(used, section(".requests")) static volatile LIMINE_BASE_REVISION(2);

LIMINE_REQUEST(memmap_request, LIMINE_MEMMAP_REQUEST, 0); // Get memory map.
LIMINE_REQUEST(hhdm_request, LIMINE_HHDM_REQUEST, 0); // Directly map 32-bit physical space.
LIMINE_REQUEST(kernel_address_request, LIMINE_KERNEL_ADDRESS_REQUEST, 0); // Get the physical kernel address.
LIMINE_REQUEST(kernel_file_request, LIMINE_KERNEL_FILE_REQUEST, 0); // For debug symbols.
LIMINE_REQUEST(framebuffer_request, LIMINE_FRAMEBUFFER_REQUEST, 1); // Initial console frame buffer.
LIMINE_REQUEST(module_request, LIMINE_MODULE_REQUEST, 0); // Get all other modules, logo.
#ifdef CONFIG_smp
LIMINE_REQUEST(smp_request, LIMINE_SMP_REQUEST, 0); // Get SMP information.
#endif
LIMINE_REQUEST(module_request, LIMINE_MODULE_REQUEST, 0); // Get all other modules.
LIMINE_REQUEST(smp_request, LIMINE_SMP_REQUEST, 0); // Get SMP information.

#ifdef CONFIG_acpi
LIMINE_REQUEST(rsdp_request, LIMINE_RSDP_REQUEST, 0); // Get ACPI RSDP table if enabled.
#endif

#ifdef CONFIG_open_firmware
LIMINE_REQUEST(dtb_request, LIMINE_DTB_REQUEST, 0); // Get device tree blob if enabled.
#endif

static BootInfo info = {0};
ATTR(used, section(".requests_end_marker")) static volatile LIMINE_REQUESTS_END_MARKER; // End requests

static BootInfo full_info = {0};

#ifdef CONFIG_smp
static void limine_init_cpu(struct limine_smp_info* smp_info)
{
arch_init_cpu(&info, (Cpu*)smp_info->extra_argument, &info.cpus[info.boot_cpu]);
arch_init_cpu(&full_info, (Cpu*)smp_info->extra_argument, &full_info.cpus[full_info.boot_cpu]);
}
#endif

void kernel_boot()
{
// Get the memory map.
kassert(memmap_request.response, "Unable to get memory map!");
struct limine_memmap_response* const mm_res = memmap_request.response;
boot_log("Bootloader provided memory map at 0x%p\n", mm_res);
kassert(hhdm_request.response, "Unable to get HHDM response!");
kassert(kernel_address_request.response, "Unable to get kernel address info!");
kassert(kernel_file_request.response, "Unable to get kernel file info!");

PhysMemory map[mm_res->entry_count];
info.mm_num = mm_res->entry_count;
info.memory_map = map;
EarlyBootInfo early_info = {0};

// Get the memory map.
struct limine_memmap_response* const mm_res = memmap_request.response;
PhysMemory map[mm_res->entry_count];
for (usize i = 0; i < mm_res->entry_count; i++)
{
map[i].address = mm_res->entries[i]->base;
Expand All @@ -82,20 +80,23 @@ void kernel_boot()
}
}

// Make sure the first 4 GiB are identity mapped so we can write to "physical" memory.
kassert(hhdm_request.response, "Unable to get HHDM response!");
kassert(kernel_address_request.response, "Unable to get kernel address info!");

// Initialize virtual memory using the memory map we got.
info.kernel_phys = (PhysAddr)kernel_address_request.response->physical_base;
info.kernel_virt = (void*)kernel_address_request.response->virtual_base;
info.phys_base = (void*)hhdm_request.response->offset;

kernel_early_init(&info);
early_info = (EarlyBootInfo) {
.memory_map = map,
.mm_num = mm_res->entry_count,
.kernel_phys = (PhysAddr)kernel_address_request.response->physical_base,
.kernel_virt = (void*)kernel_address_request.response->virtual_base,
.kernel_file = (void*)kernel_file_request.response->kernel_file->address,
.phys_base = (void*)hhdm_request.response->offset,
.cmd = kernel_file_request.response->kernel_file->cmdline,
#ifdef CONFIG_acpi
.acpi_rsdp = rsdp_request.response->address,
#endif
#ifdef CONFIG_open_firmware
.fdt_blob = dtb_request.response->dtb_ptr,
#endif
};

boot_log("HHDM offset: 0x%p\n", hhdm_request.response->offset);
boot_log("Kernel loaded at: 0x%p (0x%p)\n", kernel_address_request.response->virtual_base,
kernel_address_request.response->physical_base);
kernel_early_init(&early_info);

// Get modules.
if (module_request.response == NULL)
Expand All @@ -113,97 +114,65 @@ void kernel_boot()
boot_log("\t[%i] Address = 0x%p, Size = 0x%zx, Path = \"%s\"\n", i, files[i].address, files[i].size,
files[i].path);
}
info.file_num = module_res->module_count;
info.files = files;
full_info.file_num = module_res->module_count;
full_info.files = files;
}

// Get early framebuffer.
FrameBuffer buffer = {0};
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count == 0)
boot_log("Unable to get a framebuffer!\n");
else
{
// Construct a simple framebuffer. This will get overridden by a driver loaded at a later stage.
const struct limine_framebuffer* buf = framebuffer_request.response->framebuffers[0];
buffer.info.mmio_base = buf->address;
buffer.mode.cpp = buf->bpp / 8;
buffer.mode.width = buf->width;
buffer.mode.v_width = buf->pitch / buffer.mode.cpp;
buffer.mode.height = buf->height;
buffer.mode.v_height = buf->height;
buffer.mode.pitch = buf->pitch;

buffer.funcs = FB_DEFAULT_FUNCS;
FrameBuffer* buffer = kzalloc(sizeof(FrameBuffer));
buffer->info.mmio_base = buf->address;
buffer->mode.cpp = buf->bpp / 8;
buffer->mode.width = buf->width;
buffer->mode.v_width = buf->pitch / buffer->mode.cpp;
buffer->mode.height = buf->height;
buffer->mode.v_height = buf->height;
buffer->mode.pitch = buf->pitch;
buffer->funcs = FB_DEFAULT_FUNCS;

// If no early framebuffer has been set previously, do it now.
if (fb_get_active() == NULL)
fb_register(&buffer);
fb_register(buffer);
boot_log("Early framebuffer: Address = 0x%p, Resolution = %ux%ux%hhu (Virtual = %ux%u)\n",
buffer.info.mmio_base, buffer.mode.width, buffer.mode.height, buffer.mode.cpp * 8, buffer.mode.v_width,
buffer.mode.v_height);
buffer->info.mmio_base, buffer->mode.width, buffer->mode.height, buffer->mode.cpp * 8,
buffer->mode.v_width, buffer->mode.v_height);
}

// Get kernel file.
kassert(kernel_file_request.response, "Unable to get kernel file info!");
struct limine_kernel_file_response* const kernel_res = kernel_file_request.response;
boot_log("Kernel file loaded at: 0x%p, Size = 0x%lx\n", kernel_res->kernel_file->address,
kernel_res->kernel_file->size);

module_load_kernel_syms(kernel_res->kernel_file->address);

// Get command line.
boot_log("Command line: \"%s\"\n", kernel_res->kernel_file->cmdline);
info.cmd = kernel_res->kernel_file->cmdline;

#ifdef CONFIG_acpi
// Get ACPI RSDP.
kassert(rsdp_request.response, "Unable to get ACPI RSDP!");
boot_log("ACPI RSDP at 0x%p\n", rsdp_request.response->address);
info.acpi_rsdp = rsdp_request.response->address;
#endif

#ifdef CONFIG_open_firmware
kassert(dtb_request.response, "Unable to get device tree!");
boot_log("FDT blob at 0x%p\n", dtb_request.response->dtb_ptr);
info.fdt_blob = dtb_request.response->dtb_ptr;
#endif

fw_init(&info);

#ifdef CONFIG_smp
// TODO: Instead of relying on the bootloader to do SMP, do this ourselves.
// Get SMP info
kassert(smp_request.response, "Unable to get kernel SMP info!");
const struct limine_smp_response* smp_res = smp_request.response;

usize smp_cmdline = cmd_get_usize("smp", smp_res->cpu_count);
// Only initialize a given amount of cores, or if none/invalid the maximum cpu count.
info.cpu_num = (smp_cmdline > smp_res->cpu_count || smp_cmdline == 0) ? smp_res->cpu_count : smp_cmdline;
boot_log("Initializing %zu cores.\n", info.cpu_num);
full_info.cpu_num = (smp_cmdline > smp_res->cpu_count || smp_cmdline == 0) ? smp_res->cpu_count : smp_cmdline;
boot_log("Initializing %zu cores.\n", full_info.cpu_num);

// Mark the boot CPU ID.
#ifdef CONFIG_arch_x86_64
info.boot_cpu = smp_res->bsp_lapic_id;
full_info.boot_cpu = smp_res->bsp_lapic_id;
#elif defined(CONFIG_arch_riscv64)
info.boot_cpu = smp_res->bsp_hartid;
#endif
#else
info.cpu_num = 1;
info.boot_cpu = 0;
#endif

// Allocate CPU info.
info.cpus = kzalloc(sizeof(Cpu) * info.cpu_num);
full_info.cpus = kzalloc(sizeof(Cpu) * full_info.cpu_num);

// Start all cores.
#ifdef CONFIG_smp
for (usize i = 0; i < info.cpu_num; i++)
for (usize i = 0; i < full_info.cpu_num; i++)
{
struct limine_smp_info* smp_cpu = smp_res->cpus[i];
smp_cpu->extra_argument = (usize)&info.cpus[i];
Cpu* cpu = &info.cpus[i];
smp_cpu->extra_argument = (usize)&full_info.cpus[i];
Cpu* cpu = &full_info.cpus[i];
cpu->id = i;
#ifdef CONFIG_arch_x86_64
cpu->lapic_id = smp_cpu->lapic_id;
if (cpu->lapic_id != info.boot_cpu)
if (cpu->lapic_id != full_info.boot_cpu)
#elif defined(CONFIG_arch_riscv64)
cpu->hart_id = smp_cpu->hartid;
if (cpu->hart_id != info.boot_cpu)
Expand All @@ -212,15 +181,11 @@ void kernel_boot()
else
limine_init_cpu(smp_cpu);
}
while (info.cpu_active != info.cpu_num)
while (full_info.cpu_active != full_info.cpu_num)
{
__sync_synchronize();
asm_pause();
#else
arch_init_cpu(&info.cpus[0], &info.cpus[0]);
#endif

kernel_init(&info);
}

// Should be unreachable.
while (true)
sch_invoke();
kernel_init(&full_info);
}
5 changes: 0 additions & 5 deletions kernel/fs/devtmpfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,6 @@ bool devtmpfs_add_device(Handle* device, const char* name)
if (node != NULL)
{
thread_set_errno(EEXIST);

// TODO: Free old handle.

// Update handle.
node->handle = device;
return false;
}

Expand Down
Loading

0 comments on commit 0aded9b

Please sign in to comment.