diff --git a/boot/bootparams.h b/boot/bootparams.h new file mode 100644 index 0000000..ca16fe6 --- /dev/null +++ b/boot/bootparams.h @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef BOOTPARAMS_H +#define BOOTPARAMS_H +/* + * Provides definitions for the boot params structure passed to us by + * intermediate bootloaders when using the Linux boot protocol. This matches + * the Linux boot_params struct, although we only define the fields we are + * interested in. + * + * Copyright (C) 2020 Martin Whitaker. + */ + +#include + +typedef struct { + uint8_t orig_x; + uint8_t orig_y; + uint16_t ext_mem_k; + uint16_t orig_video_page; + uint8_t orig_video_mode; + uint8_t orig_video_cols; + uint8_t flags; + uint8_t unused2; + uint16_t orig_video_ega_bx; + uint16_t unused3; + uint8_t orig_video_lines; + uint8_t orig_video_isVGA; + uint16_t orig_video_points; + + uint16_t lfb_width; + uint16_t lfb_height; + uint16_t lfb_depth; + uint32_t lfb_base; + uint32_t lfb_size; + uint16_t cl_magic, cl_offset; + uint16_t lfb_linelength; + uint8_t red_size; + uint8_t red_pos; + uint8_t green_size; + uint8_t green_pos; + uint8_t blue_size; + uint8_t blue_pos; + uint8_t rsvd_size; + uint8_t rsvd_pos; + uint16_t vesapm_seg; + uint16_t vesapm_off; + uint16_t pages; + uint16_t vesa_attributes; + uint32_t capabilities; + uint32_t ext_lfb_base; + uint8_t _reserved[2]; +} __attribute__((packed)) screen_info_t; + +#define VIDEO_TYPE_VLFB 0x23 // VESA VGA in graphic mode +#define VIDEO_TYPE_EFI 0x70 // EFI graphic mode + +#define LFB_CAPABILITY_64BIT_BASE (1 << 1) + +typedef struct { + uint32_t loader_signature; + uint32_t sys_tab; + uint32_t mem_desc_size; + uint32_t mem_desc_version; + uint32_t mem_map; + uint32_t mem_map_size; + uint32_t sys_tab_hi; + uint32_t mem_map_hi; +} __attribute__((packed)) efi_info_t; + +#define EFI32_LOADER_SIGNATURE ('E' | ('L' << 8) | ('3' << 16) | ('2' << 24)) +#define EFI64_LOADER_SIGNATURE ('E' | ('L' << 8) | ('6' << 16) | ('4' << 24)) + +typedef enum { + E820_NONE = 0, + E820_RAM = 1, + E820_RESERVED = 2, + E820_ACPI = 3, // usable as RAM once ACPI tables have been read + E820_NVS = 4 +} e820_type_t; + +typedef struct { + uint64_t addr; + uint64_t size; + uint32_t type; +} __attribute__((packed)) e820_entry_t; + +typedef struct { + screen_info_t screen_info; + uint8_t unused1[0x1c0 - 0x040]; + efi_info_t efi_info; + uint8_t unused2[0x1e8 - 0x1e0]; + uint8_t e820_entries; + uint8_t unused3[0x214 - 0x1e9]; + uint32_t code32_start; + uint8_t unused4[0x2d0 - 0x218]; + e820_entry_t e820_map[E820_MAP_SIZE]; + uint8_t unused5[0xeec - 0xd00]; +} __attribute__((packed)) boot_params_t; + +#endif /* BOOTPARAMS_H */ diff --git a/system/pmem.c b/system/pmem.c index 39366db..3a19bd6 100644 --- a/system/pmem.c +++ b/system/pmem.c @@ -12,6 +12,7 @@ #include #include "boot.h" +#include "bootparams.h" #include "memsize.h" @@ -28,28 +29,6 @@ #define RES_START 0x0a0000 #define RES_END 0x100000 -//------------------------------------------------------------------------------ -// Types -//------------------------------------------------------------------------------ - -// The following definition must match the Linux e820_type enum. - -typedef enum { - E820_NONE = 0, - E820_RAM = 1, - E820_RESERVED = 2, - E820_ACPI = 3, // usable as RAM once ACPI tables have been read - E820_NVS = 4 -} e820_type_t; - -// The following definition must match the Linux e820_entry struct. - -typedef struct { - uint64_t addr; - uint64_t size; - uint32_t type; -} __attribute__((packed)) e820_entry_t; - //------------------------------------------------------------------------------ // Public Variables //------------------------------------------------------------------------------ @@ -277,12 +256,10 @@ void pmem_init(void) e820_entry_t sanitized_map[E820_MAP_SIZE]; num_pm_pages = 0; - - const e820_entry_t *e820_map = (e820_entry_t *)(boot_params_addr + E820_MAP); - int e820_entries = *(uint8_t *)(boot_params_addr + E820_ENTRIES); + const boot_params_t *boot_params = (boot_params_t *)boot_params_addr; - int sanitized_entries = sanitize_e820_map(sanitized_map, e820_map, e820_entries); + int sanitized_entries = sanitize_e820_map(sanitized_map, boot_params->e820_map, boot_params->e820_entries); init_pm_map(sanitized_map, sanitized_entries); sort_pm_map(); diff --git a/system/screen.c b/system/screen.c index df5cecc..b131bca 100644 --- a/system/screen.c +++ b/system/screen.c @@ -5,70 +5,17 @@ #include #include "boot.h" +#include "bootparams.h" #include "font.h" #include "vmem.h" #include "screen.h" -//------------------------------------------------------------------------------ -// Constants -//------------------------------------------------------------------------------ - -// screen_info.orig_video_isVGA values. - -#define VIDEO_TYPE_VLFB 0x23 // VESA VGA in graphic mode -#define VIDEO_TYPE_EFI 0x70 // EFI graphic mode - -// screen_info.capabilities values. - -#define LFB_CAPABILITY_64BIT_BASE (1 << 1) - //------------------------------------------------------------------------------ // Types //------------------------------------------------------------------------------ -// The following definition must match the Linux screen_info struct. - -typedef struct { - uint8_t orig_x; - uint8_t orig_y; - uint16_t ext_mem_k; - uint16_t orig_video_page; - uint8_t orig_video_mode; - uint8_t orig_video_cols; - uint8_t flags; - uint8_t unused2; - uint16_t orig_video_ega_bx; - uint16_t unused3; - uint8_t orig_video_lines; - uint8_t orig_video_isVGA; - uint16_t orig_video_points; - - uint16_t lfb_width; - uint16_t lfb_height; - uint16_t lfb_depth; - uint32_t lfb_base; - uint32_t lfb_size; - uint16_t cl_magic, cl_offset; - uint16_t lfb_linelength; - uint8_t red_size; - uint8_t red_pos; - uint8_t green_size; - uint8_t green_pos; - uint8_t blue_size; - uint8_t blue_pos; - uint8_t rsvd_size; - uint8_t rsvd_pos; - uint16_t vesapm_seg; - uint16_t vesapm_off; - uint16_t pages; - uint16_t vesa_attributes; - uint32_t capabilities; - uint32_t ext_lfb_base; - uint8_t _reserved[2]; -} __attribute__((packed)) screen_info_t; - typedef struct { uint8_t r; uint8_t g; @@ -206,7 +153,9 @@ static void put_value(int row, int col, uint16_t value) void screen_init(void) { - const screen_info_t *screen_info = (screen_info_t *)boot_params_addr; + const boot_params_t *boot_params = (boot_params_t *)boot_params_addr; + + const screen_info_t *screen_info = &boot_params->screen_info; bool use_lfb = screen_info->orig_video_isVGA == VIDEO_TYPE_VLFB || screen_info->orig_video_isVGA == VIDEO_TYPE_EFI; diff --git a/system/smp.c b/system/smp.c index 242729e..ab61557 100644 --- a/system/smp.c +++ b/system/smp.c @@ -16,6 +16,7 @@ #include #include "boot.h" +#include "bootparams.h" #include "memsize.h" #include "pmem.h" @@ -113,11 +114,6 @@ #define MADT_PF_ENABLED 0x1 #define MADT_PF_ONLINE_CAPABLE 0x2 -// Linux EFI loader signatures - -#define EL32Signature ('E' | ('L' << 8) | ('3' << 16) | ('2' << 24)) -#define EL64Signature ('E' | ('L' << 8) | ('6' << 16) | ('4' << 24)) - // Private memory heap used for AP trampoline and synchronisation objects #define HEAP_BASE_ADDR (smp_page << PAGE_SHIFT) @@ -288,19 +284,6 @@ typedef struct { uint64_t table; } efi64_config_table_t; -// The following definition must match the Linux efi_info struct. - -typedef struct { - uint32_t loader_signature; - uint32_t sys_tab; - uint32_t mem_desc_size; - uint32_t mem_desc_version; - uint32_t mem_map; - uint32_t mem_map_size; - uint32_t sys_tab_hi; - uint32_t mem_map_hi; -} efi_info_t; - //------------------------------------------------------------------------------ // Private Variables //------------------------------------------------------------------------------ @@ -574,16 +557,18 @@ static rsdp_t *find_rsdp_in_efi64_system_table(efi64_system_table_t *system_tabl static bool find_cpus_in_rsdp(void) { - efi_info_t *efi_info = (efi_info_t *)(boot_params_addr + 0x1c0); + const boot_params_t *boot_params = (boot_params_t *)boot_params_addr; + + const efi_info_t *efi_info = &boot_params->efi_info; // Search for the RSDP rsdp_t *rp = NULL; - if (efi_info->loader_signature == EL32Signature) { + if (efi_info->loader_signature == EFI32_LOADER_SIGNATURE) { uintptr_t system_table_addr = (uintptr_t)efi_info->sys_tab; rp = find_rsdp_in_efi32_system_table((efi32_system_table_t *)system_table_addr); } #ifdef __x86_64__ - if (efi_info->loader_signature == EL64Signature) { + if (efi_info->loader_signature == EFI64_LOADER_SIGNATURE) { uintptr_t system_table_addr = (uintptr_t)efi_info->sys_tab_hi << 32 | (uintptr_t)efi_info->sys_tab; rp = find_rsdp_in_efi64_system_table((efi64_system_table_t *)system_table_addr); }