mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-21 08:46:35 +00:00
feat: 允许通过multiboot引导(直到acpi初始化报错) (#914)
This commit is contained in:
@ -7,8 +7,8 @@
|
||||
|
||||
// 以下是来自 multiboot2 规范的定义
|
||||
// How many bytes from the start of the file we search for the header.
|
||||
#define MULTIBOOT_SEARCH 32768
|
||||
#define MULTIBOOT_HEADER_ALIGN 8
|
||||
#define MULTIBOOT2_SEARCH 32768
|
||||
#define MULTIBOOT2_HEADER_ALIGN 8
|
||||
|
||||
// The magic field should contain this.
|
||||
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
|
||||
@ -16,59 +16,59 @@
|
||||
|
||||
|
||||
// Alignment of multiboot modules.
|
||||
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||
#define MULTIBOOT2_MOD_ALIGN 0x00001000
|
||||
|
||||
// Alignment of the multiboot info structure.
|
||||
#define MULTIBOOT_INFO_ALIGN 0x00000008
|
||||
#define MULTIBOOT2_INFO_ALIGN 0x00000008
|
||||
|
||||
// Flags set in the 'flags' member of the multiboot header.
|
||||
|
||||
#define MULTIBOOT_TAG_ALIGN 8
|
||||
#define MULTIBOOT_TAG_TYPE_END 0
|
||||
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
||||
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
|
||||
#define MULTIBOOT_TAG_TYPE_MODULE 3
|
||||
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
|
||||
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
|
||||
#define MULTIBOOT_TAG_TYPE_MMAP 6
|
||||
#define MULTIBOOT_TAG_TYPE_VBE 7
|
||||
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
|
||||
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
|
||||
#define MULTIBOOT_TAG_TYPE_APM 10
|
||||
#define MULTIBOOT_TAG_TYPE_EFI32 11
|
||||
#define MULTIBOOT_TAG_TYPE_EFI64 12
|
||||
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
|
||||
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
|
||||
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
|
||||
#define MULTIBOOT_TAG_TYPE_NETWORK 16
|
||||
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
|
||||
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
||||
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
||||
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
||||
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
|
||||
#define MULTIBOOT2_TAG_ALIGN 8
|
||||
#define MULTIBOOT2_TAG_TYPE_END 0
|
||||
#define MULTIBOOT2_TAG_TYPE_CMDLINE 1
|
||||
#define MULTIBOOT2_TAG_TYPE_BOOT_LOADER_NAME 2
|
||||
#define MULTIBOOT2_TAG_TYPE_MODULE 3
|
||||
#define MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO 4
|
||||
#define MULTIBOOT2_TAG_TYPE_BOOTDEV 5
|
||||
#define MULTIBOOT2_TAG_TYPE_MMAP 6
|
||||
#define MULTIBOOT2_TAG_TYPE_VBE 7
|
||||
#define MULTIBOOT2_TAG_TYPE_FRAMEBUFFER 8
|
||||
#define MULTIBOOT2_TAG_TYPE_ELF_SECTIONS 9
|
||||
#define MULTIBOOT2_TAG_TYPE_APM 10
|
||||
#define MULTIBOOT2_TAG_TYPE_EFI32 11
|
||||
#define MULTIBOOT2_TAG_TYPE_EFI64 12
|
||||
#define MULTIBOOT2_TAG_TYPE_SMBIOS 13
|
||||
#define MULTIBOOT2_TAG_TYPE_ACPI_OLD 14
|
||||
#define MULTIBOOT2_TAG_TYPE_ACPI_NEW 15
|
||||
#define MULTIBOOT2_TAG_TYPE_NETWORK 16
|
||||
#define MULTIBOOT2_TAG_TYPE_EFI_MMAP 17
|
||||
#define MULTIBOOT2_TAG_TYPE_EFI_BS 18
|
||||
#define MULTIBOOT2_TAG_TYPE_EFI32_IH 19
|
||||
#define MULTIBOOT2_TAG_TYPE_EFI64_IH 20
|
||||
#define MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR 21
|
||||
|
||||
#define MULTIBOOT_HEADER_TAG_END 0
|
||||
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
||||
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
|
||||
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
|
||||
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
|
||||
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
|
||||
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
|
||||
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
|
||||
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
|
||||
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
|
||||
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
|
||||
#define MULTIBOOT2_HEADER_TAG_END 0
|
||||
#define MULTIBOOT2_HEADER_TAG_INFORMATION_REQUEST 1
|
||||
#define MULTIBOOT2_HEADER_TAG_ADDRESS 2
|
||||
#define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS 3
|
||||
#define MULTIBOOT2_HEADER_TAG_CONSOLE_FLAGS 4
|
||||
#define MULTIBOOT2_HEADER_TAG_FRAMEBUFFER 5
|
||||
#define MULTIBOOT2_HEADER_TAG_MODULE_ALIGN 6
|
||||
#define MULTIBOOT2_HEADER_TAG_EFI_BS 7
|
||||
#define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
|
||||
#define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
|
||||
#define MULTIBOOT2_HEADER_TAG_RELOCATABLE 10
|
||||
|
||||
#define MULTIBOOT_ARCHITECTURE_I386 0
|
||||
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
|
||||
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
|
||||
#define MULTIBOOT2_ARCHITECTURE_I386 0
|
||||
#define MULTIBOOT2_ARCHITECTURE_MIPS32 4
|
||||
#define MULTIBOOT2_HEADER_TAG_OPTIONAL 1
|
||||
|
||||
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
|
||||
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
|
||||
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
|
||||
#define MULTIBOOT2_LOAD_PREFERENCE_NONE 0
|
||||
#define MULTIBOOT2_LOAD_PREFERENCE_LOW 1
|
||||
#define MULTIBOOT2_LOAD_PREFERENCE_HIGH 2
|
||||
|
||||
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
||||
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
||||
#define MULTIBOOT2_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
||||
#define MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
||||
|
||||
// This should be in %eax.
|
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2badb002
|
||||
@ -94,8 +94,14 @@
|
||||
|
||||
.section ".multiboot_header", "a"
|
||||
|
||||
#define MB_FLAGS_FB 0x4
|
||||
|
||||
// reference: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Header-graphics-fields
|
||||
#define MB_HEADER_GRAPHIC_MODE_LINEAR 0
|
||||
#define MB_HEADER_GRAPHIC_MODE_TEXT 1
|
||||
|
||||
MB_MAGIC = 0x1BADB002
|
||||
MB_FLAGS = 0
|
||||
MB_FLAGS = MB_FLAGS_FB
|
||||
MB_CHECKSUM = -(MB_MAGIC + MB_FLAGS)
|
||||
|
||||
.code32
|
||||
@ -104,24 +110,42 @@ multiboot_header:
|
||||
.long MB_MAGIC
|
||||
.long MB_FLAGS
|
||||
.long MB_CHECKSUM
|
||||
// header_addr if flags[16] is set
|
||||
.long 0
|
||||
// load_addr if flags[16] is set
|
||||
.long 0
|
||||
// load_end_addr if flags[16] is set
|
||||
.long 0
|
||||
// bss_end_addr if flags[16] is set
|
||||
.long 0
|
||||
// entry_addr if flags[16] is set
|
||||
.long 0
|
||||
// mode_type if flags[2] is set
|
||||
.long MB_HEADER_GRAPHIC_MODE_LINEAR
|
||||
// width if flags[2] is set
|
||||
.long 1440
|
||||
// height if flags[2] is set
|
||||
.long 900
|
||||
// depth if flags[2] is set
|
||||
.long 32
|
||||
|
||||
|
||||
// multiboot2 文件头
|
||||
// 计算头长度
|
||||
.SET MB2_HEADER_LENGTH, multiboot2_header_end - multiboot2_header
|
||||
// 计算校验和
|
||||
.SET MB2_CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + MB2_HEADER_LENGTH)
|
||||
.SET MB2_CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_ARCHITECTURE_I386 + MB2_HEADER_LENGTH)
|
||||
// 8 字节对齐
|
||||
.code32
|
||||
.section .multiboot2_header
|
||||
.align MULTIBOOT_HEADER_ALIGN
|
||||
.align MULTIBOOT2_HEADER_ALIGN
|
||||
// 声明所属段
|
||||
|
||||
multiboot2_header:
|
||||
// 魔数
|
||||
.long MULTIBOOT2_HEADER_MAGIC
|
||||
// 架构
|
||||
.long MULTIBOOT_ARCHITECTURE_I386
|
||||
.long MULTIBOOT2_ARCHITECTURE_I386
|
||||
// 头长度
|
||||
.long MB2_HEADER_LENGTH
|
||||
// 校验和
|
||||
@ -131,15 +155,15 @@ multiboot2_header:
|
||||
// 设置帧缓冲区(同时在这里设置qemu的分辨率, 默认为: 1440*900, 还支持: 640*480, 等)
|
||||
.align 8
|
||||
framebuffer_tag_start:
|
||||
.short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
|
||||
.short MULTIBOOT_HEADER_TAG_OPTIONAL
|
||||
.short MULTIBOOT2_HEADER_TAG_FRAMEBUFFER
|
||||
.short MULTIBOOT2_HEADER_TAG_OPTIONAL
|
||||
.long framebuffer_tag_end - framebuffer_tag_start
|
||||
.long 1440 // 宽
|
||||
.long 900 // 高
|
||||
.long 32
|
||||
framebuffer_tag_end:
|
||||
.align 8
|
||||
.short MULTIBOOT_HEADER_TAG_END
|
||||
.short MULTIBOOT2_HEADER_TAG_END
|
||||
// 结束标记
|
||||
.short 0
|
||||
.long 8
|
||||
|
@ -1,5 +1,7 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::arch::init::multiboot::early_multiboot_init;
|
||||
|
||||
use super::multiboot2::early_multiboot2_init;
|
||||
|
||||
const BOOT_ENTRY_TYPE_MULTIBOOT: u64 = 1;
|
||||
@ -38,10 +40,7 @@ pub(super) fn early_boot_init(
|
||||
) -> Result<(), SystemError> {
|
||||
let boot_protocol = BootProtocol::try_from(boot_entry_type)?;
|
||||
match boot_protocol {
|
||||
BootProtocol::Multiboot => {
|
||||
// early_multiboot_init(arg1, arg2);
|
||||
unimplemented!();
|
||||
}
|
||||
BootProtocol::Multiboot => early_multiboot_init(arg1 as u32, arg2),
|
||||
BootProtocol::Multiboot2 => early_multiboot2_init(arg1 as u32, arg2),
|
||||
BootProtocol::Linux32 => {
|
||||
// linux32_init(arg1, arg2);
|
||||
|
@ -25,6 +25,7 @@ use super::{
|
||||
};
|
||||
|
||||
mod boot;
|
||||
mod multiboot;
|
||||
mod multiboot2;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
191
kernel/src/arch/x86_64/init/multiboot.rs
Normal file
191
kernel/src/arch/x86_64/init/multiboot.rs
Normal file
@ -0,0 +1,191 @@
|
||||
use core::ffi::CStr;
|
||||
|
||||
use alloc::string::{String, ToString};
|
||||
|
||||
use multiboot::MultibootInfo;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
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, MemoryManagementArch, PhysAddr},
|
||||
};
|
||||
|
||||
static MB1_INFO: Lazy<MultibootInfo> = Lazy::new();
|
||||
|
||||
struct Mb1Ops;
|
||||
|
||||
impl multiboot::MultibootOps for Mb1Ops {
|
||||
fn phys_2_virt(&self, paddr: usize) -> usize {
|
||||
unsafe { MMArch::phys_2_virt(PhysAddr::new(paddr)).unwrap().data() }
|
||||
}
|
||||
}
|
||||
struct Mb1Callback;
|
||||
|
||||
impl BootCallbacks for Mb1Callback {
|
||||
fn init_bootloader_name(&self) -> Result<Option<String>, SystemError> {
|
||||
let info = MB1_INFO.get();
|
||||
if info.boot_loader_name != 0 {
|
||||
// SAFETY: the bootloader name is C-style zero-terminated string.
|
||||
unsafe {
|
||||
let cstr_ptr =
|
||||
MMArch::phys_2_virt(PhysAddr::new(info.boot_loader_name as usize)).unwrap();
|
||||
let cstr = CStr::from_ptr(cstr_ptr.data() as *const i8);
|
||||
|
||||
let result = cstr.to_str().unwrap_or("unknown").to_string();
|
||||
return Ok(Some(result));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError> {
|
||||
// MB1不提供rsdp信息。因此,将来需要让内核支持从UEFI获取RSDP表。
|
||||
Ok(BootloaderAcpiArg::NotProvided)
|
||||
}
|
||||
|
||||
fn init_kernel_cmdline(&self) -> Result<(), SystemError> {
|
||||
let info = MB1_INFO.get();
|
||||
|
||||
if !info.has_cmdline() {
|
||||
log::debug!("No kernel command line found in multiboot1 info");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(cmdline) = unsafe { info.cmdline(&Mb1Ops) } {
|
||||
let mut guard = boot_params().write_irqsave();
|
||||
guard.boot_cmdline_append(cmdline.as_bytes());
|
||||
|
||||
log::info!("Kernel command line: {}\n", cmdline);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn early_init_framebuffer_info(
|
||||
&self,
|
||||
scinfo: &mut BootTimeScreenInfo,
|
||||
) -> Result<(), SystemError> {
|
||||
let info = MB1_INFO.get();
|
||||
let fb_table = info.framebuffer_table;
|
||||
let width = fb_table.width;
|
||||
let height = fb_table.height;
|
||||
scinfo.is_vga = true;
|
||||
scinfo.lfb_base = PhysAddr::new(fb_table.paddr as usize);
|
||||
let fb_type = fb_table.color_info().unwrap();
|
||||
|
||||
match fb_type {
|
||||
multiboot::ColorInfoType::Palette(_) => todo!(),
|
||||
multiboot::ColorInfoType::Rgb(rgb) => {
|
||||
scinfo.lfb_width = width;
|
||||
scinfo.lfb_height = height;
|
||||
scinfo.video_type = BootTimeVideoType::Vlfb;
|
||||
scinfo.lfb_depth = fb_table.bpp;
|
||||
scinfo.red_pos = rgb.red_field_position;
|
||||
scinfo.red_size = rgb.red_mask_size;
|
||||
scinfo.green_pos = rgb.green_field_position;
|
||||
scinfo.green_size = rgb.green_mask_size;
|
||||
scinfo.blue_pos = rgb.blue_field_position;
|
||||
scinfo.blue_size = rgb.blue_mask_size;
|
||||
}
|
||||
multiboot::ColorInfoType::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 * ((scinfo.lfb_depth 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 info = MB1_INFO.get();
|
||||
let mut total_mem_size = 0usize;
|
||||
let mut usable_mem_size = 0usize;
|
||||
for entry in unsafe { info.memory_map(&Mb1Ops) } {
|
||||
let start = PhysAddr::new(entry.base_addr() as usize);
|
||||
let size = entry.length() as usize;
|
||||
let area_typ = entry.memory_type();
|
||||
total_mem_size += size;
|
||||
|
||||
match area_typ {
|
||||
multiboot::MemoryType::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_multiboot1 end\n\0".as_bytes());
|
||||
log::info!(
|
||||
"Total memory size: {:#x}, Usable memory size: {:#x}",
|
||||
total_mem_size,
|
||||
usable_mem_size
|
||||
);
|
||||
|
||||
if let Some(modules_iter) = unsafe { info.modules(&Mb1Ops) } {
|
||||
for m in modules_iter {
|
||||
let base = PhysAddr::new(m.start() as usize);
|
||||
let size = m.end() as usize - m.start() as usize;
|
||||
mem_block_manager()
|
||||
.reserve_block(base, size)
|
||||
.unwrap_or_else(|e| {
|
||||
log::warn!(
|
||||
"Failed to reserve modules memory block: base={:?}, size={:#x}, error={:?}",
|
||||
base,
|
||||
size,
|
||||
e
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn early_multiboot_init(boot_magic: u32, boot_info: u64) -> Result<(), SystemError> {
|
||||
assert_eq!(boot_magic, multiboot::MAGIC);
|
||||
let boot_info = unsafe { MMArch::phys_2_virt(PhysAddr::new(boot_info as usize)).unwrap() };
|
||||
let mb1_info = unsafe { (boot_info.data() as *const MultibootInfo).as_ref().unwrap() };
|
||||
MB1_INFO.init(*mb1_info);
|
||||
|
||||
register_boot_callbacks(&Mb1Callback);
|
||||
|
||||
Ok(())
|
||||
}
|
@ -131,7 +131,7 @@ impl BootCallbacks for Mb2Callback {
|
||||
}
|
||||
};
|
||||
|
||||
scinfo.lfb_size = (width * height * ((fb_tag.bpp() as u32 + 7) / 8)) as usize;
|
||||
scinfo.lfb_size = (width * height * ((scinfo.lfb_depth as u32 + 7) / 8)) as usize;
|
||||
|
||||
scinfo.lfb_virt_base = Some(vesafb_early_map(scinfo.lfb_base, scinfo.lfb_size)?);
|
||||
|
||||
|
@ -9,7 +9,7 @@ SECTIONS
|
||||
//KERNEL_VMA = 0;
|
||||
. = 0;
|
||||
. = 0x100000;
|
||||
|
||||
_default_kernel_load_base = .;
|
||||
.boot.text :
|
||||
{
|
||||
KEEP(*(.multiboot_header))
|
||||
|
@ -141,12 +141,13 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
fn _edata();
|
||||
fn _erodata();
|
||||
fn _end();
|
||||
fn _default_kernel_load_base();
|
||||
}
|
||||
|
||||
Self::init_xd_rsvd();
|
||||
|
||||
let bootstrap_info = X86_64MMBootstrapInfo {
|
||||
kernel_load_base_paddr: 0,
|
||||
kernel_load_base_paddr: _default_kernel_load_base as usize,
|
||||
kernel_code_start: _text as usize,
|
||||
kernel_code_end: _etext as usize,
|
||||
kernel_data_end: _edata as usize,
|
||||
|
Reference in New Issue
Block a user