Skip to content
46 changes: 19 additions & 27 deletions shared/include/core/header.h
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
#ifndef _INCLUDE_CORE_HEADER
#define _INCLUDE_CORE_HEADER

#include "core/consts.h"

#if defined(CORE) || defined(UEFI)
#include <stdbool.h>
#include <stdint.h>
#elif defined(MODULE)
#include <linux/kernel.h>
#endif

#include "utils.h"

struct mem_area {
uint64_t start;
uint64_t size;
};
#include "core/consts.h"
#include "mem_area.h"

enum core_action {
CORE_ACTION_INVALID,
CORE_ACTION_STORE,
CORE_ACTION_SWITCH,

CORE_ACTION_MAX,
};

#define MAX_RAM_AREAS 64
Expand Down Expand Up @@ -64,29 +56,29 @@ struct core_header {
struct mem_area ram_areas[MAX_RAM_AREAS];
};

static inline bool is_core_header_magic_valid(const struct core_header* core_header) {
return core_header->magic == CORE_HEADER_MAGIC;
static inline bool is_core_header_magic_valid(uint32_t magic) {
return magic == CORE_HEADER_MAGIC;
}

static inline bool is_core_header_action_valid(const struct core_header* core_header) {
return core_header->action != CORE_ACTION_INVALID;
static inline bool is_core_header_action_valid(enum core_action action) {
return action != CORE_ACTION_INVALID && action < CORE_ACTION_MAX;
}

static inline bool is_core_header_facs_valid(const struct core_header* core_header) {
return core_header->facs != 0;
static inline bool is_core_header_facs_valid(uint64_t facs) {
return facs != 0;
}

static inline bool is_core_header_rsdp_valid(const struct core_header* core_header) {
return core_header->rsdp != 0;
static inline bool is_core_header_rsdp_valid(uint64_t rsdp) {
return rsdp != 0;
}

static inline bool is_core_header_ram_areas_valid(const struct core_header* core_header) {
if (core_header->ram_areas_size > ARRAY_SIZE(core_header->ram_areas)) {
static inline bool is_core_header_ram_areas_valid(const struct mem_area* ram_areas, uint32_t ram_areas_size) {
if (ram_areas_size > MAX_RAM_AREAS) {
return false;
}

for (uint32_t i = 0; i < core_header->ram_areas_size; i++) {
if (core_header->ram_areas[i].size == 0) {
for (uint32_t i = 0; i < ram_areas_size; i++) {
if (ram_areas[i].size == 0) {
return false;
}
}
Expand All @@ -95,9 +87,9 @@ static inline bool is_core_header_ram_areas_valid(const struct core_header* core
}

static inline bool is_core_header_valid(const struct core_header* core_header) {
return is_core_header_magic_valid(core_header) && is_core_header_action_valid(core_header) &&
is_core_header_facs_valid(core_header) && is_core_header_rsdp_valid(core_header) &&
is_core_header_ram_areas_valid(core_header);
return is_core_header_magic_valid(core_header->magic) && is_core_header_action_valid(core_header->action) &&
is_core_header_facs_valid(core_header->facs) && is_core_header_rsdp_valid(core_header->rsdp) &&
is_core_header_ram_areas_valid(core_header->ram_areas, core_header->ram_areas_size);
}

#endif
16 changes: 16 additions & 0 deletions shared/include/mem_area.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef _INCLUDE_MEM_AREA_H
#define _INCLUDE_MEM_AREA_H

#include <stdbool.h>
#include <stdint.h>

struct mem_area {
uint64_t start;
uint64_t size;
};

static inline bool is_mem_area_contained_in_range(const struct mem_area* area, uint64_t start, uint64_t end) {
return start <= area->start && area->start + area->size <= end;
}

#endif
9 changes: 9 additions & 0 deletions shared/src/qemu_print/qemu_print.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <wchar.h>

static void qemu_print_char(char c) {
// Use QEMU's debugcon device
Expand Down Expand Up @@ -59,6 +60,14 @@ unsigned long qemu_print(const char* fmt, ...) {
qemu_print_unsigned_num(arg, 16);
break;
}
case 's': {
wchar_t* arg = va_arg(args, wchar_t*);
for (const wchar_t* arg_c = arg; *arg_c != '\0'; arg_c++) {
// NOTE: This treats wide strings as regular strings
qemu_print_char((char)*arg_c);
}
break;
}
}
break;
}
Expand Down
8 changes: 5 additions & 3 deletions uefi/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@

#include "acpi/hook_pts.h"
#include "acpi/tables.h"
#include "core/header.h"
#include "core_header_utils.h"
#include "core_loader.h"
#include "services/hooks_loader.h"

struct core_header* g_core_header = NULL;

EFI_STATUS
efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
err_t err = SUCCESS;

InitializeLib(ImageHandle, SystemTable);

TRACE("Loading core...\n");
struct core_header* core_header = NULL;
CHECK_RETHROW(load_core(&core_header));
CHECK_RETHROW(load_core(&g_core_header));

TRACE("Locating ACPI tables...\n");
CHECK_RETHROW(find_acpi_tables());
Expand All @@ -29,7 +31,7 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
CHECK_RETHROW(create_or_hook_pts());

TRACE("Filling core header...\n");
CHECK_RETHROW(fill_core_header(core_header));
CHECK_RETHROW(fill_core_header());

cleanup:
if (IS_ERROR(err)) {
Expand Down
61 changes: 33 additions & 28 deletions uefi/core_header_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

#include <efidef.h>
#include <efilib.h>
#include <stddef.h>

#include "acpi/tables.h"
#include "core/header.h"
#include "pci.h"
#include "utils.h"

// TODO: This is currently hard coded to a virtio blk device. Make this
// configurable.
Expand All @@ -13,40 +16,42 @@

static const struct pci_dev_id g_disk_pci_id = {.vendor_id = DISK_PCI_VENDOR_ID, .device_id = DISK_PCI_DEVICE_ID};

extern struct core_header* g_core_header;

/**
* Fills `core_header.rsdp` with `g_rsdp`.
* Fills `g_core_header.rsdp` with `g_rsdp`.
*/
static void fill_rsdp(struct core_header* core_header) {
core_header->rsdp = (uint64_t)(uintptr_t)g_rsdp;
static void fill_rsdp(void) {
g_core_header->rsdp = (uint64_t)(uintptr_t)g_rsdp;
}

/**
* Fills `core_header.facs` with `g_facs`.
* Fills `g_core_header.facs` with `g_facs`.
*/
static void fill_facs(struct core_header* core_header) {
core_header->facs = (uint64_t)(uintptr_t)g_facs;
static void fill_facs(void) {
g_core_header->facs = (uint64_t)(uintptr_t)g_facs;
}

/**
* Locates the disk by enumerating the PCI bus, and fills `core_header->disk_pci`
* Locates the disk by enumerating the PCI bus, and fills `g_core_header->disk_pci`
* with the disk's PCI location, and the BIOS-initialized BARs.
*/
static err_t fill_disk_pci(struct core_header* core_header) {
static err_t fill_disk_pci(void) {
err_t err = SUCCESS;

struct pci_dev disk_pci_dev = {0};
CHECK_RETHROW(lookup_pci_dev(&disk_pci_dev, &g_disk_pci_id));

// Fill the disk's pci bus information.
core_header->disk_pci.addr.bus = disk_pci_dev.addr.bus;
core_header->disk_pci.addr.device = disk_pci_dev.addr.device;
core_header->disk_pci.addr.function = disk_pci_dev.addr.function;
g_core_header->disk_pci.addr.bus = disk_pci_dev.addr.bus;
g_core_header->disk_pci.addr.device = disk_pci_dev.addr.device;
g_core_header->disk_pci.addr.function = disk_pci_dev.addr.function;

// Fill the disk's bars.
struct pci_bar pci_bar = {0};
for (size_t i = 0; i < 6; i++) {
CHECK_RETHROW(pci_get_bar(&disk_pci_dev, i, &pci_bar));
core_header->disk_pci.bars[i] = pci_bar.addr;
g_core_header->disk_pci.bars[i] = pci_bar.addr;
}

cleanup:
Expand Down Expand Up @@ -75,22 +80,22 @@ static bool is_memory_desc_usable(const EFI_MEMORY_DESCRIPTOR* desc) {
}

/**
* Inserts a memory descriptor into `core_header->ram_areas`.
* Inserts a memory descriptor into `g_core_header->ram_areas`.
*
* This also defragments consecutive descriptors so the table is as small as possible.
*/
static err_t insert_desc(struct core_header* core_header, const EFI_MEMORY_DESCRIPTOR* desc) {
static err_t insert_desc(const EFI_MEMORY_DESCRIPTOR* desc) {
err_t err = SUCCESS;

CHECK_TRACE(core_header->ram_areas_size < ARRAY_SIZE(core_header->ram_areas),
CHECK_TRACE(g_core_header->ram_areas_size < ARRAY_SIZE(g_core_header->ram_areas),
"No space left for additional RAM areas!\n");

size_t desc_size = desc->NumberOfPages * EFI_PAGE_SIZE;
size_t desc_end = desc->PhysicalStart + desc_size;

// Try to defragment the new descriptor into an existing consecutive descriptor.
for (size_t i = 0; i < core_header->ram_areas_size; i++) {
struct mem_area* area = &core_header->ram_areas[i];
for (size_t i = 0; i < g_core_header->ram_areas_size; i++) {
struct mem_area* area = &g_core_header->ram_areas[i];

if (area->start == desc_end) {
// An existing descriptor begins where the new descriptor ends.
Expand All @@ -103,19 +108,19 @@ static err_t insert_desc(struct core_header* core_header, const EFI_MEMORY_DESCR
}
}

core_header->ram_areas[core_header->ram_areas_size].start = desc->PhysicalStart;
core_header->ram_areas[core_header->ram_areas_size].size = desc_size;
g_core_header->ram_areas[g_core_header->ram_areas_size].start = desc->PhysicalStart;
g_core_header->ram_areas[g_core_header->ram_areas_size].size = desc_size;

core_header->ram_areas_size++;
g_core_header->ram_areas_size++;

cleanup:
return err;
}

/**
* Locates all the usable memory RAM areas using the `GetMemoryMap` boot service, and fills `core_header->ram_areas`.
* Locates all the usable memory RAM areas using the `GetMemoryMap` boot service, and fills `g_core_header->ram_areas`.
*/
static err_t fill_ram_areas(struct core_header* core_header) {
static err_t fill_ram_areas(void) {
err_t err = SUCCESS;
EFI_MEMORY_DESCRIPTOR* memory_map = NULL;

Expand Down Expand Up @@ -145,7 +150,7 @@ static err_t fill_ram_areas(struct core_header* core_header) {
continue;
}

CHECK_RETHROW(insert_desc(core_header, desc));
CHECK_RETHROW(insert_desc(desc));
}

cleanup:
Expand All @@ -155,13 +160,13 @@ static err_t fill_ram_areas(struct core_header* core_header) {
return err;
}

err_t fill_core_header(struct core_header* core_header) {
err_t fill_core_header() {
err_t err = SUCCESS;

fill_rsdp(core_header);
fill_facs(core_header);
CHECK_RETHROW(fill_disk_pci(core_header));
CHECK_RETHROW(fill_ram_areas(core_header));
fill_rsdp();
fill_facs();
CHECK_RETHROW(fill_disk_pci());
CHECK_RETHROW(fill_ram_areas());

cleanup:
return err;
Expand Down
3 changes: 1 addition & 2 deletions uefi/core_header_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
#include <efi.h>
#include <efiapi.h>

#include "core/header.h"
#include "error.h"

/**
* Fills the core header with all the required information.
*/
err_t fill_core_header(struct core_header* core_header);
err_t fill_core_header();
4 changes: 3 additions & 1 deletion uefi/core_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <efilib.h>
#include <error.h>

#include "utils.h"

extern char _binary_build_core_raw_bin_start[];
extern char _binary_build_core_raw_bin_end[];

Expand Down Expand Up @@ -69,7 +71,7 @@ err_t load_core(struct core_header** core_header_out) {
CHECK_RETHROW(load_memory(CORE_PM_PHYS_ADDR, CORE_PM_START, CORE_PM_SIZE));

struct core_header* core_header = (struct core_header*)CORE_PHYS_ADDR;
CHECK(is_core_header_magic_valid(core_header));
CHECK(is_core_header_magic_valid(core_header->magic));

*core_header_out = core_header;

Expand Down
6 changes: 5 additions & 1 deletion uefi/services/headers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@

#include <efi.h>

#include "core/header.h"
#include "mem_area.h"

struct set_variable_hook_header {
EFI_SET_VARIABLE original_set_variable;
uint32_t* waking_vector_addr;
uint32_t* original_waking_vector_addr;
struct core_header* core_header;
};

struct get_memory_map_hook_header {
EFI_GET_MEMORY_MAP original_get_memory_map;
uintptr_t waking_vector_phys_addr;
EFI_INSTALL_CONFIGURATION_TABLE install_configuration_table;
struct mem_area runtime_areas[32];
};

struct virtual_address_map_event_header {
Expand Down
1 change: 1 addition & 0 deletions uefi/services/hooks/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ CFLAGS := -I$(GNU_EFI)/inc \
-ffunction-sections \
-D GNU_EFI_USE_MS_ABI \
-I . \
-I $(ROOT_DIR)/uefi \
-I $(ROOT_DIR)/shared/include/

LDFLAGS := -ffreestanding -nostdlib -nostartfiles
Expand Down
Loading