mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
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.
This commit is contained in:
parent
ac3b1dfb21
commit
edd9297eba
89 changed files with 900 additions and 1417 deletions
4
Makefile
4
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 \
|
||||
|
|
535
ape/ape.S
535
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() */
|
||||
|
||||
|
|
41
ape/ape.lds
41
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);
|
||||
|
|
|
@ -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)
|
||||
|
|
118
ape/config.h
118
ape/config.h
|
@ -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_ */
|
|
@ -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)
|
|
@ -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
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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");
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
Binary file not shown.
|
@ -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)
|
||||
|
|
44
examples/e820.c
Normal file
44
examples/e820.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -33,7 +33,6 @@ EXAMPLES_BINS = \
|
|||
$(EXAMPLES_COMS:%=%.dbg)
|
||||
|
||||
EXAMPLES_DIRECTDEPS = \
|
||||
APE_LIB \
|
||||
DSP_CORE \
|
||||
DSP_SCALE \
|
||||
DSP_TTY \
|
||||
|
|
19
examples/malloc.c
Normal file
19
examples/malloc.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
|
|
@ -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,
|
||||
|
|
|
@ -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) */
|
21
libc/runtime/e820.internal.h
Normal file
21
libc/runtime/e820.internal.h
Normal file
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
16
libc/runtime/metalprintf.internal.h
Normal file
16
libc/runtime/metalprintf.internal.h
Normal file
|
@ -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_ */
|
|
@ -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.
|
||||
*
|
||||
* <p>APM is useful for exiting programs, without needing to ask the
|
||||
* human to flip a physical switch or pass QEMU's -no-reboot flag.
|
||||
*
|
||||
* <p><b>Implementation Detail:</b> 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);
|
||||
}
|
24
libc/runtime/mman.internal.h
Normal file
24
libc/runtime/mman.internal.h
Normal file
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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_ */
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
2
libc/sysv/calls/__sys_mmap.s
Normal file
2
libc/sysv/calls/__sys_mmap.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall __sys_mmap,0x0c50c51dd20c5009,globl,hidden
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_mmap,0x0c50c51dd20c5009,globl,hidden
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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); */
|
||||
/* } */
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
||||
|
|
2
third_party/chibicc/test/test.h
vendored
2
third_party/chibicc/test/test.h
vendored
|
@ -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__)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -194,6 +194,7 @@
|
|||
"forcealign"
|
||||
"typeof"
|
||||
"textreal"
|
||||
"texthead"
|
||||
"autotype"
|
||||
"_Section"
|
||||
"_Vector_size"))
|
||||
|
|
|
@ -18,7 +18,6 @@ TOOL_NET_BINS = \
|
|||
$(TOOL_NET_COMS:%=%.dbg)
|
||||
|
||||
TOOL_NET_DIRECTDEPS = \
|
||||
APE_LIB \
|
||||
LIBC_ALG \
|
||||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
|
|
Loading…
Reference in a new issue