ekern

ekern.git
git clone git://git.lenczewski.org/ekern.git
Log | Files | Refs | README | LICENSE

commit 99dc572bec5238dfef9437ba408b7a1961dacfd2
parent 906535a2d8f653067fc7da103f870f2139a5edc7
Author: MikoĊ‚aj Lenczewski <mblenczewski@gmail.com>
Date:   Sat, 14 Sep 2024 22:27:27 +0000

Cleanup build system again, split kernel into ksetup() and kmain()

Diffstat:
Mbuild.sh | 64+++++++++++++++++++++++++++++-----------------------------------
Minclude/efi.h | 739++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Ainclude/kernel.h | 27+++++++++++++++++++++++++++
Ainclude/pe.h | 41+++++++++++++++++++++++++++++++++++++++++
Rscripts/qemu-aarch64.sh -> scripts/qemu-arm64.sh | 0
Asrc/arch/amd64/setup.c | 7+++++++
Asrc/arch/arm64/setup.c | 7+++++++
Dsrc/boot.c | 26--------------------------
Asrc/efistub.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/efistub.ld | 20--------------------
Asrc/header.S | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kernel.c | 14+++++++++++++-
Dsrc/kernel.ld | 20--------------------
Asrc/kernel.lds | 38++++++++++++++++++++++++++++++++++++++
14 files changed, 781 insertions(+), 450 deletions(-)

diff --git a/build.sh b/build.sh @@ -1,61 +1,61 @@ #!/bin/sh -#CONFIG_EFISTUB=1 - TARGET="${1:-amd64}" AS="clang" CC="clang" -LD="lld" +LD="ld.lld" +NM="llvm-nm" OBJCOPY="llvm-objcopy" -WARNINGS="-Wall -Wextra -Wpedantic -Werror" -CFLAGS="-std=c11 -ffreestanding -fno-stack-protector -fshort-wchar -mno-red-zone" +WARNINGS="-Wall -Wextra -Wpedantic -Werror -Wno-fixed-enum-extension" +CFLAGS="-std=c11 -ffreestanding -fPIC -fno-stack-protector -mno-red-zone" CPPFLAGS="-Iinclude" - -BOOT_LDFLAGS="-flavor link -subsystem:efi_application -entry:efi_main" -KERN_LDFLAGS="-flavor ld -e kmain" +LDFLAGS="" case $TARGET in amd64) + TRIPLE="x86_64-none-elf" UEFIARCH="X64" - BOOT_CFLAGS="-target x86_64-unknown-windows $CFLAGS $WARNINGS -Wno-microsoft-fixed-enum" - KERN_CFLAGS="-target x86_64-unknown-gnu $CFLAGS $WARNINGS -Wno-fixed-enum-extension" + KERNARCH="AMD64" ;; - aarch64) + arm64) + TRIPLE="aarch64-none-elf" UEFIARCH="AA64" - BOOT_CFLAGS="-target aarch64-unknown-windows $CFLAGS $WARNINGS -Wno-microsoft-fixed-enum" - KERN_CFLAGS="-target aarch64-unknown-gnu $CFLAGS $WARNINGS -Wno-fixed-enum-extension" + KERNARCH="ARM64" ;; *) - echo "Unsupported target: $TARGET, must be one of: amd64 aarch64" + echo "Unsupported target: $TARGET, must be one of: amd64 arm64" exit 1 ;; esac +KASFLAGS="-target $TRIPLE" +KCFLAGS="-target $TRIPLE $CFLAGS $WARNINGS" +KCPPFLAGS="$CPPFLAGS -D__KERNEL__=1 -D__KERNEL_${KERNARCH}__=1" +KLDFLAGS="$LDFLAGS -T src/kernel.lds" + set -ex mkdir -p bin obj mnt -if [ "${CONFIG_EFISTUB:-z}" = "z" ]; then - -# build kernel loader -$CC -o obj/boot.o -c src/boot.c $BOOT_CFLAGS $CPPFLAGS -$LD $BOOT_LDFLAGS -out:bin/boot.efi obj/boot.o - # build kernel -$CC -o obj/kernel.o -c src/kernel.c $KERN_CFLAGS $CPPFLAGS -$LD $KERN_LDFLAGS -T src/kernel.ld -o bin/kernel.elf obj/kernel.o +$CC $KCFLAGS $KCPPFLAGS -c src/efistub.c -o obj/efistub.o +$CC $KCFLAGS $KCPPFLAGS -c src/kernel.c -o obj/kernel.o +$LD $KLDFLAGS obj/efistub.o obj/kernel.o -o bin/kernel.elf -else +## generate kernel symbol offset header +SEDSCRIPT="s/^\([0-9a-fA-F]*\) [a-zA-Z] \(__.*\)/#define \2 0x\1/p" +$NM bin/kernel.elf | sed -ne "$SEDSCRIPT" > obj/voffset.h -# build kernel -$AS -o obj/efistub.o -c src/efistub-$TARGET.asm -$CC -o obj/kernel.o -c src/kernel.c $KERN_CFLAGS $CPPFLAGS -$LD -flavor ld -T src/efistub.ld -o bin/kernel.efi obj/efistub.o obj/kernel.o +## generate efistub +$AS $KASFLAGS $KCPPFLAGS -Iobj -c src/header.S -o obj/header.o -fi +## create binary image +$OBJCOPY -O binary -R .head -S bin/kernel.elf bin/kernel.bin +$OBJCOPY -O binary -S obj/header.o bin/header.bin +cat bin/header.bin bin/kernel.bin > bin/kernel.efi # build disk image (64 MiB ESP, 32 MiB data) # --- @@ -76,13 +76,7 @@ dd if=/dev/zero of=mnt/esp.img bs=512 count=131072 status=none mformat -i mnt/esp.img -F :: mmd -i mnt/esp.img ::/EFI ::/EFI/BOOT - -if [ "${CONFIG_EFISTUB:-z}" = "z" ]; then - mcopy -i mnt/esp.img bin/boot.efi ::/EFI/BOOT/BOOT$UEFIARCH.EFI - mcopy -i mnt/esp.img bin/kernel.elf ::/EFI/BOOT/kernel.elf -else - mcopy -i mnt/esp.img bin/kernel.efi ::/EFI/BOOT/BOOT$UEFIARCH.EFI -fi +mcopy -i mnt/esp.img bin/kernel.efi ::/EFI/BOOT/BOOT$UEFIARCH.EFI dd if=mnt/esp.img of=mnt/disk.img bs=512 count=131072 seek=2048 conv=notrunc status=none diff --git a/include/efi.h b/include/efi.h @@ -1,19 +1,27 @@ +/* UEFI definitions, generated from the uefi-2.10 docs + * -- + * see: https://uefi.org/specs/UEFI/2.10/index.html + */ + #ifndef EFI_H #define EFI_H -/* generated from the uefi-2.10 docs */ - #define IN #define OUT #define OPTIONAL #define CONST const -#define EFIAPI +#define EFIAPI __attribute__((ms_abi)) #include <stdalign.h> #include <stddef.h> #include <stdint.h> +/* 2.3.1. Data Types + * -- + * see: https://uefi.org/specs/UEFI/2.10/02_Overview.html#data-types + */ + typedef int8_t b8; #define true 1 @@ -50,62 +58,47 @@ typedef struct efi_guid { typedef umm efi_status_t; -#define EFI_ERROR 0x8000000000000000 -#define EFI_WARNING 0x0000000000000000 +typedef struct efi_handle { + void *v; +} efi_handle_t; -#define EFIERR(err) (EFI_ERROR | (err)) -#define EFIWARN(err) (EFI_WARNING | (err)) +typedef struct efi_event { + void *v; +} efi_event_t; -enum efi_status : u64 { - EFI_SUCCESS = 0, +typedef struct efi_lba { + u64 v; +} efi_lba_t; - EFI_WARN_UNKNOWN_GLYPH = EFIWARN(1), - EFI_WARN_DELETE_FAILURE = EFIWARN(2), - EFI_WARN_WRITE_FAILURE = EFIWARN(3), - EFI_WARN_BUFFER_TOO_SMALL = EFIWARN(4), - EFI_WARN_STALE_DATA = EFIWARN(5), - EFI_WARN_FILE_SYSTEM = EFIWARN(6), - EFI_WARN_RESET_REQUIRED = EFIWARN(7), +typedef struct efi_tpl { + umm v; +} efi_tpl_t; - EFI_LOAD_ERROR = EFIERR(1), - EFI_INVALID_PARAMETER = EFIERR(2), - EFI_UNSUPPORTED = EFIERR(3), - EFI_BAD_BUFFER_SIZE = EFIERR(4), - EFI_BUFFER_TOO_SMALL = EFIERR(5), - EFI_NOT_READY = EFIERR(6), - EFI_DEVICE_ERROR = EFIERR(7), - EFI_WRITE_PROTECTED = EFIERR(8), - EFI_OUT_OF_RESOURCES = EFIERR(9), - EFI_VOLUME_CORRUPTED = EFIERR(10), - EFI_VOLUME_FULL = EFIERR(11), - EFI_NO_MEDIA = EFIERR(12), - EFI_MEDIA_CHANGED = EFIERR(13), - EFI_NOT_FOUND = EFIERR(14), - EFI_ACCESS_DENIED = EFIERR(15), - EFI_NO_RESPONSE = EFIERR(16), - EFI_NO_MAPPING = EFIERR(17), - EFI_TIMEOUT = EFIERR(18), - EFI_NOT_STARTED = EFIERR(19), - EFI_ALREADY_STARTED = EFIERR(20), - EFI_ABORTED = EFIERR(21), - EFI_ICMP_ERROR = EFIERR(22), - EFI_TFTP_ERROR = EFIERR(23), - EFI_PROTOCOL_ERROR = EFIERR(24), - EFI_INCOMPATIBLE_VERSION = EFIERR(25), - EFI_SECURITY_VIOLATION = EFIERR(26), - EFI_CRC_ERROR = EFIERR(27), - EFI_END_OF_MEDIA = EFIERR(28), - EFI_END_OF_FILE = EFIERR(31), - EFI_INVALID_LANGUAGE = EFIERR(32), - EFI_COMPROMISED_DATA = EFIERR(33), - EFI_IP_ADDRESS_CONFLICT = EFIERR(34), - EFI_HTTP_ERROR = EFIERR(35), +struct efi_mac_addr { + u8 vs[32]; }; -typedef void *efi_handle_t; -typedef void *efi_event_t; -typedef u64 efi_lba_t; -typedef umm efi_tpl_t; +struct efi_ipv4_addr { + u8 vs[4]; +}; + +struct efi_ipv6_addr { + u8 vs[16]; +}; + +union efi_ip_addr { + struct efi_ipv4_addr v4; + struct efi_ipv6_addr v6; +}; + +/* 4. EFI System Table + * --- + * see: https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html + */ + +#define EFI_IMAGE_ENTRY_POINT(name) \ + efi_status_t (EFIAPI name) (IN efi_handle_t image_handle, \ + IN struct efi_system_table *system_table) struct efi_table_header { u64 signature; @@ -115,11 +108,6 @@ struct efi_table_header { u32 reserved0; }; -/* system table - * --- - * see: https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html - */ - struct efi_system_table { struct efi_table_header hdr; @@ -142,8 +130,19 @@ struct efi_system_table { struct efi_configuration_table *configuration_table; }; -/* boot services +/* 4.6. EFI Configuration Table & Properties Table + * --- + * see: https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html#efi-configuration-table-properties-table + */ + +struct efi_configuration_table { + efi_guid_t vendor_guid; + void *vendor_table; +}; + +/* 7. Services - Boot Services * --- + * see: https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html#efi-boot-services-table * see: https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html */ @@ -156,25 +155,23 @@ struct efi_system_table { #define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 #define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 -typedef umm efi_tpl_t; - #define TPL_APPLICATION 4 #define TPL_CALLBACK 8 #define TPL_NOTIFY 16 #define TPL_HIGH_LEVEL 31 #define EFI_EVENT_NOTIFY(name) \ - void (EFIAPI name) (IN efi_event_t event, \ - IN void *context) + void (EFIAPI *name) (IN efi_event_t event, \ + IN void *context) typedef EFI_EVENT_NOTIFY(efi_event_notify_t); #define EFI_CREATE_EVENT(name) \ - efi_status_t (EFIAPI name) (IN u32 type, \ - IN efi_tpl_t notify_tpl, \ - IN efi_event_notify_t * OPTIONAL notify_function, \ - IN void * OPTIONAL notify_context, \ - OUT efi_event_t *event) + efi_status_t (EFIAPI *name) (IN u32 type, \ + IN efi_tpl_t notify_tpl, \ + IN efi_event_notify_t * OPTIONAL notify_function, \ + IN void * OPTIONAL notify_context, \ + OUT efi_event_t *event) #define EFI_EVENT_GROUP_EXIT_BOOT_SERVICES \ ((efi_guid_t) {.vs = {0x27abf055, 0xb1b84c26, 0x8048748f, 0x37baa2df}}) @@ -198,27 +195,27 @@ typedef EFI_EVENT_NOTIFY(efi_event_notify_t); ((efi_guid_t) {.vs = {0x62ddaba56, 0x13fb485a, 0xa8daa3dd, 0x7912cb6b}}) #define EFI_CREATE_EVENT_EX(name) \ - efi_status_t (EFIAPI name) (IN u32 type, \ - IN efi_tpl_t notify_tpl, \ - IN efi_event_notify_t * OPTIONAL notify_function, \ - IN void CONST * OPTIONAL notify_context, \ - IN efi_guid_t CONST * OPTIONAL event_group, \ - OUT efi_event_t *event) + efi_status_t (EFIAPI *name) (IN u32 type, \ + IN efi_tpl_t notify_tpl, \ + IN efi_event_notify_t * OPTIONAL notify_function, \ + IN void CONST * OPTIONAL notify_context, \ + IN efi_guid_t CONST * OPTIONAL event_group, \ + OUT efi_event_t *event) #define EFI_CLOSE_EVENT(name) \ - efi_status_t (EFIAPI name) (IN efi_event_t event) + efi_status_t (EFIAPI *name) (IN efi_event_t event) #define EFI_SIGNAL_EVENT(name) \ - efi_status_t (EFIAPI name) (IN efi_event_t event) + efi_status_t (EFIAPI *name) (IN efi_event_t event) #define EFI_WAIT_FOR_EVENT(name) \ - efi_status_t (EFIAPI name) (IN umm number_of_events, \ - IN efi_event_t *event, \ - OUT umm *index) + efi_status_t (EFIAPI *name) (IN umm number_of_events, \ + IN efi_event_t *event, \ + OUT umm *index) #define EFI_CHECK_EVENT(name) \ - efi_status_t (EFIAPI name) (IN efi_event_t event) + efi_status_t (EFIAPI *name) (IN efi_event_t event) enum efi_timer_delay { EFI_TIMER_CANCEL, @@ -227,15 +224,15 @@ enum efi_timer_delay { }; #define EFI_SET_TIMER(name) \ - efi_status_t (EFIAPI name) (IN efi_event_t event, \ - IN enum efi_timer_delay type, \ - IN u64 trigger_time) + efi_status_t (EFIAPI *name) (IN efi_event_t event, \ + IN enum efi_timer_delay type, \ + IN u64 trigger_time) #define EFI_RAISE_TPL(name) \ - efi_tpl_t (EFIAPI name) (IN efi_tpl_t new_tpl) + efi_tpl_t (EFIAPI *name) (IN efi_tpl_t new_tpl) #define EFI_RESTORE_TPL(name) \ - void (EFIAPI name) (IN efi_tpl_t old_tpl) + void (EFIAPI *name) (IN efi_tpl_t old_tpl) enum efi_allocate_type { EFI_ALLOCATE_ANY_PAGES, @@ -264,7 +261,9 @@ enum efi_memory_type { EFI_MAX_MEMORY_TYPE, }; -typedef u64 efi_physical_address_t; +typedef struct efi_physical_address { + u64 v; +} efi_physical_address_t; #define EFI_MEMORY_UC 0x0000000000000001 #define EFI_MEMORY_WC 0x0000000000000002 @@ -283,7 +282,9 @@ typedef u64 efi_physical_address_t; #define EFI_MEMORY_ISA_VALID 0x4000000000000000 #define EFI_MEMORY_ISA_MASK 0x0FFFF00000000000 -typedef u64 efi_virtual_address_t; +typedef struct efi_virtual_address { + u64 v; +} efi_virtual_address_t; #define EFI_MEMORY_DESCRIPTOR_VERSION 1 @@ -296,55 +297,55 @@ struct efi_memory_descriptor { }; #define EFI_ALLOCATE_PAGES(name) \ - efi_status_t (EFIAPI name) (IN enum efi_allocate_type type, \ - IN enum efi_memory_type memory_type, \ - IN umm pages, \ - IN OUT efi_physical_address_t *memory) + efi_status_t (EFIAPI *name) (IN enum efi_allocate_type type, \ + IN enum efi_memory_type memory_type, \ + IN umm pages, \ + IN OUT efi_physical_address_t *memory) #define EFI_FREE_PAGES(name) \ - efi_status_t (EFIAPI name) (IN efi_physical_address_t memory, \ - IN umm pages) + efi_status_t (EFIAPI *name) (IN efi_physical_address_t memory, \ + IN umm pages) #define EFI_GET_MEMORY_MAP(name) \ - efi_status_t (EFIAPI name) (IN OUT umm *memory_map_size, \ - OUT struct efi_memory_descriptor *memory_map, \ - OUT umm *map_key, \ - OUT umm *descriptor_size, \ - OUT u32 *descriptor_version) + efi_status_t (EFIAPI *name) (IN OUT umm *memory_map_size, \ + OUT struct efi_memory_descriptor *memory_map, \ + OUT umm *map_key, \ + OUT umm *descriptor_size, \ + OUT u32 *descriptor_version) #define EFI_ALLOCATE_POOL(name) \ - efi_status_t (EFIAPI name) (IN enum efi_memory_type pool_type, \ - IN umm size, \ - OUT void **buffer) + efi_status_t (EFIAPI *name) (IN enum efi_memory_type pool_type, \ + IN umm size, \ + OUT void **buffer) #define EFI_FREE_POOL(name) \ - efi_status_t (EFIAPI name) (IN void *buffer) + efi_status_t (EFIAPI *name) (IN void *buffer) enum efi_interface_type { EFI_NATIVE_INTERFACE, }; #define EFI_INSTALL_PROTOCOL_INTERFACE(name) \ - efi_status_t (EFIAPI name) (IN OUT efi_handle_t *handle, \ - IN efi_guid_t *protocol, \ - IN enum efi_interface_type interface_type, \ - IN void *interface) + efi_status_t (EFIAPI *name) (IN OUT efi_handle_t *handle, \ + IN efi_guid_t *protocol, \ + IN enum efi_interface_type interface_type, \ + IN void *interface) #define EFI_UNINSTALL_PROTOCOL_INTERFACE(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t handle, \ - IN efi_guid_t *protocol, \ - IN void *interface) + efi_status_t (EFIAPI *name) (IN efi_handle_t handle, \ + IN efi_guid_t *protocol, \ + IN void *interface) #define EFI_REINSTALL_PROTOCOL_INTERFACE(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t handle, \ - IN efi_guid_t *protocol, \ - IN void *old_interface, \ - IN void *new_interface) + efi_status_t (EFIAPI *name) (IN efi_handle_t handle, \ + IN efi_guid_t *protocol, \ + IN void *old_interface, \ + IN void *new_interface) #define EFI_REGISTER_PROTOCOL_NOTIFY(name) \ - efi_status_t (EFIAPI name) (IN efi_guid_t *protocol, \ - IN efi_event_t event, \ - OUT void **registration) + efi_status_t (EFIAPI *name) (IN efi_guid_t *protocol, \ + IN efi_event_t event, \ + OUT void **registration) enum efi_locate_search_type { EFI_ALL_HANDLES, @@ -353,16 +354,16 @@ enum efi_locate_search_type { }; #define EFI_LOCATE_HANDLE(name) \ - efi_status_t (EFIAPI name) (IN enum efi_locate_search_type search_type, \ - IN efi_guid_t *OPTIONAL protocol, \ - IN void *OPTIONAL search_key, \ - IN OUT umm *buffer_size, \ - OUT efi_handle_t *buffer) + efi_status_t (EFIAPI *name) (IN enum efi_locate_search_type search_type, \ + IN efi_guid_t *OPTIONAL protocol, \ + IN void *OPTIONAL search_key, \ + IN OUT umm *buffer_size, \ + OUT efi_handle_t *buffer) #define EFI_HANDLE_PROTOCOL(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t handle, \ - IN efi_guid_t *protocol, \ - OUT void **interface) + efi_status_t (EFIAPI *name) (IN efi_handle_t handle, \ + IN efi_guid_t *protocol, \ + OUT void **interface) // TODO: implement definitions struct efi_device_path_protocol { @@ -372,9 +373,9 @@ struct efi_device_path_protocol { }; #define EFI_LOCATE_DEVICE_PATH(name) \ - efi_status_t (EFIAPI name) (IN efi_guid_t *protocol, \ - IN OUT struct efi_device_path_protocol **device_path, \ - OUT efi_handle_t *device) + efi_status_t (EFIAPI *name) (IN efi_guid_t *protocol, \ + IN OUT struct efi_device_path_protocol **device_path, \ + OUT efi_handle_t *device) #define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 #define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 @@ -384,18 +385,18 @@ struct efi_device_path_protocol { #define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 #define EFI_OPEN_PROTOCOL(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t handle, \ - IN efi_guid_t *protocol, \ - OUT void **OPTIONAL interface, \ - IN efi_handle_t agent_handle, \ - IN efi_handle_t controller_handle, \ - IN u32 attributes) + efi_status_t (EFIAPI *name) (IN efi_handle_t handle, \ + IN efi_guid_t *protocol, \ + OUT void **OPTIONAL interface, \ + IN efi_handle_t agent_handle, \ + IN efi_handle_t controller_handle, \ + IN u32 attributes) #define EFI_CLOSE_PROTOCOL(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t handle, \ - IN efi_guid_t *protocol, \ - IN efi_handle_t agent_handle, \ - IN efi_handle_t controller_handle) + efi_status_t (EFIAPI *name) (IN efi_handle_t handle, \ + IN efi_guid_t *protocol, \ + IN efi_handle_t agent_handle, \ + IN efi_handle_t controller_handle) struct efi_open_protocol_information_entry { efi_handle_t agent_handle; @@ -405,171 +406,166 @@ struct efi_open_protocol_information_entry { }; #define EFI_OPEN_PROTOCOL_INFORMATION(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t handle, \ - IN efi_guid_t *protocol, \ - OUT struct efi_open_protocol_information_entry **entry_buffer, \ - OUT umm *entry_count) + efi_status_t (EFIAPI *name) (IN efi_handle_t handle, \ + IN efi_guid_t *protocol, \ + OUT struct efi_open_protocol_information_entry **entry_buffer, \ + OUT umm *entry_count) #define EFI_CONNECT_CONTROLLER(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t controller_handle, \ - IN efi_handle_t *OPTIONAL driver_image_handle, \ - IN struct efi_device_path_protocol *OPTIONAL remaining_device_path, \ - IN b8 recursive) + efi_status_t (EFIAPI *name) (IN efi_handle_t controller_handle, \ + IN efi_handle_t *OPTIONAL driver_image_handle, \ + IN struct efi_device_path_protocol *OPTIONAL remaining_device_path, \ + IN b8 recursive) #define EFI_DISCONNECT_CONTROLLER(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t controller_handle, \ - IN efi_handle_t OPTIONAL driver_image_handle, \ - IN efi_handle_t OPTIONAL child_handle) + efi_status_t (EFIAPI *name) (IN efi_handle_t controller_handle, \ + IN efi_handle_t OPTIONAL driver_image_handle, \ + IN efi_handle_t OPTIONAL child_handle) #define EFI_PROTOCOLS_PER_HANDLE(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t handle, \ - OUT efi_guid_t ***protocol_buffer, \ - OUT umm *protocol_buffer_count) + efi_status_t (EFIAPI *name) (IN efi_handle_t handle, \ + OUT efi_guid_t ***protocol_buffer, \ + OUT umm *protocol_buffer_count) #define EFI_LOCATE_HANDLE_BUFFER(name) \ - efi_status_t (EFIAPI name) (IN enum efi_locate_search_type search_type, \ - IN efi_guid_t *OPTIONAL protocol, \ - IN void *OPTIONAL search_key, \ - OUT umm *no_handles, \ - OUT efi_handle_t **buffer) + efi_status_t (EFIAPI *name) (IN enum efi_locate_search_type search_type, \ + IN efi_guid_t *OPTIONAL protocol, \ + IN void *OPTIONAL search_key, \ + OUT umm *no_handles, \ + OUT efi_handle_t **buffer) #define EFI_LOCATE_PROTOCOL(name) \ - efi_status_t (EFIAPI name) (IN efi_guid_t *protocol, \ - IN void *OPTIONAL registration, \ - OUT void **interface) + efi_status_t (EFIAPI *name) (IN efi_guid_t *protocol, \ + IN void *OPTIONAL registration, \ + OUT void **interface) #define EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES(name) \ - efi_status_t (EFIAPI name) (IN OUT efi_handle_t *handle, ...) + efi_status_t (EFIAPI *name) (IN OUT efi_handle_t *handle, ...) #define EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t handle, ...) + efi_status_t (EFIAPI *name) (IN efi_handle_t handle, ...) #define EFI_IMAGE_LOAD(name) \ - efi_status_t (EFIAPI name) (IN b8 boot_policy, \ - IN efi_handle_t parent_image_handle, \ - IN struct efi_device_path_protocol *OPTIONAL device_path, \ - IN void *OPTIONAL source_buffer, \ - IN umm source_size, \ - OUT efi_handle_t *image_handle) + efi_status_t (EFIAPI *name) (IN b8 boot_policy, \ + IN efi_handle_t parent_image_handle, \ + IN struct efi_device_path_protocol *OPTIONAL device_path, \ + IN void *OPTIONAL source_buffer, \ + IN umm source_size, \ + OUT efi_handle_t *image_handle) #define EFI_IMAGE_START(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t image_handle, \ - OUT umm *exit_data_size, \ - OUT c16 **OPTIONAL exit_data) + efi_status_t (EFIAPI *name) (IN efi_handle_t image_handle, \ + OUT umm *exit_data_size, \ + OUT c16 **OPTIONAL exit_data) #define EFI_IMAGE_UNLOAD(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t image_handle) - -#define EFI_IMAGE_ENTRY_POINT(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t image_handle, \ - IN struct efi_system_table *system_table) + efi_status_t (EFIAPI *name) (IN efi_handle_t image_handle) #define EFI_EXIT(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t image_handle, \ - IN efi_status_t exit_status, \ - IN umm exit_data_size, \ - IN c16 *OPTIONAL exit_data) + efi_status_t (EFIAPI *name) (IN efi_handle_t image_handle, \ + IN efi_status_t exit_status, \ + IN umm exit_data_size, \ + IN c16 *OPTIONAL exit_data) #define EFI_EXIT_BOOT_SERVICES(name) \ - efi_status_t (EFIAPI name) (IN efi_handle_t image_handle, \ - IN umm map_key) + efi_status_t (EFIAPI *name) (IN efi_handle_t image_handle, \ + IN umm map_key) #define EFI_SET_WATCHDOG_TIMER(name) \ - efi_status_t (EFIAPI name) (IN umm timeout, \ - IN u64 watchdog_code, \ - IN umm data_size, \ - IN c16 *OPTIONAL watchdog_data) + efi_status_t (EFIAPI *name) (IN umm timeout, \ + IN u64 watchdog_code, \ + IN umm data_size, \ + IN c16 *OPTIONAL watchdog_data) #define EFI_STALL(name) \ - efi_status_t (EFIAPI name) (IN umm microseconds) + efi_status_t (EFIAPI *name) (IN umm microseconds) #define EFI_COPY_MEM(name) \ - efi_status_t (EFIAPI name) (IN void *destination, \ - IN void *source, \ - IN umm length) + efi_status_t (EFIAPI *name) (IN void *destination, \ + IN void *source, \ + IN umm length) #define EFI_SET_MEM(name) \ - efi_status_t (EFIAPI name) (IN void *buffer, \ - IN umm size, \ + efi_status_t (EFIAPI *name) (IN void *buffer, \ + IN umm size, \ IN u8 value) #define EFI_GET_NEXT_MONOTONIC_COUNT(name) \ - efi_status_t (EFIAPI name) (OUT u64 *count) + efi_status_t (EFIAPI *name) (OUT u64 *count) #define EFI_INSTALL_CONFIGURATION_TABLE(name) \ - efi_status_t (EFIAPI name) (IN efi_guid_t *guid, \ - IN void *table) + efi_status_t (EFIAPI *name) (IN efi_guid_t *guid, \ + IN void *table) #define EFI_CALCULATE_CRC32(name) \ - efi_status_t (EFIAPI name) (IN void *data, \ - IN umm data_size, \ - OUT u32 *crc32) + efi_status_t (EFIAPI *name) (IN void *data, \ + IN umm data_size, \ + OUT u32 *crc32) struct efi_boot_services { struct efi_table_header hdr; - EFI_RAISE_TPL(*raise_tpl); - EFI_RESTORE_TPL(*restore_tpl); - - EFI_ALLOCATE_PAGES(*allocate_pages); - EFI_FREE_PAGES(*free_pages); - EFI_GET_MEMORY_MAP(*get_memory_map); - EFI_ALLOCATE_POOL(*allocate_pool); - EFI_FREE_POOL(*free_pool); - - EFI_CREATE_EVENT(*create_event); - EFI_SET_TIMER(*set_timer); - EFI_WAIT_FOR_EVENT(*wait_for_event); - EFI_SIGNAL_EVENT(*signal_event); - EFI_CLOSE_EVENT(*close_event); - EFI_CHECK_EVENT(*check_event); - - EFI_INSTALL_PROTOCOL_INTERFACE(*install_protocol_interface); - EFI_REINSTALL_PROTOCOL_INTERFACE(*reinstall_protocol_interface); - EFI_UNINSTALL_PROTOCOL_INTERFACE(*uninstall_protocol_interface); - EFI_HANDLE_PROTOCOL(*handle_protocol); + EFI_RAISE_TPL(raise_tpl); + EFI_RESTORE_TPL(restore_tpl); + + EFI_ALLOCATE_PAGES(allocate_pages); + EFI_FREE_PAGES(free_pages); + EFI_GET_MEMORY_MAP(get_memory_map); + EFI_ALLOCATE_POOL(allocate_pool); + EFI_FREE_POOL(free_pool); + + EFI_CREATE_EVENT(create_event); + EFI_SET_TIMER(set_timer); + EFI_WAIT_FOR_EVENT(wait_for_event); + EFI_SIGNAL_EVENT(signal_event); + EFI_CLOSE_EVENT(close_event); + EFI_CHECK_EVENT(check_event); + + EFI_INSTALL_PROTOCOL_INTERFACE(install_protocol_interface); + EFI_REINSTALL_PROTOCOL_INTERFACE(reinstall_protocol_interface); + EFI_UNINSTALL_PROTOCOL_INTERFACE(uninstall_protocol_interface); + EFI_HANDLE_PROTOCOL(handle_protocol); void *reserved0; - EFI_REGISTER_PROTOCOL_NOTIFY(*register_protocol_notify); - EFI_LOCATE_HANDLE(*locate_handle); - EFI_LOCATE_DEVICE_PATH(*locate_device_path); - EFI_INSTALL_CONFIGURATION_TABLE(*install_configuration_table); + EFI_REGISTER_PROTOCOL_NOTIFY(register_protocol_notify); + EFI_LOCATE_HANDLE(locate_handle); + EFI_LOCATE_DEVICE_PATH(locate_device_path); + EFI_INSTALL_CONFIGURATION_TABLE(install_configuration_table); - EFI_IMAGE_LOAD(*load_image); - EFI_IMAGE_START(*start_image); - EFI_EXIT(*exit); - EFI_IMAGE_UNLOAD(*unload_image); - EFI_EXIT_BOOT_SERVICES(*exit_boot_services); + EFI_IMAGE_LOAD(load_image); + EFI_IMAGE_START(start_image); + EFI_EXIT(exit); + EFI_IMAGE_UNLOAD(unload_image); + EFI_EXIT_BOOT_SERVICES(exit_boot_services); - EFI_GET_NEXT_MONOTONIC_COUNT(*get_next_monotonic_count); - EFI_STALL(*stall); - EFI_SET_WATCHDOG_TIMER(*set_watchdog_timer); + EFI_GET_NEXT_MONOTONIC_COUNT(get_next_monotonic_count); + EFI_STALL(stall); + EFI_SET_WATCHDOG_TIMER(set_watchdog_timer); // EFI 1.1+ - EFI_CONNECT_CONTROLLER(*connect_controller); - EFI_DISCONNECT_CONTROLLER(*disconnect_controller); + EFI_CONNECT_CONTROLLER(connect_controller); + EFI_DISCONNECT_CONTROLLER(disconnect_controller); - EFI_OPEN_PROTOCOL(*open_protocol); - EFI_CLOSE_PROTOCOL(*close_protocol); - EFI_OPEN_PROTOCOL_INFORMATION(*open_protocol_information); - EFI_PROTOCOLS_PER_HANDLE(*protocols_per_handle); - EFI_LOCATE_HANDLE_BUFFER(*locate_handle_buffer); - EFI_LOCATE_PROTOCOL(*locate_protocol); - EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES(*install_multiple_protocol_interfaces); - EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES(*uninstall_multiple_protocol_interfaces); + EFI_OPEN_PROTOCOL(open_protocol); + EFI_CLOSE_PROTOCOL(close_protocol); + EFI_OPEN_PROTOCOL_INFORMATION(open_protocol_information); + EFI_PROTOCOLS_PER_HANDLE(protocols_per_handle); + EFI_LOCATE_HANDLE_BUFFER(locate_handle_buffer); + EFI_LOCATE_PROTOCOL(locate_protocol); + EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES(install_multiple_protocol_interfaces); + EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES(uninstall_multiple_protocol_interfaces); - EFI_CALCULATE_CRC32(*calculate_crc32); + EFI_CALCULATE_CRC32(calculate_crc32); - EFI_COPY_MEM(*copy_mem); - EFI_SET_MEM(*set_mem); + EFI_COPY_MEM(copy_mem); + EFI_SET_MEM(set_mem); // UEFI 2.0+ - EFI_CREATE_EVENT_EX(*create_event_ex); + EFI_CREATE_EVENT_EX(create_event_ex); }; - - -/* runtime services +/* 8. Services - Runtime Services * --- + * see: https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html#efi-runtime-services-table * see: https://uefi.org/specs/UEFI/2.10/08_Services_Runtime_Services.html */ @@ -613,16 +609,16 @@ struct efi_variable_authentication_3_cert_id { }; #define EFI_GET_VARIABLE(name) \ - efi_status_t (EFIAPI name) (IN c16 *variable_name, \ - IN efi_guid_t *vendor_guid, \ - OUT u32 *OPTIONAL attributes, \ - IN OUT umm *data_size, \ - OUT void *OPTIONAL data) + efi_status_t (EFIAPI *name) (IN c16 *variable_name, \ + IN efi_guid_t *vendor_guid, \ + OUT u32 *OPTIONAL attributes, \ + IN OUT umm *data_size, \ + OUT void *OPTIONAL data) #define EFI_GET_NEXT_VARIABLE_NAME(name) \ - efi_status_t (EFIAPI name) (IN OUT umm *variable_name_size, \ - IN OUT c16 *variable_name, \ - IN OUT efi_guid_t *vendor_guid) + efi_status_t (EFIAPI *name) (IN OUT umm *variable_name_size, \ + IN OUT c16 *variable_name, \ + IN OUT efi_guid_t *vendor_guid) struct win_certificate_uefi_guid { u8 pad0; // TODO @@ -654,17 +650,17 @@ struct efi_variable_authentication_3_nonce { }; #define EFI_SET_VARIABLE(name) \ - efi_status_t (EFIAPI name) (IN c16 *variable_name, \ - IN efi_guid_t *vendor_guid, \ - IN u32 attributes, \ - IN umm data_size, \ - IN void *data) + efi_status_t (EFIAPI *name) (IN c16 *variable_name, \ + IN efi_guid_t *vendor_guid, \ + IN u32 attributes, \ + IN umm data_size, \ + IN void *data) #define EFI_QUERY_VARIABLE_INFO(name) \ - efi_status_t (EFIAPI name) (IN u32 attributes, \ - OUT u64 *maximum_variable_storage_size, \ - OUT u64 *remaining_variable_storage_size, \ - OUT u64 *maximum_variable_size) + efi_status_t (EFIAPI *name) (IN u32 attributes, \ + OUT u64 *maximum_variable_storage_size, \ + OUT u64 *remaining_variable_storage_size, \ + OUT u64 *maximum_variable_size) struct efi_time_capabilities { u32 resolution; @@ -673,32 +669,32 @@ struct efi_time_capabilities { }; #define EFI_GET_TIME(name) \ - efi_status_t (EFIAPI name) (OUT struct efi_time *time, \ - OUT struct efi_time_capabilities * OPTIONAL capabilities) + efi_status_t (EFIAPI *name) (OUT struct efi_time *time, \ + OUT struct efi_time_capabilities * OPTIONAL capabilities) #define EFI_SET_TIME(name) \ - efi_status_t (EFIAPI name) (IN struct efi_time *time) + efi_status_t (EFIAPI *name) (IN struct efi_time *time) #define EFI_GET_WAKEUP_TIME(name) \ - efi_status_t (EFIAPI name) (OUT b8 *enabled, \ - OUT b8 *pending, \ - OUT struct efi_time *time) + efi_status_t (EFIAPI *name) (OUT b8 *enabled, \ + OUT b8 *pending, \ + OUT struct efi_time *time) #define EFI_SET_WAKEUP_TIME(name) \ - efi_status_t (EFIAPI name) (IN b8 enable, \ - IN struct efi_time * OPTIONAL time) + efi_status_t (EFIAPI *name) (IN b8 enable, \ + IN struct efi_time * OPTIONAL time) #define EFI_SET_VIRTUAL_ADDRESS_MAP(name) \ - efi_status_t (EFIAPI name) (IN umm memory_map_size, \ - IN umm descriptor_size, \ - IN u32 descriptor_version, \ - IN struct efi_memory_descriptor *virtual_map) + efi_status_t (EFIAPI *name) (IN umm memory_map_size, \ + IN umm descriptor_size, \ + IN u32 descriptor_version, \ + IN struct efi_memory_descriptor *virtual_map) #define EFI_OPTIONAL_PTR 0x00000001 #define EFI_CONVERT_POINTER(name) \ - efi_status_t (EFIAPI name) (IN umm debug_disposition, \ - IN void **address) + efi_status_t (EFIAPI *name) (IN umm debug_disposition, \ + IN void **address) enum efi_reset_type { EFI_RESET_COLD, @@ -708,13 +704,13 @@ enum efi_reset_type { }; #define EFI_RESET_SYSTEM(name) \ - void (EFIAPI name) (IN enum efi_reset_type reset_type, \ - IN efi_status_t reset_status, \ - IN umm data_size, \ - IN void *OPTIONAL reset_data) + void (EFIAPI *name) (IN enum efi_reset_type reset_type, \ + IN efi_status_t reset_status, \ + IN umm data_size, \ + IN void *OPTIONAL reset_data) #define EFI_GET_NEXT_HIGH_MONO_COUNT(name) \ - efi_status_t (EFIAPI name) (OUT u32 *high_count) + efi_status_t (EFIAPI *name) (OUT u32 *high_count) struct efi_capsule_block_descriptor { u64 length; @@ -741,56 +737,46 @@ struct efi_capsule_table { }; #define EFI_UPDATE_CAPSULE(name) \ - efi_status_t (EFIAPI name) (IN struct efi_capsule_header **capsule_header_array, \ - IN umm capsule_count, \ - IN efi_physical_address_t OPTIONAL scatter_gather_list) + efi_status_t (EFIAPI *name) (IN struct efi_capsule_header **capsule_header_array, \ + IN umm capsule_count, \ + IN efi_physical_address_t OPTIONAL scatter_gather_list) #define EFI_QUERY_CAPSULE_CAPABILITIES(name) \ - efi_status_t (EFIAPI name) (IN struct efi_capsule_header **capsule_header_array, \ - IN umm capsule_count, \ - OUT u64 *maxiumum_capsule_size, \ - OUT enum efi_reset_type *reset_type) + efi_status_t (EFIAPI *name) (IN struct efi_capsule_header **capsule_header_array, \ + IN umm capsule_count, \ + OUT u64 *maxiumum_capsule_size, \ + OUT enum efi_reset_type *reset_type) struct efi_runtime_services { struct efi_table_header hdr; - EFI_GET_TIME(*get_time); - EFI_SET_TIME(*set_time); - EFI_GET_WAKEUP_TIME(*get_wakeup_time); - EFI_SET_WAKEUP_TIME(*set_wakeup_time); + EFI_GET_TIME(get_time); + EFI_SET_TIME(set_time); + EFI_GET_WAKEUP_TIME(get_wakeup_time); + EFI_SET_WAKEUP_TIME(set_wakeup_time); - EFI_SET_VIRTUAL_ADDRESS_MAP(*set_virtual_address_map); - EFI_CONVERT_POINTER(*convert_pointer); + EFI_SET_VIRTUAL_ADDRESS_MAP(set_virtual_address_map); + EFI_CONVERT_POINTER(convert_pointer); - EFI_GET_VARIABLE(*get_variable); - EFI_GET_NEXT_VARIABLE_NAME(*get_next_variable_name); - EFI_SET_VARIABLE(*set_variable); + EFI_GET_VARIABLE(get_variable); + EFI_GET_NEXT_VARIABLE_NAME(get_next_variable_name); + EFI_SET_VARIABLE(set_variable); - EFI_GET_NEXT_HIGH_MONO_COUNT(*get_next_high_monotonic_count); - EFI_RESET_SYSTEM(*reset_system); + EFI_GET_NEXT_HIGH_MONO_COUNT(get_next_high_monotonic_count); + EFI_RESET_SYSTEM(reset_system); // UEFI 2.0+ - EFI_UPDATE_CAPSULE(*update_capsule); - EFI_QUERY_CAPSULE_CAPABILITIES(*query_capsule_capabilities); + EFI_UPDATE_CAPSULE(update_capsule); + EFI_QUERY_CAPSULE_CAPABILITIES(query_capsule_capabilities); - EFI_QUERY_VARIABLE_INFO(*query_variable_info); -}; - -/* configuration table - * --- - * see: https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html#efi-configuration-table-properties-table - */ - -struct efi_configuration_table { - efi_guid_t vendor_guid; - void *vendor_table; + EFI_QUERY_VARIABLE_INFO(query_variable_info); }; /* protocols * =========================================================================== */ -/* input protocol +/* 12.3. Simple Text Input Protocol * --- * see: https://uefi.org/specs/UEFI/2.10/12_Protocols_Console_Support.html#simple-text-input-protocol */ @@ -804,20 +790,20 @@ struct efi_input_key { }; #define EFI_INPUT_RESET(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_input_protocol *this, \ - IN b8 extended_verification) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_input_protocol *this, \ + IN b8 extended_verification) #define EFI_INPUT_READ_KEY(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_input_protocol *this, \ - OUT struct efi_input_key *key) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_input_protocol *this, \ + OUT struct efi_input_key *key) struct efi_simple_text_input_protocol { - EFI_INPUT_RESET(*reset); - EFI_INPUT_READ_KEY(*read_key_stroke); + EFI_INPUT_RESET(reset); + EFI_INPUT_READ_KEY(read_key_stroke); efi_event_t wait_for_key; }; -/* output protocol +/* 12.4. Simple Text Output Protocol * --- * see: https://uefi.org/specs/UEFI/2.10/12_Protocols_Console_Support.html#simple-text-output-protocol */ @@ -826,41 +812,41 @@ struct efi_simple_text_input_protocol { (efi_guid_t) {.vs = {0x387477c2, 0x69c711d2, 0x8e3900a0, 0xc969723b}} #define EFI_TEXT_RESET(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this, \ - IN b8 extended_verification) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this, \ + IN b8 extended_verification) #define EFI_TEXT_STRING(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this, \ - IN c16 *string) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this, \ + IN c16 *string) #define EFI_TEXT_TEST_STRING(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this, \ - IN c16 *string) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this, \ + IN c16 *string) #define EFI_TEXT_QUERY_MODE(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this, \ - IN umm mode_number, \ - OUT umm *columns, \ - OUT umm *rows) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this, \ + IN umm mode_number, \ + OUT umm *columns, \ + OUT umm *rows) #define EFI_TEXT_SET_MODE(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this, \ + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this, \ IN umm mode) #define EFI_TEXT_SET_ATTRIBUTE(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this, \ - IN umm attribute) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this, \ + IN umm attribute) #define EFI_TEXT_CLEAR_SCREEN(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this) #define EFI_TEXT_SET_CURSOR_POSITION(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this, \ - IN umm column, \ - IN umm row) + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this, \ + IN umm column, \ + IN umm row) #define EFI_TEXT_ENABLE_CURSOR(name) \ - efi_status_t (EFIAPI name) (IN struct efi_simple_text_output_protocol *this, \ + efi_status_t (EFIAPI *name) (IN struct efi_simple_text_output_protocol *this, \ IN b8 visible) struct efi_simple_text_output_mode { @@ -873,16 +859,73 @@ struct efi_simple_text_output_mode { }; struct efi_simple_text_output_protocol { - EFI_TEXT_RESET(*reset); - EFI_TEXT_STRING(*output_string); - EFI_TEXT_TEST_STRING(*test_string); - EFI_TEXT_QUERY_MODE(*query_mode); - EFI_TEXT_SET_MODE(*set_mode); - EFI_TEXT_SET_ATTRIBUTE(*set_attribute); - EFI_TEXT_CLEAR_SCREEN(*clear_screen); - EFI_TEXT_SET_CURSOR_POSITION(*set_cursor_position); - EFI_TEXT_ENABLE_CURSOR(*enable_cursor); + EFI_TEXT_RESET(reset); + EFI_TEXT_STRING(output_string); + EFI_TEXT_TEST_STRING(test_string); + EFI_TEXT_QUERY_MODE(query_mode); + EFI_TEXT_SET_MODE(set_mode); + EFI_TEXT_SET_ATTRIBUTE(set_attribute); + EFI_TEXT_CLEAR_SCREEN(clear_screen); + EFI_TEXT_SET_CURSOR_POSITION(set_cursor_position); + EFI_TEXT_ENABLE_CURSOR(enable_cursor); struct efi_simple_text_output_mode *mode; }; +/* Appendix D. Status Codes + * -- + * see: https://uefi.org/specs/UEFI/2.10/Apx_D_Status_Codes.html + */ + +#define EFI_ERROR 0x8000000000000000 +#define EFI_WARNING 0x0000000000000000 + +#define EFIERR(err) (EFI_ERROR | (err)) +#define EFIWARN(err) (EFI_WARNING | (err)) + +enum efi_status : u64 { + EFI_SUCCESS = 0, + + EFI_WARN_UNKNOWN_GLYPH = EFIWARN(1), + EFI_WARN_DELETE_FAILURE = EFIWARN(2), + EFI_WARN_WRITE_FAILURE = EFIWARN(3), + EFI_WARN_BUFFER_TOO_SMALL = EFIWARN(4), + EFI_WARN_STALE_DATA = EFIWARN(5), + EFI_WARN_FILE_SYSTEM = EFIWARN(6), + EFI_WARN_RESET_REQUIRED = EFIWARN(7), + + EFI_LOAD_ERROR = EFIERR(1), + EFI_INVALID_PARAMETER = EFIERR(2), + EFI_UNSUPPORTED = EFIERR(3), + EFI_BAD_BUFFER_SIZE = EFIERR(4), + EFI_BUFFER_TOO_SMALL = EFIERR(5), + EFI_NOT_READY = EFIERR(6), + EFI_DEVICE_ERROR = EFIERR(7), + EFI_WRITE_PROTECTED = EFIERR(8), + EFI_OUT_OF_RESOURCES = EFIERR(9), + EFI_VOLUME_CORRUPTED = EFIERR(10), + EFI_VOLUME_FULL = EFIERR(11), + EFI_NO_MEDIA = EFIERR(12), + EFI_MEDIA_CHANGED = EFIERR(13), + EFI_NOT_FOUND = EFIERR(14), + EFI_ACCESS_DENIED = EFIERR(15), + EFI_NO_RESPONSE = EFIERR(16), + EFI_NO_MAPPING = EFIERR(17), + EFI_TIMEOUT = EFIERR(18), + EFI_NOT_STARTED = EFIERR(19), + EFI_ALREADY_STARTED = EFIERR(20), + EFI_ABORTED = EFIERR(21), + EFI_ICMP_ERROR = EFIERR(22), + EFI_TFTP_ERROR = EFIERR(23), + EFI_PROTOCOL_ERROR = EFIERR(24), + EFI_INCOMPATIBLE_VERSION = EFIERR(25), + EFI_SECURITY_VIOLATION = EFIERR(26), + EFI_CRC_ERROR = EFIERR(27), + EFI_END_OF_MEDIA = EFIERR(28), + EFI_END_OF_FILE = EFIERR(31), + EFI_INVALID_LANGUAGE = EFIERR(32), + EFI_COMPROMISED_DATA = EFIERR(33), + EFI_IP_ADDRESS_CONFLICT = EFIERR(34), + EFI_HTTP_ERROR = EFIERR(35), +}; + #endif /* EFI_H */ diff --git a/include/kernel.h b/include/kernel.h @@ -0,0 +1,27 @@ +#ifndef KERNEL_H +#define KERNEL_H + +#include "efi.h" + +struct efi_memory_map { + umm buf_size; + struct efi_memory_descriptor *map; + umm map_size; + umm desc_size; + u32 desc_ver; + umm key; +}; + +struct efi_boot_info { + struct efi_memory_map memory_map; +}; + +extern void +ksetup(struct efi_boot_info *info); + +extern void +kmain(struct efi_boot_info *info); + + + +#endif /* KERNEL_H */ diff --git a/include/pe.h b/include/pe.h @@ -0,0 +1,41 @@ +/* PE32+ file format definitions + * -- + * see: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format + */ + +#ifndef PE_H +#define PE_H + +#define IMAGE_DOS_SIGNATURE 0x5a4d /* MZ */ +#define IMAGE_NT_SIGNATURE 0x00004550 /* PE\0\0 */ + +/* https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#machine-type */ +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 + +/* https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#characteristics */ +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 + +/* https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-image-only */ +#define PE32_MAGIC 0x20b + +/* https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#windows-subsystem */ +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 0xa + +/* https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#dll-characteristics */ +#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 +#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 +#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 + +/* https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-flags */ +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + +#endif /* PE_H */ diff --git a/scripts/qemu-aarch64.sh b/scripts/qemu-arm64.sh diff --git a/src/arch/amd64/setup.c b/src/arch/amd64/setup.c @@ -0,0 +1,7 @@ +#include "kernel.h" + +void +ksetup(struct efi_boot_info *info) +{ + (void) info; +} diff --git a/src/arch/arm64/setup.c b/src/arch/arm64/setup.c @@ -0,0 +1,7 @@ +#include "kernel.h" + +void +ksetup(struct efi_boot_info *info) +{ + (void) info; +} diff --git a/src/boot.c b/src/boot.c @@ -1,26 +0,0 @@ -#include "efi.h" - -EFI_IMAGE_ENTRY_POINT(efi_main) -{ - (void) image_handle; - - efi_status_t status; - -#if 1 - status = system_table->con_out->reset(system_table->con_out, false); - if (status != 0) - return status; - - status = system_table->con_out->clear_screen(system_table->con_out); - if (status != 0) - return status; -#endif - - status = system_table->con_out->output_string(system_table->con_out, u"UEFI"); - if (status != 0) - return status; - - system_table->runtime_services->reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); - - return EFI_SUCCESS; -} diff --git a/src/efistub.c b/src/efistub.c @@ -0,0 +1,86 @@ +#include "efi.h" + +#include "kernel.h" + +void +efi_die(struct efi_system_table *table, c16 *msg); + +EFI_IMAGE_ENTRY_POINT(__efi_entry) +{ + efi_status_t err; + + struct efi_simple_text_output_protocol *stdout = system_table->con_out; + stdout->reset(stdout, false); + stdout->output_string(stdout, u"UEFI\r\n"); + + struct efi_boot_services *boot_services = system_table->boot_services; + struct efi_boot_info boot_info; + + /* TODO: find acpi data */ + + /* TODO: setup framebuffer */ + + /* exit UEFI boot services + * NOTE: exit_boot_services() can return EFI_INVALID_PARAMETER, in + * which case the process needs to be restarted with a new + * memory map key + */ + do { + umm mem_map_size = 0, mem_map_key, descriptor_size; + u32 descriptor_version; + + err = boot_services->get_memory_map(&mem_map_size, NULL, + &mem_map_key, + &descriptor_size, + &descriptor_version); + + if (err != EFI_BUFFER_TOO_SMALL || mem_map_size == 0) + efi_die(system_table, u"ERROR: failed to get memory map size\r\n"); + + /* overallocate memory map buffer to avoid second get_memory_map() error */ + umm buf_size = mem_map_size + (4 * descriptor_size); + boot_info.memory_map.map_size = boot_info.memory_map.buf_size = buf_size; + + err = boot_services->allocate_pool(EFI_LOADER_DATA, + boot_info.memory_map.buf_size, + (void **) &boot_info.memory_map.map); + + if (err) + efi_die(system_table, u"ERROR: failed to allocate memory map buffer\r\n"); + + err = boot_services->get_memory_map(&boot_info.memory_map.map_size, + boot_info.memory_map.map, + &boot_info.memory_map.key, + &boot_info.memory_map.desc_size, + &boot_info.memory_map.desc_ver); + + if (err) { + boot_services->free_pool(boot_info.memory_map.map); + efi_die(system_table, u"ERROR: failed to get memory map\r\n"); + } + + err = boot_services->exit_boot_services(image_handle, + boot_info.memory_map.key); + + if (err == EFI_INVALID_PARAMETER) { + boot_services->free_pool(boot_info.memory_map.map); + } else { + efi_die(system_table, u"ERROR: failed to exit boot services\r\n"); + } + } while (err == EFI_INVALID_PARAMETER); + + /* go into the kernel proper */ + ksetup(&boot_info); + kmain(&boot_info); + + for (;;); + + return EFI_SUCCESS; +} + +void +efi_die(struct efi_system_table *system_table, c16 *msg) +{ + system_table->con_out->output_string(system_table->con_out, msg); + system_table->runtime_services->reset_system(EFI_RESET_SHUTDOWN, EFI_LOAD_ERROR, 0, NULL); +} diff --git a/src/efistub.ld b/src/efistub.ld @@ -1,20 +0,0 @@ -SECTIONS -{ - . = 0x100000; - - .text : { - *(.text) - } - - .data : { - *(.data) - } - - .rodata : { - *(.rodata) - } - - .bss : { - *(.bss) - } -} diff --git a/src/header.S b/src/header.S @@ -0,0 +1,142 @@ +/* PE32+ header for UEFI booting */ + +#include "pe.h" + +#include "voffset.h" + +#define ALIGN_NEXT(v, align) (((v) + ((align) - 1)) & ~((align) - 1)) + +HEADER: + +MSDOS_HDR: +MSDOS_HDR.e_magic: .short IMAGE_DOS_SIGNATURE + .short 0 +.fill 14, 4, 0x00000000 +MSDOS_HDR.e_lfanew: .int (PE_HDR - MSDOS_HDR) +MSDOS_HDR_END: + +MSDOS_STUB: +.fill 16, 4, 0x00000000 +MSDOS_STUB_END: + +PE_HDR: +PE_HDR.PEMagic: .int IMAGE_NT_SIGNATURE + +#if defined(__KERNEL_AMD64__) +PE_HDR.Machine: .short IMAGE_FILE_MACHINE_AMD64 +#elif defined(__KERNEL_ARM64__) +PE_HDR.Machine: .short IMAGE_FILE_MACHINE_ARM64 +#elif defined(__KERNEL_RISCV64__) +PE_HDR.Machine: .short IMAGE_FILE_MACHINE_RISCV64 +#else + #error "Unknown target architecture, must be one of: amd64 arm64" +#endif + +PE_HDR.NumberOfSections: .short ((SECTION_HDRS_END - SECTION_HDRS) / 40) +PE_HDR.TimeDateStamp: .int 0 +PE_HDR.PointerToSymbolTable: .int 0 +PE_HDR.NumberOfSymbols: .int 0 +PE_HDR.SizeOfOptionalHeader: .short PEOPT_HDR_END - PEOPT_HDR +PE_HDR.Characteristics: .short IMAGE_FILE_LARGE_ADDRESS_AWARE | \ + IMAGE_FILE_EXECUTABLE_IMAGE +PE_HDR_END: + +PEOPT_HDR: +PEOPT_HDR.PEOptMagic: .short PE32_MAGIC +PEOPT_HDR.MajorLinkerVersion: .byte 0 +PEOPT_HDR.MinorLinkerVersion: .byte 0 +PEOPT_HDR.SizeOfCode: .int (__etext - __text) +PEOPT_HDR.SizeOfData: .int (__edata - __data) +PEOPT_HDR.SizeOfBss: .int 0 +PEOPT_HDR.AddressOfEntryPoint: .int (__efi_entry - __image) +PEOPT_HDR.BaseOfCode: .int (__text - __image) +PEOPT_HDR.BaseOfData: /* missing due to 64-bit ImageBase in 64-bit PEs*/ + +PEOPT_HDR.ImageBase: .quad __image +PEOPT_HDR.SectionAlignment: .int __sect_alignment +PEOPT_HDR.FileAlignment: .int __sect_alignment +PEOPT_HDR.MajorOSVersion: .short 0 +PEOPT_HDR.MinorOSVersion: .short 0 +PEOPT_HDR.MajorImageVersion: .short 0 +PEOPT_HDR.MinorImageVersion: .short 0 +PEOPT_HDR.MajorSubsystemVersion:.short 0 +PEOPT_HDR.MinorSubsystemVersion:.short 0 +PEOPT_HDR.Win32VersionValue: .int 0 +PEOPT_HDR.SizeOfImage: .int ALIGN_NEXT(__eimage - __image, __sect_alignment) +PEOPT_HDR.SizeOfHeaders: .int ALIGN_NEXT(__ehead - __head, __sect_alignment) +PEOPT_HDR.Checksum: .int 0 +PEOPT_HDR.Subsystem: .short IMAGE_SUBSYSTEM_EFI_APPLICATION +PEOPT_HDR.DllCharacteristics: .short IMAGE_DLLCHARACTERISTICS_NX_COMPAT +PEOPT_HDR.SizeOfStackReserve: .quad 0x100000 +PEOPT_HDR.SizeOfStackCommit: .quad 0x1000 +PEOPT_HDR.SizeOfHeapReserve: .quad 0x100000 +PEOPT_HDR.SizeOfHeapCommit: .quad 0x1000 +PEOPT_HDR.LoaderFlags: .int 0 + +PEOPT_HDR.NumberOfRvaAndSizes: .int ((DATA_DIRS_END - DATA_DIRS) / 8) + +DATA_DIRS: + +DATA_DIRS.ExportTable: .quad 0 +DATA_DIRS.ImportTable: .quad 0 +DATA_DIRS.ResourceTable: .quad 0 +DATA_DIRS.ExceptionTable: .quad 0 +DATA_DIRS.CertificateTable.Addr:.int (__sbcert - __image) +DATA_DIRS.CertificateTable.Size:.int (__esbcert - __sbcert) +DATA_DIRS.BaseRelocationTable: .quad 0 +DATA_DIRS.Debug: .quad 0 +DATA_DIRS.Architecture: .quad 0 +DATA_DIRS.GlobalPointer: .quad 0 +DATA_DIRS.TLSTable: .quad 0 +DATA_DIRS.LoadConfiguration: .quad 0 +DATA_DIRS.BoundImportTable: .quad 0 +DATA_DIRS.ImportAddressTable: .quad 0 +DATA_DIRS.DelayImportTable: .quad 0 +DATA_DIRS.CLRRuntimeHeader: .quad 0 +DATA_DIRS.Reserved: .quad 0 + +DATA_DIRS_END: + +PEOPT_HDR_END: + +SECTION_HDRS: + +SECTION_CODE: +SECTION_CODE.Name: .ascii ".text" + .byte 0, 0, 0 +SECTION_CODE.VirtualSize: .int (__etext - __text) +SECTION_CODE.VirtualAddress: .int (__text - __image) +SECTION_CODE.SizeOfRawData: .int (__etext - __text) +SECTION_CODE.PointerToRawData: .int (__text - __image) +SECTION_CODE.PointerToRelocs: .int 0 +SECTION_CODE.PointerToLineNums: .int 0 +SECTION_CODE.NumberOfRelocs: .short 0 +SECTION_CODE.NumberOfLineNums: .short 0 +SECTION_CODE.Characteristics: .int IMAGE_SCN_CNT_CODE | \ + IMAGE_SCN_MEM_EXECUTE | \ + IMAGE_SCN_MEM_READ + +SECTION_DATA: +SECTION_DATA.Name: .ascii ".data" + .byte 0, 0, 0 +SECTION_DATA.VirtualSize: .int (__edata - __data) +SECTION_DATA.VirtualAddress: .int (__data - __image) +SECTION_DATA.SizeOfRawData: .int (__edata - __data) +SECTION_DATA.PointerToRawData: .int (__data - __image) +SECTION_DATA.PointerToRelocs: .int 0 +SECTION_DATA.PointerToLineNums: .int 0 +SECTION_DATA.NumberOfRelocs: .short 0 +SECTION_DATA.NumberOfLineNums: .short 0 +SECTION_DATA.Characteristics: .int IMAGE_SCN_CNT_INITIALIZED_DATA | \ + IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_WRITE + +SECTION_HDRS_END: + +HEADER_END: + +.balign __sect_alignment, 0 + +.if ((HEADER_END - HEADER) > (__ehead - __head)) + .err "PE header overflows allocated area" +.endif diff --git a/src/kernel.c b/src/kernel.c @@ -1,5 +1,17 @@ +#include "kernel.h" + +#if defined(__KERNEL_AMD64__) + #include "arch/amd64/setup.c" +#elif defined(__KERNEL_ARM64__) + #include "arch/arm64/setup.c" +#else + #error "Unknown target architecture, must be one of: amd64 arm64" +#endif + void -kmain(void) +kmain(struct efi_boot_info *info) { + (void) info; + for (;;); } diff --git a/src/kernel.ld b/src/kernel.ld @@ -1,20 +0,0 @@ -SECTIONS -{ - . = 0x100000; - - .text : { - *(.text) - } - - .data : { - *(.data) - } - - .rodata : { - *(.rodata) - } - - .bss : { - *(.bss) - } -} diff --git a/src/kernel.lds b/src/kernel.lds @@ -0,0 +1,38 @@ +ENTRY(__efi_entry) + +__sect_alignment = 0x1000; +__image_base = 0x140000000; + +__pe_header_area = 0x1000; +__secureboot_cert_area = 0x1000; + +SECTIONS +{ + __image = __image_base; + + .head __image_base : { + __head = .; + . = . + __pe_header_area; + __ehead = ALIGN(__sect_alignment); + } + + .text : ALIGN(__sect_alignment) { + __text = .; + *(.text*) + __etext = ALIGN(__sect_alignment); + } + + .data : ALIGN(__sect_alignment) { + __data = .; + *(.data* .rodata* .bss* COMMON) + __edata = ALIGN(__sect_alignment); + } + + .sbcert : ALIGN(__sect_alignment) { + __sbcert = .; + . = . + __secureboot_cert_area; + __esbcert = ALIGN(__sect_alignment); + } =0 + + __eimage = .; +}