-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bios: Add code to boot as Firmware ROM
The new assembly files handle: - rom16.s: Jumping from reset, transitioning to 32-bit mode - rom32.s: Copying data from ROM to RAM, jumping to PVH entry point To place this code correctly, we add a new Program Header for the code and data that expect to be in ROM. See the comments in layout.ld for more information. We also place the 32-bit GDT in the ROM. This is mostly for convenience, as it lets us use the GDT directly from the ROM code without having to do any complex offset calculations. As laying out the code for a ROM makes the binary ~45% bigger, we gate building as a ROM behind an optional feature. Signed-off-by: Joe Richey <[email protected]>
- Loading branch information
Showing
6 changed files
with
116 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,7 @@ | ||
global_asm!(include_str!("ram32.s")); | ||
global_asm!(include_str!("ram64.s")); | ||
|
||
#[cfg(feature = "rom")] | ||
global_asm!(include_str!("rom16.s")); | ||
#[cfg(feature = "rom")] | ||
global_asm!(include_str!("rom32.s")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
.section .rom16, "ax" | ||
.code16 | ||
|
||
rom16_start: | ||
# Order of instructions from Intel SDM 9.9.1 "Switching to Protected Mode" | ||
# Step 1: Disable interrupts | ||
cli | ||
|
||
# Step 2: Load the GDT | ||
# We are currently in 16-bit real mode. To enter 32-bit protected mode, we | ||
# need to load 32-bit code/data segments into our GDT. The gdt32 in ROM is | ||
# at too high of an address (right below 4G) for the data segment to reach. | ||
# | ||
# But we can load gdt32 via the code segement. After a reset, the base of | ||
# the CS register is 0xFFFF0000, which means we can access gdt32. | ||
movw $(GDT32_PTR - 0xFFFF0000), %bx | ||
lgdtl %cs:(%bx) | ||
|
||
# Step 3: Set CRO.PE (Protected Mode Enable) | ||
movl %cr0, %eax | ||
orb $0b00000001, %al # Set bit 0 | ||
movl %eax, %cr0 | ||
|
||
# Step 4: Far JMP to change execution flow and serialize the processor. | ||
# Set CS to a 32-bit Code-Segment and jump to 32-bit code. | ||
ljmpl $0x08, $rom32_start | ||
|
||
# The reset vector must go at the end of ROM, exactly 16 bytes from the end. | ||
reset_vec: # 0x0_FFFF_FFF0 | ||
jmp rom16_start | ||
.space (reset_vec + 0x10) - . # Pad to the end with zeros | ||
four_gigs: # 0x1_0000_0000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
.section .rom32, "ax" | ||
.code32 | ||
|
||
rom32_start: | ||
# Now that we are in 32-bit mode, setup all the Data-Segments to be 32-bit. | ||
movw $0x10, %ax | ||
movw %ax, %ds | ||
movw %ax, %es | ||
movw %ax, %ss | ||
movw %ax, %fs | ||
movw %ax, %gs | ||
|
||
# Needed for the REP instructions below | ||
cld | ||
|
||
copy_rom_to_ram: | ||
# This is equivalent to: memcpy(data_start, rom_data_start, data_size) | ||
movl $rom_data_start, %esi | ||
movl $data_start, %edi | ||
movl $data_size, %ecx | ||
rep movsb (%esi), (%edi) | ||
|
||
zero_bss_in_ram: | ||
# This is equivalent to: memset(bss_start, 0, bss_size) | ||
xorb %al, %al | ||
movl $bss_start, %edi | ||
movl $bss_size, %ecx | ||
rep stosb %al, (%edi) | ||
|
||
jump_to_ram: | ||
# Zero out %ebx, as we don't have a PVH StartInfo struct. | ||
xorl %ebx, %ebx | ||
|
||
# Jumping all that way from ROM (~4 GiB) to RAM (~1 MiB) is too far for a | ||
# 32-bit relative jump, so we use a 32-bit aboslute jump. | ||
movl $ram32_start, %eax | ||
jmp *%eax |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters