Skip to content

Commit

Permalink
feat: 添加对内核引导协议的抽象 (#913)
Browse files Browse the repository at this point in the history
* 添加multiboot header

* head.S传参增加bootloader类型

* feat: 添加引导加载协议的抽象,并为multiboot2实现这个抽象.

* 把framebuffer的映射地址改为从early ioremap和mmio pool分配

* riscv64能运行
  • Loading branch information
fslongjin authored Sep 5, 2024
1 parent cf7f801 commit 2b7818e
Show file tree
Hide file tree
Showing 42 changed files with 828 additions and 1,329 deletions.
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@
"assert.h": "c",
"sys_version.h": "c",
"cmd.h": "c",
"sleep.h": "c",
"net.h": "c",
"cmd_test.h": "c",
"cmpxchg.h": "c",
Expand Down
20 changes: 16 additions & 4 deletions docs/kernel/boot/bootloader.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
# 引导加载程序

## 原理
## X86_64

  目前,DragonOS支持Legacy BIOS以及UEFI两种方式,进行启动引导。
- [x] multiboot2

  `head.S`的头部包含了Multiboot2引导头,里面标志了一些Multiboot2相关的特定信息,以及一些配置命令。
## RISC-V 64

  在DragonOS的启动初期,会存储由GRUB2传来的magic number以及multiboot2_boot_info_addr。当系统进入`Start_Kernel`函数之后,将会把这两个信息保存到multiboot2驱动程序之中。信息的具体含义请参照Multiboot2 Specification进行理解,该部分难度不大,相信读者经过思考能理解其中的原理。
DragonOS在RISC-V 64上,启动流程为:

opensbi --> uboot --> DragonStub --> kernel

这个启动流程,使得DragonOS内核与具体的硬件板卡解耦,能够以同一个二进制文件,在不同的硬件板卡上启动运行。


## 内核启动回调

DragonOS对内核引导加载程序进行了抽象,体现为`BootCallbacks`这个trait。
不同的引导加载程序,实现对应的callback,初始化内核bootParams或者是其他的一些数据结构。

内核启动时,自动根据引导加载程序的类型,注册回调。并且在适当的时候,会调用这些回调函数。

## 参考资料

Expand Down
1 change: 0 additions & 1 deletion docs/kernel/boot/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@
:caption: 目录

bootloader
multiboot2
46 changes: 0 additions & 46 deletions docs/kernel/boot/multiboot2.md

This file was deleted.

5 changes: 3 additions & 2 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ fatfs-secure = ["fatfs"]

# 运行时依赖项
[dependencies]
acpi = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/acpi-rs.git", rev = "fb69243dcf" }
acpi = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/acpi-rs.git", rev = "282df2af7b" }
asm_macros = { path = "crates/asm_macros" }
atomic_enum = "=0.2.0"
bit_field = "=0.10"
bitfield-struct = "=0.5.3"
bitflags = "=1.3.2"
bitmap = { path = "crates/bitmap" }
driver_base_macros = { "path" = "crates/driver_base_macros" }
# 一个no_std的hashmap、hashset
elf = { version = "=0.7.2", default-features = false }
fdt = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/fdt", rev = "9862813020" }
# 一个no_std的hashmap、hashset
hashbrown = "=0.13.2"
ida = { path = "src/libs/ida" }
intertrait = { path = "crates/intertrait" }
Expand All @@ -63,6 +63,7 @@ lru = "0.12.3"
# target为x86_64时,使用下面的依赖
[target.'cfg(target_arch = "x86_64")'.dependencies]
mini-backtrace = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/mini-backtrace.git", rev = "e0b1d90940" }
multiboot2 = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/multiboot2", rev = "05739aab40" }
raw-cpuid = "11.0.1"
x86 = "=0.52.0"
x86_64 = "=0.14.10"
Expand Down
4 changes: 3 additions & 1 deletion kernel/src/arch/riscv64/driver/sbi.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::ptr::addr_of;

/// 向控制台打印字符串。
///
/// 该函数接受一个字节切片 `s` 作为输入,并迭代切片中的每个字节 `c`。
Expand Down Expand Up @@ -75,7 +77,7 @@ impl SbiDriver {

/// 获取probe得到的SBI扩展信息。
pub fn extensions() -> &'static SBIExtensions {
unsafe { &EXTENSIONS }
unsafe { addr_of!(EXTENSIONS).as_ref().unwrap() }
}

fn probe_extensions() -> SBIExtensions {
Expand Down
15 changes: 15 additions & 0 deletions kernel/src/arch/riscv64/init/boot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use system_error::SystemError;

use super::dragonstub::early_dragonstub_init;

#[derive(Debug)]
#[repr(u64)]
pub(super) enum BootProtocol {
DragonStub = 1,
}

pub(super) fn early_boot_init(protocol: BootProtocol) -> Result<(), SystemError> {
match protocol {
BootProtocol::DragonStub => early_dragonstub_init(),
}
}
41 changes: 41 additions & 0 deletions kernel/src/arch/riscv64/init/dragonstub.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use alloc::string::String;
use system_error::SystemError;

use crate::{
driver::video::fbdev::base::BootTimeScreenInfo,
init::boot::{register_boot_callbacks, BootCallbacks, BootloaderAcpiArg},
};

pub(super) fn early_dragonstub_init() -> Result<(), SystemError> {
register_boot_callbacks(&DragonStubCallBack);
Ok(())
}

struct DragonStubCallBack;

impl BootCallbacks for DragonStubCallBack {
fn init_bootloader_name(&self) -> Result<Option<String>, SystemError> {
Ok(format!("DragonStub").into())
}

fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError> {
Ok(BootloaderAcpiArg::NotProvided)
}

fn init_kernel_cmdline(&self) -> Result<(), SystemError> {
// parsed in `early_init_scan_chosen()`
Ok(())
}

fn early_init_framebuffer_info(
&self,
_scinfo: &mut BootTimeScreenInfo,
) -> Result<(), SystemError> {
unimplemented!("dragonstub early_init_framebuffer_info")
}

fn early_init_memory_blocks(&self) -> Result<(), SystemError> {
// parsed in `early_init_scan_memory()` and uefi driver
Ok(())
}
}
10 changes: 9 additions & 1 deletion kernel/src/arch/riscv64/init/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ use log::{debug, info};
use system_error::SystemError;

use crate::{
arch::{driver::sbi::SbiDriver, mm::init::mm_early_init},
arch::{
driver::sbi::SbiDriver,
init::boot::{early_boot_init, BootProtocol},
mm::init::mm_early_init,
},
driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
init::{boot_params, init::start_kernel},
mm::{memblock::mem_block_manager, PhysAddr, VirtAddr},
Expand All @@ -13,6 +17,9 @@ use crate::{

use super::{cpu::init_local_context, interrupt::entry::handle_exception};

mod boot;
mod dragonstub;

#[derive(Debug)]
pub struct ArchBootParams {
/// 启动时的fdt物理地址
Expand Down Expand Up @@ -119,6 +126,7 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
"DragonOS kernel is running on hart {}, fdt address:{:?}",
hartid, fdt_paddr
);
early_boot_init(BootProtocol::DragonStub).expect("Failed to init boot protocol!");
mm_early_init();

print_node(fdt.find_node("/").unwrap(), 0);
Expand Down
12 changes: 11 additions & 1 deletion kernel/src/arch/riscv64/rand.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
pub fn rand() -> usize {
unimplemented!("RiscV64 rand");
static mut SEED: u64 = 0xdead_beef_cafe_babe;
let mut buf = [0u8; size_of::<usize>()];
for x in buf.iter_mut() {
unsafe {
// from musl
SEED = SEED.wrapping_mul(0x5851_f42d_4c95_7f2d);
*x = (SEED >> 33) as u8;
}
}
let x: usize = unsafe { core::mem::transmute(buf) };
return x;
}
Loading

0 comments on commit 2b7818e

Please sign in to comment.