1 use core::cmp::min; 2 3 use acpi::rsdp::Rsdp; 4 use alloc::string::String; 5 use system_error::SystemError; 6 7 use crate::{ 8 arch::init::ArchBootParams, 9 driver::video::fbdev::base::BootTimeScreenInfo, 10 libs::lazy_init::Lazy, 11 mm::{PhysAddr, VirtAddr}, 12 }; 13 14 use super::boot_params; 15 #[derive(Debug)] 16 pub struct BootParams { 17 pub screen_info: BootTimeScreenInfo, 18 bootloader_name: Option<String>, 19 #[allow(dead_code)] 20 pub arch: ArchBootParams, 21 boot_command_line: [u8; Self::BOOT_COMMAND_LINE_SIZE], 22 pub acpi: BootloaderAcpiArg, 23 } 24 25 impl BootParams { 26 const DEFAULT: Self = BootParams { 27 screen_info: BootTimeScreenInfo::DEFAULT, 28 bootloader_name: None, 29 arch: ArchBootParams::DEFAULT, 30 boot_command_line: [0u8; Self::BOOT_COMMAND_LINE_SIZE], 31 acpi: BootloaderAcpiArg::NotProvided, 32 }; 33 34 /// 开机命令行参数字符串最大大小 35 pub const BOOT_COMMAND_LINE_SIZE: usize = 2048; 36 37 pub(super) const fn new() -> Self { 38 Self::DEFAULT 39 } 40 41 /// 开机命令行参数(原始字节数组) 42 #[allow(dead_code)] 43 pub fn boot_cmdline(&self) -> &[u8] { 44 &self.boot_command_line 45 } 46 47 /// 开机命令行参数字符串 48 pub fn boot_cmdline_str(&self) -> &str { 49 core::str::from_utf8(&self.boot_cmdline()[..self.boot_cmdline_len()]).unwrap() 50 } 51 52 pub fn bootloader_name(&self) -> Option<&str> { 53 self.bootloader_name.as_deref() 54 } 55 56 pub fn boot_cmdline_len(&self) -> usize { 57 self.boot_command_line 58 .iter() 59 .position(|&x| x == 0) 60 .unwrap_or(self.boot_command_line.len()) 61 } 62 63 /// 追加开机命令行参数 64 /// 65 /// 如果开机命令行参数已经满了,则不会追加。 66 /// 如果超过了最大长度,则截断。 67 /// 68 /// ## 参数 69 /// 70 /// - `data`:追加的数据 71 pub fn boot_cmdline_append(&mut self, data: &[u8]) { 72 if data.is_empty() { 73 return; 74 } 75 76 let mut pos: Option<usize> = None; 77 // 寻找结尾 78 for (i, x) in self.boot_command_line.iter().enumerate() { 79 if *x == 0 { 80 pos = Some(i); 81 break; 82 } 83 } 84 let pos = pos.unwrap_or(self.boot_command_line.len() - 1) as isize; 85 86 let avail = self.boot_command_line.len() as isize - pos - 1; 87 if avail <= 0 { 88 return; 89 } 90 91 let len = min(avail as usize, data.len()); 92 let pos = pos as usize; 93 self.boot_command_line[pos..pos + len].copy_from_slice(&data[0..len]); 94 95 self.boot_command_line[pos + len] = 0; 96 } 97 98 /// 获取FDT的虚拟地址 99 #[allow(dead_code)] 100 pub fn fdt(&self) -> Option<VirtAddr> { 101 #[cfg(target_arch = "riscv64")] 102 return Some(self.arch.arch_fdt()); 103 104 #[cfg(target_arch = "x86_64")] 105 return None; 106 } 107 108 /// 获取FDT的物理地址 109 #[allow(dead_code)] 110 pub fn fdt_paddr(&self) -> Option<PhysAddr> { 111 #[cfg(target_arch = "riscv64")] 112 return Some(self.arch.fdt_paddr); 113 114 #[cfg(target_arch = "x86_64")] 115 return None; 116 } 117 } 118 119 /// 开机引导回调,用于初始化内核启动参数 120 pub trait BootCallbacks: Send + Sync { 121 /// 初始化引导程序名称 122 fn init_bootloader_name(&self) -> Result<Option<String>, SystemError>; 123 /// 初始化ACPI参数 124 fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>; 125 /// 初始化内核命令行参数 126 /// 127 /// 该函数应该把内核命令行参数追加到`boot_params().boot_cmdline`中 128 fn init_kernel_cmdline(&self) -> Result<(), SystemError>; 129 /// 初始化帧缓冲区信息 130 /// 131 /// - 该函数应该把帧缓冲区信息写入`scinfo`中。 132 /// - 该函数应该在内存管理初始化之前调用。 133 fn early_init_framebuffer_info( 134 &self, 135 scinfo: &mut BootTimeScreenInfo, 136 ) -> Result<(), SystemError>; 137 138 /// 初始化内存块 139 fn early_init_memory_blocks(&self) -> Result<(), SystemError>; 140 } 141 142 static BOOT_CALLBACKS: Lazy<&'static dyn BootCallbacks> = Lazy::new(); 143 144 /// 注册开机引导回调 145 pub fn register_boot_callbacks(callbacks: &'static dyn BootCallbacks) { 146 BOOT_CALLBACKS.init(callbacks); 147 } 148 149 /// 获取开机引导回调 150 pub fn boot_callbacks() -> &'static dyn BootCallbacks { 151 let p = BOOT_CALLBACKS 152 .try_get() 153 .expect("Boot callbacks not initialized"); 154 155 *p 156 } 157 158 pub(super) fn boot_callback_except_early() { 159 let mut boot_params = boot_params().write(); 160 boot_params.bootloader_name = boot_callbacks() 161 .init_bootloader_name() 162 .expect("Failed to init bootloader name"); 163 boot_params.acpi = boot_callbacks() 164 .init_acpi_args() 165 .unwrap_or(BootloaderAcpiArg::NotProvided); 166 } 167 168 /// ACPI information from the bootloader. 169 #[derive(Copy, Clone, Debug)] 170 pub enum BootloaderAcpiArg { 171 /// The bootloader does not provide one, a manual search is needed. 172 NotProvided, 173 /// Physical address of the RSDP. 174 #[allow(dead_code)] 175 Rsdp(PhysAddr), 176 /// Address of RSDT provided in RSDP v1. 177 Rsdt(Rsdp), 178 /// Address of XSDT provided in RSDP v2+. 179 Xsdt(Rsdp), 180 } 181