Skip to main content

proka_bootloader/
lib.rs

1//! This crate provides the struct, enums about the Proka
2//! bootloader, including the boot information, and so on.
3//!
4//! # About proka bootloader
5//! Well, this bootloader is for Proka Kernel, which will obey
6//! its standard. For more information, see <url>.
7
8#![no_std]
9#![no_main]
10#![feature(custom_test_frameworks)]
11#![test_runner(self::test_runner)]
12#![reexport_test_harness_main = "test_main"]
13
14pub mod header;
15#[cfg(feature = "loader_main")]
16pub mod loader_main;
17pub mod memory;
18pub mod output;
19mod version;
20use self::memory::MemoryMap;
21use self::output::Framebuffer;
22
23/// This struct is the boot information struct, which provides
24/// the basic information, *memory map*, and so on.
25#[repr(C)]
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct BootInfo {
28    boot_mode: BootMode,
29    framebuffer: Framebuffer,
30    memmap: MemoryMap,
31    acpi_addr: u64,
32}
33
34impl BootInfo {
35    /// Initialize a new boot info object.
36    ///
37    /// Note: this object will be initialized by loader
38    /// automatically, so if you are a kernel developer, do
39    /// not use this method, because you needn't and unusable.
40    #[cfg(feature = "loader_main")]
41    pub fn new(boot_mode: BootMode, memmap: MemoryMap, fb: Framebuffer, acpi_addr: u64) -> Self {
42        Self {
43            boot_mode,
44            acpi_addr,
45            memmap,
46            framebuffer: fb,
47        }
48    }
49
50    /// Get the boot mode.
51    pub const fn boot_mode(&self) -> &BootMode {
52        &self.boot_mode
53    }
54
55    /// Get the framebuffer info.
56    pub const fn framebuffer(&self) -> &Framebuffer {
57        &self.framebuffer
58    }
59
60    /// Get the memory map.
61    pub const fn memory(&self) -> &MemoryMap {
62        &self.memmap
63    }
64
65    /// Get the ACPI RSDP's address.
66    pub const fn acpi(&self) -> u64 {
67        self.acpi_addr
68    }
69}
70
71/// This is the boot mode, only support 2 modes, which are legacy(BIOS) and UEFI.
72#[repr(C)]
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum BootMode {
75    /// The Legacy boot mode, also called BIOS boot mode.
76    ///
77    /// This mode is for older machine, and we needs implement
78    /// lots of things in it.
79    Legacy,
80
81    /// The UEFI boot mode, which is the newer mode. Lots of
82    /// new machines uses it.
83    ///
84    /// Also, some machine only support it (such as mine awa).
85    Uefi,
86}
87
88/// Get the bootinfo.
89///
90/// The BootInfo is pre-copied & fixed at the dedicated constant physical address
91/// 0x10000 by UEFI boot stage, never modified nor released in kernel lifetime.
92///
93/// # Safety
94/// Caller must ensure **before invoking**:
95/// 1. Address `0x10000` is allocated & filled with valid initialized BootInfo;
96/// 2. This range is reserved, never overwritten/freed by kernel/UEFI;
97/// 3. No mutable aliasing exists for this memory region.
98///
99/// These steps are already guaranteed by the bootloader, so invocation is generally safe
100/// in normal kernel runtime.
101///
102/// # Returns
103/// - `&'static BootInfo`: immutable static reference to the pre-filled BootInfo
104pub const fn get_bootinfo() -> &'static BootInfo {
105    const BI_PHYS: u64 = 0x10000;
106    unsafe { &*(BI_PHYS as *const BootInfo) }
107}
108
109#[cfg(test)]
110fn test_runner(tests: &[&dyn Fn()]) {
111    for test in tests {
112        test();
113    }
114}