xref: /DragonOS/kernel/src/init/boot.rs (revision 01c18c64b14b4ebabd98fa92c587c26874275eb1)
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