From edd9297ebaf3d920f87a609ab0dc5ac64707bfc3 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Tue, 23 Feb 2021 20:23:19 -0800 Subject: [PATCH] Support malloc() on bare metal Your Actually Portable Executables now contains a simple virtual memory that works similarly to the Linux Kernel in the sense that it maps your physical memory to negative addresses. This is needed to support mmap() and malloc(). This functionality has zero code size impact. For example the MODE=tiny LIFE.COM executable is still only 12KB in size. The APE bootloader code has also been simplified to improve readibility and further elevate the elegance by which we're able to support so many platforms thereby enhancing verifiability so that we may engender trust in this bootloading process. --- Makefile | 4 - ape/ape.S | 535 +++++++----------- ape/ape.lds | 41 +- ape/ape.mk | 6 +- ape/config.h | 118 ---- ape/lib/apelib.mk | 45 -- ape/lib/bootdr.S | 35 -- ape/lib/e820map.S | 37 -- ape/lib/flattenhighmemory.c | 55 -- ape/lib/g_pml4t.S | 31 - ape/lib/g_ptsp.S | 37 -- ape/lib/getpagetableentry.c | 42 -- ape/lib/kbiosdataarea.S | 45 -- ape/lib/pageunmap.c | 26 - ape/lib/smapsort.c | 46 -- ape/macros.internal.h | 7 - ape/relocations.h | 22 +- build/bootstrap/compile.com | Bin 65536 -> 65536 bytes build/definitions.mk | 3 +- examples/e820.c | 44 ++ examples/examples.mk | 1 - examples/malloc.c | 19 + libc/calls/efi.h | 12 - libc/calls/fstat.c | 4 +- libc/calls/g_fds.c | 2 +- libc/calls/internal.h | 8 +- libc/calls/nanosleep.c | 4 +- libc/calls/readv-serial.c | 2 +- libc/calls/readv.c | 3 +- libc/calls/sigaction.c | 2 +- libc/calls/writev-serial.c | 2 +- libc/calls/writev.c | 3 +- libc/crt/crt.S | 3 +- libc/dce.h | 4 - libc/integral/c.inc | 2 + libc/intrin/asan.c | 8 +- libc/macros.internal.inc | 3 + libc/nexgen32e/kcpuids.S | 2 +- libc/nexgen32e/triplf.S | 4 +- libc/nexgen32e/xlm.S | 32 -- libc/nt/efi.h | 11 +- libc/runtime/arch_prctl.c | 2 +- .../directmap-metal.c} | 51 +- .../runtime/{directmapnt.c => directmap-nt.c} | 2 +- libc/runtime/directmap.c | 12 +- .../{directmap.h => directmap.internal.h} | 4 +- libc/runtime/e820.internal.h | 21 + libc/runtime/efimain.greg.c | 175 ++++-- libc/runtime/exit.c | 6 +- libc/runtime/exit2.c | 9 +- libc/runtime/exit3.c | 29 +- libc/runtime/fork-nt.c | 2 +- .../runtime/metalprintf.greg.c | 74 ++- libc/runtime/metalprintf.internal.h | 16 + ape/lib/apm.h => libc/runtime/mman.greg.c | 140 ++++- libc/runtime/mman.internal.h | 24 + libc/runtime/mmap.c | 6 +- libc/{calls/efi.c => runtime/munmap-metal.c} | 18 +- libc/runtime/munmap.c | 2 + ape/lib/pc.h => libc/runtime/pc.internal.h | 89 +-- libc/runtime/runtime.mk | 4 + libc/runtime/winmain.greg.c | 6 +- libc/sysv/calls/__sys_mmap.s | 2 + libc/sysv/calls/sys_mmap.s | 2 - libc/sysv/syscalls.sh | 2 +- libc/sysv/systemfive.S | 45 +- libc/testlib/testlib.mk | 1 - libc/tinymath/c2rangr.S | 2 +- libc/tinymath/copysignl.S | 2 +- libc/tinymath/fmodl.S | 2 +- libc/tinymath/lroundl.S | 2 +- libc/tinymath/remainderl.S | 2 +- libc/tinymath/roundl.S | 2 +- libc/tinymath/sincosl.S | 2 +- libc/tinymath/tanl.S | 2 +- libc/zipos/zipos.mk | 1 - test/ape/lib/getpagetableentry_test.c | 65 --- test/ape/lib/smapsort_test.c | 81 --- test/ape/lib/test.mk | 55 -- test/ape/test.mk | 5 - test/test.mk | 3 +- third_party/chibicc/test/test.h | 2 +- tool/build/blinkenlights.c | 10 +- tool/build/compile.c | 1 + tool/build/dis.c | 5 +- tool/build/lib/diself.c | 12 + tool/build/lib/fpu.c | 5 +- tool/emacs/cosmo-c-keywords.el | 1 + tool/net/net.mk | 1 - 89 files changed, 900 insertions(+), 1417 deletions(-) delete mode 100644 ape/config.h delete mode 100644 ape/lib/apelib.mk delete mode 100644 ape/lib/bootdr.S delete mode 100644 ape/lib/e820map.S delete mode 100644 ape/lib/flattenhighmemory.c delete mode 100644 ape/lib/g_pml4t.S delete mode 100644 ape/lib/g_ptsp.S delete mode 100644 ape/lib/getpagetableentry.c delete mode 100644 ape/lib/kbiosdataarea.S delete mode 100644 ape/lib/pageunmap.c delete mode 100644 ape/lib/smapsort.c create mode 100644 examples/e820.c create mode 100644 examples/malloc.c delete mode 100644 libc/calls/efi.h delete mode 100644 libc/nexgen32e/xlm.S rename libc/{calls/nanosleep-uefi.c => runtime/directmap-metal.c} (60%) rename libc/runtime/{directmapnt.c => directmap-nt.c} (98%) rename libc/runtime/{directmap.h => directmap.internal.h} (69%) create mode 100644 libc/runtime/e820.internal.h rename ape/lib/mapimage.c => libc/runtime/metalprintf.greg.c (53%) create mode 100644 libc/runtime/metalprintf.internal.h rename ape/lib/apm.h => libc/runtime/mman.greg.c (58%) create mode 100644 libc/runtime/mman.internal.h rename libc/{calls/efi.c => runtime/munmap-metal.c} (82%) rename ape/lib/pc.h => libc/runtime/pc.internal.h (89%) create mode 100644 libc/sysv/calls/__sys_mmap.s delete mode 100644 libc/sysv/calls/sys_mmap.s delete mode 100644 test/ape/lib/getpagetableentry_test.c delete mode 100644 test/ape/lib/smapsort_test.c delete mode 100644 test/ape/lib/test.mk delete mode 100644 test/ape/test.mk diff --git a/Makefile b/Makefile index e9e61b85e..e2c63ea18 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,6 @@ include libc/str/str.mk # │ include third_party/xed/xed.mk # │ include third_party/zlib/zlib.mk # │ include libc/elf/elf.mk # │ -include ape/lib/apelib.mk # │ include ape/ape.mk # │ include libc/fmt/fmt.mk #─┘ include libc/calls/calls.mk #─┐ @@ -173,8 +172,6 @@ include test/libc/time/test.mk include test/libc/stdio/test.mk include test/libc/release/test.mk include test/libc/test.mk -include test/ape/lib/test.mk -include test/ape/test.mk include test/net/http/test.mk include test/net/test.mk include test/tool/build/lib/test.mk @@ -244,7 +241,6 @@ COSMOPOLITAN_OBJECTS = \ LIBC_TIME \ LIBC_ZIPOS \ THIRD_PARTY_ZLIB \ - APE_LIB \ THIRD_PARTY_MUSL \ LIBC_STDIO \ THIRD_PARTY_REGEX \ diff --git a/ape/ape.S b/ape/ape.S index 4c9714258..eedbfb64c 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -32,17 +32,16 @@ ╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│ │ αcτµαlly pδrταblε εxεcµταblε § program header │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/config.h" -#include "ape/lib/pc.h" #include "ape/macros.internal.h" #include "ape/notice.inc" #include "ape/relocations.h" +#include "libc/dce.h" #include "libc/elf/def.h" #include "libc/macho.internal.h" #include "libc/nexgen32e/uart.internal.h" #include "libc/nexgen32e/vidya.internal.h" #include "libc/nt/pedef.internal.h" -#include "libc/dce.h" +#include "libc/runtime/pc.internal.h" #include "libc/sysv/consts/prot.h" #define USE_SYMBOL_HACK 0 @@ -62,9 +61,6 @@ __ro: .endobj __ro,globl,hidden # ←for gdb readibility .previous .section .rodata.str1.1,"a",@progbits cstr: .endobj cstr,globl,hidden # ←for gdb readibility - .previous - .section .sort.rodata.real.str1.1,"a",@progbits -rlstr: .endobj rlstr,globl,hidden # ←for gdb readibility .previous .section .head,"ax",@progbits @@ -105,7 +101,7 @@ rlstr: .endobj rlstr,globl,hidden # ←for gdb readibility │ αcτµαlly pδrταblε εxεcµταblε § the old technology │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#if SupportsWindows() || SupportsUefi() || SupportsXnu() +#if SupportsWindows() || SupportsMetal() || SupportsXnu() // MZ Literally Executable Header // @@ -131,14 +127,14 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski .ascii "JT" # MZ: OEM identifier .short 0 # MZ: OEM information .org 0x40-4 # MZ: bytes reserved for you -#if SupportsWindows() || SupportsUefi() +#if SupportsWindows() || SupportsMetal() .long RVA(ape_pe) # PE: the new technology #else .long 0 #endif .endfn ape_mz,globl,hidden -#else /* !(SupportsWindows() || SupportsUefi() || SupportsXnu()) */ +#else /* !(SupportsWindows() || SupportsMetal() || SupportsXnu()) */ // ELF Literally Executable Header // @@ -168,7 +164,7 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski .short ape_elf_shnum # 3c: e_shnum .short ape_elf_shstrndx # 3e: e_shstrndx -#endif /* SupportsWindows() || SupportsUefi() || SupportsXnu() */ +#endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */ #if SupportsMetal() @@ -218,17 +214,17 @@ pc: cld .byte 0x0f,0x1f,0207 # nop rdi binbase .short (0x7c00-IMAGE_BASE_VIRTUAL)/512 #endif - mov $REAL_STACK_FRAME>>4,%di # we need a stack - xor %cx,%cx + mov $0x70000>>4,%di # we need a stack + xor %cx,%cx # 0x7f000-0x80000 mov %cx,%es rlstack %di,%cx - push %cs # memcpy() [relocate this page] - pop %ds - call 1f -1: pop %si + push %cs # determine load address + pop %ds # and relocate this code + call 1f # to a way lower address +1: pop %si # and we'll make cs zero sub $RVA(1b),%si mov $IMAGE_BASE_REAL>>4,%ax - push %ax # save real base + push %ax # save IMAGE_BASE_REAL>>4 push %ax pop %es xor %di,%di @@ -238,18 +234,18 @@ pc: cld .byte 0x0f,0x1f,0207 # nop rdi binbase .short (IMAGE_BASE_REAL-0x7c00)/512 #endif - ljmp $0,$REAL(1f) # longjmp() -1: mov %cx,%ds # %ds and %cs are now zero - mov $XLM_SIZE,%cx # memset to clear real bss - mov $XLM_BASE_REAL>>4,%ax + ljmp $0,$REAL(1f) +1: mov %cx,%ds + mov $IMAGE_BASE_REAL-0x0500,%cx # clears bss + mov $0x0500>>4,%ax # struct mman mov %ax,%es xor %ax,%ax xor %di,%di rep stosb - cmp $0x40,%dl # statfs() [disk geometry] + cmp $0x40,%dl je 6f call dsknfo - pop %es # restore real base + pop %es # restore IMAGE_BASE_REAL>>4 mov $1,%al # current sector xor %cx,%cx # current cylinder xor %dh,%dh # current head @@ -257,15 +253,7 @@ pc: cld 3: call pcread dec %di jnz 3b -6: mov $XLM(LOADSTATE),%di # ax,cx,dx,es - stosw - xchg %cx,%ax - stosw - xchg %dx,%ax - stosw - mov %es,%ax - stosw - ljmp $0,$REAL(realmodeloader) +6: ljmp $0,$REAL(realmodeloader) .endfn pc // Determines disk geometry. @@ -326,7 +314,7 @@ dsknfo: push %bx movpp %es,%ds xor %si,%si mov %si,%es - mov $XLM(DRIVE_BASE_TABLE),%si + mov $0x1510,%si # mman::pc_drive_base_table xchg %si,%di movsw #→ headunloadtime, headloadtime movsw #→ shutofftime, bytespersector @@ -379,11 +367,11 @@ pcread: push %ax add $512>>4,%si mov %si,%es inc %al # ++sector - cmp XLM(DRIVE_LAST_SECTOR),%al + cmp 0x151c,%al # mman::pc_drive_last_sector jbe 2f mov $1,%al inc %dh # ++head - cmp XLM(DRIVE_LAST_HEAD),%dh + cmp 0x1520,%dh # mman::pc_drive_last_head jbe 2f xor %dh,%dh inc %cx # ++cylinder @@ -395,6 +383,82 @@ pcread: push %ax jmp pcread .endfn pcread +// Video put string. +// +// @param di is the string +// @clob bp,bx +// @mode real +rvputs: mov %di,%si +0: lodsb + test %al,%al + je 1f + mov $7,%bx # normal mda/cga style page zero + mov $0x0e,%ah # teletype output al cp437 + int $0x10 # vidya service + jmp 0b +1: ret + .endfn rvputs + +// Abnormally halts startup. +// +// @param di message +// @mode real +// @noreturn +rldie: push %di + mov $REAL(str.error),%di + call rvputs + pop %di + call rvputs + mov $REAL(str.crlf),%di + call rvputs +0: rep nop + jmp 0b + .endfn rldie + +// Initializes present PC serial lines. +sinit4: mov $4,%cx + mov $0x400,%si # BDA.COM1 +0: lodsw + test %ax,%ax + jz 1f + push %cx + push %si + xchg %ax,%di + mov $REAL(sconf),%si + call sinit + pop %si + pop %cx +1: loop 0b + ret + .endfn sinit4,global,hidden + +// Initializes Serial Line Communications 8250 UART 16550A +// +// @param word di tty port +// @param char (*{es:,e,r}si)[4] register initial values +// @mode long,legacy,real +// @see www.lammertbies.nl/comm/info/serial-uart.html +sinit: mov %di,%dx + test %dx,%dx + jz 2f + push %dx + push %si + xor %cx,%cx + mov $UART_LCR,%cl + add %cx,%dx + lodsb %ds:(%si),%al + pop %si + or $UART_DLAB,%al + out %al,%dx + pop %dx +1: lodsb %ds:(%si),%al + out %al,%dx + inc %dx + dec %cx + jns 1b +2: ret + .endfn sinit,global,hidden + /*───────────────────────────────────────────────────────────────────────────│─╗ │ αcτµαlly pδrταblε εxεcµταblε § partition table ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ @@ -469,9 +533,7 @@ ape_disk: ╚────────────────────────────────────────────────────────────────────────────│─╝ the bourne executable & linkable format */ -#if SupportsSystemv() - -#if SupportsWindows() || SupportsUefi() || SupportsXnu() +#if SupportsWindows() || SupportsMetal() || SupportsXnu() apesh: .ascii "'\n#'\"\n" # sixth edition shebang .ascii "o=\"$(command -v \"$0\")\"\n" #if SupportsXnu() @@ -526,10 +588,11 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .ascii "fi\n" .ascii "exit $R\n" .endobj apesh -#endif /* SupportsWindows() || SupportsUefi() || SupportsXnu() */ +#endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */ +#if SupportsSystemv() || SupportsMetal() .section .elf.phdrs,"a",@progbits - .long PT_LOAD # text segment + .long PT_LOAD .long PF_R|PF_X .stub ape_rom_offset,quad .stub ape_rom_vaddr,quad @@ -537,7 +600,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .stub ape_rom_filesz,quad .stub ape_rom_memsz,quad .stub ape_rom_align,quad - .long PT_LOAD # data segment + .long PT_LOAD .long PF_R|PF_W .stub ape_ram_offset,quad .stub ape_ram_vaddr,quad @@ -545,20 +608,16 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .stub ape_ram_filesz,quad .stub ape_ram_memsz,quad .stub ape_ram_align,quad -#if SupportsLinux() -// Linux ignores mprotect() and returns 0 without this lool -// It has nothing to do with the stack, which is still exec - .long PT_GNU_STACK # p_type - .long PF_R|PF_W # p_flags - .quad 0 # p_offset - .quad 0 # p_vaddr - .quad 0 # p_paddr - .quad 0 # p_filesz - .quad 0 # p_memsz - .quad 16 # p_align -#endif + .long PT_GNU_STACK + .long PF_R|PF_W + .stub ape_stack_offset,quad + .stub ape_stack_vaddr,quad + .stub ape_stack_paddr,quad + .stub ape_stack_filesz,quad + .stub ape_stack_memsz,quad + .stub ape_stack_align,quad #if SupportsOpenbsd() || SupportsNetbsd() - .long PT_NOTE # notes + .long PT_NOTE .long PF_R .stub ape_note_offset,quad .stub ape_note_vaddr,quad @@ -568,6 +627,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .stub ape_note_align,quad #endif .previous +#endif /* SupportsSystemv() || SupportsMetal() */ #if SupportsOpenbsd() .section .note.openbsd.ident,"a",@progbits @@ -597,8 +657,6 @@ netbsd.ident: .previous #endif /* SupportsNetbsd() */ -#endif /* SupportsSystemv() */ - /* ▄▄███▄ ▄▄████████▄ ▄█████████████▄ @@ -812,7 +870,7 @@ PETEXT = 0b01110000000000000000000001100000 PEDATA = 0b11000000000000000000000011000000 PEIMPS = 0b11000000000000000000000001000000 -#if SupportsWindows() || SupportsUefi() +#if SupportsWindows() || SupportsMetal() .section .pe.header,"a",@progbits .align __SIZEOF_POINTER__ @@ -832,7 +890,7 @@ ape_pe: .ascin "PE",4 .long 0 # SizeOfUninitializedData .long RVA(ape_pe_entry) # EntryPoint .long 0 # BaseOfCode - .quad IMAGE_BASE_VIRTUAL # ImageBase + .quad ape_pe_base # ImageBase .long 4096 # SectionAlignment .long 4096 # FileAlignment .short v_ntversion # MajorOperatingSystemVersion @@ -846,11 +904,7 @@ ape_pe: .ascin "PE",4 .long RVA(_ehead) # SizeOfHeaders .long 0 # Checksum .short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console -#if SupportsWindows() - .short DLLEXE # DllCharacteristics -#else - .short 0 # DllCharacteristics -#endif + .stub v_ntdllchar,short # DllCharacteristics .quad 0x0000000000100000 # StackReserve .quad 0x00000000000fc000 # StackCommit .quad 0 # HeapReserve @@ -858,12 +912,8 @@ ape_pe: .ascin "PE",4 .long 0 # LoaderFlags .long 16 # NumberOfDirectoryEntries .long 0,0 # ExportsDirectory -#if SupportsWindows() - .long RVA(ape_idata_idt) # ImportsDirectory + .stub ape_idata,long # ImportsDirectory .stub ape_idata_idtsize,long # ImportsDirectorySize -#else - .long 0,0 # ImportsDirectory -#endif .long 0,0 # ResourcesDirectory .long 0,0 # ExceptionsDirectory .long 0,0 # SecurityDirectory @@ -874,12 +924,8 @@ ape_pe: .ascin "PE",4 .long 0,0 # ThreadLocalStorage .long 0,0 # LoadConfigurationDirectory .long 0,0 # BoundImportDirectory -#if SupportsWindows() - .long RVA(ape_idata_iat) # ImportAddressDirectory + .stub ape_idata,long # ImportAddressDirectory .stub ape_idata_iatsize,long # ImportAddressDirectorySize -#else - .long 0,0 # ImportAddressDirectory -#endif .long 0,0 # DelayImportDescriptor .long 0,0 # ComPlusRuntimeHeader .long 0,0 # Reserved @@ -896,7 +942,7 @@ ape_pe: .ascin "PE",4 .long 0 # Line Number Table Offset .short 0 # Relocation Count .short 0 # Line Number Count - .long PETEXT # Flags + .long PETEXT # Flags .previous .section .pe.sections,"a",@progbits @@ -909,10 +955,10 @@ ape_pe: .ascin "PE",4 .long 0 # Line Number Table Offset .short 0 # Relocation Count .short 0 # Line Number Count - .long PEDATA # Flags + .long PEDATA # Flags .previous -#endif /* SupportsWindows() || SupportsUefi() */ +#endif /* SupportsWindows() || SupportsMetal() */ .section .idata.ro.idt.1,"a",@progbits .type ape_idata_idtend,@object @@ -950,13 +996,6 @@ ape_idata_iatend: better code/data separation (.head is rwx[real] rx[long]) */ // NUL-Terminated Strings. -ape.str: -str.ape: - .byte 0xe0,0x63,0xe7,0xe6,0xe0,0x6c,0x6c,0x79 #αcτµαlly - .byte 0x20,0x70,0xeb,0x72,0xe7,0xe0,0x62,0x6c # pδrταbl - .byte 0xee,0x20,0xee,0x78,0xee,0x63,0xe6,0xe7 #ε εxεcµτ - .byte 0xe0,0x62,0x6c,0xee,0x0d,0x0a,0x00 #αblε. - .endobj str.ape str.error: .asciz "error: " .endobj str.error @@ -969,19 +1008,12 @@ str.cpuid: str.oldskool: .asciz "oldskool" .endobj str.oldskool -str.dsknfo: - .asciz "dsknfo" - .endobj str.dsknfo str.e820: .asciz "e820" .endobj str.e820 -str.memory: - .asciz "nomem" - .endobj str.memory str.long: .asciz "nolong" .endobj str.long - .endobj ape.str // Serial Line Configuration (8250 UART 16550) // If it's hacked, it'll at least get hacked very slowly. @@ -1071,8 +1103,8 @@ ape_grub: .align 4 ape_grub_entry: .code32 - cmp $GRUB_EAX,%eax - jne triplf +/ cmp $GRUB_EAX,%eax +/ jne triplf push $0 popf mov $0x40,%dl @@ -1088,18 +1120,12 @@ ape_grub_entry: ╚──────────────────────────────────────────────────────────────────────────────╝ the default mode of operation on modern cpus */ - nop - nop - nop - nop realmodeloader: - call16 rlinit - call16 sinit4 - mov $REAL(str.ape),%di - call16 rvputs + call rlinit + call sinit4 .optfn _start16 - call16 _start16 - call16 longmodeloader + call _start16 + call longmodeloader .endfn realmodeloader .section .sort.text.real.init.1,"ax",@progbits @@ -1112,86 +1138,6 @@ rlinit: .previous/* ret .previous -// Initializes present PC serial lines. -sinit4: mov $4,%cx - mov $kBiosDataAreaXlm+COM1,%si -0: lodsw - test %ax,%ax - jz 1f - push %cx - push %si - xchg %ax,%di - mov $REAL(sconf),%si - call16 sinit - pop %si - pop %cx -1: loop 0b - ret - .endfn sinit4,global,hidden - -// Initializes Serial Line Communications 8250 UART 16550A -// -// @param word di tty port -// @param char (*{es:,e,r}si)[4] register initial values -// @mode long,legacy,real -// @see www.lammertbies.nl/comm/info/serial-uart.html -sinit: mov %di,%dx - test %dx,%dx - jz 2f - push %dx - push %si - xorw %cx,%cx - mov $UART_LCR,%cl - add %cx,%dx - lodsb %ds:(%si),%al - pop %si - or $UART_DLAB,%al - out %al,%dx - pop %dx -1: lodsb %ds:(%si),%al - out %al,%dx - add $1,%dx - sub $1,%cx - jns 1b -2: ret - .endfn sinit,global,hidden - -// Video put string. -// -// @param di is the string -// @mode real -rvputs: push %bp - push %bx - mov %di,%si -0: lodsb - test %al,%al - je 1f - mov $7,%bx # normal mda/cga style page zero - mov $0x0e,%ah # teletype output al cp437 - int $0x10 # vidya service - jmp 0b -1: pop %bx - pop %bp - ret - .endfn rvputs - -// Abnormally halts startup. -// -// @param di message -// @mode real -// @noreturn -rldie: push %di - mov $REAL(str.error),%di - call16 rvputs - pop %di - call16 rvputs - mov $REAL(str.crlf),%di - call16 rvputs - xor %ax,%ax # get keystroke - int $0x16 # keyboard service - call16 triplf - .endfn rldie - /* █ █▒ █ █ █▓▄ █ █ @@ -1239,18 +1185,11 @@ rldie: push %di long mode is long */ longmodeloader: - call16 lcheck - call16 a20 - mov $XLM(E820),%di - mov $XLM_E820_SIZE,%si - call16 e820 - jc 9f - call16 unreal -// call hiload - call16 pinit - call16 golong -9: mov $REAL(str.e820),%ax - call16 rldie + call lcheck + call a20 + call e820 + call pinit + call golong .endfn longmodeloader // Long Mode Hardware Check @@ -1286,35 +1225,25 @@ lcheck: pushf # check for i8086 / i8088 / i80186 jne 10f xor %ax,%ax 1: ret -9: mov $REAL(str.oldskool),%ax +9: mov $REAL(str.oldskool),%di jmp 20f -10: mov $REAL(str.long),%ax +10: mov $REAL(str.long),%di jmp 20f -12: mov $REAL(str.cpuid),%ax - jmp 20f -20: call16 rldie +12: mov $REAL(str.cpuid),%di +20: call rldie .endfn lcheck // Gets memory map from BIOS. -// -// @param di paragraph aligned buffer -// @param si bytes in buffer to fill -// @return number of bytes written or CF on error -// @mode real -e820: push %bp - mov %sp,%bp - pushl $'S'<<24|'M'<<16|'A'<<8|'P' # magic @ -4(%bp) - push %bx - shr $4,%di +e820: mov $0x0510>>4,%di # mman::e820 mov %di,%es xor %edi,%edi # es:di is destination buffer xor %ebx,%ebx # ebx is an api state tracker 1: mov $0xE820,%eax # magic mov $8+8+4+4,%ecx # sizeof(struct SmapEntry) - mov -4(%bp),%edx # magic + mov $0x534d4150,%edx # magic number int $0x15 # ax,bx,cx,dx,di → ax,bx,cx jc 9f # cf = unsupported or abuse - cmp -4(%bp),%eax # more magic means success + cmp %edx,%eax # more magic means success jne 9f test %cx,%cx # discard empty results jz 5f @@ -1324,78 +1253,14 @@ e820: push %bp jnz 5f 4: add $8+8+4+4,%di # keep entry 5: test %ebx,%ebx # last entry? - jz 7f - cmp %si,%di # out of buf? + jz 8f + cmp $0x1000,%di jb 1b -7: mov %di,%ax -8: pop %bx - leave - ret -9: stc - jmp 8b +8: ret +9: mov $REAL(str.e820),%di + call rldie .endfn e820 -// Unreal Mode. -// Makes 4gb of real memory accessible via %fs segment. -unreal: cli - lgdt REAL(gdt) - mov %cr0,%eax - or $CR0_PE,%al - mov %eax,%cr0 - jmp 1f -1: mov $GDT_LEGACY_DATA,%cx - mov %cx,%fs - and $~CR0_PE,%al - mov %eax,%cr0 - ljmp $0,$REAL(1f) -1: sti - ret - .endfn unreal - -// Loads remainder of executable off disk. -hiload: push %bx - mov $IMAGE_BASE_REAL,%esi # relocate, again - mov $IMAGE_BASE_PHYSICAL,%ebx - mov $v_ape_realsectors,%ecx - shl $9,%ecx - or $-4,%edx -0: add $4,%edx - cmp %edx,%ecx - je 1f - mov %fs:(%esi,%edx),%eax - mov %eax,%fs:(%ebx,%edx) - jmp 0b -1: lea (%ebx,%edx),%ebx - mov $v_ape_highsectors,%di # then copy rest off disk - mov $REAL_SCRATCH_AREA>>4,%ax # to real memory buffer - mov %ax,%es - mov XLM(LOADSTATE)+0,%ax - mov XLM(LOADSTATE)+2,%cx - mov XLM(LOADSTATE)+4,%dx -0: test %di,%di - jz 9f - mov %di,%ax - push %bx - xor %bx,%bx - call16 pcread - pop %bx - sub %ax,%di - push %cx - mov %ax,%cx # copy real buffer to high - shl $9,%cx # no way bios loaded >64k - xor %si,%si -1: mov %es:(%si),%eax - mov %eax,%fs:(%ebx) - add $4,%ebx - add $4,%si - sub $4,%cx - jnz 1b - pop %cx - jmp 0b -9: pop %bx - ret - .endfn hiload - // Asks keyboard to grant system 65,519 more bytes of memory. // // Yup. @@ -1426,26 +1291,26 @@ a20: cli pop %ds jne 3f mov $1,%ax - call16 1f + call 1f mov $0xad,%al out %al,$0x64 - call16 1f + call 1f mov $0xd0,%al out %al,$0x64 - call16 2f + call 2f in $0x60,%al push %ax - call16 1f + call 1f mov $0xd1,%al out %al,$0x64 - call16 1f + call 1f pop %ax or $2,%al out %al,$0x60 - call16 1f + call 1f mov $0xae,%al out %al,$0x64 - call16 1f + call 1f jmp a20 1: in $0x64,%al test $2,%al @@ -1460,33 +1325,26 @@ a20: cli .endfn a20 // Initializes long mode paging. -// -// Modern computers access memory via four levels of indirection: -// -// register char (*(*(*(*ram)[512])[512])[512])[4096] asm(cr3) -// -// Your page tables grow down in memory, starting from the real -// stack segment base. This function only defines enough tables -// to get us started. -#define TIP REAL_STACK_FRAME pinit: push %ds - mov $(TIP-0x4000)>>4,%ax +#define SEG 0x79000 + mov $SEG>>4,%ax mov %ax,%ds - movl $TIP-0x2000+PAGE_V+PAGE_RW,0x3000 # PML4T→PDPT - movl $TIP-0x3000+PAGE_V+PAGE_RW,0x2000 # PDPT→PDT - movl $TIP-0x4000+PAGE_V+PAGE_RW,0x1000 # PDT→PD - mov $0x100000/0x1000,%cx # PD→512kb + movl $0x7d000+PAGE_V+PAGE_RW,0x7e000-SEG # PDPT←PML4T (+) + movl $0x7c000+PAGE_V+PAGE_RW,0x7e800-SEG # PDPT←PML4T (-) + movl $0x7b000+PAGE_V+PAGE_RW,0x7d000-SEG # PDT←PDPT (+) + movl $0x7a000+PAGE_V+PAGE_RW,0x7c000-SEG # PDT←PDPT (-) + movl $0x79000+PAGE_V+PAGE_RW,0x7b000-SEG # PD←PDT (+) + movl $0x79000+PAGE_V+PAGE_RW,0x7a000-SEG # PD←PDT (-) + mov $512,%cx # PD±2MB mov $PAGE_V+PAGE_RW,%eax xor %si,%si 0: mov %eax,(%si) add $0x1000,%eax add $8,%si loop 0b - movb $0,0 # unmap null - pop %ds - movl $TIP-0x4000,XLM(PAGE_TABLE_STACK_POINTER) # STACK→XLM - mov $TIP-0x1000,%eax # PML4T→CR3 + mov $0x7e000,%eax # PML4T←CR3 mov %eax,%cr3 + pop %ds ret .endfn pinit @@ -1494,7 +1352,7 @@ pinit: push %ds // // @see Intel Manual V3A §4.1.2 golong: cli - lidt XLM(BADIDT) + lidt 0x1522 # mman::bad_idt mov %cr4,%eax or $CR4_PAE|CR4_PGE|CR4_OSFXSR,%eax mov %eax,%cr4 @@ -1511,7 +1369,6 @@ golong: cli .endfn golong // Long mode is long. -// @noreturn .code64 long: push $GDT_LONG_DATA pop %rax @@ -1520,39 +1377,59 @@ long: push $GDT_LONG_DATA mov %eax,%es mov %eax,%fs mov %eax,%gs + mov $0x80000,%esp + xor %r12d,%r12d + xor %r13d,%r13d + xor %r14d,%r14d + xor %r15d,%r15d + xor %ebx,%ebx xor %ebp,%ebp - mov $REAL_STACK_FRAME+FRAMESIZE,%esp - call __map_image - ezlea metal.thunk,ax + push %rbp + mov $0x0500,%rdi # mman + mov %cr3,%rsi + mov $IMAGE_BASE_REAL,%edx + call __map_phdrs + push $0x037f + fldcw (%rsp) + movabs $1f,%rax jmp *%rax - .endfn long - -// Long mode in virtual address space. -// @noreturn -metal.thunk: +1: movabs $ape_stack_vaddr,%rsp + add $ape_stack_memsz,%rsp #if USE_SYMBOL_HACK .byte 0x0f,0x1f,0207 # nop rdi binbase .long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512 #endif -// 𝑠𝑙𝑖𝑑𝑒 - .endfn metal.thunk -metal: xor %eax,%eax # clear bss - mov $ape_bss_vaddr,%edi - mov $ape_bss_memsz,%ecx - rep stosb -0: .weak __hostos + movl $0,0x7b000 # unmap null 2mb + .weak __hostos ezlea __hostos,ax test %rax,%rax jz 1f movb $METAL,(%rax) -1: push $0 # auxv[0][1] - push $0 # auxv[0][0] - push $0 # envp[0] - push $0 # argv[0] - push $0 # argc - xor %edi,%edi # not freebsd +1: xor %eax,%eax + xor %ecx,%ecx + xor %edx,%edx + xor %edi,%edi + xor %esi,%esi + xor %r8d,%r8d + xor %r9d,%r9d + xor %r10d,%r10d + xor %r11d,%r11d + push $0 # auxv[1][1] + push $0 # auxv[1][0] + push $.Larg0 # auxv[0][1] + push $31 # auxv[0][0] AT_EXECFN + push $0 # envp[1] + push $.Lenv0 # envp[0] + push $0 # argv[1] + push $.Larg0 # argv[0] + push $1 # argc jmp _start - .endfn metal + .endfn long + + .rodata.str1.1 +.Larg0: .asciz "ape.com" +.Lenv0: .asciz "METAL=1" + .previous #endif /* SupportsMetal() */ diff --git a/ape/ape.lds b/ape/ape.lds index 376cc9da7..794ce1134 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -175,7 +175,7 @@ #ifdef __LINKER__ #include "ape/macros.internal.h" -#include "ape/config.h" +#include "ape/relocations.h" #include "libc/dce.h" #include "libc/nt/pedef.internal.h" #include "libc/zip.h" @@ -196,11 +196,12 @@ SECTIONS { /*BEGIN: linux addressability guarantee */ /*BEGIN: bsd addressability guarantee */ - .head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : { + .head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : AT(IMAGE_BASE_REAL) { HIDDEN(_base = .); /* Real Mode */ KEEP(*(.head)) + KEEP(*(.text.head)) /* Executable & Linkable Format */ . = ALIGN(__SIZEOF_POINTER__); @@ -220,16 +221,14 @@ SECTIONS { HIDDEN(ape_pe_sections = .); KEEP(*(.pe.sections)) HIDDEN(ape_pe_sections_end = .); - . += 1; /* Mach-O */ KEEP(*(.macho)) . = ALIGN(__SIZEOF_POINTER__); HIDDEN(ape_macho_end = .); - . += 1; KEEP(*(.ape.pad.head)) - . = ALIGN(SupportsWindows() || SupportsUefi() ? PAGESIZE : 16); + . = ALIGN(SupportsWindows() || SupportsMetal() ? PAGESIZE : 16); HIDDEN(_ehead = .); } :Head @@ -239,8 +238,8 @@ SECTIONS { /* Code that needs to be addressable in Real Mode */ *(.text.real) KEEP(*(SORT_BY_NAME(.sort.text.real.*))) - *(.rodata.real) - KEEP(*(SORT_BY_NAME(.sort.rodata.real.*))) + /**(.rodata.real) + KEEP(*(SORT_BY_NAME(.sort.rodata.real.*)))*/ HIDDEN(_ereal = .); /*END: realmode addressability guarantee */ @@ -282,7 +281,6 @@ SECTIONS { KEEP(*(.ape.pad.privileged)); HIDDEN(__privileged_start = .); HIDDEN(__test_end = .); - . += 1; *(.privileged) HIDDEN(__privileged_end = .); @@ -308,7 +306,6 @@ SECTIONS { /* Windows DLL Import Directory */ KEEP(*(.idata.ro)); KEEP(*(SORT_BY_NAME(.idata.ro.*))) - . += 1; . = ALIGN(__SIZEOF_POINTER__); PROVIDE_HIDDEN(__init_array_start = .); @@ -381,11 +378,6 @@ SECTIONS { KEEP(*(SORT_BY_NAME(.sort.bss.*))) - /* eXtreme Low Memory w/ Userspace Remapping */ - . = ALIGN(0x1000); - *(.xlm) - . = ALIGN(0x1000); - . = ALIGN(0x10000); /* for brk()/sbrk() allocation */ HIDDEN(_end = .); PROVIDE_HIDDEN(end = .); @@ -465,6 +457,13 @@ HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr); HIDDEN(ape_ram_align = PAGESIZE); HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr)); +HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz); +HIDDEN(ape_stack_vaddr = 0x700000000000 - STACKSIZE); +HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz); +HIDDEN(ape_stack_filesz = 0); +HIDDEN(ape_stack_memsz = STACKSIZE); +HIDDEN(ape_stack_align = 16); + HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr)); HIDDEN(ape_note_vaddr = ape_note); HIDDEN(ape_note_paddr = ape_rom_paddr + ape_note_offset); @@ -500,14 +499,18 @@ SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8); SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8); #endif -#if SupportsWindows() || SupportsUefi() +#if SupportsWindows() || SupportsMetal() #define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain)) PFSTUB4(ape_pe_offset, ape_pe - ape_mz); HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24)); 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_iatsize = ape_idata_iatend - ape_idata_iat); +HIDDEN(ape_pe_base = IMAGE_BASE_VIRTUAL); +HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_iat) : 0); +HIDDEN(ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0); +HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0); +HIDDEN(ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0); HIDDEN(v_ntversion = LINK_WINDOWS ? 6 : 1); +HIDDEN(v_ntdllchar = LINK_WINDOWS ? 288 : 0); HIDDEN(v_ntsubversion = LINK_WINDOWS ? 6 : 5); HIDDEN(v_ntsubsystem = (LINK_WINDOWS ? (DEFINED(GetMessage) @@ -519,7 +522,7 @@ HIDDEN(ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain); #if SupportsMetal() HIDDEN(v_ape_realsectors = - MIN(REAL_SCRATCH_AREA - IMAGE_BASE_REAL, + MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_edata), 4096)) / 512); HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512)); HIDDEN(v_ape_highsectors = @@ -609,7 +612,7 @@ CHURN(v_ape_realsectors); #if SupportsXnu() CHURN(ape_macho); #endif -#if SupportsWindows() || SupportsUefi() +#if SupportsWindows() || SupportsMetal() CHURN(ape_mz); CHURN(ape_pe); CHURN(ape_pe_offset); diff --git a/ape/ape.mk b/ape/ape.mk index 26fefdaef..cc23be31b 100644 --- a/ape/ape.mk +++ b/ape/ape.mk @@ -31,12 +31,10 @@ APE_HDRS = $(filter %.h,$(APE_FILES)) APE_INCS = $(filter %.inc,$(APE_FILES)) APE_SRCS = $(filter %.S,$(APE_FILES)) APE_OBJS = $(APE_SRCS:%.S=o/$(MODE)/%.o) -APE_DEPS = $(APE_LIB) APE_CHECKS = $(APE_HDRS:%=o/%.ok) o/$(MODE)/ape/ape.lds: \ ape/ape.lds \ - ape/config.h \ ape/macros.internal.h \ libc/dce.h \ libc/zip.h @@ -49,6 +47,4 @@ $(APE_OBJS): $(BUILD_FILES) \ ape/ape.mk .PHONY: o/$(MODE)/ape -o/$(MODE)/ape: $(APE) \ - $(APE_CHECKS) \ - o/$(MODE)/ape/lib +o/$(MODE)/ape: $(APE) $(APE_CHECKS) diff --git a/ape/config.h b/ape/config.h deleted file mode 100644 index 440a65285..000000000 --- a/ape/config.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef APE_CONFIG_H_ -#define APE_CONFIG_H_ -#include "ape/relocations.h" -#include "libc/macros.h" - -/* - * Post-Initialization Read-Only Code Size Threshold. - * - * An executable needs to have at least this much code, before the - * linker adds non-mandatory 4kb alignments. The benefit is better - * memory protection. The tradeoff is sparser binaries. - */ -#ifndef APE_PIRO_THRESHOLD -#ifdef CONFIG_DBG -#define APE_PIRO_THRESHOLD 0x1000 -#else -#define APE_PIRO_THRESHOLD 0x10000 -#endif -#endif - -#ifndef METAL_STDIN -#define METAL_STDIN COM1 -#endif -#ifndef METAL_STDOUT -#define METAL_STDOUT COM1 -#endif -#ifndef METAL_STDERR -#define METAL_STDERR COM1 -#endif - -#ifndef VIDYA_MODE -#define VIDYA_MODE VIDYA_MODE_CGA -#endif - -/* FPU Control Word (x87) Exception Masks - @see Intel Manual V1 §8.1.5 - - IM: Invalid Operation ───────────────┐ - DM: Denormal Operand ───────────────┐│ - ZM: Zero Divide ───────────────────┐││ - OM: Overflow ─────────────────────┐│││ - UM: Underflow ───────────────────┐││││ - PM: Precision ──────────────────┐│││││ - PC: Precision Control ────────┐ ││││││ - {float,∅,double,long double} │ ││││││ - RC: Rounding Control ───────┐ │ ││││││ - {even, →-∞, →+∞, →0} │┌┤ ││││││ - ┌┤││ ││││││ - d││││rr││││││*/ -#define X87_NORMAL 0b000000000001101111111 -#define X87_DTOA 0b000000000001000000000 -#define X87_DTOA_MASK 0b000000000001100000000 -#ifndef X87_DEFAULT -#define X87_DEFAULT X87_NORMAL -#endif - -#ifndef UART_BAUD_RATE -#define UART_BAUD_RATE 9600 /* bits per second ∈ [50,115200] */ -#endif -#define UART_CONF_DLR (1843200 /*hz*/ / 16 /*wut*/ / (UART_BAUD_RATE)) -#ifndef UART_CONF_IIR -/* ┌interrupt trigger level {1,4,8,14} - │ ┌enable 64 byte fifo (UART 16750+) - │ │ ┌select dma mode - │ │ │┌clear transmit fifo - │ │ ││┌clear receive fifo - ├┐│ │││┌enable fifos*/ -#define UART_CONF_IIR 0b00000000 -#endif -#ifndef UART_CONF_LCR -/* ┌dlab: flips configuration mode state - │┌enable break signal - ││ ┌parity {none,odd,even,high,low} - ││ │ ┌extra stop bit - ││ │ │┌data word length (bits+5) - ││┌┴┐│├┐*/ -#define UART_CONF_LCR 0b01000011 -#endif - -#define XLM(VAR) (XLM_BASE_REAL + XLM_##VAR) -#define XLMV(VAR) (__xlm + XLM_##VAR) -#define XLM_BASE_REAL 0x1000 -#define XLM_E820 0 -#define XLM_E820_SIZE 0x2000 -#define XLM_BIOS_DATA_AREA 0x2000 -#define XLM_BIOS_DATA_AREA_SIZE 256 -#define XLM_DRIVE_BASE_TABLE 0x2200 /* drive values are contiguous */ -#define XLM_DRIVE_BASE_TABLE_SIZE 11 -#define XLM_DRIVE_TYPE 0x220b -#define XLM_DRIVE_TYPE_SIZE 1 -#define XLM_DRIVE_LAST_SECTOR 0x220c /* 1-based inclusive, e.g. 18 */ -#define XLM_DRIVE_LAST_SECTOR_SIZE 1 -#define XLM_DRIVE_LAST_CYLINDER 0x220d /* 0-based incl, e.g. 79 */ -#define XLM_DRIVE_LAST_CYLINDER_SIZE 2 -#define XLM_DRIVE_ATTACHED 0x220f -#define XLM_DRIVE_ATTACHED_SIZE 1 -#define XLM_DRIVE_LAST_HEAD 0x2210 /* 0-based inclusive, e.g. 1 */ -#define XLM_DRIVE_LAST_HEAD_SIZE 1 -#define XLM_DRIVE 0x2211 -#define XLM_DRIVE_SIZE 1 -#define XLM_HAVEEXTMEMKB 0x2212 -#define XLM_HAVEEXTMEMKB_SIZE 4 -#define XLM_VIDEO_POSITION_FAR_POINTER 0x2216 /* video cursor far pointer */ -#define XLM_VIDEO_POSITION_FAR_POINTER_SIZE 4 -#define XLM_PAGE_TABLE_STACK_POINTER 0x2220 -#define XLM_PAGE_TABLE_STACK_POINTER_SIZE 8 -#define XLM_BADIDT 0x2230 -#define XLM_BADIDT_SIZE 6 -#define XLM_LOADSTATE 0x2240 -#define XLM_LOADSTATE_SIZE 8 -#define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000) -#define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE) - -#if !defined(__LINKER__) && !defined(__ASSEMBLER__) -extern char __xlm[XLM_SIZE]; -#endif /* !defined(__LINKER__) && !defined(__ASSEMBLER__) */ - -#endif /* APE_CONFIG_H_ */ diff --git a/ape/lib/apelib.mk b/ape/lib/apelib.mk deleted file mode 100644 index f7cf68669..000000000 --- a/ape/lib/apelib.mk +++ /dev/null @@ -1,45 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -PKGS += APE_LIB - -APE_LIB_ARTIFACTS += APE_LIB_A -APE_LIB = $(APE_LIB_A_DEPS) $(APE_LIB_A) -APE_LIB_A = o/$(MODE)/ape/lib/apelib.a -APE_LIB_A_FILES := $(wildcard ape/lib/*) -APE_LIB_A_HDRS = $(filter %.h,$(APE_LIB_A_FILES)) -APE_LIB_A_SRCS_S = $(filter %.S,$(APE_LIB_A_FILES)) -APE_LIB_A_SRCS_C = $(filter %.c,$(APE_LIB_A_FILES)) - -APE_LIB_A_SRCS = \ - $(APE_LIB_A_SRCS_S) \ - $(APE_LIB_A_SRCS_C) - -APE_LIB_A_OBJS = \ - $(APE_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \ - $(APE_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o) - -APE_LIB_A_DIRECTDEPS = \ - LIBC_NEXGEN32E \ - LIBC_INTRIN \ - LIBC_STR \ - LIBC_STUBS - -APE_LIB_A_CHECKS = $(APE_LIB_A_HDRS:%=o/$(MODE)/%.ok) -APE_LIB_A_DEPS = $(call uniq,$(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x)))) - -$(APE_LIB_A): ape/lib/ $(APE_LIB_A).pkg $(APE_LIB_A_OBJS) -$(APE_LIB_A).pkg: $(APE_LIB_A_OBJS) $(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x)_A).pkg) - -APE_LIB_LIBS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x))) -APE_LIB_SRCS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_SRCS)) -APE_LIB_HDRS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_HDRS)) -APE_LIB_BINS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_BINS)) -APE_LIB_CHECKS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_CHECKS)) -APE_LIB_OBJS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_OBJS)) -$(APE_LIB_OBJS): $(BUILD_FILES) libc/str/str.mk - -.PHONY: o/$(MODE)/ape/lib -o/$(MODE)/ape/lib: \ - $(APE_LIB_CHECKS) \ - $(APE_LIB_A) diff --git a/ape/lib/bootdr.S b/ape/lib/bootdr.S deleted file mode 100644 index 735105f91..000000000 --- a/ape/lib/bootdr.S +++ /dev/null @@ -1,35 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 sw=8 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 "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - -// Resets personal computer. -// -// @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80 -// @mode real -// @noreturn -bootdr: push %bp - mov %sp,%bp - mov %di,%dx - int $0x19 - ljmp $0xf000,$0xfff0 - .endfn bootdr,globl diff --git a/ape/lib/e820map.S b/ape/lib/e820map.S deleted file mode 100644 index 3a9a71ea0..000000000 --- a/ape/lib/e820map.S +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- 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 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 "ape/lib/pc.h" -#include "ape/config.h" -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - - .globl e820map - .hidden e820map - .type e820map,@object - .size e820map,XLM_E820_SIZE - e820map = ape_xlm + XLM_E820 - - .globl e820map_xlm - .hidden e820map_xlm - .type e820map_xlm,@object - .size e820map_xlm,XLM_E820_SIZE - e820map_xlm = XLM(E820) diff --git a/ape/lib/flattenhighmemory.c b/ape/lib/flattenhighmemory.c deleted file mode 100644 index 08cec8374..000000000 --- a/ape/lib/flattenhighmemory.c +++ /dev/null @@ -1,55 +0,0 @@ -/*-*- 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 "ape/config.h" -#include "ape/lib/pc.h" -#include "libc/bits/bits.h" -#include "libc/macros.h" - -/** - * Virtualizes physical memory. - * - * This function removes memory holes (discovered by e820() earlier) and - * creates the illusion of flat contiguous memory for as much RAM as the - * BIOS reports usable. Memory is safe to use and remap afterwards. - * - * @see ape/ape.S - */ -textreal void flattenhighmemory(struct SmapEntry *e820, struct PageTable *pml4t, - uint64_t *ptsp) { - uint64_t *entry, paddr, vaddr; - struct SmapEntry *smap, *hole; - for (smap = hole = e820, vaddr = IMAGE_BASE_VIRTUAL; smap->size; ++smap) { - while (smap->size && smap->type != kMemoryUsable) smap++; - paddr = ROUNDUP(MAX(IMAGE_BASE_PHYSICAL, smap->addr), PAGESIZE); - while (paddr < ROUNDDOWN(smap->addr + smap->size, PAGESIZE)) { - while (hole->size && - (hole->type == kMemoryUsable || hole->addr + hole->size < paddr)) { - hole++; - } - if (paddr >= hole->addr && paddr < hole->addr + hole->size) { - paddr = ROUNDUP(hole->addr + hole->size, PAGESIZE); - } else { - entry = __getpagetableentry(vaddr, 3, pml4t, ptsp); - *entry = paddr | PAGE_V | PAGE_RW; - vaddr += 0x1000; - paddr += 0x1000; - } - } - } -} diff --git a/ape/lib/g_pml4t.S b/ape/lib/g_pml4t.S deleted file mode 100644 index 129561894..000000000 --- a/ape/lib/g_pml4t.S +++ /dev/null @@ -1,31 +0,0 @@ -/*-*- 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 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 "ape/lib/pc.h" -#include "ape/config.h" -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - - .globl g_pml4t - .hidden g_pml4t - .type g_pml4t,@object - .size g_pml4t,0x1000 - g_pml4t = REAL_STACK_FRAME - 0x1000 diff --git a/ape/lib/g_ptsp.S b/ape/lib/g_ptsp.S deleted file mode 100644 index 261d2a0b8..000000000 --- a/ape/lib/g_ptsp.S +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- 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 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 "ape/lib/pc.h" -#include "ape/config.h" -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - - .globl g_ptsp - .hidden g_ptsp - .type g_ptsp,@object - .size g_ptsp,XLM_PAGE_TABLE_STACK_POINTER_SIZE - g_ptsp = ape_xlm + XLM_PAGE_TABLE_STACK_POINTER - - .globl g_ptsp_xlm - .hidden g_ptsp_xlm - .type g_ptsp_xlm,@object - .size g_ptsp_xlm,XLM_PAGE_TABLE_STACK_POINTER_SIZE - g_ptsp_xlm = XLM(PAGE_TABLE_STACK_POINTER) diff --git a/ape/lib/getpagetableentry.c b/ape/lib/getpagetableentry.c deleted file mode 100644 index 8e036a46a..000000000 --- a/ape/lib/getpagetableentry.c +++ /dev/null @@ -1,42 +0,0 @@ -/*-*- 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 "ape/lib/pc.h" -#include "libc/assert.h" - -static textreal uint64_t __pushpagetable(uint64_t *ptsp) { - return (*ptsp -= PAGESIZE) | PAGE_V | PAGE_RW; -} - -textreal uint64_t *__getpagetableentry(int64_t vaddr, unsigned depth, - struct PageTable *pml4t, - uint64_t *ptsp) { - uint64_t *entry; - unsigned char shift; - assert(depth <= 3); - assert(!(*ptsp & 0xfff)); - assert(!((uintptr_t)pml4t & 0xfff)); - shift = 39; - for (;;) { - entry = &pml4t->p[(vaddr >> shift) & 511]; - if (!depth--) return entry; - shift -= 9; - if (!*entry) *entry = __pushpagetable(ptsp); - pml4t = (void *)(*entry & PAGE_TA); - } -} diff --git a/ape/lib/kbiosdataarea.S b/ape/lib/kbiosdataarea.S deleted file mode 100644 index 664dba4b0..000000000 --- a/ape/lib/kbiosdataarea.S +++ /dev/null @@ -1,45 +0,0 @@ -/*-*- 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 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 "ape/lib/pc.h" -#include "ape/config.h" -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - - .globl kBiosDataArea - .hidden kBiosDataArea - .type kBiosDataArea,@object - .size kBiosDataArea,XLM_BIOS_DATA_AREA_SIZE - kBiosDataArea = ape_xlm + XLM_BIOS_DATA_AREA - - .globl kBiosDataAreaXlm - .hidden kBiosDataAreaXlm - .type kBiosDataAreaXlm,@object - .size kBiosDataAreaXlm,XLM_BIOS_DATA_AREA_SIZE - kBiosDataAreaXlm = XLM(BIOS_DATA_AREA) - - .section .sort.text.real.init.2.kBiosDataArea,"ax",@progbits - movpp %ds,%es # copy bios data to valid page - mov $PC_BIOS_DATA_AREA,%si - mov $XLM(BIOS_DATA_AREA),%di - mov $XLM_BIOS_DATA_AREA_SIZE,%cx - rep movsb - .previous diff --git a/ape/lib/pageunmap.c b/ape/lib/pageunmap.c deleted file mode 100644 index 9e731b455..000000000 --- a/ape/lib/pageunmap.c +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- 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 "ape/lib/pc.h" - -textreal void pageunmap(int64_t vaddr) { - uint64_t *entry; - entry = __getpagetableentry(vaddr, 3, &g_pml4t, &g_ptsp_xlm); - *entry &= ~PAGE_V; - asm volatile("invlpg\t(%0)" : /* no outputs */ : "r"(vaddr) : "memory"); -} diff --git a/ape/lib/smapsort.c b/ape/lib/smapsort.c deleted file mode 100644 index 24e1981e2..000000000 --- a/ape/lib/smapsort.c +++ /dev/null @@ -1,46 +0,0 @@ -/*-*- 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 "ape/lib/pc.h" - -textreal static unsigned smapcount(const struct SmapEntry *se) { - unsigned i = 0; - while (se[i].size) ++i; - return i; -} - -textreal static void smapsorter(size_t n, struct SmapEntry a[n]) { - struct SmapEntry t; - unsigned i, j; - for (i = 1; i < n; ++i) { - j = i; - t = a[i]; - while (j > 0 && (intptr_t)t.addr - (intptr_t)a[j - 1].addr) { - a[j] = a[j - 1]; - --j; - } - a[j] = t; - } -} - -/** - * Sorts BIOS e820 memory map. - */ -textreal void smapsort(struct SmapEntry *smap) { - smapsorter(smapcount(smap), smap); -} diff --git a/ape/macros.internal.h b/ape/macros.internal.h index 4537da0ae..578f7a885 100644 --- a/ape/macros.internal.h +++ b/ape/macros.internal.h @@ -26,13 +26,6 @@ * @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε. */ -// Calls function in real mode. -// It's needed because LLVM 8 LLD doesn't support R_X86_64_PC16. - .macro call16 name:req - mov $REAL(\name),%ax - call *%ax - .endm - // Calls near (i.e. pc+pcrel<64kB) FUNCTION. // @mode long,legacy,real // @cost 9 bytes overhead diff --git a/ape/relocations.h b/ape/relocations.h index 1500d2b64..38895bbf4 100644 --- a/ape/relocations.h +++ b/ape/relocations.h @@ -11,6 +11,8 @@ In some cases it's necessary to use addend macros that change virtual addresses into the other two types: physical and real. */ +#define IMAGE_BASE_REAL 0x2000 + #ifndef IMAGE_BASE_VIRTUAL #define IMAGE_BASE_VIRTUAL 0x400000 #endif @@ -19,26 +21,6 @@ #define IMAGE_BASE_PHYSICAL 0x100000 #endif -#ifndef REAL_SCRATCH_AREA -/** - * Location of anything goes memory for real mode. - * - * The MBR won't load program content beyond this address, so we have - * room for buffers, page tables, etc. before we reach the stack frame. - */ -#define REAL_SCRATCH_AREA 0x40000 -#endif - -#ifndef REAL_STACK_FRAME -/** - * Location of real mode 64kb stack frame. - * - * This address was chosen because memory beyond 0x80000 can't be - * accessed safely without consulting e820. - */ -#define REAL_STACK_FRAME 0x70000 -#endif - /** * Returns Relative Virtual Address. */ diff --git a/build/bootstrap/compile.com b/build/bootstrap/compile.com index 44d4fb7d1a7ca7ef07dfadc725341a5442aa1a90..d8d154d69d5887f33755027799bd57049b2d4beb 100755 GIT binary patch delta 19416 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 delta 18604 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 diff --git a/build/definitions.mk b/build/definitions.mk index 2c5549448..2e3d49ac2 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -166,7 +166,8 @@ DEFAULT_LDFLAGS = \ --gc-sections \ --build-id=none \ --no-dynamic-linker \ - -z max-page-size=0x1000 + -z max-page-size=0x1000 \ + --cref -Map=$@.map ZIPOBJ_FLAGS = \ -b$(IMAGE_BASE_VIRTUAL) diff --git a/examples/e820.c b/examples/e820.c new file mode 100644 index 000000000..28d9919cc --- /dev/null +++ b/examples/e820.c @@ -0,0 +1,44 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/fmt/itoa.h" +#include "libc/macros.h" +#include "libc/runtime/e820.internal.h" +#include "libc/runtime/pc.internal.h" +#include "libc/stdio/stdio.h" + +const char *DescribeMemoryType(int type) { + switch (type) { + case kMemoryUsable: + return "kMemoryUsable"; + case kMemoryUnusable: + return "kMemoryUnusable"; + case kMemoryAcpiReclaimable: + return "kMemoryAcpiReclaimable"; + case kMemoryAcpiNvs: + return "kMemoryAcpiNvs"; + case kMemoryBad: + return "kMemoryBad"; + default: + return "UNKNOWN"; + } +} + +int main(int argc, char *argv[]) { + int i; + const char *ts; + struct mman *mm; + mm = (struct mman *)(BANE + 0x0500); + for (i = 0; i < mm->e820n; ++i) { + printf("%p-%p %s\n", mm->e820[i].addr, mm->e820[i].size, + DescribeMemoryType(mm->e820[i].type)); + } + for (;;) asm("pause"); + return 0; +} diff --git a/examples/examples.mk b/examples/examples.mk index c011a62aa..61a20e695 100644 --- a/examples/examples.mk +++ b/examples/examples.mk @@ -33,7 +33,6 @@ EXAMPLES_BINS = \ $(EXAMPLES_COMS:%=%.dbg) EXAMPLES_DIRECTDEPS = \ - APE_LIB \ DSP_CORE \ DSP_SCALE \ DSP_TTY \ diff --git a/examples/malloc.c b/examples/malloc.c new file mode 100644 index 000000000..60e8f65fa --- /dev/null +++ b/examples/malloc.c @@ -0,0 +1,19 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/mem/mem.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" + +int main(int argc, char *argv[]) { + char *s = malloc(1024 * 1024 * 2 + argc); + strcpy(s, "hello"); + puts(s); + return 0; +} diff --git a/libc/calls/efi.h b/libc/calls/efi.h deleted file mode 100644 index 6131f3957..000000000 --- a/libc/calls/efi.h +++ /dev/null @@ -1,12 +0,0 @@ -#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_ */ diff --git a/libc/calls/fstat.c b/libc/calls/fstat.c index 4c2daa7c7..b6c20fceb 100644 --- a/libc/calls/fstat.c +++ b/libc/calls/fstat.c @@ -31,9 +31,9 @@ int fstat(int fd, struct stat *st) { if (__isfdkind(fd, kFdZip)) { return weaken(__zipos_fstat)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st); - } else if (!IsWindows() && !IsMetal() && !IsUefi()) { + } else if (!IsWindows() && !IsMetal()) { return sys_fstat(fd, st); - } else if (IsMetal() || IsUefi()) { + } else if (IsMetal()) { return fstat_metal(fd, st); } else { if (!__isfdkind(fd, kFdFile)) return ebadf(); diff --git a/libc/calls/g_fds.c b/libc/calls/g_fds.c index 769ebae34..ab33efb7f 100644 --- a/libc/calls/g_fds.c +++ b/libc/calls/g_fds.c @@ -30,7 +30,7 @@ hidden textstartup void InitializeFileDescriptors(void) { fds = VEIL("r", &g_fds); pushmov(&fds->n, ARRAYLEN(fds->__init_p)); fds->p = fds->__init_p; - if (IsMetal() || IsUefi()) { + if (IsMetal()) { pushmov(&fds->f, 3ull); fds->__init_p[STDIN_FILENO].kind = pushpop(kFdSerial); fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdSerial); diff --git a/libc/calls/internal.h b/libc/calls/internal.h index f2d5deeb7..057120d9f 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -197,7 +197,7 @@ u32 sys_getgid(void) hidden; u32 sys_getsid(int) hidden; u32 sys_gettid(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_exit(int) hidden; @@ -295,12 +295,6 @@ unsigned __wincrash_nt(struct NtExceptionPointers *); int fstat_metal(int, struct stat *); -/*───────────────────────────────────────────────────────────────────────────│─╗ -│ cosmopolitan § syscalls » uefi ─╬─│┼ -╚────────────────────────────────────────────────────────────────────────────│*/ - -int sys_nanosleep_uefi(const struct timespec *, struct timespec *); - /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § syscalls » drivers ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ diff --git a/libc/calls/nanosleep.c b/libc/calls/nanosleep.c index 7276d848c..fda4656f2 100644 --- a/libc/calls/nanosleep.c +++ b/libc/calls/nanosleep.c @@ -29,12 +29,10 @@ int nanosleep(const struct timespec *req, struct timespec *rem) { if (req->tv_sec < 0 || !(0 <= req->tv_nsec && req->tv_nsec <= 999999999)) { return einval(); } - if (!IsWindows() && !IsMetal() && !IsUefi() && !IsXnu()) { + if (!IsWindows() && !IsMetal() && !IsXnu()) { return sys_nanosleep(req, rem); } else if (IsXnu()) { return sys_nanosleep_xnu(req, rem); - } else if (IsUefi()) { - return sys_nanosleep_uefi(req, rem); } else if (IsMetal()) { return enosys(); /* TODO: Sleep on Metal */ } else { diff --git a/libc/calls/readv-serial.c b/libc/calls/readv-serial.c index a09090b4d..46dfa5db5 100644 --- a/libc/calls/readv-serial.c +++ b/libc/calls/readv-serial.c @@ -16,9 +16,9 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" #include "libc/calls/internal.h" #include "libc/nexgen32e/uart.internal.h" +#include "libc/runtime/pc.internal.h" static bool IsDataAvailable(struct Fd *fd) { return inb(fd->handle + UART_LSR) & UART_TTYDA; diff --git a/libc/calls/readv.c b/libc/calls/readv.c index c38fab845..a7e525d34 100644 --- a/libc/calls/readv.c +++ b/libc/calls/readv.c @@ -36,8 +36,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) { if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { return weaken(__zipos_read)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1); - } else if ((SupportsMetal() || SupportsUefi()) && fd < g_fds.n && - g_fds.p[fd].kind == kFdSerial) { + } else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) { return readv_serial(&g_fds.p[fd], iov, iovlen); } else if (!IsWindows()) { return sys_readv(fd, iov, iovlen); diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index 4810c7331..fbdda5854 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -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_openbsd) && sizeof(struct sigaction) > sizeof(struct sigaction_netbsd)); - if (IsMetal() || IsUefi()) return enosys(); /* TODO: Signals on Metal */ + if (IsMetal()) return enosys(); /* TODO: Signals on Metal */ if (!(0 < sig && sig < NSIG)) return einval(); if (sig == SIGKILL || sig == SIGSTOP) return einval(); if (!act) { diff --git a/libc/calls/writev-serial.c b/libc/calls/writev-serial.c index 634a12075..3afba48b5 100644 --- a/libc/calls/writev-serial.c +++ b/libc/calls/writev-serial.c @@ -16,9 +16,9 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" #include "libc/calls/internal.h" #include "libc/nexgen32e/uart.internal.h" +#include "libc/runtime/pc.internal.h" ssize_t writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) { size_t i, j, wrote = 0; diff --git a/libc/calls/writev.c b/libc/calls/writev.c index 3b4544fdd..b882f5350 100644 --- a/libc/calls/writev.c +++ b/libc/calls/writev.c @@ -39,8 +39,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) { if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { return weaken(__zipos_write)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1); - } else if ((SupportsMetal() || SupportsUefi()) && fd < g_fds.n && - g_fds.p[fd].kind == kFdSerial) { + } else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) { return writev_serial(&g_fds.p[fd], iov, iovlen); } else if (!IsWindows()) { return sys_writev(fd, iov, iovlen); diff --git a/libc/crt/crt.S b/libc/crt/crt.S index 525b0447e..dc5dc3fbd 100644 --- a/libc/crt/crt.S +++ b/libc/crt/crt.S @@ -21,7 +21,6 @@ #include "libc/notice.inc" #include "libc/runtime/internal.h" .section .start,"ax",@progbits -.align 16 // System Five userspace program entrypoint. // @@ -37,7 +36,7 @@ _start: #endif 0: mov (%rsp),%ebx # argc lea 8(%rsp),%rsi # argv - lea 24(%rsp,%rbx,8),%rdx # envp + lea 16(%rsp,%rbx,8),%rdx # envp .frame0 // bofram 9f .weak ape_idata_iat diff --git a/libc/dce.h b/libc/dce.h index ba6c25fab..e100c4da0 100644 --- a/libc/dce.h +++ b/libc/dce.h @@ -20,7 +20,6 @@ #define OPENBSD 16 #define FREEBSD 32 #define NETBSD 64 -#define UEFI 128 #ifdef NDEBUG #define NoDebug() 1 @@ -73,7 +72,6 @@ #define SupportsLinux() ((SUPPORT_VECTOR & LINUX) == LINUX) #define SupportsMetal() ((SUPPORT_VECTOR & METAL) == METAL) #define SupportsWindows() ((SUPPORT_VECTOR & WINDOWS) == WINDOWS) -#define SupportsUefi() ((SUPPORT_VECTOR & UEFI) == UEFI) #define SupportsXnu() ((SUPPORT_VECTOR & XNU) == XNU) #define SupportsFreebsd() ((SUPPORT_VECTOR & FREEBSD) == FREEBSD) #define SupportsOpenbsd() ((SUPPORT_VECTOR & OPENBSD) == OPENBSD) @@ -86,7 +84,6 @@ #define IsLinux() (SupportsLinux() && (__hostos & LINUX)) #define IsMetal() (SupportsMetal() && (__hostos & METAL)) #define IsWindows() (SupportsWindows() && (__hostos & WINDOWS)) -#define IsUefi() (SupportsUefi() && (__hostos & UEFI)) #define IsXnu() (SupportsXnu() && (__hostos & XNU)) #define IsFreebsd() (SupportsFreebsd() && (__hostos & FREEBSD)) #define IsOpenbsd() (SupportsOpenbsd() && (__hostos & OPENBSD)) @@ -97,7 +94,6 @@ #define IsLinux() $LINUX,__hostos(%rip) #define IsMetal() $METAL,__hostos(%rip) #define IsWindows() $WINDOWS,__hostos(%rip) -#define IsUefi() $UEFI,__hostos(%rip) #define IsBsd() $XNU|FREEBSD|OPENBSD|NETBSD,__hostos(%rip) #define IsXnu() $XNU,__hostos(%rip) #define IsFreebsd() $FREEBSD,__hostos(%rip) diff --git a/libc/integral/c.inc b/libc/integral/c.inc index 7175a3b16..3d4872e8c 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -603,6 +603,7 @@ typedef uint64_t uintmax_t; #define textstartup _Section(".text.startup") noinstrument #define textexit _Section(".text.exit") noinstrument #define textreal _Section(".text.real") +#define texthead _Section(".text.head") #define textwindows _Section(".text.windows") #define antiquity _Section(".text.antiquity") #else @@ -610,6 +611,7 @@ typedef uint64_t uintmax_t; #define textstartup #define textexit #define textreal +#define texthead #define textwindows #define antiquity #endif diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index 48c539ee9..441634f82 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -28,7 +28,7 @@ #include "libc/mem/hook/hook.internal.h" #include "libc/nt/enum/version.h" #include "libc/nt/runtime.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" #include "libc/sysv/consts/auxv.h" @@ -744,7 +744,7 @@ void __asan_map_shadow(uintptr_t p, size_t n) { b = ROUNDUP((uintptr_t)SHADOW(ROUNDUP((uintptr_t)p + n, 8)), 1 << 16) >> 16; for (; a < b; ++a) { if (!__asan_is_mapped(a)) { - sm = weaken(__mmap)( + sm = weaken(sys_mmap)( (void *)((uintptr_t)a << 16), 1 << 16, PROT_READ | PROT_WRITE, MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, -1, 0); if (sm.addr == MAP_FAILED || @@ -796,7 +796,7 @@ static textstartup void __asan_shadow_existing_mappings(void) { } static textstartup bool IsMemoryManagementRuntimeLinked(void) { - return weaken(_mmi) && weaken(__mmap) && weaken(MAP_ANONYMOUS) && + return weaken(_mmi) && weaken(sys_mmap) && weaken(MAP_ANONYMOUS) && weaken(FindMemoryInterval) && weaken(TrackMemoryInterval); } @@ -809,7 +809,7 @@ textstartup void __asan_init(int argc, char **argv, char **envp, __asan_exit(0); /* So `make MODE=dbg test` passes w/ Windows7 */ } REQUIRE(_mmi); - REQUIRE(__mmap); + REQUIRE(sys_mmap); REQUIRE(MAP_ANONYMOUS); REQUIRE(FindMemoryInterval); REQUIRE(TrackMemoryInterval); diff --git a/libc/macros.internal.inc b/libc/macros.internal.inc index 6db866e8d..aa4670a2c 100644 --- a/libc/macros.internal.inc +++ b/libc/macros.internal.inc @@ -27,6 +27,9 @@ .macro .real .section .text.real,"ax",@progbits .endm +.macro .head + .section .text.head,"ax",@progbits +.endm .macro .text.startup .section .text.startup,"ax",@progbits .endm diff --git a/libc/nexgen32e/kcpuids.S b/libc/nexgen32e/kcpuids.S index d3f71dd20..e6da54be8 100644 --- a/libc/nexgen32e/kcpuids.S +++ b/libc/nexgen32e/kcpuids.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/dce.h" #include "libc/macros.h" #include "libc/nexgen32e/kcpuids.h" diff --git a/libc/nexgen32e/triplf.S b/libc/nexgen32e/triplf.S index e530ba409..52219de06 100644 --- a/libc/nexgen32e/triplf.S +++ b/libc/nexgen32e/triplf.S @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "ape/macros.internal.h" -#include "ape/config.h" .real .source __FILE__ .code16 # ∩ .code32 ∩ .code64 @@ -26,7 +25,8 @@ // // @see youtu.be/GIKfEAF2Yhw?t=67 // @mode long,legacy,real -triplf: push %bp +triplf: ud2 + push %bp mov %sp,%bp sub $8,%sp movpp %bp,%si diff --git a/libc/nexgen32e/xlm.S b/libc/nexgen32e/xlm.S deleted file mode 100644 index 73d6819ab..000000000 --- a/libc/nexgen32e/xlm.S +++ /dev/null @@ -1,32 +0,0 @@ -/*-*- 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 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 "libc/macros.h" -#include "libc/notice.inc" -#include "ape/config.h" - -// eXtreme Low Memory. -// @see ape/config.h - .section .xlm,"aw",@nobits - .align 4096 -__xlm: .rept XLM_SIZE - .byte 0 - .endr - .endobj __xlm,globl,hidden - .previous - .source __FILE__ diff --git a/libc/nt/efi.h b/libc/nt/efi.h index c04b70c13..89b1c240e 100644 --- a/libc/nt/efi.h +++ b/libc/nt/efi.h @@ -258,6 +258,9 @@ typedef EFI_STATUS(EFIAPI *EFI_GET_MEMORY_MAP)( typedef EFI_STATUS(EFIAPI *EFI_ALLOCATE_POOL)(EFI_MEMORY_TYPE PoolType, uintptr_t Size, void *out_Buffer); typedef EFI_STATUS(EFIAPI *EFI_FREE_POOL)(void *Buffer); +typedef void(EFIAPI *EFI_SET_MEM)(void *Buffer, uintptr_t Size, uint8_t Value); +typedef void(EFIAPI *EFI_COPY_MEM)(void *Destination, void *Source, + uintptr_t Length); typedef EFI_STATUS(EFIAPI *EFI_CHECK_EVENT)(EFI_EVENT Event); typedef EFI_STATUS(EFIAPI *EFI_CLOSE_EVENT)(EFI_EVENT Event); @@ -346,6 +349,8 @@ typedef EFI_STATUS(EFIAPI *EFI_IMAGE_LOAD)(bool BootPolicy, uintptr_t SourceSize, EFI_HANDLE *out_ImageHandle); typedef EFI_STATUS(EFIAPI *EFI_IMAGE_UNLOAD)(EFI_HANDLE ImageHandle); +typedef EFI_STATUS(EFIAPI *EFI_EXIT_BOOT_SERVICES)(EFI_HANDLE ImageHandle, + uintptr_t MapKey); typedef struct { EFI_TABLE_HEADER Hdr; @@ -393,7 +398,7 @@ typedef struct { void *StartImage; EFI_EXIT Exit; EFI_IMAGE_UNLOAD UnloadImage; - void *ExitBootServices; + EFI_EXIT_BOOT_SERVICES ExitBootServices; EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; EFI_STALL Stall; EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; @@ -408,8 +413,8 @@ typedef struct { void *InstallMultipleProtocolInterfaces; void *UninstallMultipleProtocolInterfaces; void *CalculateCrc32; - void *CopyMem; - void *SetMem; + EFI_COPY_MEM CopyMem; + EFI_SET_MEM SetMem; EFI_CREATE_EVENT_EX CreateEventEx; } EFI_BOOT_SERVICES; diff --git a/libc/runtime/arch_prctl.c b/libc/runtime/arch_prctl.c index 4dfa5bbb5..2dbd6ffa0 100644 --- a/libc/runtime/arch_prctl.c +++ b/libc/runtime/arch_prctl.c @@ -16,13 +16,13 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" #include "libc/bits/bits.h" #include "libc/calls/calls.h" #include "libc/dce.h" #include "libc/nexgen32e/msr.h" #include "libc/nexgen32e/x86feature.h" #include "libc/runtime/interruptiblecall.h" +#include "libc/runtime/pc.internal.h" #include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" diff --git a/libc/calls/nanosleep-uefi.c b/libc/runtime/directmap-metal.c similarity index 60% rename from libc/calls/nanosleep-uefi.c rename to libc/runtime/directmap-metal.c index 94b84164f..1d751ad30 100644 --- a/libc/calls/nanosleep-uefi.c +++ b/libc/runtime/directmap-metal.c @@ -17,19 +17,48 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/efi.h" -#include "libc/nt/efi.h" +#include "libc/macros.h" +#include "libc/runtime/directmap.internal.h" +#include "libc/runtime/pc.internal.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/prot.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; +static uint64_t sys_mmap_metal_break; + +noasan struct DirectMap sys_mmap_metal(void *paddr, size_t size, int prot, + int flags, int fd, int64_t off) { + size_t i; + struct mman *mm; + struct DirectMap res; + uint64_t addr, page, *pte, *pml4t; + mm = (struct mman *)(BANE + 0x0500); + pml4t = __get_pml4t(); + size = ROUNDUP(size, 4096); + addr = (uint64_t)paddr; + if (!(flags & MAP_FIXED)) { + for (i = 0; i < size; i += 4096) { + pte = __get_virtual(mm, pml4t, addr, false); + if (pte && (*pte & PAGE_V)) { + addr = MAX(addr, sys_mmap_metal_break) + i + 4096; + i = 0; + } } - return 0; - } else { - return eintr(); + sys_mmap_metal_break = MAX(addr + size, sys_mmap_metal_break); } + for (i = 0; i < size; i += 4096) { + page = __new_page(mm); + pte = __get_virtual(mm, pml4t, addr + i, true); + if (pte && page) { + __clear_page(BANE + page); + *pte = page | ((prot & PROT_WRITE) ? PAGE_RW : 0) | PAGE_U | PAGE_V; + } else { + addr = -1; + break; + } + } + res.addr = (void *)addr; + res.maphandle = -1; + return res; } diff --git a/libc/runtime/directmapnt.c b/libc/runtime/directmap-nt.c similarity index 98% rename from libc/runtime/directmapnt.c rename to libc/runtime/directmap-nt.c index e47e40b27..464fdf537 100644 --- a/libc/runtime/directmapnt.c +++ b/libc/runtime/directmap-nt.c @@ -24,7 +24,7 @@ #include "libc/nt/memory.h" #include "libc/nt/runtime.h" #include "libc/nt/struct/overlapped.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/prot.h" diff --git a/libc/runtime/directmap.c b/libc/runtime/directmap.c index bc521e05a..b6ef53172 100644 --- a/libc/runtime/directmap.c +++ b/libc/runtime/directmap.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" #include "libc/nt/runtime.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" /** * Obtains memory mapping directly from system. @@ -28,11 +28,13 @@ * bypassed by calling this function. However the caller is responsible * for passing the magic memory handle on Windows NT to CloseHandle(). */ -noasan struct DirectMap __mmap(void *addr, size_t size, int prot, int flags, - int fd, int64_t off) { - if (!IsWindows()) { - return (struct DirectMap){sys_mmap(addr, size, prot, flags, fd, off, off), +noasan struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, + int fd, int64_t off) { + if (!IsWindows() && !IsMetal()) { + return (struct DirectMap){__sys_mmap(addr, size, prot, flags, fd, off, off), kNtInvalidHandleValue}; + } else if (IsMetal()) { + return sys_mmap_metal(addr, size, prot, flags, fd, off); } else { return sys_mmap_nt(addr, size, prot, flags, fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue, diff --git a/libc/runtime/directmap.h b/libc/runtime/directmap.internal.h similarity index 69% rename from libc/runtime/directmap.h rename to libc/runtime/directmap.internal.h index 80b9adebc..6bafebc93 100644 --- a/libc/runtime/directmap.h +++ b/libc/runtime/directmap.internal.h @@ -8,8 +8,10 @@ struct DirectMap { int64_t maphandle; }; -struct DirectMap __mmap(void *, size_t, int, int, int, int64_t); +struct DirectMap sys_mmap(void *, size_t, int, int, int, int64_t); struct DirectMap sys_mmap_nt(void *, size_t, int, int, int64_t, int64_t); +struct DirectMap sys_mmap_metal(void *, size_t, int, int, int, int64_t); +int sys_munmap_metal(void *, size_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/runtime/e820.internal.h b/libc/runtime/e820.internal.h new file mode 100644 index 000000000..7653869cd --- /dev/null +++ b/libc/runtime/e820.internal.h @@ -0,0 +1,21 @@ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_E820_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_E820_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +struct SmapEntry { + uint64_t addr; + uint64_t size; + enum { + kMemoryUsable = 1, + kMemoryUnusable = 2, + kMemoryAcpiReclaimable = 3, + kMemoryAcpiNvs = 4, + kMemoryBad = 5 + } type; + uint32_t acpi3; +}; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_E820_H_ */ diff --git a/libc/runtime/efimain.greg.c b/libc/runtime/efimain.greg.c index 72e61f931..170ade5dd 100644 --- a/libc/runtime/efimain.greg.c +++ b/libc/runtime/efimain.greg.c @@ -16,17 +16,23 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/efi.h" +#include "libc/bits/bits.h" #include "libc/dce.h" #include "libc/macros.h" #include "libc/nt/efi.h" #include "libc/nt/thunk/msabi.h" +#include "libc/runtime/e820.internal.h" #include "libc/runtime/internal.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" +#include "libc/str/str.h" + +/* TOOD: Why can't we change CR3? Could it really need PML5T? */ +/* TOOD: Why does QEMU in UEFI mode take ten seconds to boot? */ struct EfiArgs { - char *args[4096]; - char argblock[ARG_MAX]; + char *Args[0x400 / sizeof(char *)]; + char ArgBlock[0xC00]; }; static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; @@ -36,15 +42,14 @@ static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; * * 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: + * So if you want to trade away Windows so that you can use + * UEFI instead of the normal BIOS boot process, do this: * - * make -j8 CPPFLAGS=-DSUPPORT_VECTOR=251 + * STATIC_YOINK("EfiMain"); + * int main() { ... } * - * 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: + * You can use QEMU to test this, but please note that UEFI + * goes thousands of times slower than the normal BIOS boot * * qemu-system-x86_64 \ * -bios OVMF.fd \ @@ -54,41 +59,129 @@ static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; * 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) { - intptr_t argc; - struct EfiArgs *ea; - EFI_LOADED_IMAGE *img; - extern char os asm("__hostos"); - os = UEFI; - __efi_image_handle = ImageHandle; - __efi_system_table = SystemTable; - SystemTable->BootServices->AllocatePool(EfiConventionalMemory, sizeof(*ea), - &ea); + bool ispml5t; + int type, x87cw; + struct mman *mm; + uint32_t DescVersion; + uintptr_t i, j, MapSize; + struct EfiArgs *ArgBlock; + EFI_LOADED_IMAGE *ImgInfo; + EFI_MEMORY_DESCRIPTOR *Map; + uintptr_t Args, MapKey, DescSize; + uint64_t p, pe, cr4, *m, *pd, *sp, *pml4t, *pdt1, *pdt2, *pdpt1, *pdpt2; + extern char __os asm("__hostos"); + + __os = METAL; + + /* + * Allocates and clears PC-compatible memory and copies image. + */ + SystemTable->BootServices->AllocatePages( + EfiConventionalMemory, AllocateAddress, + MAX(2 * 1024 * 1024, 1024 * 1024 + (_end - _base)) / 4096, 0); + SystemTable->BootServices->SetMem(0, 0x80000, 0); + SystemTable->BootServices->CopyMem((void *)(1024 * 1024), _base, + _end - _base); + + /* + * Converts UEFI shell arguments to argv. + */ + ArgBlock = (struct EfiArgs *)0x7e000; SystemTable->BootServices->HandleProtocol(ImageHandle, - &kEfiLoadedImageProtocol, &img); - argc = GetDosArgv(img->LoadOptions, ea->argblock, ARG_MAX, ea->args, - ARRAYLEN(ea->args)); - asm("push\t$0\n\t" /* auxv[0][1] */ - "push\t$0\n\t" /* auxv[0][0] */ - "push\t$0\n\t" /* envp[0] */ - "sub\t%2,%%rsp\n\t" - "mov\t%%rsp,%%rdi\n\t" - "rep movsb\n\t" /* argv */ - "push\t%0\n\t" /* argc */ - "xor\t%%edi,%%edi\n\t" - ".weak\t_start\n\t" - "jmp\t_start" - : /* no outputs */ - : "a"(argc), "S"(ea->args), "c"((argc + 1) * 8)); + &kEfiLoadedImageProtocol, &ImgInfo); + Args = GetDosArgv(ImgInfo->LoadOptions, ArgBlock->ArgBlock, + sizeof(ArgBlock->ArgBlock), ArgBlock->Args, + ARRAYLEN(ArgBlock->Args)); + + /* + * Asks UEFI which parts of our RAM we're allowed to use. + */ + Map = NULL; + MapSize = 0; + SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize, + &DescVersion); + SystemTable->BootServices->AllocatePool(EfiLoaderData, MapSize, Map); + SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize, + &DescVersion); + asm("xor\t%0,%0" : "=r"(mm)); /* gcc assumes null isn't mapped */ + for (j = i = 0; i < MapSize / sizeof(EFI_MEMORY_DESCRIPTOR); ++i) { + if (Map[i].Type != EfiConventionalMemory) continue; + mm->e820[j].addr = Map[i].PhysicalStart; + mm->e820[j].size = Map[i].NumberOfPages * 4096; + mm->e820[j].type = kMemoryUsable; + ++j; + } + SystemTable->BootServices->FreePool(Map); + + /* + * Sets up page tables. + */ + pd = (uint64_t *)0x79000; + pdt1 = (uint64_t *)0x7b000; + pdt2 = (uint64_t *)0x7a000; + pdpt1 = (uint64_t *)0x7d000; + pdpt2 = (uint64_t *)0x7c000; + pml4t = (uint64_t *)0x7e000; + for (i = 0; i < 512; ++i) { + pd[i] = 0x1000 * i + PAGE_V + PAGE_RW; + } + pdt1[0] = (intptr_t)pd + PAGE_V + PAGE_RW; + pdt2[0] = (intptr_t)pd + PAGE_V + PAGE_RW; + pdpt1[0] = (intptr_t)pdt1 + PAGE_V + PAGE_RW; + pdpt2[0] = (intptr_t)pdt2 + PAGE_V + PAGE_RW; + pml4t[0] = (intptr_t)pdpt1 + PAGE_V + PAGE_RW; + pml4t[256] = (intptr_t)pdpt2 + PAGE_V + PAGE_RW; + __map_phdrs(mm, pml4t, 1024 * 1024); + + /* + * Asks UEFI to handover control? + */ + SystemTable->BootServices->ExitBootServices(ImageHandle, MapKey); + + /* + * Launches program. + */ + asm volatile("fldcw\t%3\n\t" + "mov\t%4,%%cr3\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" + "xor\t%%ecx,%%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" + "jmp\t_start" + : /* no outputs */ + : "a"(Args), "S"(ArgBlock->Args), "c"((Args + 1) * 8), + "m"(x87cw), "r"(pml4t) + : "memory"); + unreachable; } diff --git a/libc/runtime/exit.c b/libc/runtime/exit.c index 6cfa3cdd9..673a23705 100644 --- a/libc/runtime/exit.c +++ b/libc/runtime/exit.c @@ -20,8 +20,8 @@ #include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" -extern const uintptr_t __fini_array_start[]; -extern const uintptr_t __fini_array_end[]; +extern const uintptr_t __fini_array_start[] __attribute__((__weak__)); +extern const uintptr_t __fini_array_end[] __attribute__((__weak__)); /** * Exits process with grace. @@ -39,7 +39,7 @@ wontreturn void exit(int exitcode) { if (weaken(__cxa_finalize)) { weaken(__cxa_finalize)(NULL); } - for (p = *weaken(__fini_array_end); p > *weaken(__fini_array_start);) { + for (p = __fini_array_end; p > __fini_array_start;) { ((void (*)(void))(*--p))(); } _Exit(exitcode); diff --git a/libc/runtime/exit2.c b/libc/runtime/exit2.c index fd5464756..438fc680f 100644 --- a/libc/runtime/exit2.c +++ b/libc/runtime/exit2.c @@ -21,11 +21,14 @@ /** * Terminates process, ignoring destructors and atexit() handlers. * - * @param rc is exit code ∈ [0,256) + * When running on bare metal, this function will reboot your computer + * by hosing the interrupt descriptors and triple faulting the system. + * + * @param exitcode is masked with 255 * @asyncsignalsafe * @vforksafe * @noreturn */ -wontreturn void _exit(int rc) { - _Exit(rc); +wontreturn void _exit(int exitcode) { + _Exit(exitcode); } diff --git a/libc/runtime/exit3.c b/libc/runtime/exit3.c index d950c8bf2..657a63503 100644 --- a/libc/runtime/exit3.c +++ b/libc/runtime/exit3.c @@ -16,29 +16,36 @@ │ 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" +#include "libc/nt/thunk/msabi.h" +#include "libc/sysv/consts/nr.h" /** * Terminates process, ignoring destructors and atexit() handlers. * - * @param rc is exit code ∈ [0,256) + * When running on bare metal, this function will reboot your computer + * by hosing the interrupt descriptors and triple faulting the system. + * + * @param exitcode is masked with 255 * @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); +privileged wontreturn void _Exit(int exitcode) { + if ((!IsWindows() && !IsMetal()) || (IsMetal() && IsGenuineCosmo())) { + asm volatile("syscall" + : /* no outputs */ + : "a"(__NR_exit_group), "D"(exitcode) + : "memory"); } else if (IsWindows()) { - ExitProcess(rc & 0xff); + extern void(__msabi * __imp_ExitProcess)(uint32_t); + __imp_ExitProcess(exitcode & 0xff); } - triplf(); + asm("push\t$0\n\t" + "cli\n\t" + "lidt\t(%rsp)"); + for (;;) asm("ud2"); } diff --git a/libc/runtime/fork-nt.c b/libc/runtime/fork-nt.c index caefa4ab2..88b836974 100644 --- a/libc/runtime/fork-nt.c +++ b/libc/runtime/fork-nt.c @@ -36,7 +36,7 @@ #include "libc/nt/signals.h" #include "libc/nt/synchronization.h" #include "libc/nt/thread.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" diff --git a/ape/lib/mapimage.c b/libc/runtime/metalprintf.greg.c similarity index 53% rename from ape/lib/mapimage.c rename to libc/runtime/metalprintf.greg.c index 7eea964a7..93781a6c4 100644 --- a/ape/lib/mapimage.c +++ b/libc/runtime/metalprintf.greg.c @@ -1,7 +1,7 @@ /*-*- 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 │ +│ 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 │ @@ -16,21 +16,65 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "ape/relocations.h" +#include "libc/nexgen32e/uart.internal.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" -textreal static void __map_segment(uint64_t k, uint64_t a, uint64_t b) { - uint64_t *e; - for (; a < b; a += 0x1000) { - e = __getpagetableentry(IMAGE_BASE_VIRTUAL + a, 3, &g_pml4t, &g_ptsp_xlm); - *e = (IMAGE_BASE_REAL + a) | k; +#define PUTC(C) \ + do { \ + while (!(inb(0x3F8 + UART_LSR) & UART_TTYTXR)) { \ + asm("pause"); \ + } \ + outb(0x3F8, C); \ + } while (0) + +/** + * Prints string to serial port. + * + * This only supports %d and %s. It'll will work even if .rodata hasn't + * been loaded into memory yet. + */ +hidden textreal void(MetalPrintf)(const char *fmt, ...) { + int i; + char c; + unsigned u; + va_list va; + const char *s; + unsigned long d; + va_start(va, fmt); + for (;;) { + switch ((c = *fmt++)) { + case '\0': + va_end(va); + return; + case '%': + switch ((c = *fmt++)) { + case 's': + for (s = va_arg(va, const char *); s && *s; ++s) { + PUTC(*s); + } + break; + case 'd': + d = va_arg(va, unsigned long); + for (i = 16; i--;) { + u = (d >> (i * 4)) & 0xf; + if (u < 10) { + c = '0' + u; + } else { + u -= 10; + c = 'a' + u; + } + PUTC(c); + } + break; + default: + PUTC(c); + break; + } + break; + default: + PUTC(c); + break; + } } } - -textreal void __map_image(void) { - __map_segment(PAGE_V | PAGE_U, 0, (uintptr_t)_etext - IMAGE_BASE_VIRTUAL); - __map_segment(PAGE_V | PAGE_U | PAGE_RW, - (uintptr_t)_etext - IMAGE_BASE_VIRTUAL, - (uintptr_t)_end - IMAGE_BASE_VIRTUAL); -} diff --git a/libc/runtime/metalprintf.internal.h b/libc/runtime/metalprintf.internal.h new file mode 100644 index 000000000..0dd23224f --- /dev/null +++ b/libc/runtime/metalprintf.internal.h @@ -0,0 +1,16 @@ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_METALPRINTF_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_METALPRINTF_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +void MetalPrintf(const char *, ...); + +#define MetalPrintf(FMT, ...) \ + do { \ + const char StackFmt[] = FMT; \ + MetalPrintf(StackFmt, ##__VA_ARGS__); \ + } while (0) + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_METALPRINTF_H_ */ diff --git a/ape/lib/apm.h b/libc/runtime/mman.greg.c similarity index 58% rename from ape/lib/apm.h rename to libc/runtime/mman.greg.c index 79a38ae1b..4657f4f30 100644 --- a/ape/lib/apm.h +++ b/libc/runtime/mman.greg.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=8 sts=2 sw=2 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 │ │ │ @@ -30,29 +30,131 @@ │░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│ ╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│ -│ αcτµαlly pδrταblε εxεcµταblε § green energy │ +│ αcτµαlly pδrταblε εxεcµταblε § no-frills virtual memory management │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#ifndef APE_LIB_APM_H_ -#define APE_LIB_APM_H_ +#include "ape/relocations.h" +#include "libc/elf/def.h" +#include "libc/elf/struct/phdr.h" +#include "libc/macros.h" +#include "libc/nexgen32e/uart.internal.h" +#include "libc/runtime/e820.internal.h" +#include "libc/runtime/metalprintf.internal.h" +#include "libc/runtime/pc.internal.h" +#include "libc/runtime/runtime.h" /** - * @fileoverview Advanced Power Management. - * - *

APM is useful for exiting programs, without needing to ask the - * human to flip a physical switch or pass QEMU's -no-reboot flag. - * - *

Implementation Detail: Supporting ACPI would literally - * require implementing a programming language. - * - * @see APM BIOS Interface Specification v1.2 - * @since IBM PC/AT + * Allocates new page of physical memory. */ +noasan texthead uint64_t __new_page(struct mman *mm) { + uint64_t p; + if (mm->pdpi == mm->e820n) { + /* TODO: reclaim free pages */ + return 0; + } + while (mm->pdp >= mm->e820[mm->pdpi].addr + mm->e820[mm->pdpi].size) { + if (++mm->pdpi == mm->e820n) return 0; + mm->pdp = mm->e820[mm->pdpi].addr; + } + p = mm->pdp; + mm->pdp += 4096; + return p; +} -#define APM_SERVICE 0x15 +/** + * Returns pointer to page table entry for page at virtual address. + * Additional page tables are allocated if needed as a side-effect. + */ +noasan texthead uint64_t *__get_virtual(struct mman *mm, uint64_t *t, + int64_t vaddr, bool maketables) { + uint64_t *e, p; + unsigned char h; + for (h = 39;; h -= 9) { + e = t + ((vaddr >> h) & 511); + if (h == 12) return e; + if (!(*e & PAGE_V)) { + if (!maketables) return NULL; + if (!(p = __new_page(mm))) return NULL; + *e = p | PAGE_V | PAGE_RW; + } + t = (uint64_t *)(BANE + (*e & PAGE_TA)); + } +} -#if !(__ASSEMBLER__ + __LINKER__ + 0) +/** + * Sorts, rounds, and filters BIOS memory map. + */ +static noasan texthead void __normalize_e820(struct mman *mm) { + uint64_t a, b; + uint64_t x, y; + unsigned i, j, n; + for (n = i = 0; mm->e820[i].size; ++i) { + mm->e820[n] = mm->e820[i]; + x = mm->e820[n].addr; + y = mm->e820[n].addr + mm->e820[n].size; + a = ROUNDUP(x, 4096); + b = ROUNDDOWN(y, 4096) - a; + if (b > 0 && mm->e820[i].type == kMemoryUsable) { + mm->e820[n].addr = a; + mm->e820[n].size = b; + ++n; + } + } + for (i = 1; i < n; ++i) { + for (j = i; j > 0 && mm->e820[i].addr < mm->e820[j - 1].addr; --j) { + mm->e820[j] = mm->e820[j - 1]; + } + mm->e820[j] = mm->e820[i]; + } + mm->pdp = MAX(0x80000, mm->e820[0].addr); + mm->pdpi = 0; + mm->e820n = n; +} -void apmoff(void) wontreturn; +/** + * Identity maps all usable physical memory to its negative address. + */ +static noasan texthead void __invert_memory(struct mman *mm, uint64_t *pml4t) { + uint64_t i, j, *m, p, pe; + for (i = 0; i < mm->e820n; ++i) { + for (p = mm->e820[i].addr, pe = mm->e820[i].addr + mm->e820[i].size; + p + 0x200000 < pe; p += 4096) { + m = __get_virtual(mm, pml4t, BANE + p, true); + if (m && !(*m & PAGE_V)) { + *m = p | PAGE_V | PAGE_RW; + } + } + } +} -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* APE_LIB_APM_H_ */ +noasan texthead void __setup_mman(struct mman *mm, uint64_t *pml4t) { + __normalize_e820(mm); + __invert_memory(mm, pml4t); +} + +/** + * Maps APE-defined ELF program headers into memory and clears BSS. + */ +noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b) { + struct Elf64_Phdr *p; + uint64_t i, f, v, m, *e; + extern char ape_phdrs[] __attribute__((__weak__)); + extern char ape_phdrs_end[] __attribute__((__weak__)); + __setup_mman(mm, pml4t); + for (p = (struct Elf64_Phdr *)REAL(ape_phdrs), m = 0; + p < (struct Elf64_Phdr *)REAL(ape_phdrs_end); ++p) { + if (p->p_type == PT_LOAD || p->p_type == PT_GNU_STACK) { + f = PAGE_V | PAGE_U; + if (p->p_flags & PF_W) f |= PAGE_RW; + for (i = 0; i < p->p_memsz; i += 4096) { + if (i < p->p_filesz) { + v = b + p->p_offset + i; + m = MAX(m, v); + } else { + v = __clear_page(__new_page(mm)); + } + *__get_virtual(mm, pml4t, p->p_vaddr + i, true) = (v & PAGE_TA) | f; + } + } + } + mm->pdp = MAX(mm->pdp, m); +} diff --git a/libc/runtime/mman.internal.h b/libc/runtime/mman.internal.h new file mode 100644 index 000000000..9863579c1 --- /dev/null +++ b/libc/runtime/mman.internal.h @@ -0,0 +1,24 @@ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_MMAN_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_MMAN_H_ +#include "libc/runtime/e820.internal.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +struct mman { + int64_t pdp; /* 0x0500 */ + int32_t pdpi; /* 0x0508 */ + int32_t e820n; /* 0x050a */ + struct SmapEntry e820[256]; /* 0x0510 */ + char pc_drive_base_table[11]; /* 0x1510 */ + unsigned char pc_drive_type; /* 0x151b */ + unsigned char pc_drive_last_sector; /* 0x151c */ + unsigned short pc_drive_last_cylinder; /* 0x151d */ + unsigned char pc_drives_attached; /* 0x151f */ + unsigned char pc_drive_last_head; /* 0x1520 */ + unsigned char pc_drive; /* 0x1521 */ + char bad_idt[6]; /* 0x1522 */ +}; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_MMAN_H_ */ diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index a7bfc537c..671231932 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -24,7 +24,7 @@ #include "libc/intrin/asan.internal.h" #include "libc/macros.h" #include "libc/rand/rand.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" @@ -87,10 +87,10 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { } f = flags | MAP_FIXED; if (IsOpenbsd() && (f & MAP_GROWSDOWN)) { /* openbsd:dubstack */ - dm = __mmap(addr, size, prot, f & ~MAP_GROWSDOWN, fd, off); + dm = sys_mmap(addr, size, prot, f & ~MAP_GROWSDOWN, fd, off); if (dm.addr == MAP_FAILED) return MAP_FAILED; } - dm = __mmap(addr, size, prot, f, fd, off); + dm = sys_mmap(addr, size, prot, f, fd, off); if (dm.addr == MAP_FAILED || dm.addr != addr) { return MAP_FAILED; } diff --git a/libc/calls/efi.c b/libc/runtime/munmap-metal.c similarity index 82% rename from libc/calls/efi.c rename to libc/runtime/munmap-metal.c index dca380c0a..fba4a6ce9 100644 --- a/libc/calls/efi.c +++ b/libc/runtime/munmap-metal.c @@ -16,8 +16,18 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/efi.h" -#include "libc/nt/efi.h" +#include "libc/runtime/directmap.internal.h" +#include "libc/runtime/pc.internal.h" -EFI_HANDLE __efi_image_handle; -EFI_SYSTEM_TABLE *__efi_system_table; +int sys_munmap_metal(void *addr, size_t size) { + size_t i; + uint64_t *e; + struct mman *mm; + mm = (struct mman *)(BANE + 0x0500); + for (i = 0; i < size; i += 4096) { + e = __get_virtual(mm, __get_pml4t(), (uint64_t)addr + i, false); + if (e) *e = ~PAGE_V; + invlpg(e); + } + return 0; +} diff --git a/libc/runtime/munmap.c b/libc/runtime/munmap.c index 6a008e6bd..3309882ee 100644 --- a/libc/runtime/munmap.c +++ b/libc/runtime/munmap.c @@ -19,6 +19,7 @@ #include "libc/calls/internal.h" #include "libc/dce.h" #include "libc/macros.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" #include "libc/sysv/errfuns.h" @@ -46,5 +47,6 @@ int munmap(void *addr, size_t size) { if (!ALIGNED(addr) || !CANONICAL(addr) || !size) return einval(); if (UntrackMemoryIntervals(addr, size) == -1) return -1; if (IsWindows()) return 0; + if (IsMetal()) sys_munmap_metal(addr, size); return sys_munmap(addr, size); } diff --git a/ape/lib/pc.h b/libc/runtime/pc.internal.h similarity index 89% rename from ape/lib/pc.h rename to libc/runtime/pc.internal.h index badd3d21a..b78ff07de 100644 --- a/ape/lib/pc.h +++ b/libc/runtime/pc.internal.h @@ -32,9 +32,12 @@ ╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│ │ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#ifndef APE_LIB_PC_H_ -#define APE_LIB_PC_H_ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_PC_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_PC_H_ +#include "libc/runtime/e820.internal.h" +#include "libc/runtime/mman.internal.h" +#define BANE -140737488355328 #define BOOTSIG 0xaa55 /* master boot record signature */ #define PC_BIOS_DATA_AREA 0x400 @@ -154,35 +157,13 @@ #define PAGE_4KB /* */ 0b010000000 #define PAGE_2MB /* */ 0b110000000 #define PAGE_1GB /* */ 0b110000000 -#define PAGE_TA 0b11111111111111111111111111111111111111000000000000 -#define PAGE_PA2 0b11111111111111111111111111111000000000000000000000 +#define PAGE_TA 0x00007ffffffff000 +#define PAGE_PA2 0x00007fffffe00000 #define PAGE_XD 0x8000000000000000 #if !(__ASSEMBLER__ + __LINKER__ + 0) -#include "ape/config.h" -struct thatispacked GlobalDescriptorTable { - uint16_t size; - uint64_t *entries; -}; - -/** - * Memory hole map. - * @see wiki.osdev.org/Detecting_Memory_(x86) - * @since 2002 - */ -struct SmapEntry { - uint64_t addr; - uint64_t size; - enum { - kMemoryUsable = 1, - kMemoryUnusable = 2, - kMemoryAcpiReclaimable = 3, - kMemoryAcpiNvs = 4, - kMemoryBad = 5 - } type; - uint32_t __acpi3; /* is abstracted */ -}; +#define invlpg(p) asm volatile("invlpg\t(%0)" : : "r"(p) : "memory") struct IdtDescriptor { uint16_t offset_1; /* offset bits 0..15 */ @@ -194,37 +175,10 @@ struct IdtDescriptor { uint32_t zero; /* reserved */ }; -struct thatispacked PageTable { - uint64_t p[512]; -} forcealign(PAGESIZE); - -extern struct PageTable g_pml4t; -extern struct GlobalDescriptorTable gdt; - -extern const unsigned char kBiosDataArea[256]; -extern const unsigned char kBiosDataAreaXlm[256]; - -extern struct SmapEntry e820map[XLM_E820_SIZE / sizeof(struct SmapEntry)]; -extern struct SmapEntry e820map_xlm[XLM_E820_SIZE / sizeof(struct SmapEntry)]; - -extern uint64_t g_ptsp; -extern uint64_t g_ptsp_xlm; - -void bootdr(char drive) wontreturn; - -void smapsort(struct SmapEntry *); -uint64_t *__getpagetableentry(int64_t, unsigned, struct PageTable *, - uint64_t *); -void flattenhighmemory(struct SmapEntry *, struct PageTable *, uint64_t *); -void pageunmap(int64_t); - -forceinline unsigned long eflags(void) { - unsigned long res; - asm("pushf\n\t" - "pop\t%0" - : "=rm"(res)); - return res; -} +uint64_t *__get_virtual(struct mman *, uint64_t *, int64_t, bool); +uint64_t __clear_page(uint64_t); +uint64_t __new_page(struct mman *); +void __map_phdrs(struct mman *, uint64_t *, uint64_t); forceinline unsigned char inb(unsigned short port) { unsigned char al; @@ -238,5 +192,22 @@ forceinline void outb(unsigned short port, unsigned char byte) { : "a"(byte), "dN"(port)); } +#define __clear_page(page) \ + ({ \ + long di, cx; \ + uintptr_t Page = (uintptr_t)(page); \ + asm("rep stosb" \ + : "=D"(di), "=c"(cx), "=m"(*(char(*)[4096])Page) \ + : "0"(Page), "1"(4096), "a"(0)); \ + Page; \ + }) + +#define __get_pml4t() \ + ({ \ + intptr_t cr3; \ + asm("mov\t%%cr3,%0" : "=r"(cr3)); \ + (uint64_t *)(BANE + cr3); \ + }) + #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* APE_LIB_PC_H_ */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_PC_H_ */ diff --git a/libc/runtime/runtime.mk b/libc/runtime/runtime.mk index 4b04a50a3..26a2c5e4c 100644 --- a/libc/runtime/runtime.mk +++ b/libc/runtime/runtime.mk @@ -76,6 +76,10 @@ o/$(MODE)/libc/runtime/winmain.greg.o: \ OVERRIDE_CFLAGS += \ $(NO_MAGIC) +o/$(MODE)/libc/runtime/mman.greg.o: \ + OVERRIDE_CFLAGS += \ + -ffreestanding + o/$(MODE)/libc/runtime/ftrace.greg.o: \ OVERRIDE_CFLAGS += \ -mgeneral-regs-only diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index 106bc5f6c..b4b5516a6 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -36,7 +36,7 @@ #include "libc/nt/process.h" #include "libc/nt/runtime.h" #include "libc/nt/struct/teb.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" @@ -74,7 +74,7 @@ static noasan textwindows void NormalizeCmdExe(int version) { hstdout = GetStdHandle(pushpop(kNtStdOutputHandle)); hstderr = GetStdHandle(pushpop(kNtStdErrorHandle)); if (GetFileType((handle = hstdin)) == kNtFileTypeChar) { - SetTrueColor(); + /* SetTrueColor(); */ SetConsoleCP(kNtCpUtf8); GetConsoleMode(handle, &mode); SetConsoleMode(handle, mode | kNtEnableProcessedInput | @@ -84,7 +84,7 @@ static noasan textwindows void NormalizeCmdExe(int version) { } if (GetFileType((handle = hstdout)) == kNtFileTypeChar || GetFileType((handle = hstderr)) == kNtFileTypeChar) { - SetTrueColor(); + /* SetTrueColor(); */ SetConsoleOutputCP(kNtCpUtf8); GetConsoleMode(handle, &mode); SetConsoleMode( diff --git a/libc/sysv/calls/__sys_mmap.s b/libc/sysv/calls/__sys_mmap.s new file mode 100644 index 000000000..2c27b450b --- /dev/null +++ b/libc/sysv/calls/__sys_mmap.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall __sys_mmap,0x0c50c51dd20c5009,globl,hidden diff --git a/libc/sysv/calls/sys_mmap.s b/libc/sysv/calls/sys_mmap.s deleted file mode 100644 index 141c2e0bd..000000000 --- a/libc/sysv/calls/sys_mmap.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sys_mmap,0x0c50c51dd20c5009,globl,hidden diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index 718c9f083..f3307864d 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -44,7 +44,7 @@ scall __sys_lstat 0x1b90280282154006 globl hidden # needs __stat2linux(); block scall sys_poll 0x0d10fc0d120e6007 globl hidden scall sys_ppoll 0xfff06d221ffff10f globl hidden # consider INTON/INTOFF tutorial in examples/unbourne.c scall sys_lseek 0x0c70c71de20c7008 globl hidden # netbsd+openbsd:evilpad -scall sys_mmap 0x0c50c51dd20c5009 globl hidden # netbsd+openbsd:pad +scall __sys_mmap 0x0c50c51dd20c5009 globl hidden # netbsd+openbsd:pad scall sys_msync 0x115100041204101a globl hidden scall sys_mprotect 0x04a04a04a204a00a globl hidden scall sys_munmap 0x049049049204900b globl hidden diff --git a/libc/sysv/systemfive.S b/libc/sysv/systemfive.S index e3b1d6cd5..b41ed340f 100644 --- a/libc/sysv/systemfive.S +++ b/libc/sysv/systemfive.S @@ -104,7 +104,7 @@ __systemfive: .privileged .Lanchorpoint: -#if SupportsLinux() || SupportsMetal() || SupportsUefi() +#if SupportsLinux() || SupportsMetal() systemfive_linux: and $0xfff,%eax cmp $0xfff,%eax @@ -198,10 +198,6 @@ systemfive_xnu: testb $XNU,(%rdi) # @see libc/crt/crt.S jnz _init_systemfive_xnu #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 @@ -240,13 +236,6 @@ _init_systemfive_metal: ezlea syscon_linux,si jmp _init_systemfive_os #endif -#if SupportsUefi() -_init_systemfive_uefi: - pushb systemfive_linux-.Lanchorpoint - push $UEFI - ezlea syscon_linux,si - jmp _init_systemfive_os -#endif #if SupportsWindows() _init_systemfive_windows: pushb systemfive_enosys-.Lanchorpoint @@ -323,20 +312,22 @@ _init_systemfive_magnums: // 𝑠𝑙𝑖𝑑𝑒 #if SupportsSystemv() && !defined(TINY) _init_systemfive_stack: # determinism ftw! -#if SupportsWindows() || SupportsMetal() || SupportsUefi() - testb $WINDOWS|METAL|UEFI,__hostos(%rip) +#if SupportsWindows() || SupportsMetal() + testb $WINDOWS|METAL,__hostos(%rip) jnz _init_systemfive_done #endif push %rdi push %rsi mov __NR_mmap,%eax - mov $0x700000000000-STACKSIZE,%rdi - mov $STACKSIZE,%esi + movabs $ape_stack_vaddr,%rdi + mov $ape_stack_memsz,%esi mov $PROT_READ|PROT_WRITE,%edx mov $MAP_PRIVATE|MAP_FIXED,%r10d or MAP_ANONYMOUS,%r10d or $-1,%r8d xor %r9d,%r9d + push %rdi # vaddr of stack + push %rsi # size of stack push %r9 # openbsd:pad push %r9 # openbsd:align #if SupportsOpenbsd() @@ -351,6 +342,8 @@ _init_systemfive_stack: # determinism ftw! syscall pop %r9 pop %r9 + pop %r9 # size of stack + pop %r11 # vaddr of stack jnc 2f 1: mov %eax,%edi mov __NR_exit_group,%eax @@ -360,17 +353,23 @@ _init_systemfive_stack: # determinism ftw! .weak _mmi ezlea _mmi,cx test %rcx,%rcx + push %r9 # save the stack size jz 3f + lea -1(%r11,%r9),%r9 # need incl. interval + shr $16,%r11 # for the stack range + shr $16,%r9 movb $1,(%rcx) # _mmi.i - movl $(0x700000000000-STACKSIZE)>>16,8(%rcx) # _mmi.p[0].x - movl $(0x700000000000-1)>>16,12(%rcx) # _mmi.p[0].y + mov %r11d,8(%rcx) # _mmi.p[0].x + mov %r9d,12(%rcx) # _mmi.p[0].y mov %edx,20(%rcx) # _mmi.p[0].prot mov %r10d,24(%rcx) # _mmi.p[0].flags -3: pop %rsi +3: pop %r9 # restore stack size + pop %rsi pop %rdi leave pop %rcx - lea STACKSIZE-16(%rax),%rsp # openbsd:stackbound + lea (%rax,%r9),%rsp + sub $ape_stack_align,%rsp # openbsd:stackbound mov %rbp,(%rsp) push %rcx push %rbp @@ -414,7 +413,7 @@ syscon_end: .type syscon_end,@object .globl syscon_start .globl syscon_end -#if SupportsLinux() || SupportsMetal() || SupportsUefi() +#if SupportsLinux() || SupportsMetal() .section .sort.rodata.syscon.linux.1,"a",@progbits .align 1 syscon_linux:/* @@ -468,3 +467,7 @@ syscon_windows:/* .type syscon_windows,@object .globl syscon_windows #endif + + .weak ape_stack_vaddr + .weak ape_stack_memsz + .weak ape_stack_align diff --git a/libc/testlib/testlib.mk b/libc/testlib/testlib.mk index dacb0f6e1..85ccc3c6a 100644 --- a/libc/testlib/testlib.mk +++ b/libc/testlib/testlib.mk @@ -78,7 +78,6 @@ LIBC_TESTLIB_A_OBJS = \ $(LIBC_TESTLIB_A_ASSETS:%=o/$(MODE)/%.zip.o) LIBC_TESTLIB_A_DIRECTDEPS = \ - APE_LIB \ LIBC_ALG \ LIBC_CALLS \ LIBC_FMT \ diff --git a/libc/tinymath/c2rangr.S b/libc/tinymath/c2rangr.S index fb4fceae7..e23ec047c 100644 --- a/libc/tinymath/c2rangr.S +++ b/libc/tinymath/c2rangr.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/copysignl.S b/libc/tinymath/copysignl.S index a18af04d4..79cfde3e6 100644 --- a/libc/tinymath/copysignl.S +++ b/libc/tinymath/copysignl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/fmodl.S b/libc/tinymath/fmodl.S index 355b0a66f..dc9e4372f 100644 --- a/libc/tinymath/fmodl.S +++ b/libc/tinymath/fmodl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/lroundl.S b/libc/tinymath/lroundl.S index 52a7da0d9..ff5dd4b9e 100644 --- a/libc/tinymath/lroundl.S +++ b/libc/tinymath/lroundl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/remainderl.S b/libc/tinymath/remainderl.S index 72fc72479..a98f987f5 100644 --- a/libc/tinymath/remainderl.S +++ b/libc/tinymath/remainderl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/roundl.S b/libc/tinymath/roundl.S index 185e8a2d7..d22894cdb 100644 --- a/libc/tinymath/roundl.S +++ b/libc/tinymath/roundl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" // Rounds to nearest integer, away from zero. diff --git a/libc/tinymath/sincosl.S b/libc/tinymath/sincosl.S index da6725702..09097fea3 100644 --- a/libc/tinymath/sincosl.S +++ b/libc/tinymath/sincosl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/tanl.S b/libc/tinymath/tanl.S index 3958a13f2..e7808a9ab 100644 --- a/libc/tinymath/tanl.S +++ b/libc/tinymath/tanl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/zipos/zipos.mk b/libc/zipos/zipos.mk index 052cec6c0..cc35b0792 100644 --- a/libc/zipos/zipos.mk +++ b/libc/zipos/zipos.mk @@ -27,7 +27,6 @@ LIBC_ZIPOS_A_CHECKS = \ $(LIBC_ZIPOS_A_HDRS:%=o/$(MODE)/%.ok) LIBC_ZIPOS_A_DIRECTDEPS = \ - APE_LIB \ LIBC_CALLS \ LIBC_MEM \ LIBC_NEXGEN32E \ diff --git a/test/ape/lib/getpagetableentry_test.c b/test/ape/lib/getpagetableentry_test.c deleted file mode 100644 index 74d55bacc..000000000 --- a/test/ape/lib/getpagetableentry_test.c +++ /dev/null @@ -1,65 +0,0 @@ -/*-*- 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 "ape/lib/pc.h" -#include "libc/mem/mem.h" -#include "libc/runtime/gc.h" -#include "libc/str/str.h" -#include "libc/testlib/testlib.h" - -TEST(getpagetableentry, testLowestAddress) { - static struct PageTable pml4t; - static struct PageTable stack[3]; - uint64_t ptsp = (uintptr_t)&stack + sizeof(stack); - memset(&pml4t, 0, sizeof(pml4t)); - memset(&stack, 0, sizeof(stack)); - uint64_t vaddr = 0; - uint64_t paddr = 0x31337000; - *__getpagetableentry(vaddr, 3, &pml4t, &ptsp) = paddr | PAGE_V; - EXPECT_EQ(&stack[2].p[0], pml4t.p[0] & PAGE_TA); /* pml4t → pdpt */ - EXPECT_EQ(&stack[1].p[0], stack[2].p[0] & PAGE_TA); /* pdpt → pdt */ - EXPECT_EQ(&stack[0].p[0], stack[1].p[0] & PAGE_TA); /* pdt → pd */ - EXPECT_EQ(stack[0].p[0] & PAGE_TA, paddr); /* page */ - EXPECT_EQ(&stack, ptsp); - EXPECT_TRUE(pml4t.p[0] & PAGE_V); - EXPECT_TRUE(stack[2].p[0] & PAGE_V); - EXPECT_TRUE(stack[1].p[0] & PAGE_V); - EXPECT_TRUE(stack[0].p[0] & PAGE_V); - EXPECT_FALSE(stack[0].p[1] & PAGE_V); -} - -TEST(getpagetableentry, testHigherAddress) { - static struct PageTable pml4t; - static struct PageTable stack[3]; - uint64_t ptsp = (uintptr_t)&stack + sizeof(stack); - memset(&pml4t, 0, sizeof(pml4t)); - memset(&stack, 0, sizeof(stack)); - uint64_t vaddr = 0x133731337000; - uint64_t paddr = 0x123000; - *__getpagetableentry(vaddr, 3, &pml4t, &ptsp) = paddr | PAGE_V; - EXPECT_EQ(&stack[2].p[0], pml4t.p[38] & PAGE_TA); /* pml4t → pdpt */ - EXPECT_EQ(&stack[1].p[0], stack[2].p[220] & PAGE_TA); /* pdpt → pdt */ - EXPECT_EQ(&stack[0].p[0], stack[1].p[393] & PAGE_TA); /* pdt → pd */ - EXPECT_EQ(stack[0].p[311] & PAGE_TA, paddr); /* page */ - EXPECT_EQ(&stack, ptsp); - EXPECT_TRUE(pml4t.p[38] & PAGE_V); - EXPECT_TRUE(stack[2].p[220] & PAGE_V); - EXPECT_TRUE(stack[1].p[393] & PAGE_V); - EXPECT_TRUE(stack[0].p[311] & PAGE_V); - EXPECT_FALSE(stack[0].p[0] & PAGE_V); -} diff --git a/test/ape/lib/smapsort_test.c b/test/ape/lib/smapsort_test.c deleted file mode 100644 index 3454a68bd..000000000 --- a/test/ape/lib/smapsort_test.c +++ /dev/null @@ -1,81 +0,0 @@ -/*-*- 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 "ape/lib/pc.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "libc/testlib/testlib.h" - -TEST(smapsort, testEmpty_doesntOverrunBuffer) { - struct SmapEntry *smap = malloc(sizeof(struct SmapEntry)); - memset(smap, 0, sizeof(struct SmapEntry)); - smapsort(smap); - EXPECT_EQ(0, smap[0].addr); - EXPECT_EQ(0, smap[0].size); - free(smap); -} - -/* TEST(smapsort, testSorted_doesNothing) { */ -/* struct SmapEntry *smap = tmalloc(4 * sizeof(struct SmapEntry)); */ -/* memset(smap, 0, 4 * sizeof(struct SmapEntry)); */ -/* smap[0].addr = 0; */ -/* smap[0].size = 0x7000; */ -/* smap[0].type = kMemoryUsable; */ -/* smap[1].addr = 0x7000; */ -/* smap[1].size = 0x1000; */ -/* smap[1].type = kMemoryUnusable; */ -/* smap[2].addr = 0x14000; */ -/* smap[2].size = 0x1000; */ -/* smap[2].type = kMemoryBad; */ -/* smapsort(smap); */ -/* EXPECT_EQ(0, smap[0].addr); */ -/* EXPECT_EQ(0x7000, smap[0].size); */ -/* EXPECT_EQ(kMemoryUsable, smap[0].type); */ -/* EXPECT_EQ(0x7000, smap[1].addr); */ -/* EXPECT_EQ(0x1000, smap[1].size); */ -/* EXPECT_EQ(kMemoryUnusable, smap[1].type); */ -/* EXPECT_EQ(0x14000, smap[2].addr); */ -/* EXPECT_EQ(0x1000, smap[2].size); */ -/* EXPECT_EQ(kMemoryBad, smap[2].type); */ -/* tfree(smap); */ -/* } */ - -/* TEST(smapsort, testUnsorted_sortsByAddress) { */ -/* struct SmapEntry *smap = tmalloc(4 * sizeof(struct SmapEntry)); */ -/* memset(smap, 0, 4 * sizeof(struct SmapEntry)); */ -/* smap[2].addr = 0; */ -/* smap[2].size = 0x7000; */ -/* smap[2].type = kMemoryUsable; */ -/* smap[0].addr = 0x7000; */ -/* smap[0].size = 0x1000; */ -/* smap[0].type = kMemoryUnusable; */ -/* smap[1].addr = 0x14000; */ -/* smap[1].size = 0x1000; */ -/* smap[1].type = kMemoryBad; */ -/* smapsort(smap); */ -/* EXPECT_EQ(0, smap[0].addr); */ -/* EXPECT_EQ(0x7000, smap[0].size); */ -/* EXPECT_EQ(kMemoryUsable, smap[0].type); */ -/* EXPECT_EQ(0x7000, smap[1].addr); */ -/* EXPECT_EQ(0x1000, smap[1].size); */ -/* EXPECT_EQ(kMemoryUnusable, smap[1].type); */ -/* EXPECT_EQ(0x14000, smap[2].addr); */ -/* EXPECT_EQ(0x1000, smap[2].size); */ -/* EXPECT_EQ(kMemoryBad, smap[2].type); */ -/* tfree(smap); */ -/* } */ diff --git a/test/ape/lib/test.mk b/test/ape/lib/test.mk deleted file mode 100644 index e340fa8f2..000000000 --- a/test/ape/lib/test.mk +++ /dev/null @@ -1,55 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -PKGS += TEST_APE_LIB - -TEST_APE_LIB_SRCS := $(wildcard test/ape/lib/*.c) -TEST_APE_LIB_SRCS_TEST = $(filter %_test.c,$(TEST_APE_LIB_SRCS)) - -TEST_APE_LIB_OBJS = \ - $(TEST_APE_LIB_SRCS:%.c=o/$(MODE)/%.o) - -TEST_APE_LIB_COMS = \ - $(TEST_APE_LIB_SRCS:%.c=o/$(MODE)/%.com) - -TEST_APE_LIB_BINS = \ - $(TEST_APE_LIB_COMS) \ - $(TEST_APE_LIB_COMS:%=%.dbg) - -TEST_APE_LIB_TESTS = \ - $(TEST_APE_LIB_SRCS_TEST:%.c=o/$(MODE)/%.com.ok) - -TEST_APE_LIB_CHECKS = \ - $(TEST_APE_LIB_SRCS_TEST:%.c=o/$(MODE)/%.com.runs) - -TEST_APE_LIB_DIRECTDEPS = \ - APE_LIB \ - LIBC_INTRIN \ - LIBC_LOG \ - LIBC_MEM \ - LIBC_NEXGEN32E \ - LIBC_RUNTIME \ - LIBC_STR \ - LIBC_STUBS \ - LIBC_TESTLIB \ - LIBC_X - -TEST_APE_LIB_DEPS := \ - $(call uniq,$(foreach x,$(TEST_APE_LIB_DIRECTDEPS),$($(x)))) - -o/$(MODE)/test/ape/lib.pkg: \ - $(TEST_APE_LIB_OBJS) \ - $(foreach x,$(TEST_APE_LIB_DIRECTDEPS),$($(x)_A).pkg) - -o/$(MODE)/test/ape/lib/%.com.dbg: \ - $(TEST_APE_LIB_DEPS) \ - o/$(MODE)/test/ape/lib/%.o \ - o/$(MODE)/test/ape/lib.pkg \ - $(LIBC_TESTMAIN) \ - $(CRT) \ - $(APE) - @$(APELINK) - -.PHONY: o/$(MODE)/test/ape/lib -o/$(MODE)/test/ape/lib: $(TEST_APE_LIB_BINS) \ - $(TEST_APE_LIB_CHECKS) diff --git a/test/ape/test.mk b/test/ape/test.mk deleted file mode 100644 index cd60a65f0..000000000 --- a/test/ape/test.mk +++ /dev/null @@ -1,5 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -.PHONY: o/$(MODE)/test/ape -o/$(MODE)/test/ape: o/$(MODE)/test/ape/lib diff --git a/test/test.mk b/test/test.mk index ac1c02d1f..02f1f4274 100644 --- a/test/test.mk +++ b/test/test.mk @@ -2,8 +2,7 @@ #───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ .PHONY: o/$(MODE)/test -o/$(MODE)/test: o/$(MODE)/test/ape \ - o/$(MODE)/test/dsp \ +o/$(MODE)/test: o/$(MODE)/test/dsp \ o/$(MODE)/test/libc \ o/$(MODE)/test/net \ o/$(MODE)/test/tool diff --git a/third_party/chibicc/test/test.h b/third_party/chibicc/test/test.h index 7d1a35376..e6a6e4c7c 100644 --- a/third_party/chibicc/test/test.h +++ b/third_party/chibicc/test/test.h @@ -3,7 +3,7 @@ #include "libc/stdio/stdio.h" #include "libc/str/str.h" -STATIC_YOINK("__mmap"); /* asan needs it */ +STATIC_YOINK("sys_mmap"); /* asan needs it */ STATIC_YOINK("TrackMemoryInterval"); /* asan needs it */ #define ASSERT(x, y) Assert2(x, y, #y, __FILE__, __LINE__) diff --git a/tool/build/blinkenlights.c b/tool/build/blinkenlights.c index fa3b3cebd..47a336f23 100644 --- a/tool/build/blinkenlights.c +++ b/tool/build/blinkenlights.c @@ -2109,9 +2109,9 @@ static void OnE820(void) { if (Read32(m->dx) == 0x534D4150 && Read32(m->cx) == 24 && addr + sizeof(p) <= m->real.n) { if (!Read32(m->bx)) { - Write64(p + 000, 0); - Write64(p + 010, m->real.n); - Write32(p + 014, 1); + Write64(p + 0, 0); + Write64(p + 8, m->real.n); + Write32(p + 16, 1); memcpy(m->real.p + addr, p, sizeof(p)); SetWriteAddr(m, addr, sizeof(p)); Write32(m->cx, sizeof(p)); @@ -2716,6 +2716,7 @@ static void Tui(void) { ExecuteInstruction(m); ++opcount; if (!(action & CONTINUE) || interactive) { + if (!(action & CONTINUE)) ReactiveDraw(); ScrollMemoryViews(); } } else { @@ -2737,8 +2738,11 @@ static void Tui(void) { } while (tuimode); } else { if (OnHalt(interrupt)) { + ReactiveDraw(); + ScrollMemoryViews(); goto KeepGoing; } + ReactiveDraw(); ScrollOp(&pan.disassembly, GetDisIndex()); } TuiCleanup(); diff --git a/tool/build/compile.c b/tool/build/compile.c index be45681a4..0ea18f0ab 100644 --- a/tool/build/compile.c +++ b/tool/build/compile.c @@ -115,6 +115,7 @@ struct Command command; const char *const kSafeEnv[] = { "ADDR2LINE", // needed by GetAddr2linePath "MAKEFLAGS", // needed by IsRunningUnderMake + "MODE", // needed by test scripts "PATH", // needed by clang "PWD", // just seems plain needed "TERM", // needed by IsTerminalInarticulate diff --git a/tool/build/dis.c b/tool/build/dis.c index ac6e78a71..9bd17419b 100644 --- a/tool/build/dis.c +++ b/tool/build/dis.c @@ -281,9 +281,8 @@ int main(int argc, char *argv[]) { struct stat st; const char *path; if (argc == 1) { - path = "o/v127/examples/hello2.com.dbg"; - /* fprintf(stderr, "USAGE: %s ELF\n", program_invocation_name); */ - /* exit(1); */ + fprintf(stderr, "USAGE: %s ELF\n", program_invocation_name); + exit(1); } else { path = argv[1]; } diff --git a/tool/build/lib/diself.c b/tool/build/lib/diself.c index 03965f0f1..6231d6c24 100644 --- a/tool/build/lib/diself.c +++ b/tool/build/lib/diself.c @@ -100,6 +100,7 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) { d->syms.p[j].unique = i; d->syms.p[j].size = st[i].st_size; d->syms.p[j].name = st[i].st_name; + CHECK_GE(st[i].st_value, 0); d->syms.p[j].addr = st[i].st_value; d->syms.p[j].rank = -islocal + -isweak + -isabs + isprotected + isobject + isfunc; @@ -112,7 +113,14 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) { } static void DisSortSyms(struct Dis *d) { + size_t i, j; qsort(d->syms.p, d->syms.i, sizeof(struct DisSym), (void *)DisSymCompare); + for (i = 0; i < d->syms.i; ++i) { + if (!strcmp("_end", d->syms.stab + d->syms.p[i].name)) { + d->syms.i = i; + break; + } + } } static void DisCanonizeSyms(struct Dis *d) { @@ -178,6 +186,10 @@ long DisFindSym(struct Dis *d, int64_t addr) { l = m + 1; } } + if (r && d->syms.p[r - 1].addr < 256) { + /* XXX: prevent skewed binbase from doing weirdness */ + return -1; + } if (r && (addr == d->syms.p[r - 1].addr || (addr > d->syms.p[r - 1].addr && (addr <= d->syms.p[r - 1].addr + d->syms.p[r - 1].size || diff --git a/tool/build/lib/fpu.c b/tool/build/lib/fpu.c index dcaf02f4f..75178447a 100644 --- a/tool/build/lib/fpu.c +++ b/tool/build/lib/fpu.c @@ -16,9 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/config.h" -#include "ape/lib/pc.h" #include "libc/math.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "tool/build/lib/case.h" @@ -988,7 +987,7 @@ static void OpFnop(struct Machine *m) { } void OpFinit(struct Machine *m) { - m->fpu.cw = X87_NORMAL; + m->fpu.cw = 0x037f; m->fpu.sw = 0; m->fpu.tw = -1; } diff --git a/tool/emacs/cosmo-c-keywords.el b/tool/emacs/cosmo-c-keywords.el index 1af8f1ca3..bd3372244 100644 --- a/tool/emacs/cosmo-c-keywords.el +++ b/tool/emacs/cosmo-c-keywords.el @@ -194,6 +194,7 @@ "forcealign" "typeof" "textreal" + "texthead" "autotype" "_Section" "_Vector_size")) diff --git a/tool/net/net.mk b/tool/net/net.mk index 35fd28468..df3978d5e 100644 --- a/tool/net/net.mk +++ b/tool/net/net.mk @@ -18,7 +18,6 @@ TOOL_NET_BINS = \ $(TOOL_NET_COMS:%=%.dbg) TOOL_NET_DIRECTDEPS = \ - APE_LIB \ LIBC_ALG \ LIBC_BITS \ LIBC_CALLS \