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
new() -> Self37 pub(super) const fn new() -> Self {
38 Self::DEFAULT
39 }
40
41 /// 开机命令行参数(原始字节数组)
42 #[allow(dead_code)]
boot_cmdline(&self) -> &[u8]43 pub fn boot_cmdline(&self) -> &[u8] {
44 &self.boot_command_line
45 }
46
47 /// 开机命令行参数字符串
boot_cmdline_str(&self) -> &str48 pub fn boot_cmdline_str(&self) -> &str {
49 core::str::from_utf8(&self.boot_cmdline()[..self.boot_cmdline_len()]).unwrap()
50 }
51
bootloader_name(&self) -> Option<&str>52 pub fn bootloader_name(&self) -> Option<&str> {
53 self.bootloader_name.as_deref()
54 }
55
boot_cmdline_len(&self) -> usize56 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`:追加的数据
boot_cmdline_append(&mut self, data: &[u8])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)]
fdt(&self) -> Option<VirtAddr>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)]
fdt_paddr(&self) -> Option<PhysAddr>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 /// 初始化引导程序名称
init_bootloader_name(&self) -> Result<Option<String>, SystemError>122 fn init_bootloader_name(&self) -> Result<Option<String>, SystemError>;
123 /// 初始化ACPI参数
init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>124 fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>;
125 /// 初始化内核命令行参数
126 ///
127 /// 该函数应该把内核命令行参数追加到`boot_params().boot_cmdline`中
init_kernel_cmdline(&self) -> Result<(), SystemError>128 fn init_kernel_cmdline(&self) -> Result<(), SystemError>;
129 /// 初始化帧缓冲区信息
130 ///
131 /// - 该函数应该把帧缓冲区信息写入`scinfo`中。
132 /// - 该函数应该在内存管理初始化之前调用。
early_init_framebuffer_info( &self, scinfo: &mut BootTimeScreenInfo, ) -> Result<(), SystemError>133 fn early_init_framebuffer_info(
134 &self,
135 scinfo: &mut BootTimeScreenInfo,
136 ) -> Result<(), SystemError>;
137
138 /// 初始化内存块
early_init_memory_blocks(&self) -> Result<(), SystemError>139 fn early_init_memory_blocks(&self) -> Result<(), SystemError>;
140 }
141
142 static BOOT_CALLBACKS: Lazy<&'static dyn BootCallbacks> = Lazy::new();
143
144 /// 注册开机引导回调
register_boot_callbacks(callbacks: &'static dyn BootCallbacks)145 pub fn register_boot_callbacks(callbacks: &'static dyn BootCallbacks) {
146 BOOT_CALLBACKS.init(callbacks);
147 }
148
149 /// 获取开机引导回调
boot_callbacks() -> &'static dyn BootCallbacks150 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
boot_callback_except_early()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