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