Add UEFI support

This is mutually exclusive with Windows support. Documentation for how
to use it has been written in libc/runtime/efimain.c
This commit is contained in:
Justine Tunney 2021-02-21 16:26:36 -08:00 committed by Justine Tunney
parent c6c9b5dfde
commit 537c21338b
24 changed files with 1381 additions and 391 deletions

View file

@ -105,7 +105,7 @@ rlstr: .endobj rlstr,globl,hidden # ←for gdb readibility
αcτµαlly pδrταblε εxεcµταblε § the old technology αcτµαlly pδrταblε εxεcµταblε § the old technology
*/ */
#if SupportsWindows() || SupportsXnu() #if SupportsWindows() || SupportsUefi() || SupportsXnu()
// MZ Literally Executable Header // MZ Literally Executable Header
// //
@ -131,14 +131,14 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
.ascii "JT" # MZ: OEM identifier .ascii "JT" # MZ: OEM identifier
.short 0 # MZ: OEM information .short 0 # MZ: OEM information
.org 0x40-4 # MZ: bytes reserved for you .org 0x40-4 # MZ: bytes reserved for you
#if SupportsWindows() #if SupportsWindows() || SupportsUefi()
.long RVA(ape_pe) # PE: the new technology .long RVA(ape_pe) # PE: the new technology
#else #else
.long 0 .long 0
#endif #endif
.endfn ape_mz,globl,hidden .endfn ape_mz,globl,hidden
#else /* !(SupportsWindows() || SupportsXnu()) */ #else /* !(SupportsWindows() || SupportsUefi() || SupportsXnu()) */
// ELF Literally Executable Header // ELF Literally Executable Header
// //
@ -168,7 +168,7 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
.short ape_elf_shnum # 3c: e_shnum .short ape_elf_shnum # 3c: e_shnum
.short ape_elf_shstrndx # 3e: e_shstrndx .short ape_elf_shstrndx # 3e: e_shstrndx
#endif /* SupportsWindows() || SupportsXnu() */ #endif /* SupportsWindows() || SupportsUefi() || SupportsXnu() */
#if SupportsMetal() #if SupportsMetal()
@ -471,7 +471,7 @@ ape_disk:
#if SupportsSystemv() #if SupportsSystemv()
#if SupportsWindows() || SupportsXnu() #if SupportsWindows() || SupportsUefi() || SupportsXnu()
apesh: .ascii "'\n#'\"\n" # sixth edition shebang apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "o=\"$(command -v \"$0\")\"\n" .ascii "o=\"$(command -v \"$0\")\"\n"
#if SupportsXnu() #if SupportsXnu()
@ -526,7 +526,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "fi\n" .ascii "fi\n"
.ascii "exit $R\n" .ascii "exit $R\n"
.endobj apesh .endobj apesh
#endif /* SupportsWindows() || SupportsXnu() */ #endif /* SupportsWindows() || SupportsUefi() || SupportsXnu() */
.section .elf.phdrs,"a",@progbits .section .elf.phdrs,"a",@progbits
.long PT_LOAD # text segment .long PT_LOAD # text segment
@ -812,7 +812,7 @@ PETEXT = 0b01110000000000000000000001100000
PEDATA = 0b11000000000000000000000011000000 PEDATA = 0b11000000000000000000000011000000
PEIMPS = 0b11000000000000000000000001000000 PEIMPS = 0b11000000000000000000000001000000
#if SupportsWindows() #if SupportsWindows() || SupportsUefi()
.section .pe.header,"a",@progbits .section .pe.header,"a",@progbits
.align __SIZEOF_POINTER__ .align __SIZEOF_POINTER__
@ -830,23 +830,27 @@ ape_pe: .ascin "PE",4
.long 0 # SizeOfCode .long 0 # SizeOfCode
.long 0 # SizeOfInitializedData .long 0 # SizeOfInitializedData
.long 0 # SizeOfUninitializedData .long 0 # SizeOfUninitializedData
.long RVA(WinMain) # EntryPoint .long RVA(ape_pe_entry) # EntryPoint
.long 0 # BaseOfCode .long 0 # BaseOfCode
.quad IMAGE_BASE_VIRTUAL # ImageBase .quad IMAGE_BASE_VIRTUAL # ImageBase
.long 4096 # SectionAlignment .long 4096 # SectionAlignment
.long 4096 # FileAlignment .long 4096 # FileAlignment
.short 6 # MajorOperatingSystemVersion .short v_ntversion # MajorOperatingSystemVersion
.short 0 # MinorOperatingSystemVersion .short 0 # MinorOperatingSystemVersion
.short 0 # MajorImageVersion .short 0 # MajorImageVersion
.short 0 # MinorImageVersion .short 0 # MinorImageVersion
.short 6 # MajorSubsystemVersion .short v_ntsubversion # MajorSubsystemVersion
.short 0 # MinorSubsystemVersion .short 0 # MinorSubsystemVersion
.long 0 # Win32VersionValue .long 0 # Win32VersionValue
.long RVA(_end) # SizeOfImage .long RVA(_end) # SizeOfImage
.long RVA(_ehead) # SizeOfHeaders .long RVA(_ehead) # SizeOfHeaders
.long 0 # Checksum .long 0 # Checksum
.short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console .short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console
#if SupportsWindows()
.short DLLEXE # DllCharacteristics .short DLLEXE # DllCharacteristics
#else
.short 0 # DllCharacteristics
#endif
.quad 0x0000000000100000 # StackReserve .quad 0x0000000000100000 # StackReserve
.quad 0x00000000000fc000 # StackCommit .quad 0x00000000000fc000 # StackCommit
.quad 0 # HeapReserve .quad 0 # HeapReserve
@ -854,8 +858,12 @@ ape_pe: .ascin "PE",4
.long 0 # LoaderFlags .long 0 # LoaderFlags
.long 16 # NumberOfDirectoryEntries .long 16 # NumberOfDirectoryEntries
.long 0,0 # ExportsDirectory .long 0,0 # ExportsDirectory
#if SupportsWindows()
.long RVA(ape_idata_idt) # ImportsDirectory .long RVA(ape_idata_idt) # ImportsDirectory
.stub ape_idata_idtsize,long # ImportsDirectorySize .stub ape_idata_idtsize,long # ImportsDirectorySize
#else
.long 0,0 # ImportsDirectory
#endif
.long 0,0 # ResourcesDirectory .long 0,0 # ResourcesDirectory
.long 0,0 # ExceptionsDirectory .long 0,0 # ExceptionsDirectory
.long 0,0 # SecurityDirectory .long 0,0 # SecurityDirectory
@ -866,8 +874,12 @@ ape_pe: .ascin "PE",4
.long 0,0 # ThreadLocalStorage .long 0,0 # ThreadLocalStorage
.long 0,0 # LoadConfigurationDirectory .long 0,0 # LoadConfigurationDirectory
.long 0,0 # BoundImportDirectory .long 0,0 # BoundImportDirectory
#if SupportsWindows()
.long RVA(ape_idata_iat) # ImportAddressDirectory .long RVA(ape_idata_iat) # ImportAddressDirectory
.stub ape_idata_iatsize,long # ImportAddressDirectorySize .stub ape_idata_iatsize,long # ImportAddressDirectorySize
#else
.long 0,0 # ImportAddressDirectory
#endif
.long 0,0 # DelayImportDescriptor .long 0,0 # DelayImportDescriptor
.long 0,0 # ComPlusRuntimeHeader .long 0,0 # ComPlusRuntimeHeader
.long 0,0 # Reserved .long 0,0 # Reserved
@ -900,7 +912,7 @@ ape_pe: .ascin "PE",4
.long PEDATA # Flags .long PEDATA # Flags
.previous .previous
#endif /* SupportsWindows() */ #endif /* SupportsWindows() || SupportsUefi() */
.section .idata.ro.idt.1,"a",@progbits .section .idata.ro.idt.1,"a",@progbits
.type ape_idata_idtend,@object .type ape_idata_idtend,@object
@ -1524,22 +1536,21 @@ metal.thunk:
#endif #endif
// 𝑠𝑙𝑖𝑑𝑒 // 𝑠𝑙𝑖𝑑𝑒
.endfn metal.thunk .endfn metal.thunk
metal: metal: xor %eax,%eax # clear bss
xor %eax,%eax # clear bss
mov $ape_bss_vaddr,%edi mov $ape_bss_vaddr,%edi
mov $ape_bss_memsz,%ecx mov $ape_bss_memsz,%ecx
rep stosb rep stosb
.weak __hostos 0: .weak __hostos
ezlea __hostos,ax ezlea __hostos,ax
test %rax,%rax test %rax,%rax
jz 1f jz 1f
movb $METAL,(%rax) movb $METAL,(%rax)
1: push $0 # auxv 1: push $0 # auxv[0][1]
push $0 push $0 # auxv[0][0]
push $0 # envp push $0 # envp[0]
push $0 # auxv push $0 # argv[0]
push $0 # argc push $0 # argc
xor %edi,%edi xor %edi,%edi # not freebsd
jmp _start jmp _start
.endfn metal .endfn metal

View file

@ -229,7 +229,7 @@ SECTIONS {
. += 1; . += 1;
KEEP(*(.ape.pad.head)) KEEP(*(.ape.pad.head))
. = ALIGN(SupportsWindows() ? PAGESIZE : 16); . = ALIGN(SupportsWindows() || SupportsUefi() ? PAGESIZE : 16);
HIDDEN(_ehead = .); HIDDEN(_ehead = .);
} :Head } :Head
@ -500,15 +500,21 @@ SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8);
SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8); SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8);
#endif #endif
#if SupportsWindows() #if SupportsWindows() || SupportsUefi()
#define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain))
PFSTUB4(ape_pe_offset, ape_pe - ape_mz); PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24)); HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24));
HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40); HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40);
HIDDEN(ape_idata_idtsize = ape_idata_idtend - ape_idata_idt); HIDDEN(ape_idata_idtsize = ape_idata_idtend - ape_idata_idt);
HIDDEN(ape_idata_iatsize = ape_idata_iatend - ape_idata_iat); HIDDEN(ape_idata_iatsize = ape_idata_iatend - ape_idata_iat);
HIDDEN(v_ntsubsystem = (DEFINED(GetMessage) HIDDEN(v_ntversion = LINK_WINDOWS ? 6 : 1);
? kNtImageSubsystemWindowsGui HIDDEN(v_ntsubversion = LINK_WINDOWS ? 6 : 5);
: kNtImageSubsystemWindowsCui)); HIDDEN(v_ntsubsystem = (LINK_WINDOWS
? (DEFINED(GetMessage)
? kNtImageSubsystemWindowsGui
: kNtImageSubsystemWindowsCui)
: kNtImageSubsystemEfiApplication));
HIDDEN(ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain);
#endif #endif
#if SupportsMetal() #if SupportsMetal()
@ -603,7 +609,7 @@ CHURN(v_ape_realsectors);
#if SupportsXnu() #if SupportsXnu()
CHURN(ape_macho); CHURN(ape_macho);
#endif #endif
#if SupportsWindows() #if SupportsWindows() || SupportsUefi()
CHURN(ape_mz); CHURN(ape_mz);
CHURN(ape_pe); CHURN(ape_pe);
CHURN(ape_pe_offset); CHURN(ape_pe_offset);

View file

@ -95,7 +95,7 @@ CONFIG_COPTS += \
$(SANITIZER) $(SANITIZER)
TARGET_ARCH ?= \ TARGET_ARCH ?= \
-msse3 -march=native
OVERRIDE_CCFLAGS += \ OVERRIDE_CCFLAGS += \
-fno-pie -fno-pie

View file

@ -91,7 +91,6 @@ FTRACE = \
-pg -pg
SANITIZER = \ SANITIZER = \
-fsanitize=leak \
-fsanitize=address -fsanitize=address
NO_MAGIC = \ NO_MAGIC = \

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,30 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/dce.h" #include "libc/calls/efi.h"
#include "libc/runtime/internal.h" #include "libc/nt/efi.h"
#include "libc/macros.h"
.privileged
// Terminates process, ignoring destructors and atexit() handlers. EFI_HANDLE __efi_image_handle;
// EFI_SYSTEM_TABLE *__efi_system_table;
// @param edi is exit code ∈ [0,256)
// @asyncsignalsafe
// @vforksafe
// @noreturn
_Exit: push %rbp
mov %rsp,%rbp
#if SupportsWindows()
testb IsWindows()
jz 1f
sub $32,%rsp
movzbl %dil,%ecx # %ERRORLEVEL% is limitless
call *__imp_ExitProcess(%rip)
#endif
1: mov __NR_exit_group(%rip),%eax
syscall
#if SupportsMetal()
call triplf
#endif
.endfn _Exit,globl,protected
.hidden __NR_exit_group

12
libc/calls/efi.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_EFI_H_
#define COSMOPOLITAN_LIBC_CALLS_EFI_H_
#include "libc/nt/efi.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern EFI_HANDLE __efi_image_handle;
extern EFI_SYSTEM_TABLE *__efi_system_table;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_EFI_H_ */

View file

@ -31,9 +31,9 @@ int fstat(int fd, struct stat *st) {
if (__isfdkind(fd, kFdZip)) { if (__isfdkind(fd, kFdZip)) {
return weaken(__zipos_fstat)( return weaken(__zipos_fstat)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st); (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);
} else if (!IsWindows() && !IsMetal()) { } else if (!IsWindows() && !IsMetal() && !IsUefi()) {
return sys_fstat(fd, st); return sys_fstat(fd, st);
} else if (IsMetal()) { } else if (IsMetal() || IsUefi()) {
return fstat_metal(fd, st); return fstat_metal(fd, st);
} else { } else {
if (!__isfdkind(fd, kFdFile)) return ebadf(); if (!__isfdkind(fd, kFdFile)) return ebadf();

View file

@ -30,7 +30,7 @@ hidden textstartup void InitializeFileDescriptors(void) {
fds = VEIL("r", &g_fds); fds = VEIL("r", &g_fds);
pushmov(&fds->n, ARRAYLEN(fds->__init_p)); pushmov(&fds->n, ARRAYLEN(fds->__init_p));
fds->p = fds->__init_p; fds->p = fds->__init_p;
if (IsMetal()) { if (IsMetal() || IsUefi()) {
pushmov(&fds->f, 3ull); pushmov(&fds->f, 3ull);
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdSerial); fds->__init_p[STDIN_FILENO].kind = pushpop(kFdSerial);
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdSerial); fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdSerial);

View file

@ -199,6 +199,7 @@ u32 sys_gettid(void) hidden;
u32 sys_getuid(void) hidden; u32 sys_getuid(void) hidden;
void *sys_mmap(void *, u64, u32, u32, i64, i64, i64) hidden; void *sys_mmap(void *, u64, u32, u32, i64, i64, i64) hidden;
void *sys_mremap(void *, u64, u64, i32, void *) hidden; void *sys_mremap(void *, u64, u64, i32, void *) hidden;
void sys_exit(int) hidden;
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » system five » support cosmopolitan § syscalls » system five » support
@ -294,6 +295,12 @@ unsigned __wincrash_nt(struct NtExceptionPointers *);
int fstat_metal(int, struct stat *); int fstat_metal(int, struct stat *);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » uefi
*/
int sys_nanosleep_uefi(const struct timespec *, struct timespec *);
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § syscalls » drivers cosmopolitan § syscalls » drivers
*/ */

View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 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 "libc/calls/calls.h"
#include "libc/calls/efi.h"
#include "libc/nt/efi.h"
#include "libc/sysv/errfuns.h"
int sys_nanosleep_uefi(const struct timespec *req, struct timespec *rem) {
if (__efi_system_table->BootServices->Stall(
req->tv_sec * 1000000 + req->tv_nsec / 1000) == EFI_SUCCESS) {
if (rem) {
rem->tv_sec = 0;
rem->tv_nsec = 0;
}
return 0;
} else {
return eintr();
}
}

View file

@ -26,10 +26,15 @@
*/ */
int nanosleep(const struct timespec *req, struct timespec *rem) { int nanosleep(const struct timespec *req, struct timespec *rem) {
if (!req) return efault(); if (!req) return efault();
if (!IsWindows() && !IsMetal() && !IsXnu()) { if (req->tv_sec < 0 || !(0 <= req->tv_nsec && req->tv_nsec <= 999999999)) {
return einval();
}
if (!IsWindows() && !IsMetal() && !IsUefi() && !IsXnu()) {
return sys_nanosleep(req, rem); return sys_nanosleep(req, rem);
} else if (IsXnu()) { } else if (IsXnu()) {
return sys_nanosleep_xnu(req, rem); return sys_nanosleep_xnu(req, rem);
} else if (IsUefi()) {
return sys_nanosleep_uefi(req, rem);
} else if (IsMetal()) { } else if (IsMetal()) {
return enosys(); /* TODO: Sleep on Metal */ return enosys(); /* TODO: Sleep on Metal */
} else { } else {

View file

@ -36,7 +36,8 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_read)( return weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1); (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
} else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) { } else if ((SupportsMetal() || SupportsUefi()) && fd < g_fds.n &&
g_fds.p[fd].kind == kFdSerial) {
return readv_serial(&g_fds.p[fd], iov, iovlen); return readv_serial(&g_fds.p[fd], iov, iovlen);
} else if (!IsWindows()) { } else if (!IsWindows()) {
return sys_readv(fd, iov, iovlen); return sys_readv(fd, iov, iovlen);

View file

@ -144,7 +144,7 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) && sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) && sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd)); sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */ if (IsMetal() || IsUefi()) return enosys(); /* TODO: Signals on Metal */
if (!(0 < sig && sig < NSIG)) return einval(); if (!(0 < sig && sig < NSIG)) return einval();
if (sig == SIGKILL || sig == SIGSTOP) return einval(); if (sig == SIGKILL || sig == SIGSTOP) return einval();
if (!act) { if (!act) {

View file

@ -39,7 +39,8 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_write)( return weaken(__zipos_write)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1); (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
} else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) { } else if ((SupportsMetal() || SupportsUefi()) && fd < g_fds.n &&
g_fds.p[fd].kind == kFdSerial) {
return writev_serial(&g_fds.p[fd], iov, iovlen); return writev_serial(&g_fds.p[fd], iov, iovlen);
} else if (!IsWindows()) { } else if (!IsWindows()) {
return sys_writev(fd, iov, iovlen); return sys_writev(fd, iov, iovlen);

View file

@ -20,6 +20,7 @@
#define OPENBSD 16 #define OPENBSD 16
#define FREEBSD 32 #define FREEBSD 32
#define NETBSD 64 #define NETBSD 64
#define UEFI 128
#ifdef NDEBUG #ifdef NDEBUG
#define NoDebug() 1 #define NoDebug() 1
@ -72,6 +73,7 @@
#define SupportsLinux() ((SUPPORT_VECTOR & LINUX) == LINUX) #define SupportsLinux() ((SUPPORT_VECTOR & LINUX) == LINUX)
#define SupportsMetal() ((SUPPORT_VECTOR & METAL) == METAL) #define SupportsMetal() ((SUPPORT_VECTOR & METAL) == METAL)
#define SupportsWindows() ((SUPPORT_VECTOR & WINDOWS) == WINDOWS) #define SupportsWindows() ((SUPPORT_VECTOR & WINDOWS) == WINDOWS)
#define SupportsUefi() ((SUPPORT_VECTOR & UEFI) == UEFI)
#define SupportsXnu() ((SUPPORT_VECTOR & XNU) == XNU) #define SupportsXnu() ((SUPPORT_VECTOR & XNU) == XNU)
#define SupportsFreebsd() ((SUPPORT_VECTOR & FREEBSD) == FREEBSD) #define SupportsFreebsd() ((SUPPORT_VECTOR & FREEBSD) == FREEBSD)
#define SupportsOpenbsd() ((SUPPORT_VECTOR & OPENBSD) == OPENBSD) #define SupportsOpenbsd() ((SUPPORT_VECTOR & OPENBSD) == OPENBSD)
@ -84,6 +86,7 @@
#define IsLinux() (SupportsLinux() && (__hostos & LINUX)) #define IsLinux() (SupportsLinux() && (__hostos & LINUX))
#define IsMetal() (SupportsMetal() && (__hostos & METAL)) #define IsMetal() (SupportsMetal() && (__hostos & METAL))
#define IsWindows() (SupportsWindows() && (__hostos & WINDOWS)) #define IsWindows() (SupportsWindows() && (__hostos & WINDOWS))
#define IsUefi() (SupportsUefi() && (__hostos & UEFI))
#define IsXnu() (SupportsXnu() && (__hostos & XNU)) #define IsXnu() (SupportsXnu() && (__hostos & XNU))
#define IsFreebsd() (SupportsFreebsd() && (__hostos & FREEBSD)) #define IsFreebsd() (SupportsFreebsd() && (__hostos & FREEBSD))
#define IsOpenbsd() (SupportsOpenbsd() && (__hostos & OPENBSD)) #define IsOpenbsd() (SupportsOpenbsd() && (__hostos & OPENBSD))
@ -94,6 +97,7 @@
#define IsLinux() $LINUX,__hostos(%rip) #define IsLinux() $LINUX,__hostos(%rip)
#define IsMetal() $METAL,__hostos(%rip) #define IsMetal() $METAL,__hostos(%rip)
#define IsWindows() $WINDOWS,__hostos(%rip) #define IsWindows() $WINDOWS,__hostos(%rip)
#define IsUefi() $UEFI,__hostos(%rip)
#define IsBsd() $XNU|FREEBSD|OPENBSD|NETBSD,__hostos(%rip) #define IsBsd() $XNU|FREEBSD|OPENBSD|NETBSD,__hostos(%rip)
#define IsXnu() $XNU,__hostos(%rip) #define IsXnu() $XNU,__hostos(%rip)
#define IsFreebsd() $FREEBSD,__hostos(%rip) #define IsFreebsd() $FREEBSD,__hostos(%rip)

View file

@ -59,7 +59,7 @@
#define _KCPUIDS_VENDOR() \ #define _KCPUIDS_VENDOR() \
(((kCpuids[KCPUIDS_0H][KCPUIDS_EBX] >> 000) & 0xff) ^ \ (((kCpuids[KCPUIDS_0H][KCPUIDS_EBX] >> 000) & 0xff) ^ \
((kCpuids[KCPUIDS_0H][KCPUIDS_EDX] >> 010) & 0xff)) ((kCpuids[KCPUIDS_0H][KCPUIDS_ECX] >> 010) & 0xff))
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_VENDOR_H_ */ #endif /* COSMOPOLITAN_LIBC_NEXGEN32E_VENDOR_H_ */

424
libc/nt/efi.h Normal file
View file

@ -0,0 +1,424 @@
#ifndef COSMOPOLITAN_LIBC_NT_EFI_H_
#define COSMOPOLITAN_LIBC_NT_EFI_H_
/*
αcτµαlly pδrταblε εxεcµταblε § the unified extensible firmware interface
*/
#define EFI_SUCCESS 0x8000000000000000
#define EFI_LOAD_ERROR 0x8000000000000001
#define EFI_INVALID_PARAMETER 0x8000000000000002
#define EFI_UNSUPPORTED 0x8000000000000003
#define EFI_BAD_BUFFER_SIZE 0x8000000000000004
#define EFI_BUFFER_TOO_SMALL 0x8000000000000005
#define EFI_NOT_READY 0x8000000000000006
#define EFI_DEVICE_ERROR 0x8000000000000007
#define EFI_WRITE_PROTECTED 0x8000000000000008
#define EFI_OUT_OF_RESOURCES 0x8000000000000009
#define EFI_VOLUME_CORRUPTED 0x800000000000000a
#define EFI_VOLUME_FULL 0x800000000000000b
#define EFI_NO_MEDIA 0x800000000000000c
#define EFI_MEDIA_CHANGED 0x800000000000000d
#define EFI_NOT_FOUND 0x800000000000000e
#define EFI_ACCESS_DENIED 0x800000000000000f
#define EFI_NO_RESPONSE 0x8000000000000010
#define EFI_NO_MAPPING 0x8000000000000011
#define EFI_TIMEOUT 0x8000000000000012
#define EFI_NOT_STARTED 0x8000000000000013
#define EFI_ALREADY_STARTED 0x8000000000000014
#define EFI_ABORTED 0x8000000000000015
#define EFI_ICMP_ERROR 0x8000000000000016
#define EFI_TFTP_ERROR 0x8000000000000017
#define EFI_PROTOCOL_ERROR 0x8000000000000018
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
#define EFI_VARIABLE_APPEND_WRITE 0x00000040
#define EFI_MEMORY_UC 0x0000000000000001U
#define EFI_MEMORY_WC 0x0000000000000002U
#define EFI_MEMORY_WT 0x0000000000000004U
#define EFI_MEMORY_WB 0x0000000000000008U
#define EFI_MEMORY_UCE 0x0000000000000010U
#define EFI_MEMORY_WP 0x0000000000001000U
#define EFI_MEMORY_RP 0x0000000000002000U
#define EFI_MEMORY_XP 0x0000000000004000U
#define EFI_MEMORY_RO 0x0000000000020000U
#define EFI_MEMORY_NV 0x0000000000008000U
#define EFI_MEMORY_MORE_RELIABLE 0x0000000000010000U
#define EFI_MEMORY_RUNTIME 0x8000000000000000U
#define EFI_OPTIONAL_PTR 0x00000001
#define EFI_SCAN_NULL 0x0000
#define EFI_SCAN_UP 0x0001
#define EFI_SCAN_DOWN 0x0002
#define EFI_SCAN_RIGHT 0x0003
#define EFI_SCAN_LEFT 0x0004
#define EFI_SCAN_HOME 0x0005
#define EFI_SCAN_END 0x0006
#define EFI_SCAN_INSERT 0x0007
#define EFI_SCAN_DELETE 0x0008
#define EFI_SCAN_PAGE_UP 0x0009
#define EFI_SCAN_PAGE_DOWN 0x000A
#define EFI_SCAN_F1 0x000B
#define EFI_SCAN_F2 0x000C
#define EFI_SCAN_F3 0x000D
#define EFI_SCAN_F4 0x000E
#define EFI_SCAN_F5 0x000F
#define EFI_SCAN_F6 0x0010
#define EFI_SCAN_F7 0x0011
#define EFI_SCAN_F8 0x0012
#define EFI_SCAN_F9 0x0013
#define EFI_SCAN_F10 0x0014
#define EFI_SCAN_ESC 0x0017
#define EFI_EVT_TIMER 0x80000000
#define EFI_EVT_RUNTIME 0x40000000
#define EFI_EVT_NOTIFY_WAIT 0x00000100
#define EFI_EVT_NOTIFY_SIGNAL 0x00000200
#define EFI_EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201
#define EFI_EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202
#define EFI_EVT_RUNTIME_CONTEXT 0x20000000
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define EFIAPI __attribute__((__ms_abi__))
#define EFI_STATUS uint64_t
#define EFI_EVENT uintptr_t
#define EFI_HANDLE uintptr_t
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 enum {
EfiReservedMemoryType,
EfiLoaderCode,
EfiLoaderData,
EfiBootServicesCode,
EfiBootServicesData,
EfiRuntimeServicesCode,
EfiRuntimeServicesData,
EfiConventionalMemory,
EfiUnusableMemory,
EfiACPIReclaimMemory,
EfiACPIMemoryNVS,
EfiMemoryMappedIO,
EfiMemoryMappedIOPortSpace,
EfiPalCode,
EfiPersistentMemory,
EfiMaxMemoryType
} EFI_MEMORY_TYPE;
typedef enum {
EfiResetCold,
EfiResetWarm,
EfiResetShutdown,
EfiResetPlatformSpecific
} EFI_RESET_TYPE;
typedef enum {
AllocateAnyPages,
AllocateMaxAddress,
AllocateAddress,
MaxAllocateType
} EFI_ALLOCATE_TYPE;
typedef enum {
TimerCancel,
TimerPeriodic,
TimerRelative,
} EFI_TIMER_DELAY;
typedef struct {
uint32_t Resolution;
uint32_t Accuracy;
bool SetsToZero;
} EFI_TIME_CAPABILITIES;
typedef struct {
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
} EFI_GUID;
typedef struct {
uint16_t Year;
uint8_t Month;
uint8_t Day;
uint8_t Hour;
uint8_t Minute;
uint8_t Second;
uint8_t Pad1;
uint32_t Nanosecond;
int16_t TimeZone;
uint8_t Daylight;
uint8_t Pad2;
} EFI_TIME;
typedef struct {
uint32_t Type;
uint64_t PhysicalStart;
uint64_t VirtualStart;
uint64_t NumberOfPages;
uint64_t Attribute;
} EFI_MEMORY_DESCRIPTOR;
typedef struct {
EFI_GUID VendorGuid;
void *VendorTable;
} EFI_CONFIGURATION_TABLE;
typedef struct {
EFI_GUID CapsuleGuid;
uint32_t HeaderSize;
uint32_t Flags;
uint32_t CapsuleImageSize;
} EFI_CAPSULE_HEADER;
typedef struct {
uint16_t ScanCode;
char16_t UnicodeChar;
} EFI_INPUT_KEY;
typedef struct {
int32_t MaxMode;
int32_t Mode;
int32_t Attribute;
int32_t CursorColumn;
int32_t CursorRow;
bool CursorVisible;
} EFI_SIMPLE_TEXT_OUTPUT_MODE;
typedef struct {
uint64_t Signature;
uint32_t Revision;
uint32_t HeaderSize;
uint32_t CRC32;
uint32_t Reserved;
} EFI_TABLE_HEADER;
typedef EFI_STATUS(EFIAPI *EFI_EXIT)(EFI_HANDLE ImageHandle,
EFI_STATUS ExitStatus,
uintptr_t ExitDataSize,
char16_t *opt_ExitData);
typedef EFI_STATUS(EFIAPI *EFI_GET_VARIABLE)(char16_t *VariableName,
EFI_GUID *VendorGuid,
uint32_t *outopt_Attributes,
uintptr_t *inout_DataSize,
void *outopt_Data);
typedef EFI_STATUS(EFIAPI *EFI_SET_VARIABLE)(char16_t *VariableName,
EFI_GUID *VendorGuid,
uint32_t Attributes,
uintptr_t DataSize, void *Data);
typedef EFI_STATUS(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME)(
uintptr_t *inout_VariableNameSize, char16_t *inout_VariableName,
EFI_GUID *inout_VendorGuid);
typedef EFI_STATUS(EFIAPI *EFI_QUERY_VARIABLE_INFO)(
uint32_t Attributes, uint64_t *out_MaximumVariableStorageSize,
uint64_t *out_RemainingVariableStorageSize,
uint64_t *out_MaximumVariableSize);
typedef EFI_STATUS(EFIAPI *EFI_ALLOCATE_PAGES)(EFI_ALLOCATE_TYPE Type,
EFI_MEMORY_TYPE MemoryType,
uintptr_t Pages,
uint64_t *inout_Memory);
typedef EFI_STATUS(EFIAPI *EFI_FREE_PAGES)(uint64_t Memory, uintptr_t Pages);
typedef EFI_STATUS(EFIAPI *EFI_GET_MEMORY_MAP)(
uintptr_t *inout_MemoryMapSize, EFI_MEMORY_DESCRIPTOR *inout_MemoryMap,
uintptr_t *out_MapKey, uintptr_t *out_DescriptorSize,
uint32_t *out_DescriptorVersion);
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);
typedef EFI_STATUS(EFIAPI *EFI_WAIT_FOR_EVENT)(uintptr_t NumberOfEvents,
EFI_EVENT *Events,
uintptr_t *out_Index);
typedef EFI_STATUS(EFIAPI *EFI_SET_TIMER)(EFI_EVENT Event, EFI_TIMER_DELAY Type,
uint64_t TriggerTime);
typedef void(EFIAPI *EFI_EVENT_NOTIFY)(EFI_EVENT Event, void *Context);
typedef EFI_STATUS(EFIAPI *EFI_CREATE_EVENT)(uint32_t Type, uintptr_t NotifyTpl,
EFI_EVENT_NOTIFY NotifyFunction,
void *NotifyContext,
EFI_EVENT *out_Event);
typedef EFI_STATUS(EFIAPI *EFI_CREATE_EVENT_EX)(
uint32_t Type, uintptr_t NotifyTpl, EFI_EVENT_NOTIFY opt_NotifyFunction,
const void *opt_NotifyContext, const EFI_GUID *opt_EventGroup,
EFI_EVENT *out_Event);
typedef EFI_STATUS(EFIAPI *EFI_UPDATE_CAPSULE)(
EFI_CAPSULE_HEADER **CapsuleHeaderArray, uintptr_t CapsuleCount,
uint64_t opt_ScatterGatherList);
typedef EFI_STATUS(EFIAPI *EFI_QUERY_CAPSULE_CAPABILITIES)(
EFI_CAPSULE_HEADER **CapsuleHeaderArray, uintptr_t CapsuleCount,
uint64_t *out_MaximumCapsuleSize, EFI_RESET_TYPE *out_ResetType);
typedef EFI_STATUS(EFIAPI *EFI_GET_WAKEUP_TIME)(bool *out_Enabled,
bool *out_Pending,
EFI_TIME *out_Time);
typedef EFI_STATUS(EFIAPI *EFI_SET_WAKEUP_TIME)(bool Enable,
EFI_TIME *opt_Time);
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_SET_TIME)(EFI_TIME *Time);
typedef EFI_STATUS(EFIAPI *EFI_GET_TIME)(
EFI_TIME *out_Time, EFI_TIME_CAPABILITIES *outopt_Capabilities);
typedef EFI_STATUS(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT)(
uint32_t *out_HighCount);
typedef EFI_STATUS(EFIAPI *EFI_STALL)(uintptr_t Microseconds);
typedef EFI_STATUS(EFIAPI *EFI_GET_NEXT_MONOTONIC_COUNT)(uint64_t *out_Count);
typedef EFI_STATUS(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP)(
uintptr_t MemoryMapSize, uintptr_t DescriptorSize,
uint32_t DescriptorVersion, EFI_MEMORY_DESCRIPTOR *VirtualMap);
typedef void(EFIAPI *EFI_RESET_SYSTEM)(EFI_RESET_TYPE ResetType,
EFI_STATUS ResetStatus,
uintptr_t DataSize, void *opt_ResetData);
typedef EFI_STATUS(EFIAPI *EFI_CONVERT_POINTER)(uintptr_t DebugDisposition,
void **inout_Address);
typedef EFI_STATUS(EFIAPI *EFI_INPUT_RESET)(
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, bool ExtendedVerification);
typedef EFI_STATUS(EFIAPI *EFI_INPUT_READ_KEY)(
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, EFI_INPUT_KEY *out_Key);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_RESET)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, bool ExtendedVerification);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_STRING)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, char16_t *String);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_TEST_STRING)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, char16_t *String);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_QUERY_MODE)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, uint64_t ModeNumber,
uint64_t *out_Columns, uint64_t *out_Rows);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_SET_MODE)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, uint64_t ModeNumber);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_SET_ATTRIBUTE)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, uint64_t Attribute);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_CLEAR_SCREEN)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, uint64_t Column, uint64_t Row);
typedef EFI_STATUS(EFIAPI *EFI_TEXT_ENABLE_CURSOR)(
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, bool Visible);
typedef struct {
EFI_TABLE_HEADER Hdr;
EFI_GET_TIME GetTime;
EFI_SET_TIME SetTime;
EFI_GET_WAKEUP_TIME GetWakeupTime;
EFI_SET_WAKEUP_TIME SetWakeupTime;
EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap;
EFI_CONVERT_POINTER ConvertPointer;
EFI_GET_VARIABLE GetVariable;
EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName;
EFI_SET_VARIABLE SetVariable;
EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount;
EFI_RESET_SYSTEM ResetSystem;
EFI_UPDATE_CAPSULE UpdateCapsule;
EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities;
EFI_QUERY_VARIABLE_INFO QueryVariableInfo;
} EFI_RUNTIME_SERVICES;
typedef struct {
EFI_TABLE_HEADER Hdr;
void *RaiseTPL;
void *RestoreTPL;
EFI_ALLOCATE_PAGES AllocatePages;
EFI_FREE_PAGES FreePages;
EFI_GET_MEMORY_MAP GetMemoryMap;
void *AllocatePool;
void *FreePool;
EFI_CREATE_EVENT CreateEvent;
EFI_SET_TIMER SetTimer;
EFI_WAIT_FOR_EVENT WaitForEvent;
EFI_SIGNAL_EVENT SignalEvent;
EFI_CLOSE_EVENT CloseEvent;
EFI_CHECK_EVENT CheckEvent;
void *InstallProtocolInterface;
void *ReinstallProtocolInterface;
void *UninstallProtocolInterface;
void *HandleProtocol;
void *Reserved;
void *RegisterProtocolNotify;
void *LocateHandle;
void *LocateDevicePath;
void *InstallConfigurationTable;
void *LoadImage;
void *StartImage;
EFI_EXIT Exit;
void *UnloadImage;
void *ExitBootServices;
EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount;
EFI_STALL Stall;
EFI_SET_WATCHDOG_TIMER SetWatchdogTimer;
void *ConnectController;
void *DisconnectController;
void *OpenProtocol;
void *CloseProtocol;
void *OpenProtocolInformation;
void *ProtocolsPerHandle;
void *LocateHandleBuffer;
void *LocateProtocol;
void *InstallMultipleProtocolInterfaces;
void *UninstallMultipleProtocolInterfaces;
void *CalculateCrc32;
void *CopyMem;
void *SetMem;
EFI_CREATE_EVENT_EX CreateEventEx;
} EFI_BOOT_SERVICES;
typedef struct {
EFI_TABLE_HEADER Hdr;
char16_t *FirmwareVendor;
uint32_t FirmwareRevision;
EFI_HANDLE ConsoleInHandle;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
EFI_HANDLE ConsoleOutHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
EFI_HANDLE StandardErrorHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
EFI_RUNTIME_SERVICES *RuntimeServices;
EFI_BOOT_SERVICES *BootServices;
uintptr_t NumberOfTableEntries;
EFI_CONFIGURATION_TABLE *ConfigurationTable;
} EFI_SYSTEM_TABLE;
struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
EFI_INPUT_RESET Reset;
EFI_INPUT_READ_KEY ReadKeyStroke;
EFI_EVENT WaitForKey;
};
struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
EFI_TEXT_RESET Reset;
EFI_TEXT_STRING OutputString;
EFI_TEXT_TEST_STRING TestString;
EFI_TEXT_QUERY_MODE QueryMode;
EFI_TEXT_SET_MODE SetMode;
EFI_TEXT_SET_ATTRIBUTE SetAttribute;
EFI_TEXT_CLEAR_SCREEN ClearScreen;
EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition;
EFI_TEXT_ENABLE_CURSOR EnableCursor;
EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_EFI_H_ */

View file

@ -16,370 +16,370 @@
.tls: __declspec(thread) data (Fails with dynamically loaded DLLs -> .tls: __declspec(thread) data (Fails with dynamically loaded DLLs ->
hard to find bugs) */ hard to find bugs) */
#define kNtImageDosSignature 0x5A4D #define kNtImageDosSignature 0x5A4D
#define kNtImageOs2Signature 0x454E #define kNtImageOs2Signature 0x454E
#define kNtImageOs2SignatureLe 0x454C #define kNtImageOs2SignatureLe 0x454C
#define kNtImageVxdSignature 0x454C #define kNtImageVxdSignature 0x454C
#define kNtImageNtSignature 0x00004550 #define kNtImageNtSignature 0x00004550
#define kNtPeFileRelocsStripped 0x00001 #define kNtPeFileRelocsStripped 0x00001
#define kNtPeFileExecutableImage 0x00002 #define kNtPeFileExecutableImage 0x00002
#define kNtPeFileLineNumsStripped 0x00004 #define kNtPeFileLineNumsStripped 0x00004
#define kNtPeFileLocalSymsStripped 0x00008 #define kNtPeFileLocalSymsStripped 0x00008
#define kNtPeFile_32bitMachine 0x00100 #define kNtPeFile_32bitMachine 0x00100
#define kNtPeFileDll 0x02000 #define kNtPeFileDll 0x02000
#define kNtPe32bit 0x010b #define kNtPe32bit 0x010b
#define kNtPe64bit 0x020b #define kNtPe64bit 0x020b
#define kNtPeSectionCntCode 0x000000020 #define kNtPeSectionCntCode 0x000000020
#define kNtPeSectionCntInitializedData 0x000000040 #define kNtPeSectionCntInitializedData 0x000000040
#define kNtPeSectionCntUninitializedData 0x000000080 #define kNtPeSectionCntUninitializedData 0x000000080
#define kNtPeSectionGprel 0x000008000 #define kNtPeSectionGprel 0x000008000
#define kNtPeSectionMemDiscardable 0x02000000 #define kNtPeSectionMemDiscardable 0x02000000
#define kNtPeSectionMemNotCached 0x04000000 #define kNtPeSectionMemNotCached 0x04000000
#define kNtPeSectionMemNotPaged 0x08000000 #define kNtPeSectionMemNotPaged 0x08000000
#define kNtPeSectionMemShared 0x10000000 #define kNtPeSectionMemShared 0x10000000
#define kNtPeSectionMemExecute 0x20000000 #define kNtPeSectionMemExecute 0x20000000
#define kNtPeSectionMemRead 0x40000000 #define kNtPeSectionMemRead 0x40000000
#define kNtPeSectionMemWrite 0x80000000 #define kNtPeSectionMemWrite 0x80000000
#define kNtPeGuardCfInstrumented 0x000000100 #define kNtPeGuardCfInstrumented 0x000000100
#define kNtPeGuardCfwInstrumented 0x000000200 #define kNtPeGuardCfwInstrumented 0x000000200
#define kNtPeGuardCfFunctionTablePresent 0x000000400 #define kNtPeGuardCfFunctionTablePresent 0x000000400
#define kNtPeGuardSecurityCookieUnused 0x000000800 #define kNtPeGuardSecurityCookieUnused 0x000000800
#define kNtPeRelBasedAbsolute 0 #define kNtPeRelBasedAbsolute 0
#define kNtPeRelBasedHigh 1 #define kNtPeRelBasedHigh 1
#define kNtPeRelBasedLow 2 #define kNtPeRelBasedLow 2
#define kNtPeRelBasedHighlow 3 #define kNtPeRelBasedHighlow 3
#define kNtPeRelBasedHighadj 4 #define kNtPeRelBasedHighadj 4
#define kNtPeRelBasedMipsJmpaddr 5 #define kNtPeRelBasedMipsJmpaddr 5
#define kNtPeRelBasedSection 6 #define kNtPeRelBasedSection 6
#define kNtPeRelBasedRel32 7 #define kNtPeRelBasedRel32 7
#define kNtPeRelBasedMipsJmpaddr16 9 #define kNtPeRelBasedMipsJmpaddr16 9
#define kNtPeRelBasedIa64Imm64 9 #define kNtPeRelBasedIa64Imm64 9
#define kNtPeRelBasedDir64 10 #define kNtPeRelBasedDir64 10
#define kNtPeRelBasedHigh3adj 11 #define kNtPeRelBasedHigh3adj 11
#define kNtImageFileRelocsStripped 0x0001 #define kNtImageFileRelocsStripped 0x0001
#define kNtImageFileExecutableImage 0x0002 #define kNtImageFileExecutableImage 0x0002
#define kNtImageFileLineNumsStripped 0x0004 #define kNtImageFileLineNumsStripped 0x0004
#define kNtImageFileLocalSymsStripped 0x0008 #define kNtImageFileLocalSymsStripped 0x0008
#define kNtImageFileAggresiveWsTrim 0x0010 #define kNtImageFileAggresiveWsTrim 0x0010
#define kNtImageFileLargeAddressAware 0x0020 #define kNtImageFileLargeAddressAware 0x0020
#define kNtImageFileBytesReversedLo 0x0080 #define kNtImageFileBytesReversedLo 0x0080
#define kNtImageFile32bitMachine 0x0100 #define kNtImageFile32bitMachine 0x0100
#define kNtImageFileDebugStripped 0x0200 #define kNtImageFileDebugStripped 0x0200
#define kNtImageFileRemovableRunFromSwap 0x0400 #define kNtImageFileRemovableRunFromSwap 0x0400
#define kNtImageFileNetRunFromSwap 0x0800 #define kNtImageFileNetRunFromSwap 0x0800
#define kNtImageFileSystem 0x1000 #define kNtImageFileSystem 0x1000
#define kNtImageFileDll 0x2000 #define kNtImageFileDll 0x2000
#define kNtImageFileUpSystemOnly 0x4000 #define kNtImageFileUpSystemOnly 0x4000
#define kNtImageFileBytesReversedHi 0x8000 #define kNtImageFileBytesReversedHi 0x8000
#define kNtImageFileMachineUnknown 0 #define kNtImageFileMachineUnknown 0
#define kNtImageFileMachineTargetHost 0x0001 #define kNtImageFileMachineTargetHost 0x0001
#define kNtImageFileMachineI386 0x014c #define kNtImageFileMachineI386 0x014c
#define kNtImageFileMachineR3000 0x0162 #define kNtImageFileMachineR3000 0x0162
#define kNtImageFileMachineR4000 0x0166 #define kNtImageFileMachineR4000 0x0166
#define kNtImageFileMachineR10000 0x0168 #define kNtImageFileMachineR10000 0x0168
#define kNtImageFileMachineWcemipsv2 0x0169 #define kNtImageFileMachineWcemipsv2 0x0169
#define kNtImageFileMachineAlpha 0x0184 #define kNtImageFileMachineAlpha 0x0184
#define kNtImageFileMachineSh3 0x01a2 #define kNtImageFileMachineSh3 0x01a2
#define kNtImageFileMachineSh3dsp 0x01a3 #define kNtImageFileMachineSh3dsp 0x01a3
#define kNtImageFileMachineSh3e 0x01a4 #define kNtImageFileMachineSh3e 0x01a4
#define kNtImageFileMachineSh4 0x01a6 #define kNtImageFileMachineSh4 0x01a6
#define kNtImageFileMachineSh5 0x01a8 #define kNtImageFileMachineSh5 0x01a8
#define kNtImageFileMachineArm 0x01c0 #define kNtImageFileMachineArm 0x01c0
#define kNtImageFileMachineThumb 0x01c2 #define kNtImageFileMachineThumb 0x01c2
#define kNtImageFileMachineArmnt 0x01c4 #define kNtImageFileMachineArmnt 0x01c4
#define kNtImageFileMachineAm33 0x01d3 #define kNtImageFileMachineAm33 0x01d3
#define kNtImageFileMachinePowerpc 0x01F0 #define kNtImageFileMachinePowerpc 0x01F0
#define kNtImageFileMachinePowerpcfp 0x01f1 #define kNtImageFileMachinePowerpcfp 0x01f1
#define kNtImageFileMachineIa64 0x0200 #define kNtImageFileMachineIa64 0x0200
#define kNtImageFileMachineMips16 0x0266 #define kNtImageFileMachineMips16 0x0266
#define kNtImageFileMachineAlpha64 0x0284 #define kNtImageFileMachineAlpha64 0x0284
#define kNtImageFileMachineMipsfpu 0x0366 #define kNtImageFileMachineMipsfpu 0x0366
#define kNtImageFileMachineMipsfpu16 0x0466 #define kNtImageFileMachineMipsfpu16 0x0466
#define kNtImageFileMachineAxp64 kNtImageFileMachineAlpha64 #define kNtImageFileMachineAxp64 kNtImageFileMachineAlpha64
#define kNtImageFileMachineTricore 0x0520 #define kNtImageFileMachineTricore 0x0520
#define kNtImageFileMachineCef 0x0CEF #define kNtImageFileMachineCef 0x0CEF
#define kNtImageFileMachineEbc 0x0EBC #define kNtImageFileMachineEbc 0x0EBC
#define kNtImageFileMachineNexgen32e 0x8664 #define kNtImageFileMachineNexgen32e 0x8664
#define kNtImageFileMachineM32r 0x9041 #define kNtImageFileMachineM32r 0x9041
#define kNtImageFileMachineArm64 0xAA64 #define kNtImageFileMachineArm64 0xAA64
#define kNtImageFileMachineCee 0xC0EE #define kNtImageFileMachineCee 0xC0EE
#define kNtImageSubsystemUnknown 0 #define kNtImageSubsystemUnknown 0
#define kNtImageSubsystemNative 1 #define kNtImageSubsystemNative 1
#define kNtImageSubsystemWindowsGui 2 #define kNtImageSubsystemWindowsGui 2
#define kNtImageSubsystemWindowsCui 3 #define kNtImageSubsystemWindowsCui 3
#define kNtImageSubsystemOs2Cui 5 #define kNtImageSubsystemOs2Cui 5
#define kNtImageSubsystemPosixCui 7 #define kNtImageSubsystemPosixCui 7
#define kNtImageSubsystemNativeWindows 8 #define kNtImageSubsystemNativeWindows 8
#define kNtImageSubsystemWindowsCeGui 9 #define kNtImageSubsystemWindowsCeGui 9
#define kNtImageSubsystemEfiApplication 1 #define kNtImageSubsystemEfiApplication 10
#define kNtImageSubsystemEfiBootServiceDriver 11 #define kNtImageSubsystemEfiBootServiceDriver 11
#define kNtImageSubsystemEfiRuntimeDriver 12 #define kNtImageSubsystemEfiRuntimeDriver 12
#define kNtImageSubsystemEfiRom 13 #define kNtImageSubsystemEfiRom 13
#define kNtImageSubsystemXbox 14 #define kNtImageSubsystemXbox 14
#define kNtImageSubsystemWindowsBootApplication 16 #define kNtImageSubsystemWindowsBootApplication 16
#define kNtImageSubsystemXboxCodeCatalog 17 #define kNtImageSubsystemXboxCodeCatalog 17
#define kNtImageDllcharacteristicsHighEntropyVa 0x0020 #define kNtImageDllcharacteristicsHighEntropyVa 0x0020
#define kNtImageDllcharacteristicsDynamicBase 0x0040 #define kNtImageDllcharacteristicsDynamicBase 0x0040
#define kNtImageDllcharacteristicsForceIntegrity 0x0080 #define kNtImageDllcharacteristicsForceIntegrity 0x0080
#define kNtImageDllcharacteristicsNxCompat 0x0100 #define kNtImageDllcharacteristicsNxCompat 0x0100
#define kNtImageDllcharacteristicsNoIsolation 0x0200 #define kNtImageDllcharacteristicsNoIsolation 0x0200
#define kNtImageDllcharacteristicsNoSeh 0x0400 #define kNtImageDllcharacteristicsNoSeh 0x0400
#define kNtImageDllcharacteristicsNoBind 0x0800 #define kNtImageDllcharacteristicsNoBind 0x0800
#define kNtImageDllcharacteristicsAppcontainer 0x1000 #define kNtImageDllcharacteristicsAppcontainer 0x1000
#define kNtImageDllcharacteristicsWdmDriver 0x2000 #define kNtImageDllcharacteristicsWdmDriver 0x2000
#define kNtImageDllcharacteristicsGuardCf 0x4000 #define kNtImageDllcharacteristicsGuardCf 0x4000
#define kNtImageDllcharacteristicsTerminalServerAware 0x8000 #define kNtImageDllcharacteristicsTerminalServerAware 0x8000
#define kNtImageDirectoryEntryExport 0 #define kNtImageDirectoryEntryExport 0
#define kNtImageDirectoryEntryImport 1 #define kNtImageDirectoryEntryImport 1
#define kNtImageDirectoryEntryResource 2 #define kNtImageDirectoryEntryResource 2
#define kNtImageDirectoryEntryException 3 #define kNtImageDirectoryEntryException 3
#define kNtImageDirectoryEntrySecurity 4 #define kNtImageDirectoryEntrySecurity 4
#define kNtImageDirectoryEntryBasereloc 5 #define kNtImageDirectoryEntryBasereloc 5
#define kNtImageDirectoryEntryDebug 6 #define kNtImageDirectoryEntryDebug 6
#define kNtImageDirectoryEntryArchitecture 7 #define kNtImageDirectoryEntryArchitecture 7
#define kNtImageDirectoryEntryGlobalptr 8 #define kNtImageDirectoryEntryGlobalptr 8
#define kNtImageDirectoryEntryTls 9 #define kNtImageDirectoryEntryTls 9
#define kNtImageDirectoryEntryLoadConfig 10 #define kNtImageDirectoryEntryLoadConfig 10
#define kNtImageDirectoryEntryBoundImport 11 #define kNtImageDirectoryEntryBoundImport 11
#define kNtImageDirectoryEntryIat 12 #define kNtImageDirectoryEntryIat 12
#define kNtImageDirectoryEntryDelayImport 13 #define kNtImageDirectoryEntryDelayImport 13
#define kNtImageDirectoryEntryComDescriptor 14 #define kNtImageDirectoryEntryComDescriptor 14
#define kNtImageScnTypeNoPad 0x00000008 #define kNtImageScnTypeNoPad 0x00000008
#define kNtImageScnCntCode 0x00000020 #define kNtImageScnCntCode 0x00000020
#define kNtImageScnCntInitializedData 0x00000040 #define kNtImageScnCntInitializedData 0x00000040
#define kNtImageScnCntUninitializedData 0x00000080 #define kNtImageScnCntUninitializedData 0x00000080
#define kNtImageScnLnkOther 0x00000100 #define kNtImageScnLnkOther 0x00000100
#define kNtImageScnLnkInfo 0x00000200 #define kNtImageScnLnkInfo 0x00000200
#define kNtImageScnLnkRemove 0x00000800 #define kNtImageScnLnkRemove 0x00000800
#define kNtImageScnLnkComdat 0x00001000 #define kNtImageScnLnkComdat 0x00001000
#define kNtImageScnNoDeferSpecExc 0x00004000 #define kNtImageScnNoDeferSpecExc 0x00004000
#define kNtImageScnGprel 0x00008000 #define kNtImageScnGprel 0x00008000
#define kNtImageScnMemFardata 0x00008000 #define kNtImageScnMemFardata 0x00008000
#define kNtImageScnMemPurgeable 0x00020000 #define kNtImageScnMemPurgeable 0x00020000
#define kNtImageScnMem16bit 0x00020000 #define kNtImageScnMem16bit 0x00020000
#define kNtImageScnMemLocked 0x00040000 #define kNtImageScnMemLocked 0x00040000
#define kNtImageScnMemPreload 0x00080000 #define kNtImageScnMemPreload 0x00080000
#define kNtImageScnAlign1bytes 0x00100000 #define kNtImageScnAlign1bytes 0x00100000
#define kNtImageScnAlign2bytes 0x00200000 #define kNtImageScnAlign2bytes 0x00200000
#define kNtImageScnAlign4bytes 0x00300000 #define kNtImageScnAlign4bytes 0x00300000
#define kNtImageScnAlign8bytes 0x00400000 #define kNtImageScnAlign8bytes 0x00400000
#define kNtImageScnAlign16bytes 0x00500000 #define kNtImageScnAlign16bytes 0x00500000
#define kNtImageScnAlign32bytes 0x00600000 #define kNtImageScnAlign32bytes 0x00600000
#define kNtImageScnAlign64bytes 0x00700000 #define kNtImageScnAlign64bytes 0x00700000
#define kNtImageScnAlign128bytes 0x00800000 #define kNtImageScnAlign128bytes 0x00800000
#define kNtImageScnAlign256bytes 0x00900000 #define kNtImageScnAlign256bytes 0x00900000
#define kNtImageScnAlign512bytes 0x00A00000 #define kNtImageScnAlign512bytes 0x00A00000
#define kNtImageScnAlign1024bytes 0x00B00000 #define kNtImageScnAlign1024bytes 0x00B00000
#define kNtImageScnAlign2048bytes 0x00C00000 #define kNtImageScnAlign2048bytes 0x00C00000
#define kNtImageScnAlign4096bytes 0x00D00000 #define kNtImageScnAlign4096bytes 0x00D00000
#define kNtImageScnAlign8192bytes 0x00E00000 #define kNtImageScnAlign8192bytes 0x00E00000
#define kNtImageScnAlignMask 0x00F00000 #define kNtImageScnAlignMask 0x00F00000
#define kNtImageScnLnkNrelocOvfl 0x01000000 #define kNtImageScnLnkNrelocOvfl 0x01000000
#define kNtImageScnMemDiscardable 0x02000000 #define kNtImageScnMemDiscardable 0x02000000
#define kNtImageScnMemNotCached 0x04000000 #define kNtImageScnMemNotCached 0x04000000
#define kNtImageScnMemNotPaged 0x08000000 #define kNtImageScnMemNotPaged 0x08000000
#define kNtImageScnMemShared 0x10000000 #define kNtImageScnMemShared 0x10000000
#define kNtImageScnMemExecute 0x20000000 #define kNtImageScnMemExecute 0x20000000
#define kNtImageScnMemRead 0x40000000 #define kNtImageScnMemRead 0x40000000
#define kNtImageScnMemWrite 0x80000000 #define kNtImageScnMemWrite 0x80000000
#define kNtImageScnScaleIndex 0x00000001 #define kNtImageScnScaleIndex 0x00000001
#define kNtImageSymUndefined ((uint16_t)0) #define kNtImageSymUndefined ((uint16_t)0)
#define kNtImageSymAbsolute ((uint16_t)-1) #define kNtImageSymAbsolute ((uint16_t)-1)
#define kNtImageSymDebug ((uint16_t)-2) #define kNtImageSymDebug ((uint16_t)-2)
#define kNtImageSymSectionMax 0xFEFF #define kNtImageSymSectionMax 0xFEFF
#define kNtImageSymSectionMaxEx __LONG_MAX__ #define kNtImageSymSectionMaxEx __LONG_MAX__
#define kNtImageSymTypeNull 0x0000 #define kNtImageSymTypeNull 0x0000
#define kNtImageSymTypeVoid 0x0001 #define kNtImageSymTypeVoid 0x0001
#define kNtImageSymTypeChar 0x0002 #define kNtImageSymTypeChar 0x0002
#define kNtImageSymTypeShort 0x0003 #define kNtImageSymTypeShort 0x0003
#define kNtImageSymTypeInt 0x0004 #define kNtImageSymTypeInt 0x0004
#define kNtImageSymTypeLong 0x0005 #define kNtImageSymTypeLong 0x0005
#define kNtImageSymTypeFloat 0x0006 #define kNtImageSymTypeFloat 0x0006
#define kNtImageSymTypeDouble 0x0007 #define kNtImageSymTypeDouble 0x0007
#define kNtImageSymTypeStruct 0x0008 #define kNtImageSymTypeStruct 0x0008
#define kNtImageSymTypeUnion 0x0009 #define kNtImageSymTypeUnion 0x0009
#define kNtImageSymTypeEnum 0x000A #define kNtImageSymTypeEnum 0x000A
#define kNtImageSymTypeMoe 0x000B #define kNtImageSymTypeMoe 0x000B
#define kNtImageSymTypeByte 0x000C #define kNtImageSymTypeByte 0x000C
#define kNtImageSymTypeWord 0x000D #define kNtImageSymTypeWord 0x000D
#define kNtImageSymTypeUint 0x000E #define kNtImageSymTypeUint 0x000E
#define kNtImageSymTypeDword 0x000F #define kNtImageSymTypeDword 0x000F
#define kNtImageSymTypePcode 0x8000 #define kNtImageSymTypePcode 0x8000
#define kNtImageSymDtypeNull 0 #define kNtImageSymDtypeNull 0
#define kNtImageSymDtypePointer 1 #define kNtImageSymDtypePointer 1
#define kNtImageSymDtypeFunction 2 #define kNtImageSymDtypeFunction 2
#define kNtImageSymDtypeArray 3 #define kNtImageSymDtypeArray 3
#define kNtImageSymClassEndOfFunction ((unsigned char)-1) #define kNtImageSymClassEndOfFunction ((unsigned char)-1)
#define kNtImageSymClassNull 0x0000 #define kNtImageSymClassNull 0x0000
#define kNtImageSymClassAutomatic 0x0001 #define kNtImageSymClassAutomatic 0x0001
#define kNtImageSymClassExternal 0x0002 #define kNtImageSymClassExternal 0x0002
#define kNtImageSymClassStatic 0x0003 #define kNtImageSymClassStatic 0x0003
#define kNtImageSymClassRegister 0x0004 #define kNtImageSymClassRegister 0x0004
#define kNtImageSymClassExternalDef 0x0005 #define kNtImageSymClassExternalDef 0x0005
#define kNtImageSymClassLabel 0x0006 #define kNtImageSymClassLabel 0x0006
#define kNtImageSymClassUndefinedLabel 0x0007 #define kNtImageSymClassUndefinedLabel 0x0007
#define kNtImageSymClassMemberOfStruct 0x0008 #define kNtImageSymClassMemberOfStruct 0x0008
#define kNtImageSymClassArgument 0x0009 #define kNtImageSymClassArgument 0x0009
#define kNtImageSymClassStructTag 0x000A #define kNtImageSymClassStructTag 0x000A
#define kNtImageSymClassMemberOfUnion 0x000B #define kNtImageSymClassMemberOfUnion 0x000B
#define kNtImageSymClassUnionTag 0x000C #define kNtImageSymClassUnionTag 0x000C
#define kNtImageSymClassTypeDefinition 0x000D #define kNtImageSymClassTypeDefinition 0x000D
#define kNtImageSymClassUndefinedStatic 0x000E #define kNtImageSymClassUndefinedStatic 0x000E
#define kNtImageSymClassEnumTag 0x000F #define kNtImageSymClassEnumTag 0x000F
#define kNtImageSymClassMemberOfEnum 0x0010 #define kNtImageSymClassMemberOfEnum 0x0010
#define kNtImageSymClassRegisterParam 0x0011 #define kNtImageSymClassRegisterParam 0x0011
#define kNtImageSymClassBitField 0x0012 #define kNtImageSymClassBitField 0x0012
#define kNtImageSymClassFarExternal 0x0044 #define kNtImageSymClassFarExternal 0x0044
#define kNtImageSymClassBlock 0x0064 #define kNtImageSymClassBlock 0x0064
#define kNtImageSymClassFunction 0x0065 #define kNtImageSymClassFunction 0x0065
#define kNtImageSymClassEndOfStruct 0x0066 #define kNtImageSymClassEndOfStruct 0x0066
#define kNtImageSymClassFile 0x0067 #define kNtImageSymClassFile 0x0067
#define kNtImageSymClassSection 0x0068 #define kNtImageSymClassSection 0x0068
#define kNtImageSymClassWeakExternal 0x0069 #define kNtImageSymClassWeakExternal 0x0069
#define kNtImageSymClassClrToken 0x006B #define kNtImageSymClassClrToken 0x006B
#define kNtImageComdatSelectNoduplicates 1 #define kNtImageComdatSelectNoduplicates 1
#define kNtImageComdatSelectAny 2 #define kNtImageComdatSelectAny 2
#define kNtImageComdatSelectSameSize 3 #define kNtImageComdatSelectSameSize 3
#define kNtImageComdatSelectExactMatch 4 #define kNtImageComdatSelectExactMatch 4
#define kNtImageComdatSelectAssociative 5 #define kNtImageComdatSelectAssociative 5
#define kNtImageComdatSelectLargest 6 #define kNtImageComdatSelectLargest 6
#define kNtImageComdatSelectNewest 7 #define kNtImageComdatSelectNewest 7
#define kNtImageWeakExternSearchNolibrary 1 #define kNtImageWeakExternSearchNolibrary 1
#define kNtImageWeakExternSearchLibrary 2 #define kNtImageWeakExternSearchLibrary 2
#define kNtImageWeakExternSearchAlias 3 #define kNtImageWeakExternSearchAlias 3
#define kNtImageWeakExternAntiDependency 4 #define kNtImageWeakExternAntiDependency 4
#define kNtImageRelNexgen32eAbsolute 0x0000 #define kNtImageRelNexgen32eAbsolute 0x0000
#define kNtImageRelNexgen32eAddr64 0x0001 #define kNtImageRelNexgen32eAddr64 0x0001
#define kNtImageRelNexgen32eAddr32 0x0002 #define kNtImageRelNexgen32eAddr32 0x0002
#define kNtImageRelNexgen32eAddr32nb 0x0003 #define kNtImageRelNexgen32eAddr32nb 0x0003
#define kNtImageRelNexgen32eRel32 0x0004 #define kNtImageRelNexgen32eRel32 0x0004
#define kNtImageRelNexgen32eRel32_1 0x0005 #define kNtImageRelNexgen32eRel32_1 0x0005
#define kNtImageRelNexgen32eRel32_2 0x0006 #define kNtImageRelNexgen32eRel32_2 0x0006
#define kNtImageRelNexgen32eRel32_3 0x0007 #define kNtImageRelNexgen32eRel32_3 0x0007
#define kNtImageRelNexgen32eRel32_4 0x0008 #define kNtImageRelNexgen32eRel32_4 0x0008
#define kNtImageRelNexgen32eRel32_5 0x0009 #define kNtImageRelNexgen32eRel32_5 0x0009
#define kNtImageRelNexgen32eSection 0x000A #define kNtImageRelNexgen32eSection 0x000A
#define kNtImageRelNexgen32eSecrel 0x000B #define kNtImageRelNexgen32eSecrel 0x000B
#define kNtImageRelNexgen32eSecrel7 0x000C #define kNtImageRelNexgen32eSecrel7 0x000C
#define kNtImageRelNexgen32eToken 0x000D #define kNtImageRelNexgen32eToken 0x000D
#define kNtImageRelNexgen32eSrel32 0x000E #define kNtImageRelNexgen32eSrel32 0x000E
#define kNtImageRelNexgen32ePair 0x000F #define kNtImageRelNexgen32ePair 0x000F
#define kNtImageRelNexgen32eSspan32 0x0010 #define kNtImageRelNexgen32eSspan32 0x0010
#define kNtImageRelBasedAbsolute 0 #define kNtImageRelBasedAbsolute 0
#define kNtImageRelBasedHigh 1 #define kNtImageRelBasedHigh 1
#define kNtImageRelBasedLow 2 #define kNtImageRelBasedLow 2
#define kNtImageRelBasedHighlow 3 #define kNtImageRelBasedHighlow 3
#define kNtImageRelBasedHighadj 4 #define kNtImageRelBasedHighadj 4
#define kNtImageRelBasedMachineSpecific_5 5 #define kNtImageRelBasedMachineSpecific_5 5
#define kNtImageRelBasedReserved 6 #define kNtImageRelBasedReserved 6
#define kNtImageRelBasedMachineSpecific_7 7 #define kNtImageRelBasedMachineSpecific_7 7
#define kNtImageRelBasedMachineSpecific_8 8 #define kNtImageRelBasedMachineSpecific_8 8
#define kNtImageRelBasedMachineSpecific_9 9 #define kNtImageRelBasedMachineSpecific_9 9
#define kNtImageRelBasedDir64 10 #define kNtImageRelBasedDir64 10
#define kNtImageArchiveStartSize 8 #define kNtImageArchiveStartSize 8
#define kNtImageArchiveStart "!<arch>\n" #define kNtImageArchiveStart "!<arch>\n"
#define kNtImageArchiveEnd "`\n" #define kNtImageArchiveEnd "`\n"
#define kNtImageArchivePad "\n" #define kNtImageArchivePad "\n"
#define kNtImageArchiveLinkerMember "/ " #define kNtImageArchiveLinkerMember "/ "
#define kNtImageArchiveLongnamesMember "// " #define kNtImageArchiveLongnamesMember "// "
#define kNtImageArchiveHybridmapMember "/<HYBRIDMAP>/ " #define kNtImageArchiveHybridmapMember "/<HYBRIDMAP>/ "
#define kNtImageOrdinalFlag 0x8000000000000000 #define kNtImageOrdinalFlag 0x8000000000000000
#define NtImageOrdinal(Ordinal) (Ordinal & 0xffff) #define NtImageOrdinal(Ordinal) (Ordinal & 0xffff)
#define NtImageSnapByOrdinal(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0) #define NtImageSnapByOrdinal(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0)
#define kNtImageResourceNameIsString 0x80000000 #define kNtImageResourceNameIsString 0x80000000
#define kNtImageResourceDataIsDirectory 0x80000000 #define kNtImageResourceDataIsDirectory 0x80000000
#define kNtImageDynamicRelocationGuardRfPrologue 0x00000001 #define kNtImageDynamicRelocationGuardRfPrologue 0x00000001
#define kNtImageDynamicRelocationGuardRfEpilogue 0x00000002 #define kNtImageDynamicRelocationGuardRfEpilogue 0x00000002
#define kNtImageHotPatchBaseObligatory 0x00000001 #define kNtImageHotPatchBaseObligatory 0x00000001
#define kNtImageHotPatchChunkInverse 0x80000000 #define kNtImageHotPatchChunkInverse 0x80000000
#define kNtImageHotPatchChunkObligatory 0x40000000 #define kNtImageHotPatchChunkObligatory 0x40000000
#define kNtImageHotPatchChunkReserved 0x3FF03000 #define kNtImageHotPatchChunkReserved 0x3FF03000
#define kNtImageHotPatchChunkType 0x000FC000 #define kNtImageHotPatchChunkType 0x000FC000
#define kNtImageHotPatchChunkSourceRva 0x00008000 #define kNtImageHotPatchChunkSourceRva 0x00008000
#define kNtImageHotPatchChunkTargetRva 0x00004000 #define kNtImageHotPatchChunkTargetRva 0x00004000
#define kNtImageHotPatchChunkSize 0x00000FFF #define kNtImageHotPatchChunkSize 0x00000FFF
#define kNtImageHotPatchNone 0x00000000 #define kNtImageHotPatchNone 0x00000000
#define kNtImageHotPatchFunction 0x0001C000 #define kNtImageHotPatchFunction 0x0001C000
#define kNtImageHotPatchAbsolute 0x0002C000 #define kNtImageHotPatchAbsolute 0x0002C000
#define kNtImageHotPatchRel32 0x0003C000 #define kNtImageHotPatchRel32 0x0003C000
#define kNtImageHotPatchCallTarget 0x00044000 #define kNtImageHotPatchCallTarget 0x00044000
#define kNtImageHotPatchIndirect 0x0005C000 #define kNtImageHotPatchIndirect 0x0005C000
#define kNtImageHotPatchNoCallTarget 0x00064000 #define kNtImageHotPatchNoCallTarget 0x00064000
#define kNtImageHotPatchDynamicValue 0x00078000 #define kNtImageHotPatchDynamicValue 0x00078000
#define kNtImageGuardCfInstrumented 0x00000100 #define kNtImageGuardCfInstrumented 0x00000100
#define kNtImageGuardCfwInstrumented 0x00000200 #define kNtImageGuardCfwInstrumented 0x00000200
#define kNtImageGuardCfFunctionTablePresent 0x00000400 #define kNtImageGuardCfFunctionTablePresent 0x00000400
#define kNtImageGuardSecurityCookieUnused 0x00000800 #define kNtImageGuardSecurityCookieUnused 0x00000800
#define kNtImageGuardProtectDelayloadIat 0x00001000 #define kNtImageGuardProtectDelayloadIat 0x00001000
#define kNtImageGuardDelayloadIatInItsOwnSection 0x00002000 #define kNtImageGuardDelayloadIatInItsOwnSection 0x00002000
#define kNtImageGuardCfExportSuppressionInfoPresent 0x00004000 #define kNtImageGuardCfExportSuppressionInfoPresent 0x00004000
#define kNtImageGuardCfEnableExportSuppression 0x00008000 #define kNtImageGuardCfEnableExportSuppression 0x00008000
#define kNtImageGuardCfLongjumpTablePresent 0x00010000 #define kNtImageGuardCfLongjumpTablePresent 0x00010000
#define kNtImageGuardRfInstrumented 0x00020000 #define kNtImageGuardRfInstrumented 0x00020000
#define kNtImageGuardRfEnable 0x00040000 #define kNtImageGuardRfEnable 0x00040000
#define kNtImageGuardRfStrict 0x00080000 #define kNtImageGuardRfStrict 0x00080000
#define kNtImageGuardCfFunctionTableSizeMask 0xF0000000 #define kNtImageGuardCfFunctionTableSizeMask 0xF0000000
#define kNtImageGuardCfFunctionTableSizeShift 28 #define kNtImageGuardCfFunctionTableSizeShift 28
#define kNtImageGuardFlagFidSuppressed 0x01 #define kNtImageGuardFlagFidSuppressed 0x01
#define kNtImageGuardFlagExportSuppressed 0x02 #define kNtImageGuardFlagExportSuppressed 0x02
#define kNtImageEnclaveImportMatchNone 0x00000000 #define kNtImageEnclaveImportMatchNone 0x00000000
#define kNtImageEnclaveImportMatchUniqueId 0x00000001 #define kNtImageEnclaveImportMatchUniqueId 0x00000001
#define kNtImageEnclaveImportMatchAuthorId 0x00000002 #define kNtImageEnclaveImportMatchAuthorId 0x00000002
#define kNtImageEnclaveImportMatchFamilyId 0x00000003 #define kNtImageEnclaveImportMatchFamilyId 0x00000003
#define kNtImageEnclaveImportMatchImageId 0x00000004 #define kNtImageEnclaveImportMatchImageId 0x00000004
#define kNtImageDebugTypeUnknown 0 #define kNtImageDebugTypeUnknown 0
#define kNtImageDebugTypeCoff 1 #define kNtImageDebugTypeCoff 1
#define kNtImageDebugTypeCodeview 2 #define kNtImageDebugTypeCodeview 2
#define kNtImageDebugTypeFpo 3 #define kNtImageDebugTypeFpo 3
#define kNtImageDebugTypeMisc 4 #define kNtImageDebugTypeMisc 4
#define kNtImageDebugTypeException 5 #define kNtImageDebugTypeException 5
#define kNtImageDebugTypeFixup 6 #define kNtImageDebugTypeFixup 6
#define kNtImageDebugTypeOmapToSrc 7 #define kNtImageDebugTypeOmapToSrc 7
#define kNtImageDebugTypeOmapFromSrc 8 #define kNtImageDebugTypeOmapFromSrc 8
#define kNtImageDebugTypeBorland 9 #define kNtImageDebugTypeBorland 9
#define kNtImageDebugTypeReserved10 10 #define kNtImageDebugTypeReserved10 10
#define kNtImageDebugTypeClsid 11 #define kNtImageDebugTypeClsid 11
#define kNtImageDebugTypeVcFeature 12 #define kNtImageDebugTypeVcFeature 12
#define kNtImageDebugTypePogo 13 #define kNtImageDebugTypePogo 13
#define kNtImageDebugTypeIltcg 14 #define kNtImageDebugTypeIltcg 14
#define kNtImageDebugTypeMpx 15 #define kNtImageDebugTypeMpx 15
#define kNtImageDebugTypeRepro 16 #define kNtImageDebugTypeRepro 16
#define kNtFrameFpo 0 #define kNtFrameFpo 0
#define kNtFrameTrap 1 #define kNtFrameTrap 1
#define kNtFrameTss 2 #define kNtFrameTss 2
#define kNtFrameNonfpo 3 #define kNtFrameNonfpo 3
#define kNtImageSizeofShortName 8 #define kNtImageSizeofShortName 8
#define kNtImageSizeofSectionHeader 40 #define kNtImageSizeofSectionHeader 40
#define kNtImageSizeofSymbol 18 #define kNtImageSizeofSymbol 18
#define kNtImageEnclaveLongIdLength 32 #define kNtImageEnclaveLongIdLength 32
#define kNtImageEnclaveShortIdLength 16 #define kNtImageEnclaveShortIdLength 16
#define kNtImageNumberofDirectoryEntries 16 #define kNtImageNumberofDirectoryEntries 16
#endif /* COSMOPOLITAN_LIBC_NT_PEDEF_H_ */ #endif /* COSMOPOLITAN_LIBC_NT_PEDEF_H_ */

72
libc/runtime/efimain.c Normal file
View file

@ -0,0 +1,72 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 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 "libc/calls/efi.h"
#include "libc/dce.h"
#include "libc/nt/efi.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/runtime.h"
/**
* EFI Application Entrypoint.
*
* This entrypoint is mutually exclusive from WinMain since
* Windows apps and EFI apps use the same PE binary format.
* By default, we build binaries to support Windows. If you
* want to your APE executable to boot on UEFI instead then
* you need to run the following build command:
*
* make -j8 CPPFLAGS=-DSUPPORT_VECTOR=251
*
* That'll remove all the Windows code and turn EFI on. You
* can also remove by BIOS code too, by changing 251 to 249
* but it shouldn't matter. Here's how to emulate EFI apps:
*
* qemu-system-x86_64 \
* -bios OVMF.fd \
* -serial stdio \
* -net none \
* -drive format=raw,file=fat:rw:o/tool/viz
* FS0:
* deathstar.com
*
* If you're using the amalgamated release binaries then it
* should be possible to enable UEFI mode by having this at
* the top of your main source file to hint the APE linker:
*
* STATIC_YOINK("EfiMain");
* int main() { ... }
*
* @see libc/dce.h
*/
__msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *SystemTable) {
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"
".weak\t_start\n\t"
"jmp\t_start");
unreachable;
}

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,15 +16,16 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/macros.h" #include "libc/runtime/runtime.h"
.privileged
.source __FILE__
// Terminates process, ignoring destructors and atexit() handlers. /**
// * Terminates process, ignoring destructors and atexit() handlers.
// @param edi is exit code ∈ [0,256) *
// @asyncsignalsafe * @param rc is exit code [0,256)
// @vforksafe * @asyncsignalsafe
// @noreturn * @vforksafe
_exit: jmp _Exit * @noreturn
.endfn _exit,globl,protected */
wontreturn void _exit(int rc) {
_Exit(rc);
}

44
libc/runtime/exit3.c Normal file
View file

@ -0,0 +1,44 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 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 "libc/calls/efi.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
/**
* Terminates process, ignoring destructors and atexit() handlers.
*
* @param rc is exit code [0,256)
* @asyncsignalsafe
* @vforksafe
* @noreturn
*/
wontreturn void _Exit(int rc) {
if ((!IsWindows() && !IsMetal() && !IsUefi()) ||
(IsMetal() && IsGenuineCosmo())) {
sys_exit(rc);
} else if (IsUefi()) {
__efi_system_table->BootServices->Exit(__efi_image_handle, rc, 0, NULL);
} else if (IsWindows()) {
ExitProcess(rc & 0xff);
}
triplf();
}

View file

@ -73,12 +73,6 @@ void *sbrk(intptr_t);
int brk(void *); int brk(void *);
int NtGetVersion(void); int NtGetVersion(void);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § runtime » optimizations
*/
#define _exit(RC) _Exit(RC)
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_RUNTIME_H_ */ #endif /* COSMOPOLITAN_LIBC_RUNTIME_RUNTIME_H_ */

View file

@ -104,7 +104,7 @@ __systemfive:
.privileged .privileged
.Lanchorpoint: .Lanchorpoint:
#if SupportsLinux() || SupportsMetal() #if SupportsLinux() || SupportsMetal() || SupportsUefi()
systemfive_linux: systemfive_linux:
and $0xfff,%eax and $0xfff,%eax
cmp $0xfff,%eax cmp $0xfff,%eax
@ -194,14 +194,18 @@ systemfive_xnu:
.init.start 300,_init_systemfive .init.start 300,_init_systemfive
push %rbx push %rbx
push %rsi push %rsi
#if SupportsMetal()
testb $METAL,(%rdi) # @see ape/ape.S
jnz _init_systemfive_metal
#endif
#if SupportsXnu() #if SupportsXnu()
testb $XNU,(%rdi) # @see libc/crt/crt.S testb $XNU,(%rdi) # @see libc/crt/crt.S
jnz _init_systemfive_xnu jnz _init_systemfive_xnu
#endif #endif
#if SupportsUefi()
testb $UEFI,(%rdi) # @see ape/ape.S
jnz _init_systemfive_uefi
#endif
#if SupportsMetal()
testb $METAL,(%rdi) # @see ape/ape.S
jnz _init_systemfive_metal
#endif
#if SupportsFreebsd() #if SupportsFreebsd()
testb $FREEBSD,(%rdi) # @see libc/crt/crt.S testb $FREEBSD,(%rdi) # @see libc/crt/crt.S
jnz _init_systemfive_freebsd jnz _init_systemfive_freebsd
@ -222,7 +226,7 @@ systemfive_xnu:
lea 2(%eax),%eax lea 2(%eax),%eax
jnz 0b jnz 0b
#endif #endif
#if SupportsLinux() || SupportsMetal() #if SupportsLinux()
_init_systemfive_linux: _init_systemfive_linux:
pushb systemfive_linux-.Lanchorpoint pushb systemfive_linux-.Lanchorpoint
push $LINUX push $LINUX
@ -236,6 +240,13 @@ _init_systemfive_metal:
ezlea syscon_linux,si ezlea syscon_linux,si
jmp _init_systemfive_os jmp _init_systemfive_os
#endif #endif
#if SupportsUefi()
_init_systemfive_uefi:
pushb systemfive_linux-.Lanchorpoint
push $UEFI
ezlea syscon_linux,si
jmp _init_systemfive_os
#endif
#if SupportsWindows() #if SupportsWindows()
_init_systemfive_windows: _init_systemfive_windows:
pushb systemfive_enosys-.Lanchorpoint pushb systemfive_enosys-.Lanchorpoint
@ -312,8 +323,8 @@ _init_systemfive_magnums:
// 𝑠𝑙𝑖𝑑𝑒 // 𝑠𝑙𝑖𝑑𝑒
#if SupportsSystemv() && !defined(TINY) #if SupportsSystemv() && !defined(TINY)
_init_systemfive_stack: # determinism ftw! _init_systemfive_stack: # determinism ftw!
#if SupportsWindows() #if SupportsWindows() || SupportsMetal() || SupportsUefi()
testb IsWindows() # already did this testb $WINDOWS|METAL|UEFI,__hostos(%rip)
jnz _init_systemfive_done jnz _init_systemfive_done
#endif #endif
push %rdi push %rdi
@ -403,7 +414,7 @@ syscon_end:
.type syscon_end,@object .type syscon_end,@object
.globl syscon_start .globl syscon_start
.globl syscon_end .globl syscon_end
#if SupportsLinux() || SupportsMetal() #if SupportsLinux() || SupportsMetal() || SupportsUefi()
.section .sort.rodata.syscon.linux.1,"a",@progbits .section .sort.rodata.syscon.linux.1,"a",@progbits
.align 1 .align 1
syscon_linux:/* syscon_linux:/*

385
tool/viz/printansi.c Normal file
View file

@ -0,0 +1,385 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 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 "dsp/core/half.h"
#include "dsp/core/twixt8.h"
#include "dsp/scale/scale.h"
#include "dsp/tty/quant.h"
#include "dsp/tty/tty.h"
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/winsize.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/rand/rand.h"
#include "libc/runtime/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/termios.h"
#include "libc/x/x.h"
#include "third_party/getopt/getopt.h"
#include "third_party/stb/stb_image.h"
#include "tool/viz/lib/graphic.h"
#define SQR(x) ((x) * (x))
static struct Flags {
const char *out;
bool invert;
bool subpixel;
bool unsharp;
bool dither;
bool ruler;
bool trailingnewline;
long half;
bool full;
long width;
long height;
enum TtyBlocksSelection blocks;
enum TtyQuantizationAlgorithm quant;
} g_flags;
static wontreturn void PrintUsage(int rc, FILE *f) {
fprintf(f, "Usage: %s%s", program_invocation_name, "\
[FLAGS] [PATH]\n\
\n\
FLAGS\n\
\n\
-w INT width\n\
-h INT height\n\
-i invert\n\
-? shows this information\n\
\n\
EXAMPLES\n\
\n\
printansi.com -w80 -h40 logo.png\n\
\n\
\n");
exit(rc);
}
static int ParseNumberOption(const char *arg) {
long x;
x = strtol(arg, NULL, 0);
if (!(1 <= x && x <= INT_MAX)) {
fprintf(stderr, "invalid flexidecimal: %s\n\n", arg);
exit(EXIT_FAILURE);
}
return x;
}
static void GetOpts(int *argc, char *argv[]) {
int opt;
struct winsize ws;
g_flags.quant = kTtyQuantTrue;
g_flags.blocks = IsWindows() ? kTtyBlocksCp437 : kTtyBlocksUnicode;
if (*argc == 2 &&
(strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-help") == 0)) {
PrintUsage(EXIT_SUCCESS, stdout);
}
while ((opt = getopt(*argc, argv, "?ivpfrtxads234o:w:h:")) != -1) {
switch (opt) {
case 'o':
g_flags.out = optarg;
break;
case 'd':
g_flags.dither = true;
break;
case 's':
g_flags.unsharp = true;
break;
case 'w':
g_flags.trailingnewline = true;
g_flags.width = ParseNumberOption(optarg);
break;
case 'h':
g_flags.trailingnewline = true;
g_flags.height = ParseNumberOption(optarg);
break;
case 'f':
g_flags.full = true;
break;
case 'i':
g_flags.invert = true;
break;
case '2':
g_flags.half = true;
break;
case 'r':
g_flags.ruler = true;
break;
case 'p':
g_flags.subpixel = true;
break;
case 'a':
g_flags.quant = kTtyQuantAnsi;
break;
case 'x':
g_flags.quant = kTtyQuantXterm256;
break;
case 't':
g_flags.quant = kTtyQuantTrue;
break;
case '3':
g_flags.blocks = kTtyBlocksCp437;
break;
case '4':
g_flags.blocks = kTtyBlocksUnicode;
break;
case 'v':
++g_loglevel;
break;
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
if (optind == *argc) {
if (!g_flags.out) g_flags.out = "-";
argv[(*argc)++] = "-";
}
if (!g_flags.full && (!g_flags.width || !g_flags.width)) {
ws.ws_col = 80;
ws.ws_row = 24;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != -1 ||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
g_flags.width = ws.ws_col * (1 + !g_flags.half);
g_flags.height = ws.ws_row * 2;
}
}
ttyquantsetup(g_flags.quant, kTtyQuantRgb, g_flags.blocks);
}
static unsigned char ChessBoard(unsigned y, unsigned x, unsigned char a,
unsigned char b) {
return !((y ^ x) & (1u << 2)) ? a : b;
}
static unsigned char AlphaBackground(unsigned y, unsigned x) {
return ChessBoard(y, x, 255, 200);
}
static void *Deblinterlace(long dyn, long dxn, unsigned char dst[3][dyn][dxn],
long syn, long sxn, long scn,
const unsigned char src[syn][sxn][scn], long y0,
long yn, long x0, long xn) {
long y, x;
unsigned char c;
for (y = y0; y < yn; ++y) {
for (x = x0; x < xn; ++x) {
switch (scn) {
case 1:
c = src[y][x][0];
dst[0][y][x] = c;
dst[1][y][x] = c;
dst[2][y][x] = c;
break;
case 2:
c = twixt8(AlphaBackground(y, x), src[y][x][0], src[y][x][1]);
dst[0][y][x] = c;
dst[1][y][x] = c;
dst[2][y][x] = c;
break;
case 3:
dst[0][y][x] = src[y][x][0];
dst[1][y][x] = src[y][x][1];
dst[2][y][x] = src[y][x][2];
break;
case 4:
c = AlphaBackground(y, x);
dst[0][y][x] = twixt8(c, src[y][x][0], src[y][x][3]);
dst[1][y][x] = twixt8(c, src[y][x][1], src[y][x][3]);
dst[2][y][x] = twixt8(c, src[y][x][2], src[y][x][3]);
break;
}
}
}
return dst;
}
static void *DeblinterlaceSubpixelBgr(long dyn, long dxn,
unsigned char dst[3][dyn][dxn][3],
long syn, long sxn,
const unsigned char src[syn][sxn][4],
long y0, long yn, long x0, long xn) {
long y, x;
for (y = y0; y < yn; ++y) {
for (x = x0; x < xn; ++x) {
dst[0][y][x][0] = 0;
dst[1][y][x][0] = 0;
dst[2][y][x][0] = src[y][x][2];
dst[0][y][x][1] = 0;
dst[1][y][x][1] = src[y][x][1];
dst[2][y][x][1] = 0;
dst[0][y][x][2] = src[y][x][0];
dst[1][y][x][2] = 0;
dst[2][y][x][2] = 0;
}
}
return dst;
}
struct Block {
char16_t c;
unsigned char b[4][2];
} kBlocks[] = {
{u' ', {{0000, 0000}, {0000, 0000}, {0000, 0000}, {0000, 0000}}}, //
{u'', {{0060, 0060}, {0060, 0060}, {0060, 0060}, {0060, 0060}}}, //
{u'', {{0140, 0140}, {0140, 0140}, {0140, 0140}, {0140, 0140}}}, //
{u'', {{0300, 0300}, {0300, 0300}, {0300, 0300}, {0300, 0300}}}, //
{u'', {{0377, 0377}, {0377, 0377}, {0377, 0377}, {0377, 0377}}}, //
{u'', {{0000, 0000}, {0000, 0000}, {0377, 0377}, {0377, 0377}}}, //
{u'', {{0377, 0000}, {0377, 0000}, {0377, 0000}, {0377, 0000}}}, //
{u'', {{0000, 0377}, {0000, 0377}, {0000, 0377}, {0000, 0377}}}, //
{u'', {{0377, 0377}, {0377, 0377}, {0000, 0000}, {0000, 0000}}}, //
};
static void *Raster(long yn, long xn, unsigned char Y[yn][xn]) {
long y, x, i, j, k, s, bi, bs;
for (y = 0; y + 4 <= yn; y += 4) {
if (y) fputc('\n', stdout);
for (x = 0; x + 2 <= xn; x += 2) {
bi = 0;
bs = LONG_MAX;
for (k = 0; k < ARRAYLEN(kBlocks); ++k) {
s = 0;
for (i = 0; i < 4; ++i) {
for (j = 0; j < 2; ++j) {
s += SQR(Y[y + i][x + j] - kBlocks[k].b[i][j]);
}
}
if (s < bs) {
bi = k;
bs = s;
}
}
fputwc(kBlocks[bi].c, stdout);
}
}
fputc('\n', stdout);
return Y;
}
static void *Invert(long yn, long xn, unsigned char Y[yn][xn]) {
long y, x;
if (!g_flags.invert) {
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
Y[y][x] = 255 - Y[y][x];
}
}
}
return Y;
}
static void *Grayify(long yn, long xn, unsigned char Y[yn][xn],
const unsigned char RGB[3][yn][xn]) {
long y, x;
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
Y[y][x] = RGB[0][y][x] * .299 + RGB[1][y][x] * .587 + RGB[2][y][x] * .114;
}
}
return Y;
}
static void ProcessImage(long yn, long xn, unsigned char RGB[3][yn][xn]) {
Raster(yn, xn,
Invert(yn, xn, Grayify(yn, xn, gc(memalign(32, yn * xn)), RGB)));
}
void WithImageFile(const char *path,
void fn(long yn, long xn, unsigned char RGB[3][yn][xn])) {
struct stat st;
void *map, *data, *data2;
int fd, yn, xn, cn, dyn, dxn, syn, sxn;
CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path);
CHECK_NE(-1, fstat(fd, &st));
CHECK_GT(st.st_size, 0);
CHECK_LE(st.st_size, INT_MAX);
fadvise(fd, 0, 0, MADV_WILLNEED | MADV_SEQUENTIAL);
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
CHECK_NOTNULL(
(data = gc(stbi_load_from_memory(map, st.st_size, &xn, &yn, &cn, 0))),
"%s", path);
CHECK_NE(-1, munmap(map, st.st_size));
CHECK_NE(-1, close(fd));
if (g_flags.subpixel) {
data = DeblinterlaceSubpixelBgr(yn, xn, gc(memalign(32, yn * xn * 4 * 3)),
yn, xn, data, 0, yn, 0, xn);
xn *= 3;
} else {
data = Deblinterlace(yn, xn, gc(memalign(32, yn * xn * 4)), yn, xn, cn,
data, 0, yn, 0, xn);
cn = 3;
}
if (g_flags.height && g_flags.width) {
syn = yn;
sxn = xn;
dyn = g_flags.height * 4;
dxn = g_flags.width * 2;
while (HALF(syn) > dyn || HALF(sxn) > dxn) {
if (HALF(sxn) > dxn) {
Magikarp2xX(yn, xn, data, syn, sxn);
Magikarp2xX(yn, xn, (char *)data + yn * xn, syn, sxn);
Magikarp2xX(yn, xn, (char *)data + yn * xn * 2, syn, sxn);
sxn = HALF(sxn);
}
if (HALF(syn) > dyn) {
Magikarp2xY(yn, xn, data, syn, sxn);
Magikarp2xY(yn, xn, (char *)data + yn * xn, syn, sxn);
Magikarp2xY(yn, xn, (char *)data + yn * xn * 2, syn, sxn);
syn = HALF(syn);
}
}
data = EzGyarados(3, dyn, dxn, gc(memalign(32, dyn * dxn * 3)), cn, yn, xn,
data, 0, cn, dyn, dxn, syn, sxn, 0, 0, 0, 0);
yn = dyn;
xn = dxn;
}
fn(yn, xn, data);
}
int main(int argc, char *argv[]) {
int i;
GetOpts(&argc, argv);
stbi_set_unpremultiply_on_load(true);
for (i = optind; i < argc; ++i) {
WithImageFile(argv[i], ProcessImage);
}
return 0;
}