diff --git a/docs/README.md b/docs/README.md
index dbb205f..f7dc381 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -232,7 +232,17 @@ MPS INTI flags:
| Trigger Mode | 2 | 2 | 01 Edge-triggered, 11 Level-triggered |
-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.
+
+| Variable | Variable Size | Description |
+| Base | 64-bit | Base Address |
+| Length | 64-bit | Length in bytes |
+| Type | 32-bit | Type of memory (1 is usable) |
+| ACPI | 32-bit | See document linked below |
+
+For more information on the BIOS Memory Map: BIOS Specs
+
+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.
| Variable | Variable Size | Description |
| Type | 64-bit | The type of the memory region |
diff --git a/src/boot/uefi.asm b/src/boot/uefi.asm
index d418f09..fc75e1c 100644
--- a/src/boot/uefi.asm
+++ b/src/boot/uefi.asm
@@ -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
diff --git a/src/pure64.asm b/src/pure64.asm
index 1eae854..9ed25df 100644
--- a/src/pure64.asm
+++ b/src/pure64.asm
@@ -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:
@@ -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
@@ -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
@@ -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:
@@ -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)