Skip to content

Commit 08e4b58

Browse files
committed
Allocate kernel as normal UEFI loader data
Custom memory kinds are apparently not supported on some architectures.
1 parent 130d5f0 commit 08e4b58

File tree

5 files changed

+75
-10
lines changed

5 files changed

+75
-10
lines changed

api/src/info.rs

-2
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ pub enum MemoryRegionKind {
145145
///
146146
/// This memory should _not_ be used by the kernel.
147147
Bootloader,
148-
/// Memory mapping of the kernel.
149-
Kernel,
150148
/// An unknown memory region reported by the UEFI firmware.
151149
///
152150
/// Contains the UEFI memory type tag.

common/src/legacy_memory_region.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ where
101101
pub fn construct_memory_map(
102102
self,
103103
regions: &mut [MaybeUninit<MemoryRegion>],
104+
kernel_slice_start: u64,
105+
kernel_slice_len: u64,
104106
) -> &mut [MemoryRegion] {
105107
let mut next_index = 0;
106108

@@ -145,7 +147,52 @@ where
145147
end: end.as_u64(),
146148
kind,
147149
};
148-
Self::add_region(region, regions, &mut next_index).unwrap();
150+
151+
// check if region overlaps with kernel
152+
let kernel_slice_end = kernel_slice_start + kernel_slice_len;
153+
if region.kind == MemoryRegionKind::Usable
154+
&& kernel_slice_start < region.end
155+
&& kernel_slice_end >= region.start
156+
{
157+
// region overlaps with kernel -> we might need to split it
158+
159+
// ensure that the kernel allocation does not span multiple regions
160+
assert!(
161+
kernel_slice_start >= region.start,
162+
"region overlaps with kernel, but kernel begins before region \
163+
(kernel_slice_start: {kernel_slice_start:#x}, region_start: {:#x})",
164+
region.start
165+
);
166+
assert!(
167+
kernel_slice_end <= region.end,
168+
"region overlaps with kernel, but region ends before kernel \
169+
(kernel_slice_end: {kernel_slice_end:#x}, region_end: {:#x})",
170+
region.end,
171+
);
172+
173+
// split the region into three parts
174+
let before_kernel = MemoryRegion {
175+
end: kernel_slice_start,
176+
..region
177+
};
178+
let kernel = MemoryRegion {
179+
start: kernel_slice_start,
180+
end: kernel_slice_end,
181+
kind: MemoryRegionKind::Bootloader,
182+
};
183+
let after_kernel = MemoryRegion {
184+
start: kernel_slice_end,
185+
..region
186+
};
187+
188+
// add the three regions (empty regions are ignored in `add_region`)
189+
Self::add_region(before_kernel, regions, &mut next_index).unwrap();
190+
Self::add_region(kernel, regions, &mut next_index).unwrap();
191+
Self::add_region(after_kernel, regions, &mut next_index).unwrap();
192+
} else {
193+
// add the region normally
194+
Self::add_region(region, regions, &mut next_index).unwrap();
195+
}
149196
}
150197

151198
let initialized = &mut regions[..next_index];
@@ -161,6 +208,10 @@ where
161208
regions: &mut [MaybeUninit<MemoryRegion>],
162209
next_index: &mut usize,
163210
) -> Result<(), ()> {
211+
if region.start == region.end {
212+
// skip zero sized regions
213+
return Ok(());
214+
}
164215
unsafe {
165216
regions
166217
.get_mut(*next_index)

common/src/lib.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ pub struct SystemInfo {
5656
pub struct Kernel<'a> {
5757
pub elf: ElfFile<'a>,
5858
pub config: BootloaderConfig,
59+
pub start_address: *const u8,
60+
pub len: usize,
5961
}
6062

6163
impl<'a> Kernel<'a> {
@@ -72,6 +74,8 @@ impl<'a> Kernel<'a> {
7274
Kernel {
7375
elf: kernel_elf,
7476
config,
77+
start_address: kernel_slice.as_ptr(),
78+
len: kernel_slice.len(),
7579
}
7680
}
7781
}
@@ -151,6 +155,9 @@ where
151155
enable_write_protect_bit();
152156

153157
let config = kernel.config;
158+
let kernel_slice_start = kernel.start_address as u64;
159+
let kernel_slice_len = u64::try_from(kernel.len).unwrap();
160+
154161
let (entry_point, tls_template) = load_kernel::load_kernel(
155162
kernel,
156163
kernel_page_table,
@@ -313,6 +320,9 @@ where
313320
physical_memory_offset,
314321
recursive_index,
315322
tls_template,
323+
324+
kernel_slice_start,
325+
kernel_slice_len,
316326
}
317327
}
318328

@@ -333,6 +343,11 @@ pub struct Mappings {
333343
pub recursive_index: Option<PageTableIndex>,
334344
/// The thread local storage template of the kernel executable, if it contains one.
335345
pub tls_template: Option<TlsTemplate>,
346+
347+
/// Start address of the kernel slice allocation in memory.
348+
pub kernel_slice_start: u64,
349+
/// Size of the kernel slice allocation in memory.
350+
pub kernel_slice_len: u64,
336351
}
337352

338353
/// Allocates and initializes the boot info struct and the memory map.
@@ -357,7 +372,7 @@ where
357372
// allocate and map space for the boot info
358373
let (boot_info, memory_regions) = {
359374
let boot_info_layout = Layout::new::<BootInfo>();
360-
let regions = frame_allocator.len() + 1; // one region might be split into used/unused
375+
let regions = frame_allocator.len() + 4; // up to 4 regions might be split into used/unused
361376
let memory_regions_layout = Layout::array::<MemoryRegion>(regions).unwrap();
362377
let (combined, memory_regions_offset) =
363378
boot_info_layout.extend(memory_regions_layout).unwrap();
@@ -412,7 +427,11 @@ where
412427
log::info!("Create Memory Map");
413428

414429
// build memory map
415-
let memory_regions = frame_allocator.construct_memory_map(memory_regions);
430+
let memory_regions = frame_allocator.construct_memory_map(
431+
memory_regions,
432+
mappings.kernel_slice_start,
433+
mappings.kernel_slice_len,
434+
);
416435

417436
log::info!("Create bootinfo");
418437

uefi/src/main.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::memory_descriptor::UefiMemoryDescriptor;
77
use bootloader_api::{info::FrameBufferInfo, BootloaderConfig};
88
use bootloader_x86_64_common::{legacy_memory_region::LegacyFrameAllocator, Kernel, SystemInfo};
99
use core::{arch::asm, cell::UnsafeCell, fmt::Write, mem, panic::PanicInfo, ptr, slice};
10-
use memory_descriptor::KERNEL_MEMORY_TYPE;
1110
use uefi::{
1211
prelude::{entry, Boot, Handle, Status, SystemTable},
1312
proto::{
@@ -203,7 +202,7 @@ fn load_kernel_file_from_disk(image: Handle, st: &SystemTable<Boot>) -> Option<&
203202
.boot_services()
204203
.allocate_pages(
205204
AllocateType::AnyPages,
206-
KERNEL_MEMORY_TYPE,
205+
MemoryType::LOADER_DATA,
207206
((kernel_size - 1) / 4096) + 1,
208207
)
209208
.unwrap() as *mut u8;
@@ -283,7 +282,7 @@ fn load_kernel_file_from_tftp_boot_server(
283282
.boot_services()
284283
.allocate_pages(
285284
AllocateType::AnyPages,
286-
KERNEL_MEMORY_TYPE,
285+
MemoryType::LOADER_DATA,
287286
((kernel_size - 1) / 4096) + 1,
288287
)
289288
.expect("Failed to allocate memory for the kernel file") as *mut u8;

uefi/src/memory_descriptor.rs

-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use x86_64::PhysAddr;
77
pub struct UefiMemoryDescriptor(pub MemoryDescriptor);
88

99
const PAGE_SIZE: u64 = 4096;
10-
pub const KERNEL_MEMORY_TYPE: MemoryType = MemoryType::custom(0x80000000);
1110

1211
impl<'a> LegacyMemoryRegion for UefiMemoryDescriptor {
1312
fn start(&self) -> PhysAddr {
@@ -21,7 +20,6 @@ impl<'a> LegacyMemoryRegion for UefiMemoryDescriptor {
2120
fn kind(&self) -> MemoryRegionKind {
2221
match self.0.ty {
2322
MemoryType::CONVENTIONAL => MemoryRegionKind::Usable,
24-
other if other == KERNEL_MEMORY_TYPE => MemoryRegionKind::Kernel,
2523
other => MemoryRegionKind::UnknownUefi(other.0),
2624
}
2725
}

0 commit comments

Comments
 (0)