@@ -23,8 +23,11 @@ pub mod bios;
2323pub mod uefi;
2424
2525pub mod legacy_memory_region;
26+ /// Provides a type to keep track of used entries in a level 4 page table.
2627pub mod level_4_entries;
28+ /// Implements a loader for the kernel ELF binary.
2729pub mod load_kernel;
30+ /// Provides a logger type that logs output as text to pixel-based framebuffers.
2831pub mod logger;
2932
3033// Contains the parsed configuration table from the kernel's Cargo.toml.
@@ -42,19 +45,29 @@ include!(concat!(env!("OUT_DIR"), "/bootloader_config.rs"));
4245
4346const PAGE_SIZE : u64 = 4096 ;
4447
48+ /// Initialize a text-based logger using the given pixel-based framebuffer as output.
4549pub fn init_logger ( framebuffer : & ' static mut [ u8 ] , info : FrameBufferInfo ) {
4650 let logger = logger:: LOGGER . get_or_init ( move || logger:: LockedLogger :: new ( framebuffer, info) ) ;
4751 log:: set_logger ( logger) . expect ( "logger already set" ) ;
4852 log:: set_max_level ( log:: LevelFilter :: Trace ) ;
4953}
5054
55+ /// Required system information that should be queried from the BIOS or UEFI firmware.
5156#[ derive( Debug , Copy , Clone ) ]
5257pub struct SystemInfo {
58+ /// Start address of the pixel-based framebuffer.
5359 pub framebuffer_addr : PhysAddr ,
60+ /// Information about the framebuffer, including layout and pixel format.
5461 pub framebuffer_info : FrameBufferInfo ,
62+ /// Address of the _Root System Description Pointer_ structure of the ACPI standard.
5563 pub rsdp_addr : Option < PhysAddr > ,
5664}
5765
66+ /// Loads the kernel ELF executable into memory and switches to it.
67+ ///
68+ /// This function is a convenience function that first calls [`set_up_mappings`], then
69+ /// [`create_boot_info`], and finally [`switch_to_kernel`]. The given arguments are passed
70+ /// directly to these functions, so see their docs for more info.
5871pub fn load_and_switch_to_kernel < I , D > (
5972 kernel_bytes : & [ u8 ] ,
6073 mut frame_allocator : LegacyFrameAllocator < I , D > ,
8194 switch_to_kernel ( page_tables, mappings, boot_info, two_frames) ;
8295}
8396
84- /// Sets up mappings for a kernel stack and the framebuffer
97+ /// Sets up mappings for a kernel stack and the framebuffer.
98+ ///
99+ /// The `kernel_bytes` slice should contain the raw bytes of the kernel ELF executable. The
100+ /// `frame_allocator` argument should be created from the memory map. The `page_tables`
101+ /// argument should point to the bootloader and kernel page tables. The function tries to parse
102+ /// the ELF file and create all specified mappings in the kernel-level page table.
103+ ///
104+ /// The `framebuffer_addr` and `framebuffer_size` fields should be set to the start address and
105+ /// byte length the pixel-based framebuffer. These arguments are required because the functions
106+ /// maps this framebuffer in the kernel-level page table, unless the `map_framebuffer` config
107+ /// option is disabled.
108+ ///
109+ /// This function reacts to unexpected situations (e.g. invalid kernel ELF file) with a panic, so
110+ /// errors are not recoverable.
85111pub fn set_up_mappings < I , D > (
86112 kernel_bytes : & [ u8 ] ,
87113 frame_allocator : & mut LegacyFrameAllocator < I , D > ,
@@ -201,17 +227,31 @@ where
201227 }
202228}
203229
230+ /// Contains the addresses of all memory mappings set up by [`set_up_mappings`].
204231pub struct Mappings {
232+ /// The entry point address of the kernel.
205233 pub entry_point : VirtAddr ,
234+ /// The stack end page of the kernel.
206235 pub stack_end : Page ,
236+ /// Keeps track of used entries in the level 4 page table, useful for finding a free
237+ /// virtual memory when needed.
207238 pub used_entries : UsedLevel4Entries ,
239+ /// The start address of the framebuffer, if any.
208240 pub framebuffer : Option < VirtAddr > ,
241+ /// The start address of the physical memory mapping, if enabled.
209242 pub physical_memory_offset : Option < VirtAddr > ,
243+ /// The level 4 page table index of the recursive mapping, if enabled.
210244 pub recursive_index : Option < PageTableIndex > ,
245+ /// The thread local storage template of the kernel executable, if it contains one.
211246 pub tls_template : Option < TlsTemplate > ,
212247}
213248
214- /// Allocates and initializes the boot info struct and the memory map
249+ /// Allocates and initializes the boot info struct and the memory map.
250+ ///
251+ /// The boot info and memory map are mapped to both the kernel and bootloader
252+ /// address space at the same address. This makes it possible to return a Rust
253+ /// reference that is valid in both address spaces. The necessary physical frames
254+ /// are taken from the given `frame_allocator`.
215255pub fn create_boot_info < I , D > (
216256 mut frame_allocator : LegacyFrameAllocator < I , D > ,
217257 page_tables : & mut PageTables ,
@@ -325,15 +365,26 @@ pub fn switch_to_kernel(
325365 }
326366}
327367
368+ /// Provides access to the page tables of the bootloader and kernel address space.
328369pub struct PageTables {
370+ /// Provides access to the page tables of the bootloader address space.
329371 pub bootloader : OffsetPageTable < ' static > ,
372+ /// Provides access to the page tables of the kernel address space (not active).
330373 pub kernel : OffsetPageTable < ' static > ,
374+ /// The physical frame where the level 4 page table of the kernel address space is stored.
375+ ///
376+ /// Must be the page table that the `kernel` field of this struct refers to.
377+ ///
378+ /// This frame is loaded into the `CR3` register on the final context switch to the kernel.
331379 pub kernel_level_4_frame : PhysFrame ,
332380}
333381
334- /// Performs the actual context switch
382+ /// Performs the actual context switch.
335383///
336- /// This function should stay small because it needs to be identity-mapped.
384+ /// This function uses the given `frame_allocator` to identity map itself in the kernel-level
385+ /// page table. This is required to avoid a page fault after the context switch. Since this
386+ /// function is relatively small, only up to two physical frames are required from the frame
387+ /// allocator, so the [`TwoFrames`] type can be used here.
337388unsafe fn context_switch (
338389 addresses : Addresses ,
339390 mut kernel_page_table : OffsetPageTable ,
@@ -367,18 +418,28 @@ unsafe fn context_switch(
367418 unreachable ! ( ) ;
368419}
369420
370- pub struct Addresses {
421+ /// Memory addresses required for the context switch.
422+ struct Addresses {
371423 page_table : PhysFrame ,
372424 stack_top : VirtAddr ,
373425 entry_point : VirtAddr ,
374426 boot_info : & ' static mut crate :: boot_info:: BootInfo ,
375427}
376428
429+ /// Used for reversing two physical frames for identity mapping the context switch function.
430+ ///
431+ /// In order to prevent a page fault, the context switch function must be mapped identically in
432+ /// both address spaces. The context switch function is small, so this mapping requires only
433+ /// two physical frames (one frame is not enough because the linker might place the function
434+ /// directly before a page boundary). Since the frame allocator no longer exists when the
435+ /// context switch function is invoked, we use this type to reserve two physical frames
436+ /// beforehand.
377437pub struct TwoFrames {
378438 frames : [ Option < PhysFrame > ; 2 ] ,
379439}
380440
381441impl TwoFrames {
442+ /// Creates a new instance by allocating two physical frames from the given frame allocator.
382443 pub fn new ( frame_allocator : & mut impl FrameAllocator < Size4KiB > ) -> Self {
383444 TwoFrames {
384445 frames : [
0 commit comments