proka_bootloader/lib.rs
1//! # Proka Bootloader - The bootloader of ProkaOS
2//!
3//! [](https://www.rust-lang.org/)
4//! [](https://opensource.org/license/gpl-3.0)
5//! [](https://github.com/RainSTR-Studio/proka-bootloader/stargazers)
6//! [](https://github.com/RainSTR-Studio/proka-bootloader/issues)
7//! [](https://github.com/RainSTR-Studio/proka-bootloader/pulls)
8//! [](https://prokadoc.pages.dev/)
9//!
10//! **Copyright (C) 2026 RainSTR Studio. Licensed under GNU GPLv3.**
11//!
12//! ---
13//!
14//! ## Introduction
15//! This crate provides the struct, enums about the proka
16//! bootloader, including the boot information, memory map, and so on.
17//!
18//! ## Example
19//! Here's an example to use this crate:
20//!
21//! ```rust
22//! #![no_std]
23//! #![no_main]
24//! #![feature(custom_test_frameworks)]
25//! #![test_runner(self::test_runner)]
26//! #![reexport_test_harness_main = "test_main"]
27//!
28//! use proka_bootloader::BootInfo;
29//! use core::panic::PanicInfo;
30//!
31//! // Panic handler
32//! #[panic_handler]
33//! pub fn panic(_: &PanicInfo) -> ! {
34//! loop {}
35//! }
36//!
37//! #[unsafe(no_mangle)]
38//! #[unsafe(link_section = ".text")]
39//! pub extern "C" fn kernel_main() -> ! {
40//! let info = proka_bootloader::get_bootinfo();
41//! let framebuffer = info.framebuffer();
42//!
43//! // Draw a straight line...
44//! unsafe {
45//! let ptr = framebuffer.address() as *mut u8;
46//! for i in 0..500 {
47//! let offset = framebuffer.pitch() * i + i * framebuffer.bpp();
48//! ptr.add(offset as usize).cast::<u32>().write(0x00FFFFFF);
49//! }
50//! }
51//! loop {}
52//! }
53//!
54//! // Test runner
55//! #[cfg(test)]
56//! fn test_runner(tests: &[&'static dyn Fn()]) {
57//! for test in tests {
58//! test();
59//! }
60//! }
61//! ```
62//!
63//! ## LICENSE
64//! This crate is under license [GPL-v3](https://github.com/RainSTR-Studio/proka-exec/blob/main/LICENSE),
65//! and you must follow its rules.
66//!
67//! See [LICENSE](https://github.com/RainSTR-Studio/proka-exec/blob/main/LICENSE) file for more details.
68//!
69//! ## MSRV
70//! This crate's MSRV is `1.85.0` stable.
71#![no_std]
72#![no_main]
73#![feature(custom_test_frameworks)]
74#![test_runner(self::test_runner)]
75#![reexport_test_harness_main = "test_main"]
76
77pub mod header;
78#[cfg(feature = "loader_main")]
79pub mod loader_main;
80pub mod memory;
81pub mod output;
82mod version;
83use self::memory::MemoryMap;
84use self::output::Framebuffer;
85
86/// This struct is the boot information struct, which provides
87/// the basic information, *memory map*, and so on.
88#[repr(C, packed)]
89#[derive(Debug, Clone, PartialEq, Eq)]
90pub struct BootInfo {
91 boot_mode: BootMode,
92 framebuffer: Framebuffer,
93 memmap: MemoryMap,
94 acpi_addr: u64,
95}
96
97impl BootInfo {
98 /// Initialize a new boot info object.
99 ///
100 /// Note: this object will be initialized by loader
101 /// automatically, so if you are a kernel developer, do
102 /// not use this method, because you needn't and unusable.
103 #[cfg(feature = "loader_main")]
104 pub fn new(boot_mode: BootMode, memmap: MemoryMap, fb: Framebuffer, acpi_addr: u64) -> Self {
105 Self {
106 boot_mode,
107 acpi_addr,
108 memmap,
109 framebuffer: fb,
110 }
111 }
112
113 /// Get the boot mode.
114 pub const fn boot_mode(&self) -> BootMode {
115 self.boot_mode
116 }
117
118 /// Get the framebuffer info.
119 pub const fn framebuffer(&self) -> &Framebuffer {
120 &self.framebuffer
121 }
122
123 /// Get the memory map.
124 pub const fn memory(&self) -> &MemoryMap {
125 &self.memmap
126 }
127
128 /// Get the ACPI RSDP's address.
129 pub const fn acpi(&self) -> u64 {
130 self.acpi_addr
131 }
132}
133
134/// This is the boot mode, only support 2 modes, which are legacy(BIOS) and UEFI.
135#[repr(C)]
136#[derive(Debug, Clone, Copy, PartialEq, Eq)]
137pub enum BootMode {
138 /// The Legacy boot mode, also called BIOS boot mode.
139 ///
140 /// This mode is for older machine, and we needs implement
141 /// lots of things in it.
142 Legacy,
143
144 /// The UEFI boot mode, which is the newer mode. Lots of
145 /// new machines uses it.
146 ///
147 /// Also, some machine only support it (such as mine awa).
148 Uefi,
149}
150
151/// Get the bootinfo.
152///
153/// The BootInfo is pre-copied & fixed at the dedicated constant physical address
154/// 0x10000 by UEFI boot stage, never modified nor released in kernel lifetime.
155///
156/// # Safety
157/// Caller must ensure **before invoking**:
158/// 1. Address `0x10000` is allocated & filled with valid initialized BootInfo;
159/// 2. This range is reserved, never overwritten/freed by kernel/UEFI;
160/// 3. No mutable aliasing exists for this memory region.
161///
162/// # Note
163/// Once the kernel do remapping, i suggest that map that region as `PRESENT`,
164/// no `WRITABLE`.
165///
166/// # Returns
167/// - `&'static BootInfo`: immutable static reference to the pre-filled BootInfo
168pub const unsafe fn get_bootinfo() -> &'static BootInfo {
169 const BI_PHYS: u64 = 0x10000;
170 unsafe { &*(BI_PHYS as *const BootInfo) }
171}
172
173#[cfg(test)]
174fn test_runner(tests: &[&dyn Fn()]) {
175 for test in tests {
176 test();
177 }
178}