├── .gitignore ├── .gitmodules ├── hello-c.c ├── types.inc ├── LICENSE ├── hello-fasm.asm ├── Makefile ├── memmap.c ├── README.md └── efi.inc /.gitignore: -------------------------------------------------------------------------------- 1 | *.efi 2 | *.lib 3 | *.obj 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "efi"] 2 | path = efi 3 | url = https://github.com/yoppeh/efi.git 4 | -------------------------------------------------------------------------------- /hello-c.c: -------------------------------------------------------------------------------- 1 | 2 | #include "efi.h" 3 | 4 | 5 | EFI_HANDLE image_handle; 6 | EFI_SYSTEM_TABLE *system_table; 7 | 8 | CHAR16 *hello_str = L"Hello, you slab of warm meat!\r\n"; 9 | 10 | 11 | EFI_STATUS efi_main(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st) 12 | { 13 | image_handle = ih; 14 | system_table = st; 15 | system_table->ConOut->OutputString(system_table->ConOut, hello_str); 16 | 17 | return(EFI_SUCCESS); 18 | } 19 | -------------------------------------------------------------------------------- /types.inc: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------------------ 2 | ; types.inc 3 | ; 4 | ; Data structures, macros, constants, etc. used by the other modules. 5 | ; 6 | 7 | 8 | ; for 32/64 portability and automatic natural align in structure definitions 9 | struc int8 { 10 | . db ? 11 | } 12 | struc int16 { 13 | align 2 14 | . dw ? 15 | } 16 | struc int32 { 17 | align 4 18 | . dd ? 19 | } 20 | struc int64 { 21 | align 8 22 | . dq ? 23 | } 24 | struc intn { 25 | align 8 26 | . dq ? 27 | } 28 | struc dptr { 29 | align 8 30 | . dq ? 31 | } 32 | 33 | 34 | ; helper macro for definition of relative structure member offsets 35 | macro struct name 36 | { 37 | virtual at 0 38 | name name 39 | sizeof.#name = $ - name 40 | name equ sizeof.#name 41 | end virtual 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Warren Mann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /hello-fasm.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------------------ 2 | ; main.asm 3 | ; 4 | ; UEFI calling parameters: rcx, rdx, r8, r9, stack... 5 | ; 6 | 7 | format ms64 coff 8 | 9 | 10 | include 'types.inc' 11 | include 'efi.inc' 12 | 13 | 14 | section '.text' code executable readable 15 | 16 | public efi_main 17 | 18 | 19 | ; ------------------------------------------------------------------------------ 20 | ; Entry Point 21 | 22 | efi_main: 23 | 24 | sub rsp, 4 * 8 25 | 26 | ; Save UEFI parameters. 27 | mov [efi_image_handle], rcx 28 | mov [efi_system_table], rdx 29 | 30 | ; Print hello. 31 | lea rdx, [str_hello] 32 | call uefi_print_str 33 | 34 | mov rax, EFI_SUCCESS 35 | add rsp, 4 * 8 36 | retn 37 | 38 | 39 | uefi_print_str: 40 | 41 | sub rsp, 4 * 8 42 | mov rcx, [efi_system_table] 43 | mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut] 44 | call [rcx + EFI_SIMPLE_TEXT_OUTPUT_INTERFACE.OutputString] 45 | add rsp, 4 * 8 46 | retn 47 | 48 | 49 | section '.data' data readable writeable 50 | 51 | efi_image_handle dq (0) 52 | efi_system_table dq (0) 53 | 54 | str_hello du 'Hello, you warm slab of meat!', 13, 10, 0 55 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile 3 | # 4 | # Targets: 5 | # make ......... build all. 6 | # make all ..... build all. 7 | # make clean ... delete object files, libraries and executables. 8 | # 9 | # Variables: 10 | # EFI_PLATFORM ... 0 = IA32, 1 = X64, 2 = Itanium, 3 = ARM, 11 | # 4 = AARCH64, 5 = RISCV32, 6 = RISCV64, 12 | # 7 = RISCV128, 8 = LOONGARCH32, 9 = LOONGARCH64 13 | 14 | CC = clang 15 | CFLAGS = -I efi -target x86_64-pc-win32-coff -fno-stack-protector -fshort-wchar -mno-red-zone 16 | LD = lld-link 17 | LDFLAGS = -subsystem:efi_application -nodefaultlib -dll 18 | ifeq ($(EFI_PLATFORM),) 19 | EFI_PLATFORM = 1 20 | endif 21 | 22 | .PHONY : all clean 23 | 24 | all : hello-c.efi memmap.efi hello-fasm.efi 25 | 26 | hello-fasm.efi : hello-fasm.obj 27 | $(LD) $(LDFLAGS) -entry:efi_main $< -out:$@ 28 | 29 | hello-c.efi : hello-c.obj 30 | $(LD) $(LDFLAGS) -entry:efi_main $< -out:$@ 31 | 32 | memmap.efi : memmap.obj 33 | $(LD) $(LDFLAGS) -entry:efi_main $< -out:$@ 34 | 35 | hello-fasm.obj : hello-fasm.asm 36 | fasm $< 37 | 38 | hello-c.obj : hello-c.c 39 | $(CC) $(CFLAGS) -c $< -o $@ 40 | 41 | memmap.obj : memmap.c 42 | $(CC) $(CFLAGS) -c $< -o $@ 43 | 44 | clean: 45 | - rm -rf *.lib 46 | - rm -rf *.dll 47 | - rm -rf *.efi 48 | - rm -rf *.exe 49 | - rm -rf *.obj 50 | -------------------------------------------------------------------------------- /memmap.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * memmap.c 3 | * 4 | * A program to dump the UEFI memory map. 5 | */ 6 | 7 | #include 8 | 9 | 10 | #define CONSOLE_STR_BUFFER_MAX 128 11 | #define NULL (void *)0 12 | 13 | 14 | UINTN memory_map_key; 15 | EFI_HANDLE image_handle; 16 | EFI_SYSTEM_TABLE *system_table; 17 | 18 | CHAR16 *console_str_yes = L"yes"; 19 | CHAR16 *console_str_no = L"no"; 20 | CHAR16 *console_str_valid = L"valid"; 21 | CHAR16 *console_str_invalid = L"invalid"; 22 | CHAR16 *console_str_crlf = L"\r\n"; 23 | 24 | static CHAR16 *_tab_str = L" "; 25 | 26 | static CHAR16 *_header_str = L"physical address virtual address pages type"; 27 | 28 | 29 | static CHAR16 _hex_table[] = { 30 | L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', 31 | L'8', L'9', L'a', L'b', L'c', L'd', L'e', L'f' 32 | }; 33 | 34 | static CHAR16 *_mem_attribute[] = { 35 | L"reserved", 36 | L"loader code", 37 | L"loader data", 38 | L"boot services code", 39 | L"boot services data", 40 | L"runtime services code", 41 | L"runtime services data", 42 | L"conventional memory", 43 | L"unusable memory", 44 | L"acpi reclaim memory", 45 | L"acpi memory nvs", 46 | L"memory mapped io", 47 | L"memory mapped io port space", 48 | L"pal code", 49 | L"persistent memory" 50 | }; 51 | 52 | static CHAR16 *_mem_attribute_unrecognized = L"unrecognized"; 53 | 54 | static EFI_MEMORY_DESCRIPTOR *_mem_map = NULL; 55 | static UINTN _mem_map_size = 0; 56 | static UINTN _mem_map_desc_size = 0; 57 | static uint64_t _mem_map_num_entries = 0; 58 | static uint64_t _mem_map_alloced_pages = 0; 59 | static UINT32 _mem_map_desc_ver = 0; 60 | 61 | 62 | static void console_print(CHAR16 *s); 63 | static void console_println(CHAR16 *s); 64 | static void console_print_dec(uint64_t dec); 65 | static void console_print_hex(uint64_t hex, uint8_t width); 66 | static void dump_uefi_map(void); 67 | static int init_memory(void); 68 | 69 | 70 | EFI_STATUS efi_main(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st) 71 | { 72 | image_handle = ih; 73 | system_table = st; 74 | 75 | if (init_memory()) { 76 | return(1); 77 | } 78 | dump_uefi_map(); 79 | 80 | return(EFI_SUCCESS); 81 | } 82 | 83 | 84 | static void console_print(CHAR16 *s) 85 | { 86 | system_table->ConOut->OutputString(system_table->ConOut, s); 87 | } 88 | 89 | 90 | static void console_println(CHAR16 *s) 91 | { 92 | system_table->ConOut->OutputString(system_table->ConOut, s); 93 | system_table->ConOut->OutputString(system_table->ConOut, 94 | console_str_crlf); 95 | } 96 | 97 | 98 | static void console_print_dec(uint64_t dec) 99 | { 100 | int16_t i = CONSOLE_STR_BUFFER_MAX - 1; 101 | CHAR16 buffer[CONSOLE_STR_BUFFER_MAX]; 102 | 103 | buffer[i--] = 0x0000; 104 | 105 | do { 106 | buffer[i--] = L'0' + dec % 10; 107 | dec /= 10; 108 | } while (dec > 0 && i >= 0); 109 | i++; 110 | 111 | console_print(buffer + i); 112 | } 113 | 114 | 115 | static void console_print_hex(uint64_t hex, uint8_t width) 116 | { 117 | int16_t i = width + 1; 118 | CHAR16 buffer[CONSOLE_STR_BUFFER_MAX]; 119 | 120 | if (i >= CONSOLE_STR_BUFFER_MAX) { 121 | return; 122 | } 123 | 124 | buffer[i--] = 0x0000; 125 | buffer[i--] = L'h'; 126 | 127 | while (width && i >= 0) { 128 | buffer[i--] = _hex_table[hex & 0x0f]; 129 | hex >>= 4; 130 | width--; 131 | } 132 | 133 | console_print(buffer); 134 | } 135 | 136 | 137 | static void dump_uefi_map(void) 138 | { 139 | void *mm = _mem_map; 140 | EFI_MEMORY_DESCRIPTOR *mem_map; 141 | uint64_t i; 142 | uint64_t total_mapped = 0; 143 | 144 | _mem_map_num_entries = _mem_map_size / _mem_map_desc_size; 145 | console_println(_header_str); 146 | for (i = 0; i < _mem_map_num_entries; i++) { 147 | mem_map = (EFI_MEMORY_DESCRIPTOR *)mm; 148 | console_print_hex(mem_map->PhysicalStart, 16); 149 | console_print(_tab_str); 150 | console_print_hex(mem_map->VirtualStart, 16); 151 | console_print(_tab_str); 152 | console_print_hex(mem_map->NumberOfPages, 16); 153 | console_print(_tab_str); 154 | if (mem_map->Type >= EfiMaxMemoryType) { 155 | console_println(_mem_attribute_unrecognized); 156 | } else { 157 | console_println(_mem_attribute[mem_map->Type]); 158 | } 159 | total_mapped += mem_map->NumberOfPages * 4096; 160 | mm += _mem_map_desc_size; 161 | } 162 | console_print(L"Total memory mapped ... "); 163 | console_print_dec(total_mapped); 164 | console_print(console_str_crlf); 165 | } 166 | 167 | 168 | static int init_memory(void) 169 | { 170 | UINTN map_size; 171 | 172 | if (system_table->BootServices->GetMemoryMap(&_mem_map_size, NULL, 173 | &memory_map_key, &_mem_map_desc_size, 174 | &_mem_map_desc_ver) != EFI_BUFFER_TOO_SMALL) { 175 | console_println(L"error getting system memory map"); 176 | return 1; 177 | } 178 | 179 | map_size = (_mem_map_size + 4095) / 4096; 180 | _mem_map_alloced_pages = map_size; 181 | _mem_map_size = map_size * 4096; 182 | if (system_table->BootServices->AllocatePages(AllocateAnyPages, 183 | EfiLoaderData, map_size, 184 | (EFI_PHYSICAL_ADDRESS *)&_mem_map) != EFI_SUCCESS) { 185 | console_print(L"error allocating "); 186 | console_print_dec(_mem_map_size); 187 | console_println(L" pages for GetMemoryMap"); 188 | return 1; 189 | } 190 | 191 | /* Finally, get the memory map for real. It will be stored in the memory 192 | * area we allocated above and pointed to by _mem_map. */ 193 | if (system_table->BootServices->GetMemoryMap(&_mem_map_size, 194 | _mem_map, &memory_map_key, &_mem_map_desc_size, 195 | &_mem_map_desc_ver) != EFI_SUCCESS) { 196 | console_println(L"failed to get system memory map"); 197 | return 1; 198 | } 199 | 200 | return 0; 201 | } 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # efi-clang 2 | 3 | Build UEFI applications with the Clang compiler and LLD linker. Of course, you'll need to have those installed. I tested this with Clang v. 6.0.0. I use Arch Linux, so I installed `pacman -S clang lld`. This uses my [efi headers](https://github.com/yoppeh/efi), included as a submodule. After cloning this repo, you'd do: `git submodule update --init` to pull it in. 4 | 5 | Next, gather the topology of your EFI setup. When I partitioned my drive, I made a couple of Linux partitions and then one EFI system partition. It was formatted with fat32 and I installed systemd-boot. I made an arch directory for the Arch Linux kernel and an app directory that contains shellx64_v2.efi (The EFI shell you can get from [Tianocore](https://github.com/tianocore/tianocore.github.io/wiki/Efi-shell)). I setup systemd-boot's menu so I could either load Linux or the EFI shell at bootup. 6 | 7 | With that, you would drop into the efi-clang directory, run `make` and then `sudo cp *.efi /boot/app` (/boot is where the EFI system partition is mounted). 8 | 9 | Then reboot, choose the shell option from the boot menu and then do: 10 | 11 | `fs0:` 12 | 13 | `cd app` 14 | 15 | `hello-c.efi` 16 | 17 | `hello-fasm.efi` 18 | 19 | `memmap.efi` 20 | 21 | If you built a similar application using gnu-efi, you'll notice this executable is substantially smaller. 22 | 23 | ## Rationale 24 | 25 | Modern PC-compatible systems have replaced the old system BIOS with the Unified Extensible Firmware Interface. This is almost an operating system in itself and makes some of the vagaries of bringing up a system a little more clean than in the past. Several well-defined software interfaces are provided for mapping hardware components, figuring out memory layout, loading kernels, showing startup screens and some other boring junk operating systems have to do to survive. I recently had occasion to do some work in UEFI. 26 | 27 | UEFI has actually been around a while, but the platforms I've seen still seem a little immature. A couple of the better ones are the implementations on my Asus Zenbook Pro and the two Intel NUCs I use for development. Having downloaded a copy of the [UEFI specification](http://www.uefi.org/specifications), I set out to build a Hello World UEFI application. 28 | 29 | That's when things got a little messy. I found out there are basically three options when it comes to building UEFI applications: [Tianocore](https://www.tianocore.org/), which is Intel's UEFI build environment, [gnu-efi](https://sourceforge.net/projects/gnu-efi/), and FASM which can [natively produce EFI application binaries](https://board.flatassembler.net/topic.php?t=19540) (crazily enough). 30 | 31 | I tried Tianocore first—straight from the horse's mouth as it were. The application built fine and it worked instantly. The problem is the labyrinthine build environment. They actually recommend sticking your code somewhere in the Tianocore build tree and modifying the build files to include your application code. Sorry, Intel, but I'm not going to change the layout of my source tree to what you think it should be. Actually, with the instructions I'll provide shortly, you should be able to use Tianocore's headers and libraries and dump their build system without too much trouble. If you care about correctness (which is generally probably good) and/or aren't as mental about your build system as I am, then I would recommend going with that option. Also, Tianocore's [github repo](https://github.com/tianocore/edk2) has thorough instructions for setting it up on various platforms. 32 | 33 | Disillusioned with Tianocore's messy build environment, I decided to hold my nose and try the gnu-efi way of doing things. There was a package available for it in the Arch repository, so getting it setup was easy enough. It also took minimal effort to build a working application. I was excited it was much more straight-forward than the Tianocore mess, but I was still holding my nose. It wasn't long before I realized gnu-efi's build instructions had dumped an unreasonably large binary in my build directory. I couldn't imagine what all those bytes were doing in a little Hello World EFI application. Later, I discovered the problem: the gnu-efi application provides binary startup objects and a library for relocation and dynamic resolving of relocatable symbols. Gross. 34 | 35 | I decided I'd go with my own UEFI build environment using [Clang](https://clang.llvm.org/) and [LLD](https://lld.llvm.org/) as the compiler and linker and using my own code instead of Tianocore or gnu-efi project libraries and headers. As it turns out, I had to do considerable research before I could put all the bits together to make it work. 36 | 37 | The first thing you need is a set of header files. I built my own, using the spec. I had a creeping feeling Tianocore and GNU would use their own versions of what a header should be, and I preferred to use something custom. My application would have no startup code or link-libraries. Everything used would be defined in the project itself and linked in if it's used and rejected if not. 38 | 39 | Next, I installed the build tools themselves: clang and lld. It was an easy install on Arch Linux and I had everything up and going without incident. Then it got hard. Clang had to produce Microsoft object files to be compatible with the way UEFI does things. I had to search down the options and fiddle with them until I got them working properly. LLVM itself has to be called as though it were Microsoft's LINK. Once I got everything together, I captured it here, in git where others could use it. Take special care to examine the clang and lld commands in the makefile. 40 | 41 | Notice the code I make available doesn't use a runtime library or startup files. The loader will read it into memory and execute it directly. I prefer to access the various functions and structures in their raw form, without a library hiding the details from me. This gives me a more intimate knowledge of the library that I find useful. As I said earlier, this setup can be modified to use the official Tianocore headers. Indeed, the headers provided here are incomplete. 42 | 43 | Finally, the goal with your c compiler is to build an MS object format output file for each of your compiled modules. Those object files will be linked with Clang's linker in Microsoft LINK mode to generate a PE64 executable. 44 | 45 | I've used this to successfully build on FASM without using FASM's built-in PE format generator. I still haven't quite gotten NASM to work. The binary is recognized and loads fine and, if it does nothing but terminate, it works great! I think there are some position independent code related issues. I investigated it briefly, but didn't find a solution and had more pressing things to work on. I think NASM is very close to working and I may look into it in the future. For now, I am content to use FASM when necessary. If anyone reading this figures out the secret, I'd definitely be interested in knowing. 46 | 47 | I hope this post will find others looking into getting into UEFI and offer them some help in how it fits together. Maybe it will even give enough information to help building UEFI apps on other systems or with other compilers. 48 | 49 | Good Luck! 50 | -------------------------------------------------------------------------------- /efi.inc: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------------------ 2 | ; efi.inc 3 | ; 4 | ; UEFI declarations. 5 | 6 | 7 | ; ------------------------------------------------------------------------------ 8 | ; CONSTANTS 9 | 10 | ; error codes 11 | EFI_ERR = 0x8000000000000000 12 | EFI_SUCCESS = 0x0000000000000000 13 | EFI_LOAD_ERROR = EFI_ERR or 1 14 | EFI_INVALID_PARAMETER = EFI_ERR or 2 15 | EFI_UNSUPPORTED = EFI_ERR or 3 16 | EFI_BAD_BUFFER_SIZE = EFI_ERR or 4 17 | EFI_BUFFER_TOO_SMALL = EFI_ERR or 5 18 | EFI_NOT_READY = EFI_ERR or 6 19 | EFI_DEVICE_ERROR = EFI_ERR or 7 20 | EFI_WRITE_PROTECTED = EFI_ERR or 8 21 | EFI_OUT_OF_RESOURCES = EFI_ERR or 9 22 | EFI_VOLUME_CORRUPTED = EFI_ERR or 10 23 | EFI_VOLUME_FULL = EFI_ERR or 11 24 | EFI_NO_MEDIA = EFI_ERR or 12 25 | EFI_MEDIA_CHANGED = EFI_ERR or 13 26 | EFI_NOT_FOUND = EFI_ERR or 14 27 | EFI_ACCESS_DENIED = EFI_ERR or 15 28 | EFI_NO_RESPONSE = EFI_ERR or 16 29 | EFI_NO_MAPPING = EFI_ERR or 17 30 | EFI_TIMEOUT = EFI_ERR or 18 31 | EFI_NOT_STARTED = EFI_ERR or 19 32 | EFI_ALREADY_STARTED = EFI_ERR or 20 33 | EFI_ABORTED = EFI_ERR or 21 34 | EFI_ICMP_ERROR = EFI_ERR or 22 35 | EFI_TFTP_ERROR = EFI_ERR or 23 36 | EFI_PROTOCOL_ERROR = EFI_ERR or 24 37 | 38 | ; allocation types 39 | EFI_ALLOCATE_TYPE_ALLOCATE_ANY_PAGES = 0x00000000 40 | EFI_ALLOCATE_TYPE_ALLOCATE_MAX_ADDRESS = 0x00000001 41 | EFI_ALLOCATE_ALLOCATE_ADDRESS = 0x00000002 42 | EFI_ALLOCATE_MAX_ALLOCATE_TYPE = 0x00000003 43 | 44 | ; memory types 45 | EFI_MEMORY_TYPE_RESERVED = 0x00000000 46 | EFI_MEMORY_TYPE_LOADER_CODE = 0x00000001 47 | EFI_MEMORY_TYPE_LOADER_DATA = 0x00000002 48 | EFI_MEMORY_TYPE_BOOT_SERVICES_CODE = 0x00000003 49 | EFI_MEMORY_TYPE_BOOT_SERVICES_DATA = 0x00000004 50 | EFI_MEMORY_TYPE_RUNTIME_SERVICES_CODE = 0x00000005 51 | EFI_MEMORY_TYPE_RUNTIME_SERVICES_DATA = 0x00000006 52 | EFI_MEMORY_TYPE_CONVENTIONAL = 0x00000007 53 | EFI_MEMORY_TYPE_UNUSABLE = 0x00000008 54 | EFI_MEMORY_TYPE_ACPI_RECLAIM = 0x00000009 55 | EFI_MEMORY_TYPE_ACPI_NVS = 0x0000000a 56 | EFI_MEMORY_TYPE_MEMORY_MAPPED_IO = 0x0000000b 57 | EFI_MEMORY_TYPE_MEMORY_MAPPED_IO_PORT_SPACE = 0x0000000c 58 | EFI_MEMORY_TYPE_PAL_CODE = 0x0000000d 59 | EFI_MEMORY_TYPE_PERSISTENT = 0x0000000e 60 | EFI_MEMORY_TYPE_MAX = 0x0000000f 61 | 62 | ; graphics pixel formats 63 | PixelRedGreenBlueReserved8BitPerColor = 0x00000000 64 | PixelBlueGreenRedReserved8BitPerColor = 0x00000001 65 | PixelBitMask = 0x00000002 66 | PixelBltOnly = 0x00000003 67 | PixelFormatMax = 0x00000004 68 | 69 | 70 | ; ------------------------------------------------------------------------------ 71 | ; STRUCTURES 72 | 73 | struc EFI_GUID { 74 | .Lo int64 75 | .Hi int64 76 | } 77 | struct EFI_GUID 78 | 79 | struc EFI_TABLE_HEADER { 80 | .Signature int64 81 | .Revision int32 82 | .HeaderSize int32 83 | .CRC32 int32 84 | .Reserved int32 85 | } 86 | struct EFI_TABLE_HEADER 87 | 88 | struc EFI_SYSTEM_TABLE { 89 | .Hdr EFI_TABLE_HEADER 90 | .FirmwareVendor dptr 91 | .FirmwareRevision int32 92 | .ConsoleInHandle dptr 93 | .ConIn dptr 94 | .ConsoleOutHandle dptr 95 | .ConOut dptr 96 | .StandardErrorHandle dptr 97 | .StdErr dptr 98 | .RuntimeServices dptr 99 | .BootServices dptr 100 | .NumberOfTableEntries intn 101 | .ConfigurationTable dptr 102 | } 103 | struct EFI_SYSTEM_TABLE 104 | 105 | struc EFI_BOOT_SERVICES { 106 | .Hdr EFI_TABLE_HEADER 107 | .RaiseTPL dptr 108 | .RestoreTPL dptr 109 | .AllocatePages dptr 110 | .FreePages dptr 111 | .GetMemoryMap dptr 112 | .AllocatePool dptr 113 | .FreePool dptr 114 | .CreateEvent dptr 115 | .SetTimer dptr 116 | .WaitForEvent dptr 117 | .SignalEvent dptr 118 | .CloseEvent dptr 119 | .CheckEvent dptr 120 | .InstallProtocolInterface dptr 121 | .ReinstallProtocolInterface dptr 122 | .UninstallProtocolInterface dptr 123 | .HandleProtocol dptr 124 | .Reserved dptr 125 | .RegisterProtocolNotify dptr 126 | .LocateHandle dptr 127 | .LocateDevicePath dptr 128 | .InstallConfigurationTable dptr 129 | .LoadImage dptr 130 | .StartImage dptr 131 | .Exit dptr 132 | .UnloadImage dptr 133 | .ExitBootServices dptr 134 | .GetNextMonotonicCount dptr 135 | .Stall dptr 136 | .SetWatchdogTimer dptr 137 | .ConnectController dptr 138 | .DisconnectController dptr 139 | .OpenProtocol dptr 140 | .CloseProtocol dptr 141 | .OpenProtocolInformation dptr 142 | .ProtocolsPerHandle dptr 143 | .LocateHandleBuffer dptr 144 | .LocateProtocol dptr 145 | .InstallMultipleProtocolInterfaces dptr 146 | .UninstallMultipleProtocolInterfaces dptr 147 | .CalculateCrc32 dptr 148 | .CopyMem dptr 149 | .SetMem dptr 150 | .CreateEventEx dptr 151 | } 152 | struct EFI_BOOT_SERVICES 153 | 154 | struc EFI_MEMORY_DESCRIPTOR { 155 | .Type int32 156 | .PhysicalStart int64 157 | .VirtualStart int64 158 | .NumberOfPages int64 159 | .Attribute int64 160 | } 161 | struct EFI_MEMORY_DESCRIPTOR 162 | 163 | struc EFI_SIMPLE_TEXT_OUTPUT_INTERFACE { 164 | .Reset dptr 165 | .OutputString dptr 166 | .TestString dptr 167 | .QueryMode dptr 168 | .SetMode dptr 169 | .SetAttribute dptr 170 | .ClearScreen dptr 171 | .SetCursorPosition dptr 172 | .EnableCursor dptr 173 | .Mode dptr 174 | } 175 | struct EFI_SIMPLE_TEXT_OUTPUT_INTERFACE 176 | 177 | struc EFI_SIMPLE_TEXT_INPUT_INTERFACE { 178 | .Reset dptr 179 | .ReadKeyStroke dptr 180 | .WaitForKey dptr 181 | } 182 | struct EFI_SIMPLE_TEXT_INPUT_INTERFACE 183 | 184 | struc EFI_GRAPHICS_OUTPUT_PROTOCOL { 185 | .QueryMode dptr 186 | .SetMode dptr 187 | .Blt dptr 188 | .Mode dptr 189 | } 190 | struct EFI_GRAPHICS_OUTPUT_PROTOCOL 191 | 192 | struc EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE { 193 | .MaxMode int32 194 | .Mode int32 195 | .Info dptr 196 | .SizeOfInfo intn 197 | .FrameBufferBase dptr 198 | .FrameBufferSize intn 199 | } 200 | struct EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE 201 | 202 | struc EFI_PIXEL_BITMASK { 203 | .RedMask int32 204 | .GreenMask int32 205 | .BlueMask int32 206 | .ReservedMask int32 207 | } 208 | struct EFI_PIXEL_BITMASK 209 | 210 | struc EFI_GRAPHICS_OUTPUT_MODE_INFORMATION { 211 | .Version int32 212 | .HorizontalResolution int32 213 | .VerticalResolution int32 214 | .PixelFormat EFI_PIXEL_BITMASK 215 | .PixelInformation int32 216 | .PixelsPerScanLine int32 217 | } 218 | struct EFI_GRAPHICS_OUTPUT_MODE_INFORMATION 219 | 220 | 221 | struc EFI_CONFIGURATION_TABLE { 222 | .VendorGuid EFI_GUID 223 | .VendorTable dptr 224 | } 225 | struct EFI_CONFIGURATION_TABLE 226 | --------------------------------------------------------------------------------