From 2b7818e80e00fcfe4d03533f587cc125ea5e4bec Mon Sep 17 00:00:00 2001 From: LoGin Date: Thu, 5 Sep 2024 21:12:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AF=B9=E5=86=85?= =?UTF-8?q?=E6=A0=B8=E5=BC=95=E5=AF=BC=E5=8D=8F=E8=AE=AE=E7=9A=84=E6=8A=BD?= =?UTF-8?q?=E8=B1=A1=20(#913)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加multiboot header * head.S传参增加bootloader类型 * feat: 添加引导加载协议的抽象,并为multiboot2实现这个抽象. * 把framebuffer的映射地址改为从early ioremap和mmio pool分配 * riscv64能运行 --- .vscode/settings.json | 1 - docs/kernel/boot/bootloader.md | 20 +- docs/kernel/boot/index.rst | 1 - docs/kernel/boot/multiboot2.md | 46 -- kernel/Cargo.toml | 5 +- kernel/src/arch/riscv64/driver/sbi.rs | 4 +- kernel/src/arch/riscv64/init/boot.rs | 15 + kernel/src/arch/riscv64/init/dragonstub.rs | 41 ++ kernel/src/arch/riscv64/init/mod.rs | 10 +- kernel/src/arch/riscv64/rand.rs | 12 +- kernel/src/arch/x86_64/asm/head.S | 86 +++- kernel/src/arch/x86_64/init/boot.rs | 55 +++ kernel/src/arch/x86_64/init/mod.rs | 18 +- kernel/src/arch/x86_64/init/multiboot2.rs | 248 +++++++++++ kernel/src/arch/x86_64/link.lds | 1 + kernel/src/arch/x86_64/mm/mod.rs | 98 +---- kernel/src/arch/x86_64/pci/pci.rs | 16 +- kernel/src/driver/Makefile | 2 +- kernel/src/driver/acpi/Makefile | 10 - kernel/src/driver/acpi/acpi.c | 35 -- kernel/src/driver/acpi/acpi.h | 37 -- kernel/src/driver/acpi/c_adapter.rs | 8 - kernel/src/driver/acpi/mod.rs | 83 ++-- kernel/src/driver/multiboot2/Makefile | 10 - kernel/src/driver/multiboot2/multiboot2.c | 165 ------- kernel/src/driver/multiboot2/multiboot2.h | 473 --------------------- kernel/src/driver/video/fbdev/vesafb.rs | 85 +--- kernel/src/driver/video/mod.rs | 52 +-- kernel/src/include/bindings/wrapper.h | 16 - kernel/src/init/boot.rs | 176 ++++++++ kernel/src/init/init.rs | 14 +- kernel/src/init/mod.rs | 99 +---- kernel/src/libs/lib_ui/screen_manager.rs | 11 +- kernel/src/mm/c_adapter.rs | 54 +-- kernel/src/mm/mm.h | 60 +-- kernel/src/mm/mmio_buddy.rs | 28 ++ kernel/src/mm/page.rs | 4 +- kernel/src/net/event_poll/mod.rs | 3 +- kernel/src/syscall/syscall.c | 1 - kernel/src/time/sleep.h | 13 - kernel/src/time/sleep.rs | 40 -- user/apps/test_gettimeofday/main.c | 1 - 42 files changed, 828 insertions(+), 1329 deletions(-) delete mode 100644 docs/kernel/boot/multiboot2.md create mode 100644 kernel/src/arch/riscv64/init/boot.rs create mode 100644 kernel/src/arch/riscv64/init/dragonstub.rs create mode 100644 kernel/src/arch/x86_64/init/boot.rs create mode 100644 kernel/src/arch/x86_64/init/multiboot2.rs delete mode 100644 kernel/src/driver/acpi/Makefile delete mode 100644 kernel/src/driver/acpi/acpi.c delete mode 100644 kernel/src/driver/acpi/acpi.h delete mode 100644 kernel/src/driver/acpi/c_adapter.rs delete mode 100644 kernel/src/driver/multiboot2/Makefile delete mode 100644 kernel/src/driver/multiboot2/multiboot2.c delete mode 100644 kernel/src/driver/multiboot2/multiboot2.h create mode 100644 kernel/src/init/boot.rs delete mode 100644 kernel/src/time/sleep.h diff --git a/.vscode/settings.json b/.vscode/settings.json index fbf3caea8..fb915c105 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -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", diff --git a/docs/kernel/boot/bootloader.md b/docs/kernel/boot/bootloader.md index 60d5129dd..7d9e1d183 100644 --- a/docs/kernel/boot/bootloader.md +++ b/docs/kernel/boot/bootloader.md @@ -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或者是其他的一些数据结构。 + +内核启动时,自动根据引导加载程序的类型,注册回调。并且在适当的时候,会调用这些回调函数。 ## 参考资料 diff --git a/docs/kernel/boot/index.rst b/docs/kernel/boot/index.rst index 3285e1cfd..006564bf2 100644 --- a/docs/kernel/boot/index.rst +++ b/docs/kernel/boot/index.rst @@ -8,4 +8,3 @@ :caption: 目录 bootloader - multiboot2 diff --git a/docs/kernel/boot/multiboot2.md b/docs/kernel/boot/multiboot2.md deleted file mode 100644 index 2de824681..000000000 --- a/docs/kernel/boot/multiboot2.md +++ /dev/null @@ -1,46 +0,0 @@ -# Multiboot2支持模块 - -  Multiboot2支持模块提供对Multiboot2协议的支持。位于`kernel/driver/multiboot2`文件夹中。 - -  根据Multiboot2协议,操作系统能够从BootLoader处获得一些信息,比如基本的硬件信息以及ACPI表的起始地址等。 - ---- - -## 数据结构 - -  `kernel/driver/multiboot2/multiboot2.h`中按照Multiboot2协议的规定,定义了大部分的数据结构,具体细节可查看该文件: [DragonOS/multiboot2.h at master · fslongjin/DragonOS · GitHub](https://github.com/fslongjin/DragonOS/blob/master/kernel/driver/multiboot2/multiboot2.h) - ---- - -## 迭代器 - -  由于Multiboot2的信息存储在自`multiboot2_boot_info_addr`开始的一段连续的内存空间之中,且不同类型的header的长度不同,因此设计了一迭代器`multiboot2_iter`。 - -### 函数原型 - -```c -void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned int *), - void *data, unsigned int *count) -``` - -**_fun** - -  指定的handler。当某个header的tag与该handler所处理的tag相同时,handler将处理该header,并返回true。 - -  其第一个参数为tag类型,第二个参数为返回的数据的指针,第三个值为计数(某些没有用到该值的地方,该值可以为空) - -**data** - -  传递给`_fun`的第二个参数,`_fun`函数将填充该指针所指向的内存区域,从而返回数据。 - -**count** - -  当返回的**data**为一个列表时,通过该值来指示列表中有多少项。 - ---- - -## 迭代工作函数 - -  在模块中,按照我们需要获取不同类型的tag的需要,定义了一些迭代器工作函数。 - - diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 36a01f659..fad66f6b9 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -27,7 +27,7 @@ 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" @@ -35,9 +35,9 @@ 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" } @@ -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" diff --git a/kernel/src/arch/riscv64/driver/sbi.rs b/kernel/src/arch/riscv64/driver/sbi.rs index d859db74f..717c4d501 100644 --- a/kernel/src/arch/riscv64/driver/sbi.rs +++ b/kernel/src/arch/riscv64/driver/sbi.rs @@ -1,3 +1,5 @@ +use core::ptr::addr_of; + /// 向控制台打印字符串。 /// /// 该函数接受一个字节切片 `s` 作为输入,并迭代切片中的每个字节 `c`。 @@ -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 { diff --git a/kernel/src/arch/riscv64/init/boot.rs b/kernel/src/arch/riscv64/init/boot.rs new file mode 100644 index 000000000..49c890ce4 --- /dev/null +++ b/kernel/src/arch/riscv64/init/boot.rs @@ -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(), + } +} diff --git a/kernel/src/arch/riscv64/init/dragonstub.rs b/kernel/src/arch/riscv64/init/dragonstub.rs new file mode 100644 index 000000000..738318698 --- /dev/null +++ b/kernel/src/arch/riscv64/init/dragonstub.rs @@ -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, SystemError> { + Ok(format!("DragonStub").into()) + } + + fn init_acpi_args(&self) -> Result { + 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(()) + } +} diff --git a/kernel/src/arch/riscv64/init/mod.rs b/kernel/src/arch/riscv64/init/mod.rs index b71c077d2..913c20822 100644 --- a/kernel/src/arch/riscv64/init/mod.rs +++ b/kernel/src/arch/riscv64/init/mod.rs @@ -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}, @@ -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物理地址 @@ -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); diff --git a/kernel/src/arch/riscv64/rand.rs b/kernel/src/arch/riscv64/rand.rs index 373f84faf..17edfa82e 100644 --- a/kernel/src/arch/riscv64/rand.rs +++ b/kernel/src/arch/riscv64/rand.rs @@ -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::()]; + 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; } diff --git a/kernel/src/arch/x86_64/asm/head.S b/kernel/src/arch/x86_64/asm/head.S index 9fa106f96..05244594c 100644 --- a/kernel/src/arch/x86_64/asm/head.S +++ b/kernel/src/arch/x86_64/asm/head.S @@ -13,8 +13,7 @@ // The magic field should contain this. #define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 -// This should be in %eax. -#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289 + // Alignment of multiboot modules. #define MULTIBOOT_MOD_ALIGN 0x00001000 @@ -71,7 +70,15 @@ #define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1 #define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 +// This should be in %eax. +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2badb002 +#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289 +// 存储到boot_entry_type的值 +#define BOOT_ENTRY_TYPE_MULTIBOOT 1 +#define BOOT_ENTRY_TYPE_MULTIBOOT2 2 +#define BOOT_ENTRY_TYPE_LINUX_32 3 +#define BOOT_ENTRY_TYPE_LINUX_64 4 // 直接用 -m64 编译出来的是 64 位代码, // 但是启动后的机器是 32 位的,相当于在 32 位机器上跑 64 位程序。 @@ -85,25 +92,40 @@ // 声明这一段代码以 32 位模式编译 .code32 +.section ".multiboot_header", "a" + +MB_MAGIC = 0x1BADB002 +MB_FLAGS = 0 +MB_CHECKSUM = -(MB_MAGIC + MB_FLAGS) + +.code32 +multiboot_header: + .align 8 + .long MB_MAGIC + .long MB_FLAGS + .long MB_CHECKSUM + + // multiboot2 文件头 // 计算头长度 -.SET HEADER_LENGTH, multiboot_header_end - multiboot_header +.SET MB2_HEADER_LENGTH, multiboot2_header_end - multiboot2_header // 计算校验和 -.SET CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH) +.SET MB2_CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + MB2_HEADER_LENGTH) // 8 字节对齐 -.section .multiboot_header +.code32 +.section .multiboot2_header .align MULTIBOOT_HEADER_ALIGN // 声明所属段 -multiboot_header: +multiboot2_header: // 魔数 .long MULTIBOOT2_HEADER_MAGIC // 架构 .long MULTIBOOT_ARCHITECTURE_I386 // 头长度 - .long HEADER_LENGTH + .long MB2_HEADER_LENGTH // 校验和 - .long CHECKSUM + .long MB2_CHECKSUM // 添加其它内容在此,详细信息见 Multiboot2 Specification version 2.0.pdf // 设置帧缓冲区(同时在这里设置qemu的分辨率, 默认为: 1440*900, 还支持: 640*480, 等) @@ -121,13 +143,13 @@ framebuffer_tag_end: // 结束标记 .short 0 .long 8 -multiboot_header_end: +multiboot2_header_end: .section .bootstrap + .global _start .type _start, @function -# 在 multiboot2.cpp 中定义 .extern _start64 .extern boot_info_addr @@ -136,12 +158,30 @@ ENTRY(_start) // 关中断 cli - // multiboot2_info 结构体指针 - mov %ebx, mb2_info + // multiboot2_info/ multiboot_info 结构体指针 + mov %ebx, mb_entry_info //mov %ebx, %e8 - // 魔数 - mov %eax, mb2_magic - + // multiboot魔数 + mov %eax, mb_entry_magic + + mov $MULTIBOOT_BOOTLOADER_MAGIC, %ebx + cmp %eax, %ebx + je bl_magic_is_mb + mov $MULTIBOOT2_BOOTLOADER_MAGIC, %ebx + cmp %eax, %ebx + je bl_magic_is_mb2 + jmp halt // unreachable + +bl_magic_is_mb: + mov $BOOT_ENTRY_TYPE_MULTIBOOT, %ebx + mov %ebx, boot_entry_type + jmp protected_mode_setup +bl_magic_is_mb2: + mov $BOOT_ENTRY_TYPE_MULTIBOOT2, %ebx + mov %ebx, boot_entry_type + jmp protected_mode_setup + +protected_mode_setup: //mov %eax, %e9 / 从保护模式跳转到长模式 // 1. 允许 PAE @@ -225,9 +265,10 @@ switch_to_start64: .code64 -is_from_ap: - +halt: + cli hlt + jmp halt .global _start64 .type _start64, @function @@ -435,10 +476,11 @@ repeat_set_idt: // 传参 - movq mb2_info, %rdi - movq mb2_magic, %rsi + movq mb_entry_info, %rdi + movq mb_entry_magic, %rsi movq %r13, %rdx // GDT size movq %r12, %r10 // IDT size + movq boot_entry_type, %r8 lretq @@ -573,8 +615,10 @@ IDT_BASE64: .quad IDT_Table + 0xffff800000000000 .section .bootstrap.data -mb2_magic: .quad 0 -mb2_info: .quad 0 +mb_entry_magic: .quad 0 +mb_entry_info: .quad 0 +// 引导协议类型 +boot_entry_type: .quad 0 .code32 // 临时页表 4KB/页 diff --git a/kernel/src/arch/x86_64/init/boot.rs b/kernel/src/arch/x86_64/init/boot.rs new file mode 100644 index 000000000..12b587c59 --- /dev/null +++ b/kernel/src/arch/x86_64/init/boot.rs @@ -0,0 +1,55 @@ +use system_error::SystemError; + +use super::multiboot2::early_multiboot2_init; + +const BOOT_ENTRY_TYPE_MULTIBOOT: u64 = 1; +const BOOT_ENTRY_TYPE_MULTIBOOT2: u64 = 2; +const BOOT_ENTRY_TYPE_LINUX_32: u64 = 3; +const BOOT_ENTRY_TYPE_LINUX_64: u64 = 4; + +#[derive(Debug)] +#[repr(u64)] +enum BootProtocol { + Multiboot = 1, + Multiboot2, + Linux32, + Linux64, +} + +impl TryFrom for BootProtocol { + type Error = SystemError; + + fn try_from(value: u64) -> Result { + match value { + BOOT_ENTRY_TYPE_MULTIBOOT => Ok(BootProtocol::Multiboot), + BOOT_ENTRY_TYPE_MULTIBOOT2 => Ok(BootProtocol::Multiboot2), + BOOT_ENTRY_TYPE_LINUX_32 => Ok(BootProtocol::Linux32), + BOOT_ENTRY_TYPE_LINUX_64 => Ok(BootProtocol::Linux64), + _ => Err(SystemError::EINVAL), + } + } +} + +#[inline(never)] +pub(super) fn early_boot_init( + boot_entry_type: u64, + arg1: u64, + arg2: u64, +) -> Result<(), SystemError> { + let boot_protocol = BootProtocol::try_from(boot_entry_type)?; + match boot_protocol { + BootProtocol::Multiboot => { + // early_multiboot_init(arg1, arg2); + unimplemented!(); + } + BootProtocol::Multiboot2 => early_multiboot2_init(arg1 as u32, arg2), + BootProtocol::Linux32 => { + // linux32_init(arg1, arg2); + unimplemented!(); + } + BootProtocol::Linux64 => { + // linux64_init(arg1, arg2); + unimplemented!(); + } + } +} diff --git a/kernel/src/arch/x86_64/init/mod.rs b/kernel/src/arch/x86_64/init/mod.rs index c1ae2d8d7..d51d73abf 100644 --- a/kernel/src/arch/x86_64/init/mod.rs +++ b/kernel/src/arch/x86_64/init/mod.rs @@ -1,4 +1,7 @@ -use core::sync::atomic::{compiler_fence, Ordering}; +use core::{ + hint::spin_loop, + sync::atomic::{compiler_fence, Ordering}, +}; use log::debug; use system_error::SystemError; @@ -11,6 +14,8 @@ use crate::{ mm::{MemoryManagementArch, PhysAddr}, }; +use self::boot::early_boot_init; + use super::{ driver::{ hpet::{hpet_init, hpet_instance}, @@ -19,6 +24,9 @@ use super::{ MMArch, }; +mod boot; +mod multiboot2; + #[derive(Debug)] pub struct ArchBootParams {} @@ -31,7 +39,6 @@ extern "C" { static mut IDT_Table: [usize; 0usize]; fn head_stack_start(); - fn multiboot2_init(mb2_info: u64, mb2_magic: u32) -> bool; } #[no_mangle] @@ -41,6 +48,7 @@ unsafe extern "C" fn kernel_main( mb2_magic: u64, bsp_gdt_size: u64, bsp_idt_size: u64, + boot_entry_type: u64, ) -> ! { let mut gdtp = DescriptorTablePointer::::default(); let gdt_vaddr = @@ -59,7 +67,11 @@ unsafe extern "C" fn kernel_main( x86::dtables::lidt(&idtp); compiler_fence(Ordering::SeqCst); - multiboot2_init(mb2_info, (mb2_magic & 0xFFFF_FFFF) as u32); + if early_boot_init(boot_entry_type, mb2_magic, mb2_info).is_err() { + loop { + spin_loop(); + } + } compiler_fence(Ordering::SeqCst); start_kernel(); diff --git a/kernel/src/arch/x86_64/init/multiboot2.rs b/kernel/src/arch/x86_64/init/multiboot2.rs new file mode 100644 index 000000000..c302c0a94 --- /dev/null +++ b/kernel/src/arch/x86_64/init/multiboot2.rs @@ -0,0 +1,248 @@ +use core::hint::spin_loop; + +use acpi::rsdp::Rsdp; +use alloc::string::{String, ToString}; +use multiboot2::{BootInformation, BootInformationHeader, MemoryAreaType, RsdpV1Tag}; +use system_error::SystemError; + +use crate::{ + arch::mm::x86_64_set_kernel_load_base_paddr, + driver::{ + serial::serial8250::send_to_default_serial8250_port, + video::fbdev::{ + base::{BootTimeScreenInfo, BootTimeVideoType}, + vesafb::vesafb_early_map, + }, + }, + init::{ + boot::{register_boot_callbacks, BootCallbacks, BootloaderAcpiArg}, + boot_params, + }, + libs::lazy_init::Lazy, + mm::{memblock::mem_block_manager, PhysAddr}, +}; + +pub(super) const MULTIBOOT2_ENTRY_MAGIC: u32 = multiboot2::MAGIC; +static MB2_INFO: Lazy = Lazy::new(); +const MB2_RAW_INFO_MAX_SIZE: usize = 4096; + +static mut MB2_RAW_INFO: [u8; MB2_RAW_INFO_MAX_SIZE] = [0u8; MB2_RAW_INFO_MAX_SIZE]; + +fn mb2_rsdp_v1_tag_to_rsdp_struct(tag: &RsdpV1Tag) -> Rsdp { + Rsdp { + signature: tag.signature, + checksum: tag.checksum, + oem_id: tag.oem_id, + revision: tag.revision, + rsdt_address: tag.rsdt_address, + length: 0, + xsdt_address: 0, + ext_checksum: 0, + reserved: [0u8; 3], + } +} + +fn mb2_rsdp_v2_tag_to_rsdp_struct(tag: &multiboot2::RsdpV2Tag) -> Rsdp { + Rsdp { + signature: tag.signature, + checksum: tag.checksum, + oem_id: tag.oem_id, + revision: tag.revision, + rsdt_address: tag.rsdt_address, + length: tag.length, + xsdt_address: tag.xsdt_address, + ext_checksum: tag.ext_checksum, + reserved: tag._reserved, + } +} +struct Mb2Callback; + +impl BootCallbacks for Mb2Callback { + fn init_bootloader_name(&self) -> Result, SystemError> { + let name = MB2_INFO + .get() + .boot_loader_name_tag() + .expect("MB2: Bootloader name tag not found!") + .name() + .expect("Failed to parse bootloader name!") + .to_string(); + Ok(Some(name)) + } + + fn init_acpi_args(&self) -> Result { + if let Some(v1_tag) = MB2_INFO.get().rsdp_v1_tag() { + Ok(BootloaderAcpiArg::Rsdt(mb2_rsdp_v1_tag_to_rsdp_struct( + v1_tag, + ))) + } else if let Some(v2_tag) = MB2_INFO.get().rsdp_v2_tag() { + Ok(BootloaderAcpiArg::Xsdt(mb2_rsdp_v2_tag_to_rsdp_struct( + v2_tag, + ))) + } else { + Ok(BootloaderAcpiArg::NotProvided) + } + } + + fn init_kernel_cmdline(&self) -> Result<(), SystemError> { + let cmdline = MB2_INFO + .get() + .command_line_tag() + .expect("Mb2: Command line tag not found!") + .cmdline() + .expect("Mb2: Failed to parse command line!"); + boot_params() + .write_irqsave() + .boot_cmdline_append(cmdline.as_bytes()); + Ok(()) + } + + fn early_init_framebuffer_info( + &self, + scinfo: &mut BootTimeScreenInfo, + ) -> Result<(), SystemError> { + let Some(Ok(fb_tag)) = MB2_INFO.get().framebuffer_tag() else { + return Err(SystemError::ENODEV); + }; + let width = fb_tag.width(); + let height = fb_tag.height(); + scinfo.is_vga = true; + scinfo.lfb_base = PhysAddr::new(fb_tag.address() as usize); + + let fb_type = fb_tag.buffer_type().unwrap(); + match fb_type { + multiboot2::FramebufferType::Indexed { palette: _ } => todo!(), + multiboot2::FramebufferType::RGB { red, green, blue } => { + scinfo.lfb_width = width; + scinfo.lfb_height = height; + scinfo.video_type = BootTimeVideoType::Vlfb; + scinfo.lfb_depth = fb_tag.bpp(); + scinfo.red_pos = red.position; + scinfo.red_size = red.size; + scinfo.green_pos = green.position; + scinfo.green_size = green.size; + scinfo.blue_pos = blue.position; + scinfo.blue_size = blue.size; + } + multiboot2::FramebufferType::Text => { + scinfo.origin_video_cols = width as u8; + scinfo.origin_video_lines = height as u8; + scinfo.video_type = BootTimeVideoType::Mda; + scinfo.lfb_depth = 8; + } + }; + + scinfo.lfb_size = (width * height * ((fb_tag.bpp() as u32 + 7) / 8)) as usize; + + scinfo.lfb_virt_base = Some(vesafb_early_map(scinfo.lfb_base, scinfo.lfb_size)?); + + return Ok(()); + } + + fn early_init_memory_blocks(&self) -> Result<(), SystemError> { + let mb2_info = MB2_INFO.get(); + send_to_default_serial8250_port("init_memory_area_from_multiboot2\n\0".as_bytes()); + + let mem_regions_tag = mb2_info + .memory_map_tag() + .expect("MB2: Memory map tag not found!"); + let mut total_mem_size = 0usize; + let mut usable_mem_size = 0usize; + for region in mem_regions_tag.memory_areas() { + let start = PhysAddr::new(region.start_address() as usize); + let size = region.size() as usize; + let area_typ = MemoryAreaType::from(region.typ()); + total_mem_size += size; + + match area_typ { + MemoryAreaType::Available => { + usable_mem_size += size; + mem_block_manager() + .add_block(start, size) + .unwrap_or_else(|e| { + log::warn!( + "Failed to add memory block: base={:?}, size={:#x}, error={:?}", + start, + size, + e + ); + }); + } + + _ => { + mem_block_manager() + .reserve_block(start, size) + .unwrap_or_else(|e| { + log::warn!( + "Failed to reserve memory block: base={:?}, size={:#x}, error={:?}", + start, + size, + e + ); + }); + } + } + } + send_to_default_serial8250_port("init_memory_area_from_multiboot2 end\n\0".as_bytes()); + log::info!( + "Total memory size: {:#x}, Usable memory size: {:#x}", + total_mem_size, + usable_mem_size + ); + + // Add the boot module region since Grub does not specify it. + let mb2_module_tag = mb2_info.module_tags(); + for module in mb2_module_tag { + let start = PhysAddr::new(module.start_address() as usize); + let size = module.module_size() as usize; + mem_block_manager() + .reserve_block(start, size) + .unwrap_or_else(|e| { + log::warn!( + "Failed to reserve memory block for mb2 modules: base={:?}, size={:#x}, error={:?}", + start, + size, + e + ); + }); + } + + // setup kernel load base + self.setup_kernel_load_base(); + + Ok(()) + } +} + +impl Mb2Callback { + fn setup_kernel_load_base(&self) { + let mb2_info = MB2_INFO.get(); + let kernel_start = mb2_info + .load_base_addr_tag() + .expect("MB2: Load base address tag not found!") + .load_base_addr(); + let loadbase = PhysAddr::new(kernel_start as usize); + x86_64_set_kernel_load_base_paddr(loadbase); + } +} +pub(super) fn early_multiboot2_init(boot_magic: u32, boot_info: u64) -> Result<(), SystemError> { + assert_eq!(boot_magic, MULTIBOOT2_ENTRY_MAGIC); + let bi_ptr = boot_info as usize as *const BootInformationHeader; + let bi_size = unsafe { (*bi_ptr).total_size() as usize }; + assert!(bi_size <= MB2_RAW_INFO_MAX_SIZE); + unsafe { + core::ptr::copy_nonoverlapping(bi_ptr as *const u8, MB2_RAW_INFO.as_mut_ptr(), bi_size); + } + + let boot_info = + unsafe { BootInformation::load(MB2_RAW_INFO.as_mut_ptr() as *const BootInformationHeader) } + .inspect_err(|_| loop { + spin_loop(); + }) + .unwrap(); + + MB2_INFO.init(boot_info); + + register_boot_callbacks(&Mb2Callback); + + return Ok(()); +} diff --git a/kernel/src/arch/x86_64/link.lds b/kernel/src/arch/x86_64/link.lds index 34f318182..ca264e15f 100644 --- a/kernel/src/arch/x86_64/link.lds +++ b/kernel/src/arch/x86_64/link.lds @@ -13,6 +13,7 @@ SECTIONS .boot.text : { KEEP(*(.multiboot_header)) + KEEP(*(.multiboot2_header)) *(.bootstrap) *(.bootstrap.code64) *(.bootstrap.data) diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index f5c5badc6..9d9531aa4 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -6,15 +6,13 @@ pub mod pkru; use alloc::sync::Arc; use alloc::vec::Vec; use hashbrown::HashSet; -use log::{debug, info, warn}; +use log::{debug, info}; use x86::time::rdtsc; use x86_64::registers::model_specific::EferFlags; use crate::driver::serial::serial8250::send_to_default_serial8250_port; -use crate::include::bindings::bindings::{ - multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t, - multiboot_tag_load_base_addr_t, -}; + +use crate::init::boot::boot_callbacks; use crate::libs::align::page_align_up; use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window; use crate::libs::spinlock::SpinLock; @@ -34,9 +32,7 @@ use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, VmFlags use system_error::SystemError; use core::arch::asm; -use core::ffi::c_void; use core::fmt::Debug; -use core::mem::{self}; use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; @@ -63,6 +59,12 @@ pub struct X86_64MMBootstrapInfo { pub(super) static mut BOOTSTRAP_MM_INFO: Option = None; +pub(super) fn x86_64_set_kernel_load_base_paddr(paddr: PhysAddr) { + unsafe { + BOOTSTRAP_MM_INFO.as_mut().unwrap().kernel_load_base_paddr = paddr.data(); + } +} + /// @brief X86_64的内存管理架构结构体 #[derive(Debug, Clone, Copy, Hash)] pub struct X86_64MMArch; @@ -125,8 +127,8 @@ impl MemoryManagementArch for X86_64MMArch { const USER_STACK_START: VirtAddr = VirtAddr::new(0x6ffff0a00000); const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffffb00000000000); - /// 设置FIXMAP区域大小为1M - const FIXMAP_SIZE: usize = 256 * 4096; + /// 设置FIXMAP区域大小为16M + const FIXMAP_SIZE: usize = 256 * 4096 * 16; const MMIO_BASE: VirtAddr = VirtAddr::new(0xffffa10000000000); const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT; @@ -142,10 +144,9 @@ impl MemoryManagementArch for X86_64MMArch { } Self::init_xd_rsvd(); - let load_base_paddr = Self::get_load_base_paddr(); let bootstrap_info = X86_64MMBootstrapInfo { - kernel_load_base_paddr: load_base_paddr.data(), + kernel_load_base_paddr: 0, kernel_code_start: _text as usize, kernel_code_end: _etext as usize, kernel_data_end: _edata as usize, @@ -157,8 +158,10 @@ impl MemoryManagementArch for X86_64MMArch { BOOTSTRAP_MM_INFO = Some(bootstrap_info); } - // 初始化物理内存区域(从multiboot2中获取) - Self::init_memory_area_from_multiboot2().expect("init memory area failed"); + // 初始化物理内存区域 + boot_callbacks() + .early_init_memory_blocks() + .expect("init memory area failed"); debug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO }); debug!("phys[0]=virt[0x{:x}]", unsafe { @@ -168,7 +171,7 @@ impl MemoryManagementArch for X86_64MMArch { // 初始化内存管理器 unsafe { allocator_init() }; - send_to_default_serial8250_port("x86 64 init done\n\0".as_bytes()); + send_to_default_serial8250_port("x86 64 mm init done\n\0".as_bytes()); } /// @brief 刷新TLB中,关于指定虚拟地址的条目 @@ -416,73 +419,6 @@ const fn protection_map() -> [EntryFlags; 16] { } impl X86_64MMArch { - unsafe fn get_load_base_paddr() -> PhysAddr { - let mut mb2_lb_info: [multiboot_tag_load_base_addr_t; 512] = mem::zeroed(); - send_to_default_serial8250_port("get_load_base_paddr begin\n\0".as_bytes()); - - let mut mb2_count: u32 = 0; - multiboot2_iter( - Some(multiboot2_get_load_base), - &mut mb2_lb_info as *mut [multiboot_tag_load_base_addr_t; 512] as usize as *mut c_void, - &mut mb2_count, - ); - - if mb2_count == 0 { - send_to_default_serial8250_port( - "get_load_base_paddr mb2_count == 0, default to 1MB\n\0".as_bytes(), - ); - return PhysAddr::new(0x100000); - } - - let phys = mb2_lb_info[0].load_base_addr as usize; - - return PhysAddr::new(phys); - } - unsafe fn init_memory_area_from_multiboot2() -> Result { - // 这个数组用来存放内存区域的信息(从C获取) - let mut mb2_mem_info: [multiboot_mmap_entry_t; 512] = mem::zeroed(); - send_to_default_serial8250_port("init_memory_area_from_multiboot2 begin\n\0".as_bytes()); - - let mut mb2_count: u32 = 0; - multiboot2_iter( - Some(multiboot2_get_memory), - &mut mb2_mem_info as *mut [multiboot_mmap_entry_t; 512] as usize as *mut c_void, - &mut mb2_count, - ); - send_to_default_serial8250_port("init_memory_area_from_multiboot2 2\n\0".as_bytes()); - - let mb2_count = mb2_count as usize; - let mut areas_count = 0usize; - let mut total_mem_size = 0usize; - for info_entry in mb2_mem_info.iter().take(mb2_count) { - // Only use the memory area if its type is 1 (RAM) - if info_entry.type_ == 1 { - // Skip the memory area if its len is 0 - if info_entry.len == 0 { - continue; - } - - total_mem_size += info_entry.len as usize; - - mem_block_manager() - .add_block( - PhysAddr::new(info_entry.addr as usize), - info_entry.len as usize, - ) - .unwrap_or_else(|e| { - warn!( - "Failed to add memory block: base={:#x}, size={:#x}, error={:?}", - info_entry.addr, info_entry.len, e - ); - }); - areas_count += 1; - } - } - send_to_default_serial8250_port("init_memory_area_from_multiboot2 end\n\0".as_bytes()); - info!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024); - return Ok(areas_count); - } - fn init_xd_rsvd() { // 读取ia32-EFER寄存器的值 let efer: EferFlags = x86_64::registers::model_specific::Efer::read(); diff --git a/kernel/src/arch/x86_64/pci/pci.rs b/kernel/src/arch/x86_64/pci/pci.rs index 427d6c88b..c7fe5f0a6 100644 --- a/kernel/src/arch/x86_64/pci/pci.rs +++ b/kernel/src/arch/x86_64/pci/pci.rs @@ -1,4 +1,5 @@ -use crate::arch::TraitPciArch; +use crate::arch::io::PortIOArch; +use crate::arch::{CurrentPortIOArch, TraitPciArch}; use crate::driver::acpi::acpi_manager; use crate::driver::pci::ecam::{pci_ecam_root_info_manager, EcamRootInfo}; use crate::driver::pci::pci::{ @@ -6,7 +7,6 @@ use crate::driver::pci::pci::{ PORT_PCI_CONFIG_DATA, }; use crate::driver::pci::root::{pci_root_manager, PciRoot}; -use crate::include::bindings::bindings::{io_in32, io_in8, io_out32}; use crate::init::initcall::INITCALL_SUBSYS; use crate::mm::PhysAddr; @@ -22,7 +22,7 @@ impl X86_64PciArch { /// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/pci/early.c?fi=read_pci_config_byte#19 fn read_config_early(bus: u8, slot: u8, func: u8, offset: u8) -> u8 { unsafe { - io_out32( + CurrentPortIOArch::out32( PORT_PCI_CONFIG_ADDRESS, 0x80000000 | ((bus as u32) << 16) @@ -31,7 +31,7 @@ impl X86_64PciArch { | offset as u32, ); } - let value = unsafe { io_in8(PORT_PCI_CONFIG_DATA + (offset & 3) as u16) }; + let value = unsafe { CurrentPortIOArch::in8(PORT_PCI_CONFIG_DATA + (offset & 3) as u16) }; return value; } } @@ -45,8 +45,8 @@ impl TraitPciArch for X86_64PciArch { | (offset & 0xfc) as u32 | (0x80000000); let ret = unsafe { - io_out32(PORT_PCI_CONFIG_ADDRESS, address); - let temp = io_in32(PORT_PCI_CONFIG_DATA); + CurrentPortIOArch::out32(PORT_PCI_CONFIG_ADDRESS, address); + let temp = CurrentPortIOArch::in32(PORT_PCI_CONFIG_DATA); temp }; return ret; @@ -59,9 +59,9 @@ impl TraitPciArch for X86_64PciArch { | (offset & 0xfc) as u32 | (0x80000000); unsafe { - io_out32(PORT_PCI_CONFIG_ADDRESS, address); + CurrentPortIOArch::out32(PORT_PCI_CONFIG_ADDRESS, address); // 写入数据 - io_out32(PORT_PCI_CONFIG_DATA, data); + CurrentPortIOArch::out32(PORT_PCI_CONFIG_DATA, data); } } diff --git a/kernel/src/driver/Makefile b/kernel/src/driver/Makefile index c8e9e35f1..8cc629113 100644 --- a/kernel/src/driver/Makefile +++ b/kernel/src/driver/Makefile @@ -1,7 +1,7 @@ CFLAGS += -I . -kernel_driver_subdirs:=acpi multiboot2 +kernel_driver_subdirs:= ECHO: @echo "$@" diff --git a/kernel/src/driver/acpi/Makefile b/kernel/src/driver/acpi/Makefile deleted file mode 100644 index f85134716..000000000 --- a/kernel/src/driver/acpi/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -SRC = $(wildcard *.c) -OBJ = $(SRC:.c=.o) -CFLAGS += -I . - -.PHONY: all - -all: $(OBJ) - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ \ No newline at end of file diff --git a/kernel/src/driver/acpi/acpi.c b/kernel/src/driver/acpi/acpi.c deleted file mode 100644 index a73903be9..000000000 --- a/kernel/src/driver/acpi/acpi.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "acpi.h" -#include -#include - -extern void rs_acpi_init(uint64_t rsdp_paddr1, uint64_t rsdp_paddr2); - -static struct acpi_RSDP_t *rsdpv1; -static struct acpi_RSDP_2_t *rsdpv2; - -static struct multiboot_tag_old_acpi_t old_acpi; -static struct multiboot_tag_new_acpi_t new_acpi; - -/** - * @brief 初始化acpi模块 - * - */ -void acpi_init() -{ - kinfo("Initializing ACPI..."); - - // 获取物理地址 - int reserved; - - multiboot2_iter(multiboot2_get_acpi_old_RSDP, &old_acpi, &reserved); - rsdpv1 = &(old_acpi.rsdp); - - multiboot2_iter(multiboot2_get_acpi_new_RSDP, &new_acpi, &reserved); - rsdpv2 = &(new_acpi.rsdp); - - // rsdpv1、rsdpv2,二者有一个能成功即可 - rs_acpi_init((uint64_t)rsdpv1, (uint64_t)rsdpv2); - - kinfo("ACPI module initialized!"); - return; -} diff --git a/kernel/src/driver/acpi/acpi.h b/kernel/src/driver/acpi/acpi.h deleted file mode 100644 index 1e6bcac8a..000000000 --- a/kernel/src/driver/acpi/acpi.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * 解析acpi信息的模块 - **/ - -#pragma once - -#include -#include - -struct acpi_RSDP_t -{ - unsigned char Signature[8]; - unsigned char Checksum; - unsigned char OEMID[6]; - - unsigned char Revision; - - // 32bit physical address of the RSDT - uint RsdtAddress; -} __attribute__((packed)); - -struct acpi_RSDP_2_t -{ - struct acpi_RSDP_t rsdp1; - - // fields below are only valid when the revision value is 2 or above - // 表的长度(单位:字节)从offset=0开始算 - uint Length; - // 64bit的XSDT的物理地址 - ul XsdtAddress; - unsigned char ExtendedChecksum; // 整个表的checksum,包括了之前的checksum区域 - - unsigned char Reserved[3]; -} __attribute__((packed)); - -// 初始化acpi模块 -void acpi_init(); \ No newline at end of file diff --git a/kernel/src/driver/acpi/c_adapter.rs b/kernel/src/driver/acpi/c_adapter.rs deleted file mode 100644 index e4636c203..000000000 --- a/kernel/src/driver/acpi/c_adapter.rs +++ /dev/null @@ -1,8 +0,0 @@ -use super::acpi_manager; - -#[no_mangle] -unsafe extern "C" fn rs_acpi_init(rsdp_vaddr1: u64, rsdp_vaddr2: u64) { - acpi_manager() - .init(rsdp_vaddr1, rsdp_vaddr2) - .expect("rs_acpi_init(): failed to init acpi"); -} diff --git a/kernel/src/driver/acpi/mod.rs b/kernel/src/driver/acpi/mod.rs index 8525f5f17..e7fb8fe15 100644 --- a/kernel/src/driver/acpi/mod.rs +++ b/kernel/src/driver/acpi/mod.rs @@ -1,4 +1,4 @@ -use core::{fmt::Debug, hint::spin_loop, ptr::NonNull}; +use core::{fmt::Debug, ptr::NonNull}; use acpi::{AcpiHandler, AcpiTables, PlatformInfo}; use alloc::{string::ToString, sync::Arc}; @@ -7,6 +7,7 @@ use log::{error, info}; use crate::{ arch::MMArch, driver::base::firmware::sys_firmware_kset, + init::{boot::BootloaderAcpiArg, boot_params}, libs::align::{page_align_down, page_align_up, AlignedBox}, mm::{ mmio_buddy::{mmio_pool, MMIOSpaceGuard}, @@ -20,7 +21,6 @@ use super::base::kset::KSet; extern crate acpi; pub mod bus; -mod c_adapter; pub mod glue; pub mod pmtmr; mod sysfs; @@ -56,7 +56,7 @@ impl AcpiManager { /// ## 参考资料 /// /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/acpi/bus.c#1390 - pub fn init(&self, rsdp_vaddr1: u64, rsdp_vaddr2: u64) -> Result<(), SystemError> { + fn init(&self) -> Result<(), SystemError> { info!("Initializing Acpi Manager..."); // 初始化`/sys/firmware/acpi`的kset @@ -65,45 +65,45 @@ impl AcpiManager { unsafe { ACPI_KSET_INSTANCE = Some(kset.clone()); } - self.map_tables(rsdp_vaddr1, rsdp_vaddr2)?; + let acpi_args = boot_params().read().acpi; + if let BootloaderAcpiArg::NotProvided = acpi_args { + error!("acpi_init(): ACPI not provided by bootloader"); + return Err(SystemError::ENODEV); + } + + self.map_tables(acpi_args)?; self.bus_init()?; info!("Acpi Manager initialized."); return Ok(()); } - fn map_tables(&self, rsdp_vaddr1: u64, rsdp_vaddr2: u64) -> Result<(), SystemError> { - let rsdp_paddr1 = Self::rsdp_paddr(rsdp_vaddr1); - let res1 = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr1.data()) }; - let e1; - match res1 { - // 如果rsdpv1能够获取到acpi_table,则就用该表,不用rsdpv2了 + fn map_tables(&self, acpi_args: BootloaderAcpiArg) -> Result<(), SystemError> { + let table_paddr: PhysAddr = match acpi_args { + BootloaderAcpiArg::Rsdt(rsdpv1) => Self::rsdp_paddr(&rsdpv1), + BootloaderAcpiArg::Xsdt(rsdpv2) => Self::rsdp_paddr(&rsdpv2), + _ => { + error!( + "AcpiManager::map_tables(): unsupported acpi_args: {:?}", + acpi_args + ); + return Err(SystemError::ENODEV); + } + }; + let res = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, table_paddr.data()) }; + match res { Ok(acpi_table) => { Self::set_acpi_table(acpi_table); return Ok(()); } Err(e) => { - e1 = e; - Self::drop_rsdp_tmp_box(); - } - } - - let rsdp_paddr2 = Self::rsdp_paddr(rsdp_vaddr2); - let res2 = unsafe { acpi::AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp_paddr2.data()) }; - match res2 { - Ok(acpi_table) => { - Self::set_acpi_table(acpi_table); - } - // 如果rsdpv1和rsdpv2都无法获取到acpi_table,说明有问题,打印报错信息后进入死循环 - Err(e2) => { - error!("acpi_init(): failed to parse acpi tables, error: (rsdpv1: {:?}) or (rsdpv2: {:?})", e1, e2); + error!( + "AcpiManager::map_tables(): failed to map tables, error: {:?}", + e + ); Self::drop_rsdp_tmp_box(); - loop { - spin_loop(); - } + return Err(SystemError::ENODEV); } } - - return Ok(()); } /// 通过RSDP虚拟地址获取RSDP物理地址 @@ -115,13 +115,18 @@ impl AcpiManager { /// ## 返回值 /// /// RSDP物理地址 - fn rsdp_paddr(rsdp_vaddr: u64) -> PhysAddr { + fn rsdp_paddr(rsdp_instance: &acpi::rsdp::Rsdp) -> PhysAddr { unsafe { RSDP_TMP_BOX = Some(AlignedBox::new_zeroed().expect("rs_acpi_init(): failed to alloc")) }; + let size = core::mem::size_of::(); - let tmp_data = - unsafe { core::slice::from_raw_parts(rsdp_vaddr as usize as *const u8, size) }; + let tmp_data = unsafe { + core::slice::from_raw_parts( + rsdp_instance as *const acpi::rsdp::Rsdp as usize as *const u8, + size, + ) + }; unsafe { RSDP_TMP_BOX.as_mut().unwrap()[0..size].copy_from_slice(tmp_data) }; let rsdp_paddr = unsafe { MMArch::virt_2_phys(VirtAddr::new( @@ -221,3 +226,17 @@ impl AcpiHandler for AcpiHandlerImpl { drop(mmio_guard); } } + +#[inline(never)] +pub fn acpi_init() -> Result<(), SystemError> { + #[cfg(target_arch = "x86_64")] + { + acpi_manager().init() + } + + #[cfg(not(target_arch = "x86_64"))] + { + log::warn!("acpi_init(): unsupported arch"); + return Ok(()); + } +} diff --git a/kernel/src/driver/multiboot2/Makefile b/kernel/src/driver/multiboot2/Makefile deleted file mode 100644 index f85134716..000000000 --- a/kernel/src/driver/multiboot2/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -SRC = $(wildcard *.c) -OBJ = $(SRC:.c=.o) -CFLAGS += -I . - -.PHONY: all - -all: $(OBJ) - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ \ No newline at end of file diff --git a/kernel/src/driver/multiboot2/multiboot2.c b/kernel/src/driver/multiboot2/multiboot2.c deleted file mode 100644 index 234ee599a..000000000 --- a/kernel/src/driver/multiboot2/multiboot2.c +++ /dev/null @@ -1,165 +0,0 @@ -#include "multiboot2.h" - -#include -#include -// uintptr_t multiboot2_boot_info_addr; -// unsigned int multiboot2_magic; -unsigned int multiboot2_boot_info_size; - -#define MBI_RAW_MAX_SIZE 409600 -// 由于启动时传递的mb2 info所在的地址,在内存管理初始化之后会被覆盖,所以需要将其拷贝到一个固定的位置 -static uint8_t mbi_raw[MBI_RAW_MAX_SIZE] = {0}; -bool multiboot2_init(uint64_t mb2_info_paddr, uint32_t mb2_magic) -{ - uint64_t vaddr = (uint64_t)phys_2_virt(mb2_info_paddr); - if (mb2_magic != MULTIBOOT2_BOOTLOADER_MAGIC) - return false; - // vaddr+0 处保存了大小 - multiboot2_boot_info_size = *(uint32_t *)vaddr; - if (multiboot2_boot_info_size > MBI_RAW_MAX_SIZE) - return false; - - memcpy((void *)mbi_raw, (void *)vaddr, multiboot2_boot_info_size); - - return true; -} - -void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned int *), - void *data, unsigned int *count) -{ - // kdebug("multiboot2_boot_info_addr=%#018lx", multiboot2_boot_info_addr); - - // uintptr_t addr = multiboot2_boot_info_addr; - - // for(int i=0;i<8192;i++) - // { - // mbi_raw[i] = ((uint8_t *)multiboot2_boot_info_addr)[i]; - // } - uint8_t * addr = mbi_raw; - // 接下来的第8字节开始,为 tag 信息 - struct iter_data_t *tag = (struct iter_data_t *)((void *)addr + 8); - for (; tag->type != MULTIBOOT_TAG_TYPE_END; - tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8))) - { - - if (_fun(tag, data, count) == true) - { - return; - } - } - return; -} - -// 读取 grub2 传递的物理内存信息,保存到 e820map_t 结构体中 -// 一般而言是这样的 -// 地址(长度) 类型 -// 0x00(0x9F000) 0x1 -// 0x9F000(0x1000) 0x2 -// 0xE8000(0x18000) 0x2 -// 0x100000(0x7EF0000) 0x1 -// 0x7FF0000(0x10000) 0x3 -// 0xFFFC0000(0x40000) 0x2 -/** - * @brief 获取multiboot2协议提供的内存区域信息 - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data 返回信息的结构体指针 - * @param count 返回数组的长度 - * @return true - * @return false - */ -bool multiboot2_get_memory(const struct iter_data_t *_iter_data, void *data, unsigned int *count) -{ - if (_iter_data->type != MULTIBOOT_TAG_TYPE_MMAP) - return false; - - struct multiboot_mmap_entry_t *resource = (struct multiboot_mmap_entry_t *)data; - struct multiboot_mmap_entry_t *mmap = ((struct multiboot_tag_mmap_t *)_iter_data)->entries; - *count = 0; - for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size; - mmap = (struct multiboot_mmap_entry_t *)((uint8_t *)mmap + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size)) - { - *resource = *mmap; - // 将指针进行增加 - resource = (struct multiboot_mmap_entry_t *)((uint8_t *)resource + ((struct multiboot_tag_mmap_t *)_iter_data)->entry_size); - ++(*count); - } - return true; -} - -/** - * @brief 获取VBE信息 - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data 返回信息的结构体指针 - */ -bool multiboot2_get_VBE_info(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved) -{ - - if (_iter_data->type != MULTIBOOT_TAG_TYPE_VBE) - return false; - *(struct multiboot_tag_vbe_t *)data = *(struct multiboot_tag_vbe_t *)_iter_data; - return true; -} - -/// @brief 获取加载基地址 -/// @param _iter_data -/// @param data -/// @param reserved -/// @return -bool multiboot2_get_load_base(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved) -{ - - if (_iter_data->type != MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR) - return false; - *(struct multiboot_tag_load_base_addr_t *)data = *(struct multiboot_tag_load_base_addr_t *)_iter_data; - return true; -} - -/** - * @brief 获取帧缓冲区信息 - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data 返回信息的结构体指针 - */ -bool multiboot2_get_Framebuffer_info(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved) -{ - if (_iter_data->type != MULTIBOOT_TAG_TYPE_FRAMEBUFFER) - return false; - *(struct multiboot_tag_framebuffer_info_t *)data = *(struct multiboot_tag_framebuffer_info_t *)_iter_data; - return true; -} - -/** - * @brief 获取acpi旧版RSDP - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data old RSDP的结构体指针 - * @param reserved - * @return uint8_t* struct multiboot_tag_old_acpi_t - */ -bool multiboot2_get_acpi_old_RSDP(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved) -{ - if (_iter_data->type != MULTIBOOT_TAG_TYPE_ACPI_OLD) - return false; - - *(struct multiboot_tag_old_acpi_t *)data = *(struct multiboot_tag_old_acpi_t *)_iter_data; - - return true; -} - -/** - * @brief 获取acpi新版RSDP - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data old RSDP的结构体指针 - * @param reserved - * @return uint8_t* struct multiboot_tag_old_acpi_t - */ -bool multiboot2_get_acpi_new_RSDP(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved) -{ - if (_iter_data->type != MULTIBOOT_TAG_TYPE_ACPI_NEW) - return false; - *(struct multiboot_tag_new_acpi_t *)data = *(struct multiboot_tag_new_acpi_t *)_iter_data; - return true; -} \ No newline at end of file diff --git a/kernel/src/driver/multiboot2/multiboot2.h b/kernel/src/driver/multiboot2/multiboot2.h deleted file mode 100644 index 3f087d7fa..000000000 --- a/kernel/src/driver/multiboot2/multiboot2.h +++ /dev/null @@ -1,473 +0,0 @@ -/** - * @file multiboot2.h - * @brief multiboot2 解析 - */ - -#pragma once - -#include -#include "stdbool.h" -#include -#include - -/// @see Multiboot2 Specification version 2.0.pdf -// 启动后,在 32 位内核进入点,机器状态如下: -// 1. CS 指向基地址为 0x00000000,限长为4G – 1的代码段描述符。 -// 2. DS,SS,ES,FS 和 GS 指向基地址为0x00000000,限长为4G – -// 1的数据段描述符。 -// 3. A20 地址线已经打开。 -// 4. 页机制被禁止。 -// 5. 中断被禁止。 -// 6. EAX = 0x2BADB002 -// 7. 系统信息和启动信息块的线性地址保存在 EBX中(相当于一个指针)。 -// 以下即为这个信息块的结构 - -/** - * @brief MULTIBOOT2 接口抽象 - */ - -/* How many bytes from the start of the file we search for the header. */ -static const unsigned int MULTIBOOT_SEARCH = 32768; -static const unsigned int MULTIBOOT_HEADER_ALIGN = 8; - -/* The magic field should contain this. */ -static const unsigned int MULTIBOOT2_HEADER_MAGIC = 0xe85250d6; - -/* This should be in %eax. */ -static const unsigned int MULTIBOOT2_BOOTLOADER_MAGIC = 0x36d76289; - -/* Alignment of multiboot modules. */ -static const unsigned int MULTIBOOT_MOD_ALIGN = 0x00001000; - -/* Alignment of the multiboot info structure. */ -static const unsigned int MULTIBOOT_INFO_ALIGN = 0x00000008; - -/* Flags set in the 'flags' member of the multiboot header. */ - -static const unsigned int MULTIBOOT_TAG_ALIGN = 8; -static const unsigned int MULTIBOOT_TAG_TYPE_END = 0; -static const unsigned int MULTIBOOT_TAG_TYPE_CMDLINE = 1; -static const unsigned int MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME = 2; -static const unsigned int MULTIBOOT_TAG_TYPE_MODULE = 3; -static const unsigned int MULTIBOOT_TAG_TYPE_BASIC_MEMINFO = 4; -static const unsigned int MULTIBOOT_TAG_TYPE_BOOTDEV = 5; -static const unsigned int MULTIBOOT_TAG_TYPE_MMAP = 6; -static const unsigned int MULTIBOOT_TAG_TYPE_VBE = 7; -static const unsigned int MULTIBOOT_TAG_TYPE_FRAMEBUFFER = 8; -static const unsigned int MULTIBOOT_TAG_TYPE_ELF_SECTIONS = 9; -static const unsigned int MULTIBOOT_TAG_TYPE_APM = 10; -static const unsigned int MULTIBOOT_TAG_TYPE_EFI32 = 11; -static const unsigned int MULTIBOOT_TAG_TYPE_EFI64 = 12; -static const unsigned int MULTIBOOT_TAG_TYPE_SMBIOS = 13; -static const unsigned int MULTIBOOT_TAG_TYPE_ACPI_OLD = 14; -static const unsigned int MULTIBOOT_TAG_TYPE_ACPI_NEW = 15; -static const unsigned int MULTIBOOT_TAG_TYPE_NETWORK = 16; -static const unsigned int MULTIBOOT_TAG_TYPE_EFI_MMAP = 17; -static const unsigned int MULTIBOOT_TAG_TYPE_EFI_BS = 18; -static const unsigned int MULTIBOOT_TAG_TYPE_EFI32_IH = 19; -static const unsigned int MULTIBOOT_TAG_TYPE_EFI64_IH = 20; -static const unsigned int MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR = 21; - -static const unsigned int MULTIBOOT_HEADER_TAG_END = 0; -static const unsigned int MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST = - 1; -static const unsigned int MULTIBOOT_HEADER_TAG_ADDRESS = 2; -static const unsigned int MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS = 3; -static const unsigned int MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS = 4; -static const unsigned int MULTIBOOT_HEADER_TAG_FRAMEBUFFER = 5; -static const unsigned int MULTIBOOT_HEADER_TAG_MODULE_ALIGN = 6; -static const unsigned int MULTIBOOT_HEADER_TAG_EFI_BS = 7; -static const unsigned int MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 = - 8; -static const unsigned int MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 = - 9; -static const unsigned int MULTIBOOT_HEADER_TAG_RELOCATABLE = 10; - -static const unsigned int MULTIBOOT_ARCHITECTURE_I386 = 0; -static const unsigned int MULTIBOOT_ARCHITECTURE_MIPS32 = 4; -static const unsigned int MULTIBOOT_HEADER_TAG_OPTIONAL = 1; - -static const unsigned int MULTIBOOT_LOAD_PREFERENCE_NONE = 0; -static const unsigned int MULTIBOOT_LOAD_PREFERENCE_LOW = 1; -static const unsigned int MULTIBOOT_LOAD_PREFERENCE_HIGH = 2; - -static const unsigned int MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED = - 1; -static const unsigned int MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED = - 2; - -static const unsigned int MULTIBOOT_MEMORY_AVAILABLE = 1; -static const unsigned int MULTIBOOT_MEMORY_RESERVED = 2; -static const unsigned int MULTIBOOT_MEMORY_ACPI_RECLAIMABLE = 3; -static const unsigned int MULTIBOOT_MEMORY_NVS = 4; -static const unsigned int MULTIBOOT_MEMORY_BADRAM = 5; - -struct multiboot_header_t -{ - // Must be MULTIBOOT_MAGIC - see above. - unsigned int magic; - // ISA - unsigned int architecture; - // Total header length. - unsigned int header_length; - // The above fields plus this one must equal 0 mod 2^32. - unsigned int checksum; -}; - -struct multiboot_header_tag_t -{ - uint16_t type; - uint16_t flags; - unsigned int size; -}; -struct multiboot_header_tag_information_request_t -{ - uint16_t type; - uint16_t flags; - unsigned int size; - - unsigned int requests[0]; -}; -struct multiboot_header_tag_address_t -{ - uint16_t type; - uint16_t flags; - unsigned int size; - - unsigned int header_addr; - unsigned int load_addr; - unsigned int load_end_addr; - unsigned int bss_end_addr; -}; - -struct multiboot_header_tag_entry_address_t -{ - uint16_t type; - uint16_t flags; - unsigned int size; - - unsigned int entry_addr; -}; - -struct multiboot_header_tag_console_flags_t -{ - uint16_t type; - uint16_t flags; - unsigned int size; - - unsigned int console_flags; -}; - -struct multiboot_header_tag_framebuffer_t -{ - uint16_t type; - uint16_t flags; - unsigned int size; - - unsigned int width; - unsigned int height; - unsigned int depth; -}; - -struct multiboot_header_tag_module_align_t -{ - uint16_t type; - uint16_t flags; - unsigned int size; -}; - -struct multiboot_header_tag_relocatable_t -{ - uint16_t type; - uint16_t flags; - unsigned int size; - - unsigned int min_addr; - unsigned int max_addr; - unsigned int align; - unsigned int preference; -}; - -struct multiboot_color_t -{ - uint8_t red; - uint8_t green; - uint8_t blue; -}; - -// multiboot2协议的内存区域信息 -struct multiboot_mmap_entry_t -{ - uint64_t addr; - uint64_t len; - unsigned int type; - unsigned int reserved; -}; - -struct multiboot_tag_t -{ - unsigned int type; - unsigned int size; -}; - -struct multiboot_tag_string_t -{ - struct multiboot_tag_t tag_t; - char string[0]; -}; - -struct multiboot_tag_module_t -{ - struct multiboot_tag_t tag_t; - unsigned int mod_start; - unsigned int mod_end; - char cmdline[0]; -}; - -struct multiboot_tag_basic_meminfo_t -{ - struct multiboot_tag_t tag_t; - unsigned int mem_lower; - unsigned int mem_upper; -}; - -struct multiboot_tag_bootdev_t -{ - struct multiboot_tag_t tag_t; - unsigned int biosdev; - unsigned int slice; - unsigned int part; -}; - -struct multiboot_tag_mmap_t -{ - struct multiboot_tag_t tag_t; - unsigned int entry_size; - unsigned int entry_version; - struct multiboot_mmap_entry_t entries[0]; -}; - -struct multiboot_vbe_info_block_t -{ - uint8_t external_specification[512]; -}; - -struct multiboot_vbe_mode_info_block_t -{ - uint8_t external_specification[256]; -}; - -// bootloader传递的VBE信息的结构体 -struct multiboot_tag_vbe_t -{ - struct multiboot_tag_t tag_t; - uint16_t vbe_mode; - uint16_t vbe_interface_seg; - uint16_t vbe_interface_off; - uint16_t vbe_interface_len; - - // The fields ‘vbe_control_info’ and ‘vbe_mode_info’ contain VBE control information returned by the VBE Function 00h and VBE mode information - // returned by the VBE Function 01h, respectively. - struct multiboot_vbe_info_block_t vbe_control_info; - struct multiboot_vbe_mode_info_block_t vbe_mode_info; -}; - -struct multiboot_tag_framebuffer_info_t -{ - struct multiboot_tag_t tag_t; - uint64_t framebuffer_addr; - uint32_t framebuffer_pitch; // 帧缓存上界 - // width and height expressed in pixels except type=2 - // when type=2, they are expressed in characters - uint32_t framebuffer_width; - uint32_t framebuffer_height; - // number of bits per pixel. - uint8_t framebuffer_bpp; - // 帧缓存的类型 - uint8_t framebuffer_type; - uint8_t reserved; -}; - -// indexed color -struct multiboot_tag_framebuffer_info_type0_t -{ - struct multiboot_tag_framebuffer_info_t header; - uint32_t framebuffer_palette_num_colors; - struct multiboot_color_t color_desc; -}; - -// direct RGB color -struct multiboot_tag_framebuffer_info_type1_t -{ - struct multiboot_tag_framebuffer_info_t header; - - uint8_t framebuffer_red_field_position; - uint8_t framebuffer_red_mask_size; - uint8_t framebuffer_green_field_position; - uint8_t framebuffer_green_mask_size; - uint8_t framebuffer_blue_field_position; - uint8_t framebuffer_blue_mask_size; -}; - -struct multiboot_tag_elf_sections_t -{ - struct multiboot_tag_t tag_t; - unsigned int num; - unsigned int entsize; - // 段字符串表索引 - unsigned int shndx; - char sections[0]; -}; - -struct multiboot_tag_apm_t -{ - struct multiboot_tag_t tag_t; - uint16_t version; - uint16_t cseg; - unsigned int offset; - uint16_t cseg_16; - uint16_t dseg; - uint16_t flags; - uint16_t cseg_len; - uint16_t cseg_16_len; - uint16_t dseg_len; -}; - -struct multiboot_tag_efi32_t -{ - struct multiboot_tag_t tag_t; - unsigned int pointer; -}; - -struct multiboot_tag_efi64_t -{ - struct multiboot_tag_t tag_t; - uint64_t pointer; -}; - -struct multiboot_tag_smbios_t -{ - struct multiboot_tag_t tag_t; - uint8_t major; - uint8_t minor; - uint8_t reserved[6]; - uint8_t tables[0]; -}; - -struct multiboot_tag_old_acpi_t -{ - struct multiboot_tag_t tag_t; - //uint8_t rsdp[0]; - struct acpi_RSDP_t rsdp; -}; - -struct multiboot_tag_new_acpi_t -{ - struct multiboot_tag_t tag_t; - //uint8_t rsdp[0]; - struct acpi_RSDP_2_t rsdp; -}; - -struct multiboot_tag_network_t -{ - struct multiboot_tag_t tag_t; - uint8_t dhcpack[0]; -}; - -struct multiboot_tag_efi_mmap_t -{ - struct multiboot_tag_t tag_t; - unsigned int descr_size; - unsigned int descr_vers; - uint8_t efi_mmap[0]; -}; - -struct multiboot_tag_efi32_ih_t -{ - struct multiboot_tag_t tag_t; - unsigned int pointer; -}; - -struct multiboot_tag_efi64_ih_t -{ - struct multiboot_tag_t tag_t; - uint64_t pointer; -}; - -struct multiboot_tag_load_base_addr_t -{ - struct multiboot_tag_t tag_t; - unsigned int load_base_addr; -}; - -// 迭代变量 -// 与 multiboot_tag_t 相同 -struct iter_data_t -{ - unsigned int type; - unsigned int size; -}; - -/** - * @brief 初始化 - * @return true 成功 - * @return false 失败 - */ -bool multiboot2_init(uint64_t mb2_info_paddr, uint32_t mb2_magic); - -/** - * @brief 迭代器 - * @param _fun 迭代操作 - * @param _data 数据 - */ -void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned int *), - void *_data, unsigned int *count); - -/** - * @brief 获取multiboot2协议提供的内存区域信息 - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data 返回信息的结构体指针 - * @param count 返回数组的长度 - * @return true - * @return false - */ -bool multiboot2_get_memory(const struct iter_data_t *_iter_data, void *_data, unsigned int *count); - -bool multiboot2_get_load_base(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved); - -/** - * @brief 获取VBE信息 - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data 返回信息的结构体指针 - */ -bool multiboot2_get_VBE_info(const struct iter_data_t *_iter_data, void *_data, unsigned int *reserved); - -/** - * @brief 获取帧缓冲区信息 - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data 返回信息的结构体指针 - */ -bool multiboot2_get_Framebuffer_info(const struct iter_data_t *_iter_data, void *_data, unsigned int *reserved); - -/** - * @brief 获取acpi旧版RSDP - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data old RSDP的结构体指针 - * @param reserved - * @return uint8_t* - */ -bool multiboot2_get_acpi_old_RSDP(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved); - -/** - * @brief 获取acpi新版RSDP - * - * @param _iter_data 要被迭代的信息的结构体 - * @param _data old RSDP的结构体指针 - * @param reserved - * @return uint8_t* struct multiboot_tag_old_acpi_t - */ -bool multiboot2_get_acpi_new_RSDP(const struct iter_data_t *_iter_data, void *data, unsigned int *reserved); \ No newline at end of file diff --git a/kernel/src/driver/video/fbdev/vesafb.rs b/kernel/src/driver/video/fbdev/vesafb.rs index a5c486964..0c58c161a 100644 --- a/kernel/src/driver/video/fbdev/vesafb.rs +++ b/kernel/src/driver/video/fbdev/vesafb.rs @@ -1,8 +1,4 @@ -use core::{ - ffi::{c_uint, c_void}, - mem::MaybeUninit, - sync::atomic::AtomicBool, -}; +use core::sync::atomic::AtomicBool; use alloc::{ string::{String, ToString}, @@ -14,7 +10,6 @@ use system_error::SystemError; use unified_init::macros::unified_init; use crate::{ - arch::MMArch, driver::{ base::{ class::Class, @@ -36,21 +31,13 @@ use crate::{ sysfs::{file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport}, vfs::syscall::ModeType, }, - include::bindings::bindings::{ - multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t, - FRAME_BUFFER_MAPPING_OFFSET, - }, - init::{boot_params, initcall::INITCALL_DEVICE}, + init::{boot::boot_callbacks, boot_params, initcall::INITCALL_DEVICE}, libs::{ - align::page_align_up, once::Once, rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, spinlock::SpinLock, }, - mm::{ - allocator::page_frame::PageFrameCount, no_init::pseudo_map_phys, MemoryManagementArch, - PhysAddr, VirtAddr, - }, + mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr}, }; use super::base::{ @@ -933,68 +920,18 @@ pub fn vesa_fb_driver_init() -> Result<(), SystemError> { } /// 在内存管理初始化之前,初始化vesafb -pub fn vesafb_early_init() -> Result { - let mut _reserved: u32 = 0; - - let mut fb_info: MaybeUninit = MaybeUninit::uninit(); - //从multiboot2中读取帧缓冲区信息至fb_info - - // todo: 换成rust的,并且检测是否成功获取 - unsafe { - multiboot2_iter( - Some(multiboot2_get_Framebuffer_info), - fb_info.as_mut_ptr() as usize as *mut c_void, - &mut _reserved as *mut c_uint, - ) - }; - unsafe { fb_info.assume_init() }; - let fb_info: multiboot_tag_framebuffer_info_t = unsafe { core::mem::transmute(fb_info) }; +pub fn vesafb_early_init() -> Result<(), SystemError> { + let mut boot_params_guard = boot_params().write(); + boot_callbacks().early_init_framebuffer_info(&mut boot_params_guard.screen_info)?; - // todo: 判断是否有vesa帧缓冲区,这里暂时直接设置true HAS_VESA_FB.store(true, core::sync::atomic::Ordering::SeqCst); - let width = fb_info.framebuffer_width; - let height = fb_info.framebuffer_height; + return Ok(()); +} + +pub fn vesafb_early_map(paddr: PhysAddr, size: usize) -> Result { + let (buf_vaddr, _) = EarlyIoRemap::map(paddr, size, false)?; - let mut boot_params_guard = boot_params().write(); - let boottime_screen_info = &mut boot_params_guard.screen_info; - - boottime_screen_info.is_vga = true; - - boottime_screen_info.lfb_base = PhysAddr::new(fb_info.framebuffer_addr as usize); - - if fb_info.framebuffer_type == 2 { - //当type=2时,width与height用字符数表示,故depth=8 - boottime_screen_info.origin_video_cols = width as u8; - boottime_screen_info.origin_video_lines = height as u8; - boottime_screen_info.video_type = BootTimeVideoType::Mda; - boottime_screen_info.lfb_depth = 8; - } else { - //否则为图像模式,depth应参照帧缓冲区信息里面的每个像素的位数 - boottime_screen_info.lfb_width = width; - boottime_screen_info.lfb_height = height; - boottime_screen_info.video_type = BootTimeVideoType::Vlfb; - boottime_screen_info.lfb_depth = fb_info.framebuffer_bpp as u8; - } - - boottime_screen_info.lfb_size = - (width * height * ((fb_info.framebuffer_bpp as u32 + 7) / 8)) as usize; - - // let buf_vaddr = VirtAddr::new(0xffff800003200000); - let buf_vaddr = VirtAddr::new( - crate::include::bindings::bindings::SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE as usize - + FRAME_BUFFER_MAPPING_OFFSET as usize, - ); - boottime_screen_info.lfb_virt_base = Some(buf_vaddr); - - let init_text = "Video driver to map.\n\0"; - send_to_default_serial8250_port(init_text.as_bytes()); - - // 地址映射 - let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize); - let count = - PageFrameCount::new(page_align_up(boottime_screen_info.lfb_size) / MMArch::PAGE_SIZE); - unsafe { pseudo_map_phys(buf_vaddr, paddr, count) }; return Ok(buf_vaddr); } diff --git a/kernel/src/driver/video/mod.rs b/kernel/src/driver/video/mod.rs index e9a705140..726dd3895 100644 --- a/kernel/src/driver/video/mod.rs +++ b/kernel/src/driver/video/mod.rs @@ -9,10 +9,7 @@ use crate::{ rwlock::{RwLock, RwLockReadGuard}, spinlock::SpinLock, }, - mm::{ - allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::EntryFlags, - MemoryManagementArch, - }, + mm::{mmio_buddy::mmio_pool, page::EntryFlags}, time::timer::{Timer, TimerFunction}, }; use alloc::{boxed::Box, sync::Arc}; @@ -74,46 +71,33 @@ impl VideoRefreshManager { } /** - * @brief VBE帧缓存区的地址重新映射 - * 将帧缓存区映射到地址SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE处 + * VBE帧缓存区的地址重新映射 */ fn init_frame_buffer(&self) { info!("Re-mapping VBE frame buffer..."); - let buf_vaddr = boot_params() - .read_irqsave() - .screen_info - .lfb_virt_base - .unwrap(); + let mut bp = boot_params().write_irqsave(); + let buf_size = bp.screen_info.lfb_size; - let mut frame_buffer_info_guard = self.device_buffer.write(); + let mmio_guard = mmio_pool().create_mmio(page_align_up(buf_size)).unwrap(); + let mmio_guard = Arc::new(mmio_guard); + let buf_vaddr = mmio_guard.vaddr(); + bp.screen_info.lfb_virt_base = Some(buf_vaddr); + + let mut frame_buffer_info_guard: crate::libs::rwlock::RwLockWriteGuard = + self.device_buffer.write(); + unsafe { frame_buffer_info_guard.set_device_buffer_mmio_guard(mmio_guard.clone()) }; if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_guard).buf { *vaddr = buf_vaddr; } - // 地址映射 - let mut paddr = boot_params().read().screen_info.lfb_base; - let count = PageFrameCount::new( - page_align_up(frame_buffer_info_guard.buf_size()) / MMArch::PAGE_SIZE, - ); + let paddr = bp.screen_info.lfb_base; let page_flags: EntryFlags = EntryFlags::new().set_execute(true).set_write(true); - let mut kernel_mapper = KernelMapper::lock(); - let mut kernel_mapper = kernel_mapper.as_mut(); - assert!(kernel_mapper.is_some()); - let mut vaddr = buf_vaddr; unsafe { - for _ in 0..count.data() { - let flusher = kernel_mapper - .as_mut() - .unwrap() - .map_phys(vaddr, paddr, page_flags) - .unwrap(); - - flusher.flush(); - vaddr += MMArch::PAGE_SIZE; - paddr += MMArch::PAGE_SIZE; - } - } + mmio_guard + .map_phys_with_flags(paddr, page_align_up(buf_size), page_flags) + .expect("Failed to map VBE frame buffer!") + }; info!("VBE frame buffer successfully Re-mapped!"); } @@ -196,6 +180,7 @@ impl VideoRefreshManager { screen_info.lfb_depth.into(), buf_flag, buf_vaddr, + None, ) .unwrap(); } else { @@ -208,6 +193,7 @@ impl VideoRefreshManager { screen_info.lfb_depth.into(), buf_flag, buf_vaddr, + None, ) .unwrap(); } diff --git a/kernel/src/include/bindings/wrapper.h b/kernel/src/include/bindings/wrapper.h index c82bca636..f4f160d5e 100644 --- a/kernel/src/include/bindings/wrapper.h +++ b/kernel/src/include/bindings/wrapper.h @@ -10,19 +10,3 @@ */ #pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include