ekern

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

boot-amd64.asm (16789B)


      1 .intel_syntax
      2 
      3 .globl EntryPoint
      4 
      5 .equ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION, 10
      6 
      7 .equ IMAGE_MACHINE_x64, 0x8664
      8 
      9 .equ IMAGE_FILE_EXECUTABLE_IMAGE, 0x0002
     10 .equ IMAGE_FILE_LARGE_ADDRESS_AWARE, 0x0020
     11 .equ IMAGE_FILE_DEBUG_STRIPPED, 0x0200
     12 
     13 .equ PE32PLUS_MAGIC, 0x020b
     14 
     15 .equ IMAGE_SCN_CNT_CODE, 0x00000020
     16 .equ IMAGE_SCN_CNT_DATA, 0x00000040
     17 .equ IMAGE_SCN_MEM_SHARED, 0x10000000
     18 .equ IMAGE_SCN_MEM_EXECUTE, 0x20000000
     19 .equ IMAGE_SCN_MEM_READ, 0x40000000
     20 .equ IMAGE_SCN_MEM_WRITE, 0x80000000
     21 
     22 .code64
     23 
     24 .section .header, "a", %progbits
     25 BEGIN:
     26 
     27 HEADER:
     28 
     29 MSDOS_HDR:
     30 MSDOS_HDR.e_magic: 		.byte 'M', 'Z', 0x00, 0x00
     31 .fill 14, 4, 0x00000000
     32 MSDOS_HDR.e_lfanew: 		.int (PE_HDR - MSDOS_HDR)
     33 MSDOS_HDR_END:
     34 
     35 MSDOS_STUB:
     36 .fill 16, 4, 0x00000000
     37 MSDOS_STUB_END:
     38 
     39 PE_HDR:
     40 PE_HDR.PEMagic:			.byte 'P', 'E', 0x00, 0x00
     41 PE_HDR.Machine:			.short IMAGE_MACHINE_x64
     42 PE_HDR.NumberOfSections:	.short 2
     43 PE_HDR.TimeDateStamp:		.int 1717539955
     44 PE_HDR.PointerToSymbolTable:	.int 0
     45 PE_HDR.NumberOfSymbols:		.int 0
     46 PE_HDR.SizeOfOptionalHeader:	.short (PEOPT_HDR_END - PEOPT_HDR)
     47 PE_HDR.Characteristics:		.short (IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_LARGE_ADDRESS_AWARE | IMAGE_FILE_EXECUTABLE_IMAGE)
     48 PE_HDR_END:
     49 
     50 PEOPT_HDR:
     51 PEOPT_HDR.PEOptMagic:		.short PE32PLUS_MAGIC
     52 PEOPT_HDR.MajorLinkerVersion:	.byte 0
     53 PEOPT_HDR.MinorLinkerVersion:	.byte 0
     54 PEOPT_HDR.SizeOfCode:		.int (CODE_END - CODE)
     55 PEOPT_HDR.SizeOfData:		.int (DATA_END - DATA)
     56 PEOPT_HDR.SizeOfBss:		.int 0
     57 PEOPT_HDR.AddressOfEntryPoint:	.int (EntryPoint - BEGIN)
     58 PEOPT_HDR.BaseOfCode:		.int (CODE - BEGIN)
     59 
     60 PEOPT_HDR.BaseOfData:		/* missing due to 64-bit ImageBase in 64-bit PEs*/
     61 PEOPT_HDR.ImageBase:		.quad 0x40000
     62 PEOPT_HDR.SectionAlignment:	.int 0x1000
     63 PEOPT_HDR.FileAlignment:	.int 0x1000
     64 PEOPT_HDR.MajorOSVersion:	.short 0
     65 PEOPT_HDR.MinorOSVersion:	.short 0
     66 PEOPT_HDR.MajorImageVersion:	.short 0
     67 PEOPT_HDR.MinorImageVersion:	.short 0
     68 PEOPT_HDR.MajorSubsystemVersion:.short 0
     69 PEOPT_HDR.MinorSubsystemVersion:.short 0
     70 PEOPT_HDR.Win32VersionValue:	.int 0
     71 PEOPT_HDR.SizeOfImage:		.int (END - BEGIN)
     72 PEOPT_HDR.SizeOfHeaders:	.int (HEADER_END - HEADER)
     73 PEOPT_HDR.Checksum:		.int 0
     74 PEOPT_HDR.Subsystem:		.short EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
     75 PEOPT_HDR.DllCharacteristics:	.short 0
     76 PEOPT_HDR.SizeOfStackReserve:	.quad 0x200000
     77 PEOPT_HDR.SizeOfStackCommit:	.quad 0x1000
     78 PEOPT_HDR.SizeOfHeapReserve:	.quad 0x200000
     79 PEOPT_HDR.SizeOfHeapCommit:	.quad 0x1000
     80 PEOPT_HDR.LoaderFlags:		.int 0
     81 PEOPT_HDR.NumberOfRvaAndSizes:	.int 0
     82 
     83 PEOPT_HDR_END:
     84 
     85 SECTIONS_HDR:
     86 
     87 SECTION_CODE:
     88 SECTION_CODE.Name:		.byte '.', 't', 'e', 'x', 't', 0x00, 0x00, 0x00
     89 SECTION_CODE.VirtualSize:	.int (CODE_END - CODE)
     90 SECTION_CODE.VirtualAddress:	.int (CODE - BEGIN)
     91 SECTION_CODE.SizeOfRawData:	.int (CODE_END - CODE)
     92 SECTION_CODE.PointerToRawData:	.int (CODE - BEGIN)
     93 SECTION_CODE.PointerToRelocs:	.int 0
     94 SECTION_CODE.PointerToLineNums:	.int 0
     95 SECTION_CODE.NumberOfRelocs:	.short 0
     96 SECTION_CODE.NumberOfLineNums:	.short 0
     97 SECTION_CODE.Characteristics:	.int (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ)
     98 
     99 SECTION_DATA:
    100 SECTION_DATA.Name:		.byte '.', 'd', 'a', 't', 'a', 0x00, 0x00, 0x00
    101 SECTION_DATA.VirtualSize:	.int (DATA_END - DATA)
    102 SECTION_DATA.VirtualAddress:	.int (DATA - BEGIN)
    103 SECTION_DATA.SizeOfRawData:	.int (DATA_END - DATA)
    104 SECTION_DATA.PointerToRawData:	.int (DATA - BEGIN)
    105 SECTION_DATA.PointerToRelocs:	.int 0
    106 SECTION_DATA.PointerToLineNums:	.int 0
    107 SECTION_DATA.NumberOfRelocs:	.short 0
    108 SECTION_DATA.NumberOfLineNums:	.short 0
    109 SECTION_DATA.Characteristics:	.int (IMAGE_SCN_CNT_DATA | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)
    110 
    111 SECTIONS_HDR_END:
    112 
    113 HEADER_END:
    114 
    115 .align 16
    116 .section .text, "ax", %progbits
    117 
    118 CODE:
    119 
    120 .equ	EFI_SUCCESS, 			0
    121 
    122 .equ	EFI_ERROR, 			0x8000000000000000
    123 .equ	EFI_LOAD_ERROR,			1
    124 .equ	EFI_INVALID_PARAMETER,		2
    125 .equ	EFI_UNSUPPORTED,		3
    126 .equ	EFI_BUFFER_TOO_SMALL,		4
    127 .equ	EFI_NOT_FOUND,			14
    128 
    129 .equ	EFI_WARNING,			0x0000000000000000
    130 
    131 /* typedef void *EFI_HANDLE;
    132  * typedef EFI_HANDLE EFI_IMAGE_HANDLE;
    133  *
    134  * typedef struct {
    135  *   u64 Signature;
    136  *   u32 Revision;
    137  *   u32 HeaderSize;
    138  *   u32 CRC32;
    139  *   u32 Reserved;
    140  * } EFI_TABLE_HEADER;
    141  */
    142 .equ	EFI_TABLE_HEADER_SZ, 24
    143 
    144 /* typedef struct {
    145  *   EFI_GUID  VendorGuid;
    146  *   void     *VendorTable;
    147  * } EFI_CONFIGURATION_TABLE;
    148  *
    149  * typedef struct {
    150  *   EFI_TABLE_HEADER                 Hdr;
    151  *   c16                             *FirmwareVendor;
    152  *   u32                              FirmwareRevision;
    153  *   EFI_HANDLE                       ConsoleInHandle;
    154  *   EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *ConIn;
    155  *   EFI_HANDLE                       ConsoleOutHandle;
    156  *   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
    157  *   EFI_HANDLE                       StandardErrorHandle;
    158  *   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
    159  *   EFI_RUNTIME_SERVICES            *RuntimeServices;
    160  *   EFI_BOOT_SERVICES               *BootServices;
    161  *   umm                              NumberOfTableEntries;
    162  *   EFI_CONFIGURATION_TABLE         *ConfigurationTable;
    163  * } EFI_SYSTEM_TABLE;
    164  */
    165 .equ	EFI_SYSTEM_TABLE_CON_IN,		(EFI_TABLE_HEADER_SZ + 24)
    166 .equ	EFI_SYSTEM_TABLE_CON_OUT,		(EFI_TABLE_HEADER_SZ + 40)
    167 .equ	EFI_SYSTEM_TABLE_STD_ERR,		(EFI_TABLE_HEADER_SZ + 56)
    168 .equ	EFI_SYSTEM_TABLE_RUNTIME_SERVICES, 	(EFI_TABLE_HEADER_SZ + 64)
    169 .equ	EFI_SYSTEM_TABLE_BOOT_SERVICES,		(EFI_TABLE_HEADER_SZ + 72)
    170 .equ	EFI_SYSTEM_TABLE_NUBER_OF_TABLE_ENTS,	(EFI_TABLE_HEADER_SZ + 80)
    171 .equ	EFI_SYSTEM_TABLE_CONFIGURATION_TABLE,	(EFI_TABLE_HEADER_SZ + 88)
    172 
    173 /* typedef struct {
    174  *   EFI_INPUT_RESET    Reset;
    175  *   EFI_INPUT_READ_KEY ReadKeyStroke;
    176  *   EFI_EVENT          WaitForKey;
    177  * } EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
    178  *
    179  * typedef struct {
    180  *   s32 MaxMode;
    181  *
    182  *   s32 Mode;
    183  *   s32 Attribute;
    184  *   s32 CursorColumn;
    185  *   s32 CursorRow;
    186  *   b8  CursorVisible;
    187  * } SIMPLE_TEXT_OUTPUT_MODE;
    188  *
    189  * typedef struct {
    190  *   EFI_TEXT_RESET                Reset;
    191  *   EFI_TEXT_STRING               OutputString;
    192  *   EFI_TEXT_TEST_STRING          TestString;
    193  *   EFI_TEXT_QUERY_MODE           QueryMode;
    194  *   EFI_TEXT_SET_MODE             SetMode;
    195  *   EFI_TEXT_SET_ATTRIBUTE        SetAttribute;
    196  *   EFI_TEXT_CLEAR_SCREEN         ClearScreen;
    197  *   EFI_TEXT_SET_CURSOR_POSITION  SetCursorPosition;
    198  *   EFI_TEXT_ENABLE_CURSOR        EnableCursor;
    199  *   SIMPLE_TEXT_OUTPUT_MODE      *Mode;
    200  * } EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
    201  */
    202 .equ	EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_RESET,		0
    203 .equ	EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OUTPUT_STRING,	8
    204 .equ	EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_SET_ATTRIBUTE,	40
    205 .equ	EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_CLEAR_SCREEN,	48
    206 
    207 .equ	EFI_FG_WHITE,		0x0F
    208 
    209 .equ	EFI_BG_BLACK,		0x00
    210 .equ	EFI_BG_RED,		0x40
    211 
    212 /* typedef struct {
    213  *   EFI_TABLE_HEADER             Hdr;
    214  *
    215  *   EFI_GET_TIME                 GetTime;
    216  *   EFI_SET_TIME                 SetTime;
    217  *   EFI_GET_WAKEUP_TIME          GetWakeupTime;
    218  *   EFI_SET_WAKEUP_TIME          SetWakeupTime;
    219  *
    220  *   EFI_SET_VIRTUAL_ADDRESS_MAP  SetVirtualAddressMap;
    221  *   EFI_CONVERT_POINTER          ConvertPointer;
    222  *
    223  *   EFI_GET_VARIABLE             GetVariable;
    224  *   EFI_GET_NEXT_VARIABLE_NAME   GetNextVariableName;
    225  *   EFI_SET_VARIABLE             SetVariable;
    226  *
    227  *   EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHightMonotonicCount;
    228  *   EFI_RESET_SYSTEM             ResetSystem;
    229  *
    230  *   // UEFI 2.0+ specified fields
    231  * } EFI_RUNTIME_SERVICES;
    232  */
    233 .equ	EFI_RUNTIME_SERVICES_RESET_SYSTEM,	(EFI_TABLE_HEADER_SZ + 80)
    234 
    235 .equ	EFI_RESET_COLD,			0
    236 .equ	EFI_RESET_WARM,			1
    237 .equ	EFI_RESET_SHUTDOWN,		2
    238 .equ	EFI_RESET_PLATFORM_SPECIFIC,	3
    239 
    240 /* typedef struct {
    241  *   EFI_TABLE_HEADER                           Hdr;
    242  *
    243  *   EFI_RAISE_TPL                              RaiseTPL;
    244  *   EFI_RESTORE_TPL                            RestoreTPL;
    245  *
    246  *   EFI_ALLOCATE_PAGES                         AllocatePages;
    247  *   EFI_FREE_PAGES                             FreePages;
    248  *   EFI_GET_MEMORY_MAP                         GetMemoryMap;
    249  *   EFI_ALLOCATE_POOL                          AllocatePool;
    250  *   EFI_FREE_POOL                              FreePool;
    251  *
    252  *   EFI_CREATE_EVENT                           CreateEvent;
    253  *   EFI_SET_TIMER                              SetTimer;
    254  *   EFI_WAIT_FOR_EVENT                         WaitForEvent;
    255  *   EFI_SIGNAL_EVENT                           SignalEvent;
    256  *   EFI_CLOSE_EVENT                            CloseEvent;
    257  *   EFI_CHECK_EVENT                            CheckEvent;
    258  *
    259  *   EFI_INSTALL_PROTOCOL_INTERFACE             InstallProtocolInterface;
    260  *   EFI_REINSTALL_PROTOCOL_INTERFACE           ReinstallProtocolInterface;
    261  *   EFI_UNINSTALL_PROTOCOL_INTERFACE           UninstallProtocolInterface;
    262  *   EFI_HANDLE_PROTOCOL                        HandleProtocol;
    263  *   void                                      *Reserved;
    264  *   EFI_REGISTER_PROTOCOL_NOTIFY               RegisterProtocolNotify;
    265  *   EFI_LOCATE_HANDLE                          LocateHandle;
    266  *   EFI_LOCATE_DEVICE_PATH                     LocateDevicePath;
    267  *   EFI_INSTALL_CONFIGURATION_TABLE            InstallConfigurationTable;
    268  *
    269  *   EFI_IMAGE_LOAD                             LoadImage;
    270  *   EFI_IMAGE_START                            StartImage;
    271  *   EFI_EXIT                                   Exit;
    272  *   EFI_IMAGE_UNLOAD                           UnloadImage;
    273  *   EFI_EXIT_BOOT_SERVICES                     ExitBootServices;
    274  *
    275  *   EFI_GET_NEXT_MONOTONIC_COUNT               GetNextMonotonicCount;
    276  *   EFI_STALL                                  Stall;
    277  *   EFI_SET_WATCHDOG_TIMER                     SetWatchdogTimer;
    278  *
    279  *   //  EFI 1.1+ specified fields
    280  *   EFI_CONNECT_CONTROLLER                     ConnectController;
    281  *   EFI_DISCONNECT_CONTROLLER                  DisconnectController;
    282  *
    283  *   EFI_OPEN_PROTOCOL                          OpenProtocol;
    284  *   EFI_CLOSE_PROTOCOL                         CloseProtocol;
    285  *   EFI_OPEN_PROTOCOL_INFORMATION              OpenProtocolInformation;
    286  *
    287  *   EFI_PROTOCOLS_PER_HANDLE                   ProtocolsPerHandle;
    288  *   EFI_LOCATE_HANDLE_BUFFER                   LocateHandleBuffer;
    289  *   EFI_LOCATE_PROTOCOL                        LocateProtocol;
    290  *   EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES   InstallMultipleProtocolInterfaces;
    291  *   EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces;
    292  *
    293  *   EFI_CALCULATE_CRC32                        CalculateCRC32;
    294  *
    295  *   EFI_COPY_MEM                               CopyMem;
    296  *   EFI_SET_MEM                                SetMem;
    297  *
    298  *   // UEFI 2.0+ specified fields
    299  * } EFI_BOOT_SERVICES;
    300  */
    301 .equ	EFI_BOOT_SERVICES_GET_MEMORY_MAP,	(EFI_TABLE_HEADER_SZ + 40)
    302 .equ	EFI_BOOT_SERVICES_EXIT,			(EFI_TABLE_HEADER_SZ + 192)
    303 .equ	EFI_BOOT_SERVICES_EXIT_BOOT_SERVICES,	(EFI_TABLE_HEADER_SZ + 208)
    304 .equ	EFI_BOOT_SERVICES_STALL,		(EFI_TABLE_HEADER_SZ + 224)
    305 .equ	EFI_BOOT_SERVICES_LOCATE_PROTOCOL,	(EFI_TABLE_HEADER_SZ + 296)
    306 
    307 .equ	MICROS,	1000000
    308 
    309 /* we get called with the following state:
    310  *   rcx: EFI_HANDLE
    311  *   rdx: EFI_SYSTEM_TABLE *
    312  *   rsp: 8 byte offset, <retaddr>
    313  *
    314  * NOTE: UEFI requires a 16-byte aligned stack, and due to the return address
    315  *       being passed on the stack, we have an 8-byte offset. UEFI also expects
    316  *       a 32-byte shadow space to allow pushing all 4 potential arg registers.
    317  */
    318 EntryPoint:
    319 
    320 	/* NOTE: fix up the stack due to the following rules:
    321 	 * sub rsp, (a + b*8)
    322 	 *   - a : realign stack pointer to 16-bytes, accounting for the passed retaddr
    323 	 *   - b : we need to reserve shadow space for preserved registers
    324 	 */
    325 	sub rsp, (8 + 8*8)
    326 
    327 	mov rax, [rdx + EFI_SYSTEM_TABLE_CON_OUT]
    328 	mov rax, [rax + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_RESET]
    329 	mov rcx, [rdx + EFI_SYSTEM_TABLE_CON_OUT]
    330 	xor rdx, rdx
    331 	call rax
    332 
    333 	mov rax, [rdx + EFI_SYSTEM_TABLE_CON_OUT]
    334 	mov rax, [rax + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OUTPUT_STRING]
    335 	mov rcx, [rdx + EFI_SYSTEM_TABLE_CON_OUT]
    336 	lea rdx, [MSG_LOAD_KERNEL]
    337 	call rax
    338 
    339 wait:
    340 	jmp wait
    341 
    342 	add rsp, (8 + 8*8)
    343 	ret
    344 
    345 	mov EFI_IMAGE_HANDLE, rcx
    346 	mov EFI_SYSTEM_TABLE, rdx
    347 
    348 	mov rax, [rdx + EFI_SYSTEM_TABLE_CON_OUT]
    349 	mov EFI_STDOUT, rax
    350 
    351 	mov rax, [rdx + EFI_SYSTEM_TABLE_RUNTIME_SERVICES]
    352 	mov EFI_RUNTIME_SERVICES, rax
    353 
    354 	mov rax, [rdx + EFI_SYSTEM_TABLE_BOOT_SERVICES]
    355 	mov EFI_BOOT_SERVICES, rax
    356 
    357 	mov rax, [rdx + EFI_SYSTEM_TABLE_CONFIGURATION_TABLE]
    358 	mov EFI_CONFIGURATION_TABLE, rax
    359 
    360 	jmp load_kernel
    361 
    362 get_memory_map:
    363 	/* typedef struct {
    364 	 *   u32                  Type;
    365 	 *   EFI_PHYSICAL_ADDRESS PhysicalStart;
    366 	 *   EFI_VIRTUAL_ADDRESS  VirtualStart;
    367 	 *   u64                  NumberOfPages;
    368 	 *   u64                  Attribute;
    369 	 * } EFI_MEMORY_DESCRIPTOR;
    370 	 *
    371 	 * typedef EFI_STATUS (EFIAPI *EFI_GET_MEMORY_MAP) (
    372 	 *   IN OUT umm                *MemoryMapSize,
    373 	 *   OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
    374 	 *   OUT umm                   *MapKey,
    375 	 *   OUT umm                   *DescriptorSize,
    376 	 *   OUT u32                   *DescriptorVersion
    377 	 * );
    378 	 */
    379 	lea rcx, MEMORY_MAP_SIZE
    380 	lea rdx, MEMORY_MAP
    381 	lea r8,  MEMORY_MAP_KEY
    382 	lea r9,  MEMORY_DESCRIPTOR_SIZE
    383 	lea rax, MEMORY_DESCRIPTOR_VERSION
    384 	mov [rsp+32], rax
    385 	mov rax, EFI_BOOT_SERVICES
    386 	call [rax + EFI_BOOT_SERVICES_GET_MEMORY_MAP]
    387 	cmp al, EFI_BUFFER_TOO_SMALL	/* correct buffer size returned in [MEMORY_MAP_SIZE] */
    388 	je get_memory_map
    389 
    390 	cmp rax, EFI_SUCCESS
    391 	jne failure
    392 
    393 	/* typedef EFI_STATUS (EFIAPI *EFI_EXIT_BOOT_SERVICES) (
    394 	 *   IN EFI_HANDLE ImageHandle,
    395 	 *   IN umm        MapKey
    396 	 * );
    397 	 */
    398 	mov rcx, EFI_IMAGE_HANDLE
    399 	mov rdx, MEMORY_MAP_KEY
    400 	mov rax, EFI_BOOT_SERVICES
    401 	call [rax + EFI_BOOT_SERVICES_EXIT_BOOT_SERVICES]
    402 	cmp rax, EFI_SUCCESS		/* was our memory map key invalid? */
    403 	jne get_memory_map
    404 
    405 load_kernel:
    406 
    407 	/* typedef EFI_STATUS (EFIAPI *EFI_TEXT_RESET) (
    408 	 *   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
    409 	 *   IN b8                               ExtendedVerification
    410 	 * );
    411 	 */
    412 	mov rcx, EFI_STDOUT
    413 	mov rdx, 1
    414 	call [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_RESET]
    415 	cmp rax, EFI_SUCCESS
    416 	jne failure
    417 
    418 	/* typedef EFI_STATUS (EFIAPI *EFI_TEXT_SET_ATTRIBUTE) (
    419 	 *   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
    420 	 *   IN umm                              Attribute
    421 	 * );
    422 	 */
    423 	mov rcx, EFI_STDOUT
    424 	mov rdx, EFI_FG_WHITE | EFI_BG_BLACK
    425 	call [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_SET_ATTRIBUTE]
    426 	cmp rax, EFI_SUCCESS
    427 	jne failure
    428 
    429 	/* typedef EFI_STATUS (EFIAPI *EFI_TEXT_OUTPUT_CLEAR_SCREEN) (
    430 	 *   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
    431 	 * );
    432 	 */
    433 	mov rcx, EFI_STDOUT
    434 	call [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_CLEAR_SCREEN]
    435 	cmp rax, EFI_SUCCESS
    436 	jne failure
    437 
    438 	/* typedef EFI_STATUS (EFIAPI *EFI_TEXT_OUTPUT_STRING) (
    439 	 *   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
    440 	 *   IN c16                             *String
    441 	 * );
    442 	 */
    443 	mov rcx, EFI_STDOUT
    444 	lea rdx, MSG_LOAD_KERNEL
    445 	call [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OUTPUT_STRING]
    446 	cmp rax, EFI_SUCCESS
    447 	jne failure
    448 
    449 	/* typedef EFI_STATUS (EFIAPI *EFI_STALL) (
    450 	 *   IN umm Microseconds
    451 	 * );
    452 	 */
    453 	mov rcx, 10 * MICROS
    454 	mov rax, [EFI_BOOT_SERVICES]
    455 	call [rax + EFI_BOOT_SERVICES_STALL]
    456 
    457 	/* TODO: enable efi framebuffer for drawing */
    458 
    459 	/* typedef EFI_STATUS (EFIAPI *EFI_RESET_SYSTEM) (
    460 	 *   IN EFI_RESET_TYPE  ResetType,
    461 	 *   IN EFI_STATUS      ExitStatus,
    462 	 *   IN umm             DataSize,
    463 	 *   IN c16            *ResetData OPTIONAL
    464 	 * );
    465 	 */
    466 	mov rcx, EFI_RESET_SHUTDOWN
    467 	mov rdx, EFI_SUCCESS
    468 	mov r8,  0
    469 	mov r9,  0
    470 	mov rax, [EFI_RUNTIME_SERVICES]
    471 	call [rax + EFI_RUNTIME_SERVICES_RESET_SYSTEM]
    472 
    473 	/* EFI_RESET_SYSTEM does not return */
    474 
    475 	mov rax, EFI_SUCCESS
    476 	jmp exit
    477 
    478 failure:
    479 	mov rcx, [EFI_STDOUT]
    480 	lea rdx, [MSG_FAILURE]
    481 	call [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OUTPUT_STRING]
    482 
    483 	/* typedef EFI_STATUS (EFIAPI *EFI_EXIT) (
    484 	 *   IN EFI_HANDLE  ImageHandle,
    485 	 *   IN EFI_STATUS  ExitStatus,
    486 	 *   IN umm         ExitDataSize,
    487 	 *   IN c16        *ExitData OPTIONAL
    488 	 * );
    489 	 */
    490 	mov rcx, [EFI_IMAGE_HANDLE]
    491 	mov rdx, EFI_ERROR | EFI_LOAD_ERROR
    492 	mov r8,  0
    493 	mov r9,  0
    494 	mov rax, [EFI_BOOT_SERVICES]
    495 	call [rax + EFI_BOOT_SERVICES_EXIT]
    496 
    497 	/* EFI_EXIT does not return */
    498 
    499 	mov rax, EFI_ERROR | EFI_LOAD_ERROR
    500 	jmp exit
    501 
    502 exit:
    503 	add rsp, (8 + 8*8) /* undo UEFI stack constraints */
    504 	retn
    505 
    506 CODE_END:
    507 
    508 .align 4096
    509 .section .data, "aw", %progbits
    510 
    511 DATA:
    512 
    513 MSG_LOAD_KERNEL:		.short 'U', 'E', 'F', 'I', 13, 10, 0
    514 
    515 .align 16
    516 EFI_IMAGE_HANDLE:		.quad 0
    517 EFI_SYSTEM_TABLE:		.quad 0
    518 
    519 EFI_STDOUT:			.quad 0
    520 
    521 EFI_RUNTIME_SERVICES:		.quad 0
    522 EFI_BOOT_SERVICES:		.quad 0
    523 EFI_CONFIGURATION_TABLE:	.quad 0
    524 
    525 MEMORY_MAP_SIZE:		.quad (32 * 1024)	/* initially requested memory map buffer size */
    526 MEMORY_MAP:			.quad 0x200000		/* address at which to place the memory map */
    527 MEMORY_MAP_KEY:			.quad 0
    528 MEMORY_DESCRIPTOR_SIZE:		.quad 0
    529 MEMORY_DESCRIPTOR_VERSION:	.quad 0
    530 
    531 /* all strings are in unicode */
    532 .align 16
    533 MSG_FAILURE:			.short 'F', 'A', 'I', 'L', 13, 10, 0
    534 
    535 /*
    536 .align 16
    537 MSG_LOAD_KERNEL:		.short 'U', 'E', 'F', 'I', 13, 10, 0
    538 */
    539 
    540 DATA_END:
    541 
    542 .align 4096
    543 PAYLOAD:
    544 
    545 PAYLOAD_END:
    546 
    547 END: