Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase portability though existing Info trait #228

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/arch/x86_64/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub fn stack_range() -> Range<usize> {

const NUM_MEM_DESCS: usize = 4;

pub const KERNEL_START: u64 = 0x20_0000;

pub static MEM_LAYOUT: MemoryLayout<NUM_MEM_DESCS> = [
MemoryDescriptor {
name: "PVH Header",
Expand Down
14 changes: 13 additions & 1 deletion src/bootinfo.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2022 Akira Moroo

use crate::layout::MemoryDescriptor;

// Common data needed for all boot paths
pub trait Info {
// Name of for this boot protocol
fn name(&self) -> &str;
// Starting address of the Root System Descriptor Pointer
fn rsdp_addr(&self) -> u64;
fn rsdp_addr(&self) -> Option<u64> {
None
}
// Address of FDT to use for booting if present
fn fdt_addr(&self) -> Option<u64> {
None
}
// The kernel command line (not including null terminator)
fn cmdline(&self) -> &[u8];
// Methods to access the Memory map
fn num_entries(&self) -> usize;
fn entry(&self, idx: usize) -> MemoryEntry;
// Where to load kernel
fn kernel_load_addr(&self) -> u64;
// Reference to memory layout
fn memory_layout(&self) -> &'static [MemoryDescriptor];
}

pub struct MemoryEntry {
Expand Down
10 changes: 4 additions & 6 deletions src/bzimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,18 @@ impl From<fat::Error> for Error {
}
}

const KERNEL_LOCATION: u64 = 0x20_0000;

#[repr(transparent)]
pub struct Kernel(Params);

impl Kernel {
pub fn new(info: &dyn Info) -> Self {
let mut kernel = Self(Params::default());
kernel.0.acpi_rsdp_addr = info.rsdp_addr();
kernel.0.acpi_rsdp_addr = info.rsdp_addr().unwrap_or_default();
kernel.0.set_entries(info);
kernel
}

pub fn load_kernel(&mut self, f: &mut dyn Read) -> Result<(), Error> {
pub fn load_kernel(&mut self, info: &dyn Info, f: &mut dyn Read) -> Result<(), Error> {
self.0.hdr = Header::from_file(f)?;

if self.0.hdr.boot_flag != 0xAA55 || self.0.hdr.header != *b"HdrS" {
Expand All @@ -67,13 +65,13 @@ impl Kernel {
let setup_bytes = (setup_sects + 1) * SectorBuf::len() as u32;
let remaining_bytes = f.get_size() - setup_bytes;

let mut region = MemoryRegion::new(KERNEL_LOCATION, remaining_bytes as u64);
let mut region = MemoryRegion::new(info.kernel_load_addr(), remaining_bytes as u64);
f.seek(setup_bytes)?;
f.load_file(&mut region)?;

// Fill out "write/modify" fields
self.0.hdr.type_of_loader = 0xff; // Unknown Loader
self.0.hdr.code32_start = KERNEL_LOCATION as u32; // Where we load the kernel
self.0.hdr.code32_start = info.kernel_load_addr() as u32; // Where we load the kernel
self.0.hdr.cmd_line_ptr = CMDLINE_START as u32; // Where we load the cmdline
Ok(())
}
Expand Down
10 changes: 8 additions & 2 deletions src/coreboot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ impl Info for StartInfo {
fn name(&self) -> &str {
"coreboot"
}
fn rsdp_addr(&self) -> u64 {
self.rsdp_addr
fn rsdp_addr(&self) -> Option<u64> {
Some(self.rsdp_addr)
}
fn cmdline(&self) -> &[u8] {
b""
Expand All @@ -111,6 +111,12 @@ impl Info for StartInfo {
let entry = unsafe { &*ptr.add(idx) };
MemoryEntry::from(*entry)
}
fn kernel_load_addr(&self) -> u64 {
crate::arch::x86_64::layout::KERNEL_START
}
fn memory_layout(&self) -> &'static [crate::layout::MemoryDescriptor] {
&crate::arch::x86_64::layout::MEM_LAYOUT[..]
}
}

fn find_header(start: u64, len: usize) -> Option<u64> {
Expand Down
11 changes: 2 additions & 9 deletions src/efi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -936,13 +936,7 @@ fn populate_allocator(info: &dyn bootinfo::Info, image_address: u64, image_size:
}
}

#[cfg(target_arch = "aarch64")]
use crate::arch::aarch64::layout::MEM_LAYOUT;

#[cfg(target_arch = "x86_64")]
use crate::arch::x86_64::layout::MEM_LAYOUT;

for descriptor in MEM_LAYOUT {
for descriptor in info.memory_layout() {
let memory_type = match descriptor.attribute {
layout::MemoryAttribute::Code => efi::RUNTIME_SERVICES_CODE,
layout::MemoryAttribute::Data => efi::RUNTIME_SERVICES_DATA,
Expand Down Expand Up @@ -1072,9 +1066,8 @@ pub fn efi_exec(
block: *const crate::block::VirtioBlockDevice,
) {
let vendor_data = 0u32;
let acpi_rsdp_ptr = info.rsdp_addr();

let ct_entry = if acpi_rsdp_ptr != 0 {
let ct_entry = if let Some(acpi_rsdp_ptr) = info.rsdp_addr() {
efi::ConfigurationTable {
vendor_guid: Guid::from_fields(
0x8868_e871,
Expand Down
43 changes: 37 additions & 6 deletions src/fdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,42 @@

use fdt::Fdt;

use crate::bootinfo::{EntryType, Info, MemoryEntry};
use crate::{
bootinfo::{EntryType, Info, MemoryEntry},
layout::MemoryDescriptor,
};

pub struct StartInfo<'a> {
acpi_rsdp_addr: Option<u64>,
fdt_addr: u64,
fdt: Fdt<'a>,
kernel_load_addr: u64,
memory_layout: &'static [MemoryDescriptor],
}

impl StartInfo<'_> {
pub fn new(ptr: *const u8) -> Self {
pub fn new(
ptr: *const u8,
acpi_rsdp_addr: Option<u64>,
kernel_load_addr: u64,
memory_layout: &'static [MemoryDescriptor],
) -> Self {
let fdt = unsafe {
match Fdt::from_ptr(ptr) {
Ok(fdt) => fdt,
Err(e) => panic!("Failed to create device tree object: {:?}", e),
}
};

Self { fdt }
let fdt_addr = ptr as u64;

Self {
fdt_addr,
fdt,
acpi_rsdp_addr,
kernel_load_addr,
memory_layout,
}
}

pub fn find_compatible_region(&self, with: &[&str]) -> Option<(*const u8, usize)> {
Expand All @@ -35,9 +55,12 @@ impl Info for StartInfo<'_> {
"FDT"
}

fn rsdp_addr(&self) -> u64 {
// TODO: Remove reference to a platform specific value.
crate::arch::aarch64::layout::map::dram::ACPI_START as u64
fn rsdp_addr(&self) -> Option<u64> {
self.acpi_rsdp_addr
}

fn fdt_addr(&self) -> Option<u64> {
Some(self.fdt_addr)
}

fn cmdline(&self) -> &[u8] {
Expand All @@ -63,4 +86,12 @@ impl Info for StartInfo<'_> {
}
panic!("No valid memory entry found");
}

fn kernel_load_addr(&self) -> u64 {
self.kernel_load_addr
}

fn memory_layout(&self) -> &'static [MemoryDescriptor] {
self.memory_layout
}
}
2 changes: 1 addition & 1 deletion src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ pub fn load_default_entry(
let mut kernel = Kernel::new(info);

let mut bzimage_file = fs.open(bzimage_path)?;
kernel.load_kernel(&mut bzimage_file)?;
kernel.load_kernel(info, &mut bzimage_file)?;

if !initrd_path.is_empty() {
let mut initrd_file = fs.open(initrd_path)?;
Expand Down
15 changes: 9 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ mod bootinfo;
mod bzimage;
#[cfg(target_arch = "x86_64")]
mod cmos;
#[cfg(target_arch = "x86_64")]
mod coreboot;
mod delay;
mod efi;
Expand Down Expand Up @@ -128,11 +129,8 @@ fn boot_from_device(device: &mut block::VirtioBlockDevice, info: &dyn bootinfo::
log!("Found bootloader: {}", efi::EFI_BOOT_PATH);

let mut l = pe::Loader::new(&mut file);
#[cfg(target_arch = "aarch64")]
let load_addr = arch::aarch64::layout::map::dram::KERNEL_START as u64;
#[cfg(target_arch = "x86_64")]
let load_addr = 0x20_0000;
let (entry_addr, load_addr, size) = match l.load(load_addr) {

let (entry_addr, load_addr, size) = match l.load(info.kernel_load_addr()) {
Ok(load_info) => load_info,
Err(err) => {
log!("Error loading executable: {:?}", err);
Expand Down Expand Up @@ -170,7 +168,12 @@ pub extern "C" fn rust64_start(x0: *const u8) -> ! {
arch::aarch64::simd::setup_simd();
arch::aarch64::paging::setup();

let info = fdt::StartInfo::new(x0);
let info = fdt::StartInfo::new(
x0,
Some(arch::aarch64::layout::map::dram::ACPI_START as u64),
arch::aarch64::layout::map::dram::KERNEL_START as u64,
&crate::arch::aarch64::layout::MEM_LAYOUT[..],
);

if let Some((base, length)) = info.find_compatible_region(&["pci-host-ecam-generic"]) {
pci::init(base as u64, length as u64);
Expand Down
11 changes: 9 additions & 2 deletions src/pvh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::mem::size_of;
use crate::{
bootinfo::{EntryType, Info, MemoryEntry},
common,
layout::MemoryDescriptor,
};

// Structures from xen/include/public/arch-x86/hvm/start_info.h
Expand Down Expand Up @@ -44,8 +45,8 @@ impl Info for StartInfo {
fn name(&self) -> &str {
"PVH Boot Protocol"
}
fn rsdp_addr(&self) -> u64 {
self.rsdp_paddr
fn rsdp_addr(&self) -> Option<u64> {
Some(self.rsdp_paddr)
}
fn cmdline(&self) -> &[u8] {
unsafe { common::from_cstring(self.cmdline_paddr) }
Expand All @@ -63,6 +64,12 @@ impl Info for StartInfo {
let entry = unsafe { *ptr.add(idx) };
MemoryEntry::from(entry)
}
fn kernel_load_addr(&self) -> u64 {
crate::arch::x86_64::layout::KERNEL_START
}
fn memory_layout(&self) -> &'static [MemoryDescriptor] {
&crate::arch::x86_64::layout::MEM_LAYOUT[..]
}
}

// The PVH Boot Protocol starts at the 32-bit entrypoint to our firmware.
Expand Down