[metal] Get examples/vga2.c VGA output working for UEFI boot

This commit is contained in:
tkchia 2022-11-12 20:54:49 +00:00
parent 9fe2f55113
commit dfd7f9aa1b
6 changed files with 354 additions and 106 deletions

View file

@ -27,8 +27,13 @@ STATIC_YOINK("_idt");
STATIC_YOINK("EfiMain");
int main(int argc, char *argv[]) {
int i;
volatile int x = 1;
volatile int y = 2;
printf("argc = %d\n", argc);
for (i = 0; i < argc; ++i) {
printf("argv[%d] = \"%s\"\n", i, argv[i]);
}
printf("\e[92;44mHello World!\e[0m %d\n", 1 / (x + y - 3));
for (;;);
}

View file

@ -177,6 +177,7 @@ privileged static void klog(const char *b, size_t n) {
__imp_WriteFile(__imp_GetStdHandle(kNtStdErrorHandle), b, n, &wrote, 0);
__imp_SetLastError(e);
} else if (IsMetal()) {
if (_weaken(_klog_vga)) _weaken(_klog_vga)(b, n);
for (i = 0; i < n; ++i) {
for (;;) {
dx = 0x3F8 + UART_LSR;
@ -189,7 +190,6 @@ privileged static void klog(const char *b, size_t n) {
: /* no inputs */
: "a"(b[i]), "dN"(dx));
}
if (_weaken(_klog_vga)) _weaken(_klog_vga)(b, n);
} else {
asm volatile("syscall"
: "=a"(rax), "=D"(rdi), "=S"(rsi), "=d"(rdx)

View file

@ -236,14 +236,23 @@ noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
*/
noasan textreal void __reclaim_boot_pages(struct mman *mm, uint64_t skip_start,
uint64_t skip_end) {
uint64_t p = mm->frp, q = IMAGE_BASE_REAL, e;
e = mm->e820[0].addr + mm->e820[0].size;
while (q != e) {
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + q);
rp->next = p;
p = q;
q += 4096;
if (q == skip_start) q = skip_end;
uint64_t p = mm->frp, q = IMAGE_BASE_REAL, i, n = mm->e820n, b, e;
for (i = 0; i < n; ++i) {
b = mm->e820[i].addr;
if (b >= IMAGE_BASE_PHYSICAL) break;
e = MIN(IMAGE_BASE_PHYSICAL, b + mm->e820[i].size);
q = MAX(IMAGE_BASE_REAL, b);
while (q < e) {
struct ReclaimedPage *rp;
if (q == skip_start) {
q = skip_end;
if (q >= e) break;
}
rp = (struct ReclaimedPage *)(BANE + q);
rp->next = p;
p = q;
q += 4096;
}
}
mm->frp = p;
}

View file

@ -97,6 +97,12 @@
0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B \
} \
}
#define GRAPHICS_OUTPUT_PROTOCOL \
{ \
0x9042A9DE, 0x23DC, 0x4A38, { \
0x96, 0xFB, 0x7A, 0xDE, 0xD0, 0x80, 0x51, 0x6A \
} \
}
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -113,6 +119,7 @@ COSMOPOLITAN_C_START_
typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL;
typedef enum {
EfiReservedMemoryType,
@ -214,6 +221,54 @@ typedef struct {
bool CursorVisible;
} EFI_SIMPLE_TEXT_OUTPUT_MODE;
typedef enum {
PixelRedGreenBlueReserved8BitPerColor,
PixelBlueGreenRedReserved8BitPerColor,
PixelBitMask,
PixelBltOnly,
PixelFormatMax
} EFI_GRAPHICS_PIXEL_FORMAT;
typedef struct {
uint32_t RedMask;
uint32_t GreenMask;
uint32_t BlueMask;
uint32_t ReservedMask;
} EFI_PIXEL_BITMASK;
typedef struct {
uint32_t Version;
uint32_t HorizontalResolution;
uint32_t VerticalResolution;
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
EFI_PIXEL_BITMASK PixelInformation;
uint32_t PixelsPerScanLine;
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
typedef struct {
uint8_t Blue;
uint8_t Green;
uint8_t Red;
uint8_t Reserved;
} EFI_GRAPHICS_OUTPUT_BLT_PIXEL;
typedef enum {
EfiBltVideoFill,
EfiBltVideoToBltBuffer,
EfiBltBufferToVideo,
EfiBltVideoToVideo,
EfiGraphicsOutputBltOperationMax
} EFI_GRAPHICS_OUTPUT_BLT_OPERATION;
typedef struct {
uint32_t MaxMode;
uint32_t Mode;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
uint32_t SizeOfInfo;
uint64_t FrameBufferBase;
uint32_t FrameBufferSize;
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
typedef struct {
uint64_t Signature;
uint32_t Revision;
@ -300,6 +355,9 @@ typedef EFI_STATUS(EFIAPI *EFI_SET_WATCHDOG_TIMER)(uintptr_t Timeout,
uint64_t WatchdogCode,
uintptr_t DataSize,
char16_t *opt_WatchdogData);
typedef EFI_STATUS(EFIAPI *EFI_LOCATE_PROTOCOL)(EFI_GUID *Protocol,
void *Registration,
void *Interface);
typedef EFI_STATUS(EFIAPI *EFI_SET_TIME)(EFI_TIME *Time);
typedef EFI_STATUS(EFIAPI *EFI_GET_TIME)(
@ -343,6 +401,19 @@ 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_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE)(
EFI_GRAPHICS_OUTPUT_PROTOCOL *This, uint32_t ModeNumber,
uint32_t *SizeOfInfo, EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info);
typedef EFI_STATUS(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE)(
EFI_GRAPHICS_OUTPUT_PROTOCOL *This, uint32_t ModeNumber);
typedef EFI_STATUS(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT)(
EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
uint32_t SourceX, uint32_t SourceY,
uint32_t DestinationX, uint32_t DestinationY,
uint32_t Width, uint32_t Height, uint32_t Delta);
typedef EFI_STATUS(EFIAPI *EFI_HANDLE_PROTOCOL)(EFI_HANDLE Handle,
EFI_GUID *Protocol,
void *out_Interface);
@ -414,7 +485,7 @@ typedef struct {
void *OpenProtocolInformation;
void *ProtocolsPerHandle;
void *LocateHandleBuffer;
void *LocateProtocol;
EFI_LOCATE_PROTOCOL LocateProtocol;
void *InstallMultipleProtocolInterfaces;
void *UninstallMultipleProtocolInterfaces;
void *CalculateCrc32;
@ -458,6 +529,13 @@ struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
};
struct _EFI_GRAPHICS_OUTPUT_PROTOCOL {
EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode;
EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode;
EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt;
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
};
typedef struct {
uint32_t Revision;
EFI_HANDLE ParentHandle;

View file

@ -16,9 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "ape/relocations.h"
#include "ape/sections.internal.h"
#include "libc/dce.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/newbie.h"
#include "libc/intrin/weaken.h"
#include "libc/macros.internal.h"
#include "libc/nt/efi.h"
#include "libc/nt/thunk/msabi.h"
@ -37,6 +40,80 @@ struct EfiArgs {
};
static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
static const EFI_GUID kEfiGraphicsOutputProtocol = GRAPHICS_OUTPUT_PROTOCOL;
extern const char vga_console[];
extern void _EfiPostboot(struct mman *, uint64_t *, uintptr_t, char **);
static void EfiInitVga(struct mman *mm, EFI_SYSTEM_TABLE *SystemTable) {
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphInfo;
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *GraphMode;
EFI_PIXEL_BITMASK *PixelInfo;
unsigned vid_typ = PC_VIDEO_TEXT;
size_t bytes_per_pix = 0;
SystemTable->BootServices->LocateProtocol(&kEfiGraphicsOutputProtocol, NULL,
&GraphInfo);
GraphMode = GraphInfo->Mode;
switch (GraphMode->Info->PixelFormat) {
case PixelRedGreenBlueReserved8BitPerColor:
vid_typ = PC_VIDEO_RGBX8888;
bytes_per_pix = 4;
break;
case PixelBlueGreenRedReserved8BitPerColor:
vid_typ = PC_VIDEO_BGRX8888;
bytes_per_pix = 4;
break;
case PixelBitMask:
PixelInfo = &GraphMode->Info->PixelInformation;
switch (le32toh(PixelInfo->RedMask)) {
case 0x00FF0000U:
if (le32toh(PixelInfo->ReservedMask) >= 0x01000000U &&
le32toh(PixelInfo->GreenMask) == 0x0000FF00U &&
le32toh(PixelInfo->BlueMask) == 0x000000FFU) {
vid_typ = PC_VIDEO_BGRX8888;
bytes_per_pix = 4;
}
break;
case 0x000000FFU:
if (le32toh(PixelInfo->ReservedMask) >= 0x01000000U &&
le32toh(PixelInfo->GreenMask) == 0x0000FF00U &&
le32toh(PixelInfo->BlueMask) == 0x00FF0000U) {
vid_typ = PC_VIDEO_RGBX8888;
bytes_per_pix = 4;
}
break;
case 0x0000F800U:
if (le32toh(PixelInfo->ReservedMask) <= 0x0000FFFFU &&
le32toh(PixelInfo->GreenMask) == 0x000007E0U &&
le32toh(PixelInfo->BlueMask) == 0x0000001FU) {
vid_typ = PC_VIDEO_BGR565;
bytes_per_pix = 2;
}
break;
case 0x00007C00U:
if (le32toh(PixelInfo->ReservedMask) <= 0x0000FFFFU &&
le32toh(PixelInfo->GreenMask) == 0x000003E0U &&
le32toh(PixelInfo->BlueMask) == 0x0000001FU) {
vid_typ = PC_VIDEO_BGR555;
bytes_per_pix = 2;
}
break;
}
default:
notpossible;
}
if (!bytes_per_pix) notpossible;
mm->pc_video_type = vid_typ;
mm->pc_video_stride = GraphMode->Info->PixelsPerScanLine * bytes_per_pix;
mm->pc_video_width = GraphMode->Info->HorizontalResolution;
mm->pc_video_height = GraphMode->Info->VerticalResolution;
mm->pc_video_framebuffer = GraphMode->FrameBufferBase;
mm->pc_video_framebuffer_size = GraphMode->FrameBufferSize;
mm->pc_video_curs_info.y = mm->pc_video_curs_info.x = 0;
SystemTable->BootServices->SetMem((void *)GraphMode->FrameBufferBase,
GraphMode->FrameBufferSize, 0);
}
/**
* EFI Application Entrypoint.
@ -62,19 +139,8 @@ static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
*
* @see libc/dce.h
*/
__msabi noasan __attribute__((__naked__))
EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
asm volatile("mov\t$0f,%esp\n\t"
"and\t$-16,%esp\n\t"
"jmp\t_DoEfiMain\n\t"
".bss\n\t"
".space\t8192\n"
"0:\n\t"
".previous");
}
__msabi noasan EFI_STATUS _DoEfiMain(EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *SystemTable) {
__msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *SystemTable) {
int type, x87cw = 0x037f;
struct mman *mm;
uint32_t DescVersion;
@ -82,18 +148,37 @@ __msabi noasan EFI_STATUS _DoEfiMain(EFI_HANDLE ImageHandle,
struct EfiArgs *ArgBlock;
EFI_LOADED_IMAGE *ImgInfo;
EFI_MEMORY_DESCRIPTOR *Map, *Desc;
uint64_t NewBase = 1024 * 1024;
uint64_t Address;
uintptr_t Args, MapKey, DescSize;
uint64_t p, pe, cr4, *m, *pd, *sp, *pml4t, *pdt1, *pdt2, *pdpt1, *pdpt2;
/*
* Allocates and clears PC-compatible memory and copies image.
* Allocates and clears PC-compatible memory and copies image. Marks the
* pages as EfiRuntimeServicesData, so that we can simply free up all
* EfiLoader... and EfiBootServices... pages later. The first page at
* address 0 is normally already allocated as EfiBootServicesData, so
* handle it separately.
*/
Address = 0;
SystemTable->BootServices->AllocatePages(
AllocateAddress, EfiConventionalMemory,
MAX(2 * 1024 * 1024, 1024 * 1024 + (_end - _base)) / 4096, &NewBase);
SystemTable->BootServices->SetMem(0, 0x80000, 0);
SystemTable->BootServices->CopyMem((void *)(1024 * 1024), _base,
AllocateAddress, EfiRuntimeServicesData, 4096 / 4096, &Address);
Address = 4096;
SystemTable->BootServices->AllocatePages(
AllocateAddress, EfiRuntimeServicesData, (IMAGE_BASE_REAL - 4096) / 4096,
&Address);
Address = 0x79000;
SystemTable->BootServices->AllocatePages(
AllocateAddress, EfiRuntimeServicesData,
(0x7e000 - 0x79000 + sizeof(struct EfiArgs) + 4095) / 4096, &Address);
Address = IMAGE_BASE_PHYSICAL;
SystemTable->BootServices->AllocatePages(
AllocateAddress, EfiRuntimeServicesData,
((_end - _base) + 4095) / 4096, &Address);
mm = (struct mman *)0x0500;
SystemTable->BootServices->SetMem(mm, sizeof(*mm), 0);
SystemTable->BootServices->SetMem((void *)0x79000,
0x7e000 - 0x79000 + sizeof(struct EfiArgs), 0);
SystemTable->BootServices->CopyMem((void *)IMAGE_BASE_PHYSICAL, _base,
_end - _base);
/*
@ -106,6 +191,13 @@ __msabi noasan EFI_STATUS _DoEfiMain(EFI_HANDLE ImageHandle,
sizeof(ArgBlock->ArgBlock), ArgBlock->Args,
ARRAYLEN(ArgBlock->Args));
/*
* Gets information about our current video mode. Clears the screen.
* TODO: if needed, switch to a video mode that has a linear frame buffer
* type we support.
*/
if (_weaken(vga_console)) EfiInitVga(mm, SystemTable);
/*
* Asks UEFI which parts of our RAM we're allowed to use.
*/
@ -117,13 +209,20 @@ __msabi noasan EFI_STATUS _DoEfiMain(EFI_HANDLE ImageHandle,
MapSize *= 2;
SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize,
&DescVersion);
mm = (struct mman *)0x0500;
for (j = i = 0, Desc = Map; i < MapSize / DescSize; ++i) {
if (Desc->Type == EfiConventionalMemory) {
mm->e820[j].addr = Desc->PhysicalStart;
mm->e820[j].size = Desc->NumberOfPages * 4096;
mm->e820[j].type = kMemoryUsable;
++j;
switch (Desc->Type) {
case EfiLoaderCode:
case EfiLoaderData:
case EfiBootServicesCode:
case EfiBootServicesData:
if (Desc->PhysicalStart != 0)
break;
/* fallthrough */
case EfiConventionalMemory:
mm->e820[j].addr = Desc->PhysicalStart;
mm->e820[j].size = Desc->NumberOfPages * 4096;
mm->e820[j].type = kMemoryUsable;
++j;
}
Desc = (EFI_MEMORY_DESCRIPTOR *)((char *)Desc + DescSize);
}
@ -154,77 +253,8 @@ __msabi noasan EFI_STATUS _DoEfiMain(EFI_HANDLE ImageHandle,
SystemTable->BootServices->ExitBootServices(ImageHandle, MapKey);
/*
* Switches to copied image.
* Switches to copied image and launches program.
*/
asm volatile("cli\n\t"
"add\t%1,%%rsp\n\t"
"lea\t0f(%1),%0\n\t"
"jmp\t*%0\n"
"0:\n\t"
"mov\t%2,%%cr3\n\t"
"add\t%3,%%rsp\n\t"
"lea\t1f(%1),%0\n\t"
"add\t%3,%0\n\t"
"jmp\t*%0\n"
"1:"
: "=&r"(p)
: "r"(1024 * 1024 - (uint64_t)_base), "r"(pml4t), "r"(BANE));
/*
* Sets up virtual memory mapping.
*/
__map_phdrs(mm, pml4t, 1024 * 1024, 1024 * 1024 + (_end - _base));
__reclaim_boot_pages(mm, 0x79000, 0x7f000);
/*
* Launches program.
*/
asm volatile("fldcw\t%3\n\t"
".weak\t_gdtr\n\t"
"lgdt\t_gdtr\n\t"
"mov\t%w6,%%ds\n\t"
"mov\t%w6,%%ss\n\t"
"mov\t%w6,%%es\n\t"
"mov\t%w6,%%fs\n\t"
"mov\t%w6,%%gs\n\t"
".weak\tape_stack_vaddr\n\t"
".weak\tape_stack_memsz\n\t"
"movabs\t$ape_stack_vaddr,%%rsp\n\t"
"add\t$ape_stack_memsz,%%rsp\n\t"
"push\t$0\n\t" /* auxv[1][1] */
"push\t$0\n\t" /* auxv[1][0] */
"push\t(%1)\n\t" /* auxv[0][1] */
"push\t$31\n\t" /* auxv[0][0] AT_EXECFN */
"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"
"xor\t%%eax,%%eax\n\t"
"xor\t%%ebx,%%ebx\n\t"
"mov\t%4,%%ecx\n\t"
"xor\t%%edx,%%edx\n\t"
"xor\t%%edi,%%edi\n\t"
"xor\t%%esi,%%esi\n\t"
"xor\t%%ebp,%%ebp\n\t"
"xor\t%%r8d,%%r8d\n\t"
"xor\t%%r9d,%%r9d\n\t"
"xor\t%%r10d,%%r10d\n\t"
"xor\t%%r11d,%%r11d\n\t"
"xor\t%%r12d,%%r12d\n\t"
"xor\t%%r13d,%%r13d\n\t"
"xor\t%%r14d,%%r14d\n\t"
"xor\t%%r15d,%%r15d\n\t"
".weak\t_start\n\t"
"push\t%5\n\t"
"push\t$_start\n\t"
"lretq"
: /* no outputs */
: "a"(Args), "S"(ArgBlock->Args), "c"((Args + 1) * 8),
"m"(x87cw), "i"(_HOSTMETAL), "i"(GDT_LONG_CODE),
"r"(GDT_LONG_DATA)
: "memory");
_EfiPostboot(mm, pml4t, Args, ArgBlock->Args);
unreachable;
}

126
libc/runtime/efipostboot.S Normal file
View file

@ -0,0 +1,126 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "ape/relocations.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/runtime/pc.internal.h"
.real
// Start the Cosmopolitan runtime after exiting UEFI Boot Services.
//
// @param rdi is mm
// @param rsi is new pml4t
// @param rdx is argc
// @param rcx is argv
// @see libc/runtime/efimain.greg.c
_EfiPostboot:
cli
// Define handy mnemonics for parameters & constants stored in
// call-saved registers.
#define rMm %r12
#define rArgc %r13
#define rArgv %r14
#define rBane %r15
movabs $BANE,rBane
mov %rdi,rMm
mov %rdx,rArgc
lea (rBane,%rcx),rArgv
mov $PHYSICAL(.Ltmpstk),%rax # switch to temporary stack
and $-16,%al # in physical space
xchg %rax,%rsp
mov $PHYSICAL(0f),%eax # resume execution in copied
jmp *%rax # image
0: mov $EFER,%ecx # enable syscall/sysret & nx
rdmsr
or $EFER_SCE|EFER_NXE,%eax
wrmsr
mov %rsi,%cr3 # load new page table
add rBane,%rsp # we can now switch stack to
add rBane,rMm # negative address space
mov $1024*1024,%edx # set up virtual memory
mov $1024*1024+_end,%ecx # mapping
sub $_base,%ecx
call __map_phdrs
mov $1f,%eax # switch rip to virtual
jmp *%rax # address space
1: push $0x037f
fldcw (%rsp)
.weak _gdtr
lgdt _gdtr # switch to our own GDT
mov $GDT_LONG_DATA,%ax
mov %ax,%ds
mov %ax,%ss
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
.weak ape_stack_vaddr
.weak ape_stack_memsz
movabs $ape_stack_vaddr,%rsp # switch to final stack in
add $ape_stack_memsz,%rsp # virtual address space
movl $0,0x7b000 # unmap null 2mb
mov rMm,%rdi
xor %esi,%esi # free up now-unused pages
xor %edx,%edx
call __reclaim_boot_pages
push .Lenv0(%rip) # envp[0][0]
mov %rsp,%rbp
push $0 # auxv[1][1]
push $0 # auxv[1][0]
mov (rArgv),%rax
add rBane,%rax
push %rax # auxv[0][1]
push $31 # auxv[0][0] AT_EXECFN
push $0 # envp[1]
push %rbp # envp[0]
push $0 # argv[argc] NULL
lea -8(rArgv,rArgc,8),%rsi # push rest of argv, &
mov rArgc,%rcx # adjust pointers to point to
std # negative space
2: lodsq
add rBane,%rax
push %rax
loop 2b
cld
push rArgc # argc
pushpop _HOSTMETAL,%rcx # sets __hostos in crt.S
xor %ebp,%ebp
xor %eax,%eax
xor %ebx,%ebx
xor %edx,%edx
xor %edi,%edi
xor %esi,%esi
xor %r8d,%r8d
xor %r9d,%r9d
xor %r10d,%r10d
xor %r11d,%r11d
xor %r12d,%r12d
xor %r13d,%r13d
xor %r14d,%r14d
xor %r15d,%r15d
push $GDT_LONG_CODE
.weak _start
push $_start
lretq
.endfn _EfiPostboot,globl,hidden
.rodata
.Lenv0: .asciz "METAL=1"
.bss
.space 0x1000
.Ltmpstk:
.previous