Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,17 @@ MPS INTI flags:
<tr><td>Trigger Mode</td><td>2</td><td>2</td><td>01 Edge-triggered, 11 Level-triggered</td></tr>
</table>

A copy of the UEFI System Memory Map is stored at memory address `0x0000000000006000`. Each UEFI record is 48 bytes in length and the memory map is terminated by a blank record.
A copy of the BIOS System Memory Map is stored at memory address `0x0000000000006000`. Each BIOS record is 32 bytes in length and the memory map is terminated by a blank record.
<table border="1" cellpadding="2" cellspacing="0">
<tr><th>Variable</th><th>Variable Size</th><th>Description</th></tr>
<tr><td>Base</td><td>64-bit</td><td>Base Address</td></tr>
<tr><td>Length</td><td>64-bit</td><td>Length in bytes</td></tr>
<tr><td>Type</td><td>32-bit</td><td>Type of memory (1 is usable)</td></tr>
<tr><td>ACPI</td><td>32-bit</td><td>See document linked below</td></tr>
</table>
For more information on the BIOS Memory Map: <a href="https://wiki.osdev.org/Detecting_Memory_(x86)#BIOS_Function:_INT_0x15,_EAX_=_0xE820">BIOS Specs</a>

A copy of the UEFI System Memory Map is stored at memory address `0x0000000000220000`. Each UEFI record is 48 bytes in length and the memory map is terminated by a blank record.
<table border="1" cellpadding="2" cellspacing="0">
<tr><th>Variable</th><th>Variable Size</th><th>Description</th></tr>
<tr><td>Type</td><td>64-bit</td><td>The type of the memory region</td></tr>
Expand Down
2 changes: 1 addition & 1 deletion src/boot/uefi.asm
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ FBS: dq 0 ; Frame buffer size
HR: dq 0 ; Horizontal Resolution
VR: dq 0 ; Vertical Resolution
PPSL: dq 0 ; PixelsPerScanLine
memmap: dq 0x200000 ; Store the Memory Map from UEFI here
memmap: dq 0x220000 ; Store the Memory Map from UEFI here
memmapsize: dq 32768 ; Max size we are expecting in bytes
memmapkey: dq 0
memmapdescsize: dq 0
Expand Down
100 changes: 57 additions & 43 deletions src/pure64.asm
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ msg_boot_done:
; PDPTE is stored at 0x0000000000003000, create the first entry there
; A single PDPTE can map 1GiB
; A single PDPTE is 8 bytes in length
; 4 entries are created to map the first 4GiB of RAM
mov ecx, 4 ; number of PDPE's to make.. each PDPE maps 1GiB of physical memory
; FIXME - This willy completely fill the 64K set for the low PDE (only 16GiB identity mapped)
mov ecx, 16 ; number of PDPE's to make.. each PDPE maps 1GiB of physical memory
mov edi, 0x00003000 ; location of low PDPE
mov eax, 0x00010007 ; Bits 0 (P), 1 (R/W), 2 (U/S), location of first low PD (4KiB aligned)
pdpte_low:
Expand All @@ -290,7 +290,7 @@ pdpte_low:
; A single PDE is 8 bytes in length
mov edi, 0x00010000 ; Location of first PDE
mov eax, 0x00000087 ; Bits 0 (P), 1 (R/W), 2 (U/S), and 7 (PS) set
mov ecx, 2048 ; Create 2048 2MiB page maps
mov ecx, 8192 ; Create 8192 2MiB page maps
pde_low: ; Create a 2MiB page
stosq
add rax, 0x00200000 ; Increment by 2MiB
Expand Down Expand Up @@ -381,44 +381,50 @@ clearcs64:
stosd
stosd ; Write 8 bytes in total to overwrite the 'far jump' and marker

; Parse the Memory Map at 0x200000
; Parse the Memory Map from BIOS/UEFI
cmp byte [p_BootMode], 'U'
jne bios_memmap

; Parse the memory map provided by UEFI
uefi_memmap:
xor ebx, ebx ; Running counter of 4K pages
mov esi, 0x200000
; Process the UEFI memory map to find all possible 2MiB pages that are free to use
; Build an available memory map at 0x200000
xor ebx, ebx ; Running counter of available MiBs
mov esi, 0x00220000
mov edi, 0x00200000 ; 2MiB
sub esi, 48
uefi_memmap_next:
add esi, 48
mov rax, [rsi]
cmp rax, 7 ; EfiConventionalMemory (Free)
je uefi_memmap_conventional
mov rax, [rsi+24]
cmp rax, 0
je uefi_memmap_end
uefi_memmap_skip:
add esi, 48
jmp uefi_memmap_next
uefi_memmap_conventional:
mov rax, [rsi + 24]
mov rax, [rsi+8] ; Physical Address
stosq
mov rax, [rsi+24] ; Number of 4 KiB pages
shr rax, 8 ; Convert to MiB
stosq
cmp rax, 0
jne uefi_memmap_keeprecord
sub rdi, 16
uefi_memmap_keeprecord:
add rbx, rax
jmp uefi_memmap_skip
jmp uefi_memmap_next
uefi_memmap_end:
shr rbx, 8
mov dword [p_mem_amount], ebx

; FIXME - Don't hardcode the RAM to 64MiB
mov eax, 64
mov dword [p_mem_amount], eax

jmp memmap_end

; Parse the memory map provided by BIOS
bios_memmap:
; Process the E820 memory map to find all possible 2MiB pages that are free to use
; Build a map at 0x400000
; Build an available memory map at 0x200000
xor ecx, ecx
xor ebx, ebx ; Counter for pages found
xor ebx, ebx ; Running counter of available MiBs
mov esi, 0x00006000 ; E820 Map location
mov edi, 0x00200000 ; 2MiB
bios_memmap_nextentry:
add esi, 16 ; Skip ESI to type marker
mov eax, [esi] ; Load the 32-bit type marker
Expand All @@ -428,44 +434,37 @@ bios_memmap_nextentry:
je bios_memmap_processfree
add esi, 16 ; Skip ESI to start of next entry
jmp bios_memmap_nextentry

bios_memmap_processfree:
; TODO Check ACPI 3.0 Extended Attributes - Bit 0 should be set
sub esi, 16
mov rax, [rsi] ; Physical start address
add esi, 8
mov rcx, [rsi] ; Physical length
add esi, 24
shr rcx, 21 ; Convert bytes to # of 2 MiB pages
shr rcx, 20 ; Convert bytes to MiB
cmp rcx, 0 ; Do we have at least 1 page?
je bios_memmap_nextentry
shl rax, 1
mov edx, 0x1FFFFF
not rdx ; Clear bits 20 - 0
and rax, rdx
; At this point RAX points to the start and RCX has the # of pages
shr rax, 21 ; page # to start on
mov rdi, 0x400000 ; 4 MiB into physical memory
add rdi, rax
mov al, 1
stosq
mov rax, rcx
stosq
add ebx, ecx
rep stosb
jmp bios_memmap_nextentry

bios_memmap_end820:
shl ebx, 1
sub ebx, 2 ; Subtract 2MiB for the CPU stacks
mov dword [p_mem_amount], ebx

memmap_end:

sub ebx, 2 ; Subtract 2MiB for the CPU stacks
mov dword [p_mem_amount], ebx
xor eax, eax
stosq
stosq

; Create the High Page-Directory-Pointer-Table Entries (PDPTE)
; High PDPTE is stored at 0x0000000000004000, create the first entry there
; A single PDPTE can map 1GiB with 2MiB pages
; A single PDPTE is 8 bytes in length
; 1 entry is created to map the first 1GiB of physical RAM to 0xFFFF800000000000
; FIXME - Create more than just one PDPE depending on the amount of RAM in the system
add rcx, 1 ; number of PDPE's to make.. each PDPE maps 1GB of physical memory
mov ecx, dword [p_mem_amount]
shr ecx, 10 ; MBs -> GBs
add rcx, 1 ; Add 1. This is the number of PDPE's to make
mov edi, 0x00004000 ; location of high PDPE
mov eax, 0x00020007 ; location of first high PD. Bits (0) P, 1 (R/W), and 2 (U/S) set
create_pdpe_high:
Expand All @@ -478,17 +477,32 @@ create_pdpe_high:
; Create the High Page-Directory Entries (PDE).
; A single PDE can map 2MiB of RAM
; A single PDE is 8 bytes in length
mov esi, 0x00200000 ; Location of the available memory map
mov edi, 0x00020000 ; Location of first PDE
mov eax, 0x0000008F ; Bits 0 (P), 1 (R/W), 2 (U/S), 3 (PWT), and 7 (PS) set
add rax, 0x00400000 ; Start at 4MiB in (0-2MiB for system, 2MiB-4MiB for stacks)
mov ecx, [p_mem_amount]
shr ecx, 1
pde_next_range:
lodsq ; Load the base
xchg rax, rcx
lodsq ; Load the length
xchg rax, rcx
cmp rax, 0 ; Check if at end of records
je pde_end ; Bail out if so
cmp rax, 0x00100000
jg skipfirst4mb
add rax, 0x00300000 ; Add 3 MiB to the base
sub rcx, 3 ; Subtract 3 MiB from the length
skipfirst4mb:
shr ecx, 1 ; Quick divide by 2 for 2 MB pages
add rax, 0x0000008F ; Bits 0 (P), 1 (R/W), 2 (U/S), 3 (PWT), and 7 (PS) set
pde_high: ; Create a 2MiB page
stosq
add rax, 0x00200000 ; Increment by 2MiB
cmp ecx, 0
je pde_next_range
dec ecx
cmp ecx, 0
jne pde_high
jmp pde_next_range
pde_end:

; Build the IDT
xor edi, edi ; create the 64-bit IDT (at linear address 0x0000000000000000)
Expand Down