From d8b6a6123acfa9296f93c64cd6fa5b400dc6acc2 Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Fri, 2 Aug 2024 16:49:24 -0400 Subject: [PATCH 1/4] BIOS memory mapping works --- docs/README.md | 12 ++++++++++- src/pure64.asm | 55 ++++++++++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/docs/README.md b/docs/README.md index dbb205f..3f2982b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -232,7 +232,17 @@ MPS INTI flags: Trigger Mode2201 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. + + + + + + +
VariableVariable SizeDescription
Base64-bitBase Address
Length64-bitLength in bytes
Type32-bitType of memory (1 is usable)
ACPI32-bitSee 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 `0x0000000000200000`. Each UEFI record is 48 bytes in length and the memory map is terminated by a blank record. diff --git a/src/pure64.asm b/src/pure64.asm index 1eae854..16c6054 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 @@ -415,10 +415,11 @@ uefi_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 a map at 0x200000 xor ecx, ecx xor ebx, ebx ; Counter for pages found 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 @@ -430,42 +431,34 @@ bios_memmap_nextentry: 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: - ; 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 +471,31 @@ 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 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) From ef314a7c25f60e65df46cbd68ff1dd44f3b6d54d Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Sat, 3 Aug 2024 12:20:17 -0400 Subject: [PATCH 2/4] UEFI booting with memmap --- docs/README.md | 2 +- src/boot/uefi.asm | 2 +- src/pure64.asm | 32 +++++++++++++++++++------------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/docs/README.md b/docs/README.md index 3f2982b..f7dc381 100644 --- a/docs/README.md +++ b/docs/README.md @@ -242,7 +242,7 @@ A copy of the BIOS System Memory Map is stored at memory address `0x000000000000
VariableVariable SizeDescription
Type64-bitThe type of the memory region
For more information on the BIOS Memory Map: BIOS Specs -A copy of the UEFI System Memory Map is stored at memory address `0x0000000000200000`. Each UEFI record is 48 bytes in length and the memory map is terminated by a blank record. +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. 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 16c6054..ed436a5 100644 --- a/src/pure64.asm +++ b/src/pure64.asm @@ -387,8 +387,9 @@ clearcs64: ; Parse the memory map provided by UEFI uefi_memmap: - xor ebx, ebx ; Running counter of 4K pages - mov esi, 0x200000 + xor ebx, ebx ; Running counter of MiBs + mov esi, 0x00220000 + mov edi, 0x00200000 ; 2MiB uefi_memmap_next: mov rax, [rsi] cmp rax, 7 ; EfiConventionalMemory (Free) @@ -399,17 +400,18 @@ 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 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 @@ -447,10 +449,13 @@ bios_memmap_processfree: jmp bios_memmap_nextentry bios_memmap_end820: - 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 @@ -490,11 +495,12 @@ skipfirst4mb: 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 From 920050376293dadcdefde3891541ac1b656c0235 Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Sat, 3 Aug 2024 13:40:46 -0400 Subject: [PATCH 3/4] UEFI working --- src/pure64.asm | 53 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/src/pure64.asm b/src/pure64.asm index ed436a5..9a668dc 100644 --- a/src/pure64.asm +++ b/src/pure64.asm @@ -381,28 +381,31 @@ 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 MiBs +; 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+8] ; Physical Address stosq - mov rax, [rsi + 24] ; Number of 4 KiB pages + mov rax, [rsi+24] ; Number of 4 KiB pages shr rax, 8 ; Convert to MiB stosq cmp rax, 0 @@ -410,16 +413,16 @@ uefi_memmap_conventional: sub rdi, 16 uefi_memmap_keeprecord: add rbx, rax - jmp uefi_memmap_skip + jmp uefi_memmap_next uefi_memmap_end: 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 0x200000 +; 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: @@ -457,6 +460,10 @@ memmap_end: stosq stosq +; UEFI HACKIN' +; cmp byte [p_BootMode], 'U' +; je hack + ; 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 @@ -502,6 +509,36 @@ pde_high: ; Create a 2MiB page jne pde_high jmp pde_next_range pde_end: + jmp idt + +; UEFI HACKIN' START + +hack: + mov rcx, 1 ; number of PDPE's to make.. each PDPE maps 1GB of physical memory + 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 +hack_create_pdpe_high: + stosq + add rax, 0x00001000 ; 4K later (512 records x 8 bytes) + dec ecx + cmp ecx, 0 + jne hack_create_pdpe_high + + 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, 64 + shr ecx, 1 +hack_pde_high: ; Create a 2MiB page + stosq + add rax, 0x00200000 ; Increment by 2MiB + dec ecx + cmp ecx, 0 + jne hack_pde_high + +; UEFI HACKIN' END + +idt: ; Build the IDT xor edi, edi ; create the 64-bit IDT (at linear address 0x0000000000000000) From 155ecd6c817c640dfbe979c5a225ebfb612e7bfb Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Sat, 3 Aug 2024 17:50:41 -0400 Subject: [PATCH 4/4] Cleanup prior to merge --- src/pure64.asm | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/pure64.asm b/src/pure64.asm index 9a668dc..9ed25df 100644 --- a/src/pure64.asm +++ b/src/pure64.asm @@ -434,7 +434,6 @@ 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 @@ -450,7 +449,6 @@ bios_memmap_processfree: stosq add ebx, ecx jmp bios_memmap_nextentry - bios_memmap_end820: memmap_end: @@ -460,10 +458,6 @@ memmap_end: stosq stosq -; UEFI HACKIN' -; cmp byte [p_BootMode], 'U' -; je hack - ; 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 @@ -509,36 +503,6 @@ pde_high: ; Create a 2MiB page jne pde_high jmp pde_next_range pde_end: - jmp idt - -; UEFI HACKIN' START - -hack: - mov rcx, 1 ; number of PDPE's to make.. each PDPE maps 1GB of physical memory - 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 -hack_create_pdpe_high: - stosq - add rax, 0x00001000 ; 4K later (512 records x 8 bytes) - dec ecx - cmp ecx, 0 - jne hack_create_pdpe_high - - 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, 64 - shr ecx, 1 -hack_pde_high: ; Create a 2MiB page - stosq - add rax, 0x00200000 ; Increment by 2MiB - dec ecx - cmp ecx, 0 - jne hack_pde_high - -; UEFI HACKIN' END - -idt: ; Build the IDT xor edi, edi ; create the 64-bit IDT (at linear address 0x0000000000000000)
VariableVariable SizeDescription
Type64-bitThe type of the memory region