feat: 允许通过multiboot引导(直到acpi初始化报错) (#914)

This commit is contained in:
LoGin
2024-09-06 20:04:36 +08:00
committed by GitHub
parent 886ce28516
commit db7c782a9a
12 changed files with 847 additions and 63 deletions

View File

@ -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

View File

@ -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);

View File

@ -25,6 +25,7 @@ use super::{
};
mod boot;
mod multiboot;
mod multiboot2;
#[derive(Debug)]

View 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(())
}

View File

@ -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)?);

View File

@ -9,7 +9,7 @@ SECTIONS
//KERNEL_VMA = 0;
. = 0;
. = 0x100000;
_default_kernel_load_base = .;
.boot.text :
{
KEEP(*(.multiboot_header))

View File

@ -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,