diff --git a/build/definitions.mk b/build/definitions.mk index f2942a71c..2c5549448 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -53,7 +53,7 @@ XARGS ?= xargs -P4 -rs8000 NICE ?= build/actuallynice DOT ?= dot GZ ?= gzip -CLANG = clang-10 +CLANG = clang FC = gfortran #/opt/cross9f/bin/x86_64-linux-musl-gfortran # see build/compile, etc. which run third_party/gcc/unbundle.sh diff --git a/libc/nt/efi.h b/libc/nt/efi.h index 1c6edd7d9..c04b70c13 100644 --- a/libc/nt/efi.h +++ b/libc/nt/efi.h @@ -91,6 +91,13 @@ #define EFI_EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 #define EFI_EVT_RUNTIME_CONTEXT 0x20000000 +#define LOADED_IMAGE_PROTOCOL \ + { \ + 0x5B1B31A1, 0x9562, 0x11d2, { \ + 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B \ + } \ + } + #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -210,6 +217,12 @@ typedef struct { uint32_t Reserved; } EFI_TABLE_HEADER; +typedef struct { + uint8_t Type; + uint8_t SubType; + uint8_t Length[2]; +} EFI_DEVICE_PATH_PROTOCOL; + typedef EFI_STATUS(EFIAPI *EFI_EXIT)(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus, uintptr_t ExitDataSize, @@ -242,6 +255,10 @@ typedef EFI_STATUS(EFIAPI *EFI_GET_MEMORY_MAP)( uintptr_t *out_MapKey, uintptr_t *out_DescriptorSize, uint32_t *out_DescriptorVersion); +typedef EFI_STATUS(EFIAPI *EFI_ALLOCATE_POOL)(EFI_MEMORY_TYPE PoolType, + uintptr_t Size, void *out_Buffer); +typedef EFI_STATUS(EFIAPI *EFI_FREE_POOL)(void *Buffer); + typedef EFI_STATUS(EFIAPI *EFI_CHECK_EVENT)(EFI_EVENT Event); typedef EFI_STATUS(EFIAPI *EFI_CLOSE_EVENT)(EFI_EVENT Event); typedef EFI_STATUS(EFIAPI *EFI_SIGNAL_EVENT)(EFI_EVENT Event); @@ -318,6 +335,18 @@ typedef EFI_STATUS(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION)( typedef EFI_STATUS(EFIAPI *EFI_TEXT_ENABLE_CURSOR)( EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, bool Visible); +typedef EFI_STATUS(EFIAPI *EFI_HANDLE_PROTOCOL)(EFI_HANDLE Handle, + EFI_GUID *Protocol, + void *out_Interface); + +typedef EFI_STATUS(EFIAPI *EFI_IMAGE_LOAD)(bool BootPolicy, + EFI_HANDLE ParentImageHandle, + EFI_DEVICE_PATH_PROTOCOL *DevicePath, + void *opt_SourceBuffer, + uintptr_t SourceSize, + EFI_HANDLE *out_ImageHandle); +typedef EFI_STATUS(EFIAPI *EFI_IMAGE_UNLOAD)(EFI_HANDLE ImageHandle); + typedef struct { EFI_TABLE_HEADER Hdr; EFI_GET_TIME GetTime; @@ -343,8 +372,8 @@ typedef struct { EFI_ALLOCATE_PAGES AllocatePages; EFI_FREE_PAGES FreePages; EFI_GET_MEMORY_MAP GetMemoryMap; - void *AllocatePool; - void *FreePool; + EFI_ALLOCATE_POOL AllocatePool; + EFI_FREE_POOL FreePool; EFI_CREATE_EVENT CreateEvent; EFI_SET_TIMER SetTimer; EFI_WAIT_FOR_EVENT WaitForEvent; @@ -354,16 +383,16 @@ typedef struct { void *InstallProtocolInterface; void *ReinstallProtocolInterface; void *UninstallProtocolInterface; - void *HandleProtocol; + EFI_HANDLE_PROTOCOL HandleProtocol; void *Reserved; void *RegisterProtocolNotify; void *LocateHandle; void *LocateDevicePath; void *InstallConfigurationTable; - void *LoadImage; + EFI_IMAGE_LOAD LoadImage; void *StartImage; EFI_EXIT Exit; - void *UnloadImage; + EFI_IMAGE_UNLOAD UnloadImage; void *ExitBootServices; EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; EFI_STALL Stall; @@ -419,6 +448,22 @@ struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; }; +typedef struct { + uint32_t Revision; + EFI_HANDLE ParentHandle; + EFI_SYSTEM_TABLE *SystemTable; + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + void *Reserved; + uint32_t LoadOptionsSize; + void *LoadOptions; + void *ImageBase; + uint64_t ImageSize; + EFI_MEMORY_TYPE ImageCodeType; + EFI_MEMORY_TYPE ImageDataType; + EFI_IMAGE_UNLOAD Unload; +} EFI_LOADED_IMAGE; + COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_NT_EFI_H_ */ diff --git a/libc/runtime/efimain.c b/libc/runtime/efimain.greg.c similarity index 76% rename from libc/runtime/efimain.c rename to libc/runtime/efimain.greg.c index a135312aa..72e61f931 100644 --- a/libc/runtime/efimain.c +++ b/libc/runtime/efimain.greg.c @@ -18,10 +18,19 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/efi.h" #include "libc/dce.h" +#include "libc/macros.h" #include "libc/nt/efi.h" #include "libc/nt/thunk/msabi.h" +#include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" +struct EfiArgs { + char *args[4096]; + char argblock[ARG_MAX]; +}; + +static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; + /** * EFI Application Entrypoint. * @@ -39,7 +48,7 @@ * * qemu-system-x86_64 \ * -bios OVMF.fd \ - * -serial stdio \ + * -nographic \ * -net none \ * -drive format=raw,file=fat:rw:o/tool/viz * FS0: @@ -56,17 +65,30 @@ */ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { + intptr_t argc; + struct EfiArgs *ea; + EFI_LOADED_IMAGE *img; extern char os asm("__hostos"); os = UEFI; __efi_image_handle = ImageHandle; __efi_system_table = SystemTable; - asm("push\t$0\n\t" - "push\t$0\n\t" - "push\t$0\n\t" - "push\t$0\n\t" - "push\t$0\n\t" - "xor\t%edi,%edi\n\t" + SystemTable->BootServices->AllocatePool(EfiConventionalMemory, sizeof(*ea), + &ea); + SystemTable->BootServices->HandleProtocol(ImageHandle, + &kEfiLoadedImageProtocol, &img); + argc = GetDosArgv(img->LoadOptions, ea->argblock, ARG_MAX, ea->args, + ARRAYLEN(ea->args)); + asm("push\t$0\n\t" /* auxv[0][1] */ + "push\t$0\n\t" /* auxv[0][0] */ + "push\t$0\n\t" /* envp[0] */ + "sub\t%2,%%rsp\n\t" + "mov\t%%rsp,%%rdi\n\t" + "rep movsb\n\t" /* argv */ + "push\t%0\n\t" /* argc */ + "xor\t%%edi,%%edi\n\t" ".weak\t_start\n\t" - "jmp\t_start"); + "jmp\t_start" + : /* no outputs */ + : "a"(argc), "S"(ea->args), "c"((argc + 1) * 8)); unreachable; }