Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit af99f0f

Browse files
authored
Merge pull request #466 from rust-osdev/fix/frame-buffer-not-in-first-pml4
copy more PML4 entries
2 parents 5d318bf + 9726814 commit af99f0f

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

‎common/src/level_4_entries.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@ impl UsedLevel4Entries {
3939
rng: config.mappings.aslr.then(entropy::build_rng),
4040
};
4141

42-
used.entry_state[0] = true; // TODO: Can we do this dynamically?
42+
// The bootloader maps of the kernel's memory into its own page tables.
43+
// We need to prevent overlaps, so mark all memory that could already
44+
// be used by the bootload as inaccessible.
45+
46+
// All memory in this range is identity mapped.
47+
used.mark_range_as_used(0, max_phys_addr.as_u64());
48+
49+
// The bootload needs to access the frame buffer.
50+
if let Some(frame_buffer) = framebuffer {
51+
used.mark_range_as_used(frame_buffer.addr.as_u64(), frame_buffer.info.byte_len);
52+
}
4353

4454
// Mark the statically configured ranges from the config as used.
4555

‎uefi/src/main.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
144144
let mut frame_allocator =
145145
LegacyFrameAllocator::new(memory_map.entries().copied().map(UefiMemoryDescriptor));
146146

147-
let page_tables = create_page_tables(&mut frame_allocator);
147+
let max_phys_addr = frame_allocator.max_phys_addr();
148+
let page_tables = create_page_tables(&mut frame_allocator, max_phys_addr, framebuffer.as_ref());
148149
let mut ramdisk_len = 0u64;
149150
let ramdisk_addr = if let Some(rd) = ramdisk {
150151
ramdisk_len = rd.len() as u64;
@@ -385,6 +386,8 @@ fn load_file_from_tftp_boot_server(
385386
/// Creates page table abstraction types for both the bootloader and kernel page tables.
386387
fn create_page_tables(
387388
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
389+
max_phys_addr: PhysAddr,
390+
frame_buffer: Option<&RawFrameBufferInfo>,
388391
) -> bootloader_x86_64_common::PageTables {
389392
// UEFI identity-maps all memory, so the offset between physical and virtual addresses is 0
390393
let phys_offset = VirtAddr::new(0);
@@ -410,9 +413,21 @@ fn create_page_tables(
410413
}
411414
};
412415

413-
// copy the first entry (we don't need to access more than 512 GiB; also, some UEFI
414-
// implementations seem to create an level 4 table entry 0 in all slots)
415-
new_table[0] = old_table[0].clone();
416+
// copy the pml4 entries for all identity mapped memory.
417+
let end_addr = VirtAddr::new(max_phys_addr.as_u64() - 1);
418+
for p4 in 0..=usize::from(end_addr.p4_index()) {
419+
new_table[p4] = old_table[p4].clone();
420+
}
421+
422+
// copy the pml4 entry for the frame buffer (the frame buffer is not
423+
// necessarily part of the identity mapping).
424+
if let Some(frame_buffer) = frame_buffer {
425+
let start_addr = VirtAddr::new(frame_buffer.addr.as_u64());
426+
let end_addr = start_addr + frame_buffer.info.byte_len;
427+
for p4 in usize::from(start_addr.p4_index())..=usize::from(end_addr.p4_index()) {
428+
new_table[p4] = old_table[p4].clone();
429+
}
430+
}
416431

417432
// the first level 4 table entry is now identical, so we can just load the new one
418433
unsafe {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /