12b7818e8SLoGin use core::cmp::min;
22b7818e8SLoGin
32b7818e8SLoGin use acpi::rsdp::Rsdp;
42b7818e8SLoGin use alloc::string::String;
52b7818e8SLoGin use system_error::SystemError;
62b7818e8SLoGin
72b7818e8SLoGin use crate::{
82b7818e8SLoGin arch::init::ArchBootParams,
92b7818e8SLoGin driver::video::fbdev::base::BootTimeScreenInfo,
102b7818e8SLoGin libs::lazy_init::Lazy,
112b7818e8SLoGin mm::{PhysAddr, VirtAddr},
122b7818e8SLoGin };
132b7818e8SLoGin
142b7818e8SLoGin use super::boot_params;
152b7818e8SLoGin #[derive(Debug)]
162b7818e8SLoGin pub struct BootParams {
172b7818e8SLoGin pub screen_info: BootTimeScreenInfo,
182b7818e8SLoGin bootloader_name: Option<String>,
192b7818e8SLoGin #[allow(dead_code)]
202b7818e8SLoGin pub arch: ArchBootParams,
212b7818e8SLoGin boot_command_line: [u8; Self::BOOT_COMMAND_LINE_SIZE],
222b7818e8SLoGin pub acpi: BootloaderAcpiArg,
232b7818e8SLoGin }
242b7818e8SLoGin
252b7818e8SLoGin impl BootParams {
262b7818e8SLoGin const DEFAULT: Self = BootParams {
272b7818e8SLoGin screen_info: BootTimeScreenInfo::DEFAULT,
282b7818e8SLoGin bootloader_name: None,
292b7818e8SLoGin arch: ArchBootParams::DEFAULT,
302b7818e8SLoGin boot_command_line: [0u8; Self::BOOT_COMMAND_LINE_SIZE],
312b7818e8SLoGin acpi: BootloaderAcpiArg::NotProvided,
322b7818e8SLoGin };
332b7818e8SLoGin
342b7818e8SLoGin /// 开机命令行参数字符串最大大小
352b7818e8SLoGin pub const BOOT_COMMAND_LINE_SIZE: usize = 2048;
362b7818e8SLoGin
new() -> Self372b7818e8SLoGin pub(super) const fn new() -> Self {
382b7818e8SLoGin Self::DEFAULT
392b7818e8SLoGin }
402b7818e8SLoGin
412b7818e8SLoGin /// 开机命令行参数(原始字节数组)
422b7818e8SLoGin #[allow(dead_code)]
boot_cmdline(&self) -> &[u8]432b7818e8SLoGin pub fn boot_cmdline(&self) -> &[u8] {
442b7818e8SLoGin &self.boot_command_line
452b7818e8SLoGin }
462b7818e8SLoGin
472b7818e8SLoGin /// 开机命令行参数字符串
boot_cmdline_str(&self) -> &str482b7818e8SLoGin pub fn boot_cmdline_str(&self) -> &str {
492b7818e8SLoGin core::str::from_utf8(self.boot_cmdline()).unwrap()
502b7818e8SLoGin }
512b7818e8SLoGin
bootloader_name(&self) -> Option<&str>522b7818e8SLoGin pub fn bootloader_name(&self) -> Option<&str> {
532b7818e8SLoGin self.bootloader_name.as_deref()
542b7818e8SLoGin }
552b7818e8SLoGin
562b7818e8SLoGin /// 追加开机命令行参数
572b7818e8SLoGin ///
582b7818e8SLoGin /// 如果开机命令行参数已经满了,则不会追加。
592b7818e8SLoGin /// 如果超过了最大长度,则截断。
602b7818e8SLoGin ///
612b7818e8SLoGin /// ## 参数
622b7818e8SLoGin ///
632b7818e8SLoGin /// - `data`:追加的数据
boot_cmdline_append(&mut self, data: &[u8])642b7818e8SLoGin pub fn boot_cmdline_append(&mut self, data: &[u8]) {
652b7818e8SLoGin if data.is_empty() {
662b7818e8SLoGin return;
672b7818e8SLoGin }
682b7818e8SLoGin
692b7818e8SLoGin let mut pos: Option<usize> = None;
702b7818e8SLoGin // 寻找结尾
712b7818e8SLoGin for (i, x) in self.boot_command_line.iter().enumerate() {
722b7818e8SLoGin if *x == 0 {
732b7818e8SLoGin pos = Some(i);
742b7818e8SLoGin break;
752b7818e8SLoGin }
762b7818e8SLoGin }
772b7818e8SLoGin let pos = pos.unwrap_or(self.boot_command_line.len() - 1) as isize;
782b7818e8SLoGin
792b7818e8SLoGin let avail = self.boot_command_line.len() as isize - pos - 1;
802b7818e8SLoGin if avail <= 0 {
812b7818e8SLoGin return;
822b7818e8SLoGin }
832b7818e8SLoGin
842b7818e8SLoGin let len = min(avail as usize, data.len());
852b7818e8SLoGin let pos = pos as usize;
862b7818e8SLoGin self.boot_command_line[pos..pos + len].copy_from_slice(&data[0..len]);
872b7818e8SLoGin
882b7818e8SLoGin self.boot_command_line[pos + len] = 0;
892b7818e8SLoGin }
902b7818e8SLoGin
912b7818e8SLoGin /// 获取FDT的虚拟地址
922b7818e8SLoGin #[allow(dead_code)]
fdt(&self) -> Option<VirtAddr>932b7818e8SLoGin pub fn fdt(&self) -> Option<VirtAddr> {
942b7818e8SLoGin #[cfg(target_arch = "riscv64")]
952b7818e8SLoGin return Some(self.arch.arch_fdt());
962b7818e8SLoGin
972b7818e8SLoGin #[cfg(target_arch = "x86_64")]
982b7818e8SLoGin return None;
992b7818e8SLoGin }
1002b7818e8SLoGin
1012b7818e8SLoGin /// 获取FDT的物理地址
1022b7818e8SLoGin #[allow(dead_code)]
fdt_paddr(&self) -> Option<PhysAddr>1032b7818e8SLoGin pub fn fdt_paddr(&self) -> Option<PhysAddr> {
1042b7818e8SLoGin #[cfg(target_arch = "riscv64")]
1052b7818e8SLoGin return Some(self.arch.fdt_paddr);
1062b7818e8SLoGin
1072b7818e8SLoGin #[cfg(target_arch = "x86_64")]
1082b7818e8SLoGin return None;
1092b7818e8SLoGin }
1102b7818e8SLoGin }
1112b7818e8SLoGin
1122b7818e8SLoGin /// 开机引导回调,用于初始化内核启动参数
1132b7818e8SLoGin pub trait BootCallbacks: Send + Sync {
1142b7818e8SLoGin /// 初始化引导程序名称
init_bootloader_name(&self) -> Result<Option<String>, SystemError>1152b7818e8SLoGin fn init_bootloader_name(&self) -> Result<Option<String>, SystemError>;
1162b7818e8SLoGin /// 初始化ACPI参数
init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>1172b7818e8SLoGin fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>;
1182b7818e8SLoGin /// 初始化内核命令行参数
1192b7818e8SLoGin ///
1202b7818e8SLoGin /// 该函数应该把内核命令行参数追加到`boot_params().boot_cmdline`中
init_kernel_cmdline(&self) -> Result<(), SystemError>1212b7818e8SLoGin fn init_kernel_cmdline(&self) -> Result<(), SystemError>;
1222b7818e8SLoGin /// 初始化帧缓冲区信息
1232b7818e8SLoGin ///
1242b7818e8SLoGin /// - 该函数应该把帧缓冲区信息写入`scinfo`中。
1252b7818e8SLoGin /// - 该函数应该在内存管理初始化之前调用。
early_init_framebuffer_info( &self, scinfo: &mut BootTimeScreenInfo, ) -> Result<(), SystemError>1262b7818e8SLoGin fn early_init_framebuffer_info(
1272b7818e8SLoGin &self,
1282b7818e8SLoGin scinfo: &mut BootTimeScreenInfo,
1292b7818e8SLoGin ) -> Result<(), SystemError>;
1302b7818e8SLoGin
1312b7818e8SLoGin /// 初始化内存块
early_init_memory_blocks(&self) -> Result<(), SystemError>1322b7818e8SLoGin fn early_init_memory_blocks(&self) -> Result<(), SystemError>;
1332b7818e8SLoGin }
1342b7818e8SLoGin
1352b7818e8SLoGin static BOOT_CALLBACKS: Lazy<&'static dyn BootCallbacks> = Lazy::new();
1362b7818e8SLoGin
1372b7818e8SLoGin /// 注册开机引导回调
register_boot_callbacks(callbacks: &'static dyn BootCallbacks)1382b7818e8SLoGin pub fn register_boot_callbacks(callbacks: &'static dyn BootCallbacks) {
1392b7818e8SLoGin BOOT_CALLBACKS.init(callbacks);
1402b7818e8SLoGin }
1412b7818e8SLoGin
1422b7818e8SLoGin /// 获取开机引导回调
boot_callbacks() -> &'static dyn BootCallbacks1432b7818e8SLoGin pub fn boot_callbacks() -> &'static dyn BootCallbacks {
1442b7818e8SLoGin let p = BOOT_CALLBACKS
1452b7818e8SLoGin .try_get()
1462b7818e8SLoGin .expect("Boot callbacks not initialized");
1472b7818e8SLoGin
1482b7818e8SLoGin *p
1492b7818e8SLoGin }
1502b7818e8SLoGin
boot_callback_except_early()1512b7818e8SLoGin pub(super) fn boot_callback_except_early() {
1522b7818e8SLoGin boot_callbacks()
1532b7818e8SLoGin .init_kernel_cmdline()
154*db7c782aSLoGin .inspect_err(|e| {
155*db7c782aSLoGin log::error!("Failed to init kernel cmdline: {:?}", e);
156*db7c782aSLoGin })
157*db7c782aSLoGin .ok();
158*db7c782aSLoGin
1592b7818e8SLoGin let mut boot_params = boot_params().write();
1602b7818e8SLoGin boot_params.bootloader_name = boot_callbacks()
1612b7818e8SLoGin .init_bootloader_name()
1622b7818e8SLoGin .expect("Failed to init bootloader name");
1632b7818e8SLoGin boot_params.acpi = boot_callbacks()
1642b7818e8SLoGin .init_acpi_args()
1652b7818e8SLoGin .unwrap_or(BootloaderAcpiArg::NotProvided);
1662b7818e8SLoGin }
1672b7818e8SLoGin
1682b7818e8SLoGin /// ACPI information from the bootloader.
1692b7818e8SLoGin #[derive(Copy, Clone, Debug)]
1702b7818e8SLoGin pub enum BootloaderAcpiArg {
1712b7818e8SLoGin /// The bootloader does not provide one, a manual search is needed.
1722b7818e8SLoGin NotProvided,
1732b7818e8SLoGin /// Physical address of the RSDP.
1742b7818e8SLoGin #[allow(dead_code)]
1752b7818e8SLoGin Rsdp(PhysAddr),
1762b7818e8SLoGin /// Address of RSDT provided in RSDP v1.
1772b7818e8SLoGin Rsdt(Rsdp),
1782b7818e8SLoGin /// Address of XSDT provided in RSDP v2+.
1792b7818e8SLoGin Xsdt(Rsdp),
1802b7818e8SLoGin }
181