mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-27 13:00:28 +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
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,58 +0,0 @@
|
|||
/*-*- 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│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ 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. │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § green energy │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_LIB_APM_H_
|
||||
#define APE_LIB_APM_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
|
||||
*/
|
||||
|
||||
#define APM_SERVICE 0x15
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
void apmoff(void) wontreturn;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* APE_LIB_APM_H_ */
|
|
@ -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,36 +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 "ape/relocations.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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -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");
|
||||
}
|
242
ape/lib/pc.h
242
ape/lib/pc.h
|
@ -1,242 +0,0 @@
|
|||
/*-*- 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│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ 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. │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_LIB_PC_H_
|
||||
#define APE_LIB_PC_H_
|
||||
|
||||
#define BOOTSIG 0xaa55 /* master boot record signature */
|
||||
#define PC_BIOS_DATA_AREA 0x400
|
||||
|
||||
#define kInterruptFlag (1u << 9)
|
||||
|
||||
/* FPU Status Word (x87)
|
||||
@see Intel Manual V1 §8.1.3
|
||||
IE: Invalid Operation ────────────────┐
|
||||
DE: Denormalized Operand ────────────┐│
|
||||
ZE: Zero Divide ────────────────────┐││
|
||||
OE: Overflow Flag ─────────────────┐│││
|
||||
UE: Underflow Flag ───────────────┐││││
|
||||
PE: Precision Flag ──────────────┐│││││
|
||||
SF: Stack Fault ────────────────┐││││││
|
||||
ES: Exception Summary Status ──┐│││││││
|
||||
C0-3: Condition Codes ──┬────┐ ││││││││
|
||||
TOP of Stack Pointer ─────┐ │ ││││││││
|
||||
B: FPU Busy ───────────┐│ │ │ ││││││││
|
||||
││┌┴┐┌┼┐││││││││
|
||||
│↓│ │↓↓↓││││││││*/
|
||||
#define FPU_IE 0b0000000000100000000000001
|
||||
#define FPU_ZE 0b0000000000100000000000100
|
||||
#define FPU_SF 0b0000000000000000001000000
|
||||
#define FPU_C0 0b0000000000000000100000000
|
||||
#define FPU_C1 0b0000000000000001000000000
|
||||
#define FPU_C2 0b0000000000000010000000000
|
||||
#define FPU_C3 0b0000000000100000000000000
|
||||
|
||||
#define CR0_PE 0x01 /* protected mode enabled */
|
||||
#define CR0_MP 0x02 /* monitor coprocessor */
|
||||
#define CR0_EM 0x04 /* no x87 fpu present if set */
|
||||
#define CR0_TS 0x08 /* task switched x87 */
|
||||
#define CR0_ET 0x10 /* extension type 287 or 387 */
|
||||
#define CR0_NE 0x20 /* enable x87 error reporting */
|
||||
#define CR0_WP 0x00010000 /* write protect read-only pages @pl0 */
|
||||
#define CR0_AM 0x00040000 /* alignment mask */
|
||||
#define CR0_NW 0x20000000 /* global write-through cache disable */
|
||||
#define CR0_CD 0x40000000 /* global cache disable */
|
||||
#define CR0_PG 0x80000000 /* paging enabled */
|
||||
|
||||
#define CR4_VME 0x01 /* virtual 8086 mode extension */
|
||||
#define CR4_PVI 0x02 /* protected mode virtual interrupts */
|
||||
#define CR4_TSD 0x04 /* time stamp disable (rdtsc) */
|
||||
#define CR4_DE 0x08 /* debugging extensions */
|
||||
#define CR4_PSE 0x10 /* page size extension */
|
||||
#define CR4_PAE 0x20 /* physical address extension */
|
||||
#define CR4_MCE 0x40 /* machine check exception */
|
||||
#define CR4_PGE 0x80 /* page global enabled */
|
||||
#define CR4_OSFXSR 0x0200 /* enable SSE and fxsave/fxrestor */
|
||||
#define CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */
|
||||
#define CR4_LA57 0x1000 /* enable level-5 paging */
|
||||
#define CR4_VMXE 0x2000 /* enable VMX operations */
|
||||
#define CR4_SMXE 0x4000 /* enable SMX operations */
|
||||
#define CR4_FSGSBASE 0x00010000 /* enable *FSBASE and *GSBASE instructions */
|
||||
#define CR4_PCIDE 0x00020000 /* enable process-context identifiers */
|
||||
#define CR4_OSXSAVE 0x00040000 /* enable XSAVE */
|
||||
|
||||
#define XCR0_X87 0x01
|
||||
#define XCR0_SSE 0x02
|
||||
#define XCR0_AVX 0x04
|
||||
#define XCR0_BNDREG 0x08
|
||||
#define XCR0_BNDCSR 0x10
|
||||
#define XCR0_OPMASK 0x20
|
||||
#define XCR0_ZMM_HI256 0x40
|
||||
#define XCR0_HI16_ZMM 0x80
|
||||
|
||||
#define EFER 0xc0000080 /* extended feature enable register */
|
||||
#define EFER_SCE 0x01 /* system call extensions */
|
||||
#define EFER_LME 0x0100 /* long mode enable */
|
||||
#define EFER_LMA 0x0400 /* long mode active */
|
||||
#define EFER_NXE 0x0800 /* no-execute enable */
|
||||
|
||||
#define GDT_REAL_CODE 8
|
||||
#define GDT_REAL_DATA 16
|
||||
#define GDT_LEGACY_CODE 24
|
||||
#define GDT_LEGACY_DATA 32
|
||||
#define GDT_LONG_CODE 40
|
||||
#define GDT_LONG_DATA 48
|
||||
|
||||
#define PIC1 0x20 /* IO base address for master PIC */
|
||||
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||
#define PIC1_CMD PIC1
|
||||
#define PIC1_DATA (PIC1 + 1)
|
||||
#define PIC2_CMD PIC2
|
||||
#define PIC2_DATA (PIC2 + 1)
|
||||
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
||||
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
||||
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
||||
|
||||
/* Long Mode Paging
|
||||
@see Intel Manual V.3A §4.1 §4.5
|
||||
IsValid (ignored on CR3) V┐
|
||||
┌XD:No Inst. Fetches (if NXE) IsWritable (ignored on CR3) RW┐│
|
||||
│ Permit User-Mode Access - u┐││
|
||||
│ Page-level Write-Through - PWT┐│││
|
||||
│ Page-level Cache Disable - PCD┐││││
|
||||
│ Set if has been read - Accessed┐│││││
|
||||
│ Set if has been written - Dirty┐││││││
|
||||
│ IsPage (if PDPTE/PDE) or PAT (if PT)┐│││││││
|
||||
│ (If this maps 2MB/1GB page and CR4.PGE) Global┐││││││││
|
||||
│ (If IsPage 2MB/1GB, see Intel V3A § 11.12) PAT │││││││││
|
||||
│ │ │││││││││
|
||||
│ ┌────────────────────────────────────┤ │││││││││
|
||||
│ Must Be 0┐│ Next Page Table Address (!IsPage) │ │││││││││
|
||||
│ │├────────────────────────────────────┤ │││││││││
|
||||
│ ││ Physical Address 4KB │ │││││││││
|
||||
│┌───┐┌─────┐│├───────────────────────────┐ │ign│││││││││
|
||||
││PKE││ ign │││ Physical Address 2MB │ │┌┴┐│││││││││
|
||||
││ ││ ││├──────────────────┐ │ ││ ││││││││││
|
||||
││ ││ │││ Phys. Addr. 1GB │ │ ││ ││││││││││
|
||||
││ ││ │││ │ │ ││ ││││││││││
|
||||
6666555555555544444444443333333333222222222211111111110000000000
|
||||
3210987654321098765432109876543210987654321098765432109876543210*/
|
||||
#define PAGE_V /* */ 0b000000001
|
||||
#define PAGE_RW /* */ 0b000000010
|
||||
#define PAGE_U /* */ 0b000000100
|
||||
#define PAGE_4KB /* */ 0b010000000
|
||||
#define PAGE_2MB /* */ 0b110000000
|
||||
#define PAGE_1GB /* */ 0b110000000
|
||||
#define PAGE_TA 0b11111111111111111111111111111111111111000000000000
|
||||
#define PAGE_PA2 0b11111111111111111111111111111000000000000000000000
|
||||
#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 */
|
||||
};
|
||||
|
||||
struct IdtDescriptor {
|
||||
uint16_t offset_1; /* offset bits 0..15 */
|
||||
uint16_t selector; /* a code segment selector in GDT or LDT */
|
||||
uint8_t ist; /* bits 0..2 hold stack table offset, rest are zero */
|
||||
uint8_t type_attr; /* type and attributes */
|
||||
uint16_t offset_2; /* offset bits 16..31 */
|
||||
uint32_t offset_3; /* offset bits 32..63 */
|
||||
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;
|
||||
}
|
||||
|
||||
forceinline unsigned char inb(unsigned short port) {
|
||||
unsigned char al;
|
||||
asm volatile("inb\t%1,%0" : "=a"(al) : "dN"(port));
|
||||
return al;
|
||||
}
|
||||
|
||||
forceinline void outb(unsigned short port, unsigned char byte) {
|
||||
asm volatile("outb\t%0,%1"
|
||||
: /* no inputs */
|
||||
: "a"(byte), "dN"(port));
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* APE_LIB_PC_H_ */
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue