Skip to content

Commit e1c825f

Browse files
authored
Make bootloader compatible with Theseus (#2)
Summary of changes: - Add size to boot info - Add modules to boot info - Add kernel elf sections to boot info - Remove BIOS building from build script - Make kernel stack page aligned - Modify stack to use last page of memory (fixes rust-osdev#294) - Add stack guard page - Remove push operation from context switch - Modify frame allocator to only allocate frames above 0x10000 Signed-off-by: Klim Tsoutsman <[email protected]>
1 parent 669e3c0 commit e1c825f

File tree

6 files changed

+676
-348
lines changed

6 files changed

+676
-348
lines changed

Diff for: api/src/info.rs

+140-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::{ops, slice};
1+
use core::{ops, slice, str};
22

33
use crate::config::ApiVersion;
44

@@ -22,6 +22,8 @@ use crate::config::ApiVersion;
2222
pub struct BootInfo {
2323
/// The version of the `bootloader_api` crate. Must match the `bootloader` version.
2424
pub api_version: ApiVersion,
25+
/// The size of the boot info.
26+
pub size: usize,
2527
/// A map of the physical memory regions of the underlying machine.
2628
///
2729
/// The bootloader queries this information from the BIOS/UEFI firmware and translates this
@@ -52,21 +54,28 @@ pub struct BootInfo {
5254
pub rsdp_addr: Optional<u64>,
5355
/// The thread local storage (TLS) template of the kernel executable, if present.
5456
pub tls_template: Optional<TlsTemplate>,
57+
/// Files stored in the modules subdirectory of the kernel image.
58+
pub modules: Modules,
59+
/// The ELF sections of the kernel executable.
60+
pub elf_sections: ElfSections,
5561
}
5662

5763
impl BootInfo {
58-
/// Create a new boot info structure with the given memory map.
64+
/// Create a new boot info structure with the given memory map, modules, and elf sections.
5965
///
6066
/// The other fields are initialized with default values.
61-
pub fn new(memory_regions: MemoryRegions) -> Self {
67+
pub fn new(memory_regions: MemoryRegions, modules: Modules, elf_sections: ElfSections) -> Self {
6268
Self {
6369
api_version: ApiVersion::new_default(),
70+
size: 0,
6471
memory_regions,
6572
framebuffer: Optional::None,
6673
physical_memory_offset: Optional::None,
6774
recursive_index: Optional::None,
6875
rsdp_addr: Optional::None,
6976
tls_template: Optional::None,
77+
modules,
78+
elf_sections,
7079
}
7180
}
7281
}
@@ -275,6 +284,134 @@ pub struct TlsTemplate {
275284
pub mem_size: u64,
276285
}
277286

287+
/// FFI-safe slice of [`Module`] structs, semantically equivalent to
288+
/// `&'static mut [Module]`.
289+
#[derive(Debug)]
290+
#[repr(C)]
291+
pub struct Modules {
292+
pub(crate) ptr: *mut Module,
293+
pub(crate) len: usize,
294+
}
295+
296+
impl ops::Deref for Modules {
297+
type Target = [Module];
298+
299+
fn deref(&self) -> &Self::Target {
300+
unsafe { slice::from_raw_parts(self.ptr, self.len) }
301+
}
302+
}
303+
304+
impl ops::DerefMut for Modules {
305+
fn deref_mut(&mut self) -> &mut Self::Target {
306+
unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
307+
}
308+
}
309+
310+
impl From<&'static mut [Module]> for Modules {
311+
fn from(modules: &'static mut [Module]) -> Self {
312+
Self {
313+
ptr: modules.as_mut_ptr(),
314+
len: modules.len(),
315+
}
316+
}
317+
}
318+
319+
impl From<Modules> for &'static mut [Module] {
320+
fn from(modules: Modules) -> Self {
321+
unsafe { slice::from_raw_parts_mut(modules.ptr, modules.len) }
322+
}
323+
}
324+
325+
/// A file.
326+
#[derive(Debug, Clone, Copy)]
327+
#[repr(C)]
328+
pub struct Module {
329+
/// The name of the module encoded as a null-terminated UTF-8 string.
330+
pub name: [u8; 64],
331+
/// The offset in bytes from the start of the modules.
332+
///
333+
/// The offset is guaranteed to be page aligned.
334+
pub offset: usize,
335+
/// The length of the module in bytes.
336+
pub len: usize,
337+
}
338+
339+
impl Module {
340+
/// The name of the module.
341+
pub fn name(&self) -> &str {
342+
let end = self
343+
.name
344+
.iter()
345+
.position(|byte| *byte == 0)
346+
.unwrap_or_else(|| self.name.len());
347+
str::from_utf8(&self.name[..end]).expect("invalid bytes in module name")
348+
}
349+
}
350+
351+
/// FFI-safe slice of [`ElfSection`] structs, semantically equivalent to
352+
/// `&'static mut [ElfSection]`.
353+
#[derive(Debug)]
354+
#[repr(C)]
355+
pub struct ElfSections {
356+
pub(crate) ptr: *mut ElfSection,
357+
pub(crate) len: usize,
358+
}
359+
360+
impl ops::Deref for ElfSections {
361+
type Target = [ElfSection];
362+
363+
fn deref(&self) -> &Self::Target {
364+
unsafe { slice::from_raw_parts(self.ptr, self.len) }
365+
}
366+
}
367+
368+
impl ops::DerefMut for ElfSections {
369+
fn deref_mut(&mut self) -> &mut Self::Target {
370+
unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
371+
}
372+
}
373+
374+
impl From<&'static mut [ElfSection]> for ElfSections {
375+
fn from(elf_sections: &'static mut [ElfSection]) -> Self {
376+
Self {
377+
ptr: elf_sections.as_mut_ptr(),
378+
len: elf_sections.len(),
379+
}
380+
}
381+
}
382+
383+
impl From<ElfSections> for &'static mut [ElfSection] {
384+
fn from(elf_sections: ElfSections) -> Self {
385+
unsafe { slice::from_raw_parts_mut(elf_sections.ptr, elf_sections.len) }
386+
}
387+
}
388+
389+
/// An ELF section.
390+
#[derive(Debug, Clone, Copy)]
391+
#[repr(C)]
392+
pub struct ElfSection {
393+
/// The name of the section encoded as a null-terminated UTF-8 string.
394+
pub name: [u8; 64],
395+
/// The starting virtual address of the section.
396+
pub start: usize,
397+
/// The size of the section in bytes.
398+
pub size: usize,
399+
/// The section flags.
400+
pub flags: u64,
401+
}
402+
403+
impl ElfSection {
404+
/// The name of the section.
405+
pub fn name(&self) -> &str {
406+
let end = self
407+
.name
408+
.iter()
409+
.position(|byte| *byte == 0)
410+
.unwrap_or_else(|| self.name.len());
411+
str::from_utf8(&self.name[..end]).expect("invalid bytes in section name")
412+
}
413+
}
414+
278415
/// FFI-safe variant of [`Option`].
279416
///
280417
/// Implements the [`From`] and [`Into`] traits for easy conversion to and from [`Option`].

0 commit comments

Comments
 (0)