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:
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 = .;
+}