1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/openeuler-stratovirt

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
bootparam.rs 8.2 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
liuxiangdong Отправлено 2 лет назад 74c9827
// Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved.
//
// StratoVirt is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
use std::sync::Arc;
use anyhow::{anyhow, Result};
use super::{
X86BootLoaderConfig, EBDA_START, MB_BIOS_BEGIN, REAL_MODE_IVT_BEGIN, VGA_RAM_BEGIN,
VMLINUX_RAM_START,
};
use crate::error::BootLoaderError;
use address_space::AddressSpace;
use util::byte_code::ByteCode;
pub const E820_RAM: u32 = 1;
pub const E820_RESERVED: u32 = 2;
pub const BOOT_VERSION: u16 = 0x0200;
pub const BOOT_FLAG: u16 = 0xAA55;
pub const HDRS: u32 = 0x5372_6448;
pub const UNDEFINED_ID: u8 = 0xFF;
// Loader type ID: OVMF UEFI virtualization stack.
pub const UEFI_OVMF_ID: u8 = 0xB;
// Structures below sourced from:
// https://www.kernel.org/doc/html/latest/x86/boot.html
// https://www.kernel.org/doc/html/latest/x86/zero-page.html
#[repr(C, packed)]
#[derive(Debug, Default, Copy, Clone)]
pub struct RealModeKernelHeader {
pub setup_sects: u8,
root_flags: u16,
syssize: u32,
ram_size: u16,
video_mode: u16,
root_dev: u16,
boot_flag: u16,
jump: u16,
pub header: u32,
pub version: u16,
realmode_swtch: u32,
start_sys_seg: u16,
kernel_version: u16,
pub type_of_loader: u8,
pub loadflags: u8,
setup_move_size: u16,
pub code32_start: u32,
ramdisk_image: u32,
ramdisk_size: u32,
bootsect_kludge: u32,
heap_end_ptr: u16,
ext_loader_ver: u8,
ext_loader_type: u8,
cmdline_ptr: u32,
initrd_addr_max: u32,
kernel_alignment: u32,
relocatable_kernel: u8,
min_alignment: u8,
xloadflags: u16,
cmdline_size: u32,
hardware_subarch: u32,
hardware_subarch_data: u64,
payload_offset: u32,
payload_length: u32,
setup_data: u64,
pref_address: u64,
init_size: u32,
handover_offset: u32,
kernel_info_offset: u32,
}
impl ByteCode for RealModeKernelHeader {}
impl RealModeKernelHeader {
pub fn new() -> Self {
RealModeKernelHeader {
boot_flag: BOOT_FLAG,
header: HDRS,
type_of_loader: UNDEFINED_ID,
..Default::default()
}
}
pub fn check_valid_kernel(&self) -> Result<()> {
if self.header != HDRS {
return Err(anyhow!(BootLoaderError::ElfKernel));
}
if (self.version < BOOT_VERSION) || ((self.loadflags & 0x1) == 0x0) {
return Err(anyhow!(BootLoaderError::InvalidBzImage));
}
if self.version < 0x202 {
return Err(anyhow!(BootLoaderError::OldVersionKernel));
}
Ok(())
}
pub fn set_cmdline(&mut self, cmdline_addr: u32, cmdline_size: u32) {
self.cmdline_ptr = cmdline_addr;
self.cmdline_size = cmdline_size;
}
pub fn set_ramdisk(&mut self, addr: u32, size: u32) {
self.ramdisk_image = addr;
self.ramdisk_size = size;
}
}
#[repr(C, packed)]
#[derive(Debug, Default, Copy, Clone)]
pub struct E820Entry {
addr: u64,
size: u64,
type_: u32,
}
impl E820Entry {
pub(crate) fn new(addr: u64, size: u64, type_: u32) -> E820Entry {
E820Entry { addr, size, type_ }
}
}
impl ByteCode for E820Entry {}
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct BootParams {
screen_info: [u8; 0x40],
apm_bios_info: [u8; 0x14],
pad1: u32,
tboot_addr: [u8; 0x8],
ist_info: [u8; 0x10],
pad2: [u8; 0x10],
hd0_info: [u8; 0x10],
hd1_info: [u8; 0x10],
sys_desc_table: [u8; 0x10],
olpc_ofw_header: [u8; 0x10],
ext_ramdisk_image: u32,
ext_ramdisk_size: u32,
ext_cmd_line_ptr: u32,
pad3: [u8; 0x74],
edid_info: [u8; 0x80],
efi_info: [u8; 0x20],
alt_mem_k: u32,
scratch: u32,
e820_entries: u8,
eddbuf_entries: u8,
edd_mbr_sig_buf_entries: u8,
kbd_status: u8,
secure_boot: u8,
pad4: u16,
sentinel: u8,
pad5: u8,
kernel_header: RealModeKernelHeader, // offset: 0x1f1
pad6: [u8; 0x24],
edd_mbr_sig_buffer: [u8; 0x40],
e820_table: [E820Entry; 0x80],
pad8: [u8; 0x30],
eddbuf: [u8; 0x1ec],
}
impl ByteCode for BootParams {}
impl Default for BootParams {
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
}
}
impl BootParams {
pub fn new(kernel_header: RealModeKernelHeader) -> Self {
BootParams {
kernel_header,
..Default::default()
}
}
pub fn add_e820_entry(&mut self, addr: u64, size: u64, type_: u32) {
self.e820_table[self.e820_entries as usize] = E820Entry::new(addr, size, type_);
self.e820_entries += 1;
}
pub fn setup_e820_entries(
&mut self,
config: &X86BootLoaderConfig,
sys_mem: &Arc<AddressSpace>,
) {
self.add_e820_entry(
REAL_MODE_IVT_BEGIN,
EBDA_START - REAL_MODE_IVT_BEGIN,
E820_RAM,
);
self.add_e820_entry(EBDA_START, VGA_RAM_BEGIN - EBDA_START, E820_RESERVED);
self.add_e820_entry(MB_BIOS_BEGIN, 0, E820_RESERVED);
let high_memory_start = VMLINUX_RAM_START;
let layout_32bit_gap_end = config.gap_range.0 + config.gap_range.1;
let mem_end = sys_mem.memory_end_address().raw_value();
if mem_end < layout_32bit_gap_end {
self.add_e820_entry(high_memory_start, mem_end - high_memory_start, E820_RAM);
} else {
self.add_e820_entry(
high_memory_start,
config.gap_range.0 - high_memory_start,
E820_RAM,
);
self.add_e820_entry(
layout_32bit_gap_end,
mem_end - layout_32bit_gap_end,
E820_RAM,
);
}
}
}
#[cfg(test)]
mod test {
use std::path::PathBuf;
use std::sync::Arc;
use super::super::X86BootLoaderConfig;
use super::*;
use address_space::{AddressSpace, GuestAddress, HostMemMapping, Region};
#[test]
fn test_boot_param() {
let root = Region::init_container_region(0x2000_0000, "root");
let space = AddressSpace::new(root.clone(), "space").unwrap();
let ram1 = Arc::new(
HostMemMapping::new(
GuestAddress(0),
None,
0x1000_0000,
None,
false,
false,
false,
)
.unwrap(),
);
let region_a = Region::init_ram_region(ram1.clone(), "region_a");
root.add_subregion(region_a, ram1.start_address().raw_value())
.unwrap();
let config = X86BootLoaderConfig {
kernel: Some(PathBuf::new()),
initrd: Some(PathBuf::new()),
kernel_cmdline: String::from("this_is_a_piece_of_test_string"),
cpu_count: 2,
gap_range: (0xC000_0000, 0x4000_0000),
ioapic_addr: 0xFEC0_0000,
lapic_addr: 0xFEE0_0000,
prot64_mode: false,
ident_tss_range: None,
};
let boot_hdr = RealModeKernelHeader::default();
let mut boot_params = BootParams::new(boot_hdr);
boot_params.setup_e820_entries(&config, &space);
assert_eq!(boot_params.e820_entries, 4);
assert!(boot_params.e820_table[0].addr == 0);
assert!(boot_params.e820_table[0].addr == 0);
assert!(boot_params.e820_table[0].size == 0x0009_FC00);
assert!(boot_params.e820_table[0].type_ == 1);
assert!(boot_params.e820_table[1].addr == 0x0009_FC00);
assert!(boot_params.e820_table[1].size == 0x400);
assert!(boot_params.e820_table[1].type_ == 2);
assert!(boot_params.e820_table[2].addr == 0x000F_0000);
assert!(boot_params.e820_table[2].size == 0);
assert!(boot_params.e820_table[2].type_ == 2);
assert!(boot_params.e820_table[3].addr == 0x0010_0000);
assert!(boot_params.e820_table[3].size == 0x0ff0_0000);
assert!(boot_params.e820_table[3].type_ == 1);
}
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/openeuler-stratovirt.git
git@gitlife.ru:oschina-mirror/openeuler-stratovirt.git
oschina-mirror
openeuler-stratovirt
openeuler-stratovirt
v2.3.0