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

bootinfo: Add architecture-independent memory entry #212

Merged
merged 1 commit into from
Nov 28, 2022
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
85 changes: 66 additions & 19 deletions src/boot.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2022 Akira Moroo

use core::mem;

use crate::{
bootinfo::{EntryType, Info, MemoryEntry},
common,
fat::{Error, Read},
mem::MemoryRegion,
};

// 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;
// The kernel command line (not including null terminator)
fn cmdline(&self) -> &[u8];
// Methods to access the E820 Memory map
fn num_entries(&self) -> u8;
fn entry(&self, idx: u8) -> E820Entry;
}

#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
pub struct E820Entry {
Expand All @@ -29,6 +20,61 @@ pub struct E820Entry {

impl E820Entry {
pub const RAM_TYPE: u32 = 1;
pub const RESERVED_TYPE: u32 = 2;
pub const ACPI_RECLAIMABLE_TYPE: u32 = 3;
pub const ACPI_NVS_TYPE: u32 = 4;
pub const BAD_TYPE: u32 = 5;
pub const VENDOR_RESERVED_TYPE: u32 = 6; // coreboot only
pub const COREBOOT_TABLE_TYPE: u32 = 16; // coreboot only
}

impl From<u32> for EntryType {
fn from(value: u32) -> Self {
match value {
E820Entry::RAM_TYPE => Self::Ram,
E820Entry::RESERVED_TYPE => Self::Reserved,
E820Entry::ACPI_RECLAIMABLE_TYPE => Self::AcpiReclaimable,
E820Entry::ACPI_NVS_TYPE => Self::AcpiNvs,
E820Entry::BAD_TYPE => Self::Bad,
E820Entry::VENDOR_RESERVED_TYPE => Self::VendorReserved,
E820Entry::COREBOOT_TABLE_TYPE => Self::CorebootTable,
_ => panic!("Unsupported e820 type"),
}
}
}

impl From<EntryType> for u32 {
fn from(value: EntryType) -> Self {
match value {
EntryType::Ram => E820Entry::RAM_TYPE,
EntryType::Reserved => E820Entry::RESERVED_TYPE,
EntryType::AcpiReclaimable => E820Entry::ACPI_RECLAIMABLE_TYPE,
EntryType::AcpiNvs => E820Entry::ACPI_NVS_TYPE,
EntryType::Bad => E820Entry::BAD_TYPE,
EntryType::VendorReserved => E820Entry::VENDOR_RESERVED_TYPE,
EntryType::CorebootTable => E820Entry::COREBOOT_TABLE_TYPE,
}
}
}

impl From<MemoryEntry> for E820Entry {
fn from(value: MemoryEntry) -> Self {
Self {
addr: value.addr,
size: value.size,
entry_type: u32::from(value.entry_type),
}
}
}

impl From<E820Entry> for MemoryEntry {
fn from(value: E820Entry) -> Self {
Self {
addr: value.addr,
size: value.size,
entry_type: EntryType::from(value.entry_type),
}
}
}

// The so-called "zeropage"
Expand Down Expand Up @@ -80,9 +126,9 @@ impl Default for Params {

impl Params {
pub fn set_entries(&mut self, info: &dyn Info) {
self.e820_entries = info.num_entries();
self.e820_entries = info.num_entries() as u8;
for i in 0..self.e820_entries {
self.e820_table[i as usize] = info.entry(i);
self.e820_table[i as usize] = info.entry(i as usize).into();
}
}
}
Expand All @@ -97,12 +143,13 @@ impl Info for Params {
fn cmdline(&self) -> &[u8] {
unsafe { common::from_cstring(self.hdr.cmd_line_ptr as u64) }
}
fn num_entries(&self) -> u8 {
self.e820_entries
fn num_entries(&self) -> usize {
self.e820_entries as usize
}
fn entry(&self, idx: u8) -> E820Entry {
fn entry(&self, idx: usize) -> MemoryEntry {
assert!(idx < self.num_entries());
self.e820_table[idx as usize]
let entry = self.e820_table[idx];
MemoryEntry::from(entry)
}
}

Expand Down
32 changes: 32 additions & 0 deletions src/bootinfo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2022 Akira Moroo

// 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;
// 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;
}

pub struct MemoryEntry {
pub addr: u64,
pub size: u64,
pub entry_type: EntryType,
}

#[derive(PartialEq)]
pub enum EntryType {
Ram,
Reserved,
AcpiReclaimable,
AcpiNvs,
Bad,
VendorReserved,
CorebootTable,
}
5 changes: 3 additions & 2 deletions src/bzimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use atomic_refcell::AtomicRefCell;

use crate::{
block::SectorBuf,
boot::{E820Entry, Header, Info, Params},
boot::{Header, Params},
bootinfo::{EntryType, Info},
fat::{self, Read},
mem::MemoryRegion,
};
Expand Down Expand Up @@ -95,7 +96,7 @@ impl Kernel {
let mut current_addr = None;
for i in 0..self.0.num_entries() {
let entry = self.0.entry(i);
if entry.entry_type != E820Entry::RAM_TYPE {
if entry.entry_type != EntryType::Ram {
continue;
}

Expand Down
27 changes: 17 additions & 10 deletions src/coreboot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use core::mem::size_of;

use crate::boot::{E820Entry, Info};
use crate::bootinfo::{EntryType, Info, MemoryEntry};

#[derive(Debug)]
#[repr(C)]
Expand Down Expand Up @@ -38,13 +38,24 @@ struct Forward {
forward: u64,
}

#[derive(Clone, Copy)]
#[repr(packed, C)]
struct MemMapEntry {
addr: u64,
size: u64,
entry_type: u32,
}

impl From<MemMapEntry> for MemoryEntry {
fn from(value: MemMapEntry) -> Self {
Self {
addr: value.addr,
size: value.size,
entry_type: EntryType::from(value.entry_type),
}
}
}

#[derive(Debug)]
#[repr(C)]
pub struct StartInfo {
Expand Down Expand Up @@ -88,21 +99,17 @@ impl Info for StartInfo {
fn cmdline(&self) -> &[u8] {
b""
}
fn num_entries(&self) -> u8 {
fn num_entries(&self) -> usize {
if self.memmap_addr == 0 {
return 0;
}
self.memmap_entries as u8
self.memmap_entries
}
fn entry(&self, idx: u8) -> E820Entry {
fn entry(&self, idx: usize) -> MemoryEntry {
assert!(idx < self.num_entries());
let ptr = self.memmap_addr as *const MemMapEntry;
let entry = unsafe { &*ptr.offset(idx as isize) };
E820Entry {
addr: entry.addr,
size: entry.size,
entry_type: entry.entry_type,
}
let entry = unsafe { &*ptr.add(idx) };
MemoryEntry::from(*entry)
}
}

Expand Down
23 changes: 13 additions & 10 deletions src/efi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use r_efi::{
system::{ConfigurationTable, RuntimeServices},
};

use crate::boot;
use crate::bootinfo;
use crate::layout;
use crate::rtc;

Expand Down Expand Up @@ -916,16 +916,19 @@ const PAGE_SIZE: u64 = 4096;
const HEAP_SIZE: usize = 256 * 1024 * 1024;

// Populate allocator from E820, fixed ranges for the firmware and the loaded binary.
fn populate_allocator(info: &dyn boot::Info, image_address: u64, image_size: u64) {
fn populate_allocator(info: &dyn bootinfo::Info, image_address: u64, image_size: u64) {
for i in 0..info.num_entries() {
let entry = info.entry(i);
if entry.entry_type == boot::E820Entry::RAM_TYPE {
ALLOCATOR.borrow_mut().add_initial_allocation(
efi::CONVENTIONAL_MEMORY,
entry.size / PAGE_SIZE,
entry.addr,
efi::MEMORY_WB,
);
match entry.entry_type {
bootinfo::EntryType::Ram => {
ALLOCATOR.borrow_mut().add_initial_allocation(
efi::CONVENTIONAL_MEMORY,
entry.size / PAGE_SIZE,
entry.addr,
efi::MEMORY_WB,
);
}
_ => continue,
}
}

Expand Down Expand Up @@ -1057,7 +1060,7 @@ pub fn efi_exec(
address: u64,
loaded_address: u64,
loaded_size: u64,
info: &dyn boot::Info,
info: &dyn bootinfo::Info,
fs: &crate::fat::Filesystem,
block: *const crate::block::VirtioBlockDevice,
) {
Expand Down
7 changes: 5 additions & 2 deletions src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use crate::{
block::SectorBuf,
boot,
bootinfo,
bzimage::{self, Kernel},
common::ascii_strip,
fat::{self, Read},
Expand Down Expand Up @@ -217,7 +217,10 @@ fn default_entry_path(fs: &fat::Filesystem) -> Result<[u8; 260], Error> {
Ok(entry_path)
}

pub fn load_default_entry(fs: &fat::Filesystem, info: &dyn boot::Info) -> Result<Kernel, Error> {
pub fn load_default_entry(
fs: &fat::Filesystem,
info: &dyn bootinfo::Info,
) -> Result<Kernel, Error> {
let default_entry_path = default_entry_path(fs)?;
let default_entry_path = ascii_strip(&default_entry_path);

Expand Down
5 changes: 3 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod common;
mod arch;
mod block;
mod boot;
mod bootinfo;
mod bzimage;
#[cfg(target_arch = "x86_64")]
mod cmos;
Expand Down Expand Up @@ -75,7 +76,7 @@ fn panic(_: &PanicInfo) -> ! {
const VIRTIO_PCI_VENDOR_ID: u16 = 0x1af4;
const VIRTIO_PCI_BLOCK_DEVICE_ID: u16 = 0x1042;

fn boot_from_device(device: &mut block::VirtioBlockDevice, info: &dyn boot::Info) -> bool {
fn boot_from_device(device: &mut block::VirtioBlockDevice, info: &dyn bootinfo::Info) -> bool {
if let Err(err) = device.init() {
log!("Error configuring block device: {:?}", err);
return false;
Expand Down Expand Up @@ -153,7 +154,7 @@ pub extern "C" fn rust64_start(#[cfg(not(feature = "coreboot"))] pvh_info: &pvh:
}

#[cfg(target_arch = "x86_64")]
fn main(info: &dyn boot::Info) -> ! {
fn main(info: &dyn bootinfo::Info) -> ! {
log!("\nBooting with {}", info.name());

pci::print_bus();
Expand Down
26 changes: 16 additions & 10 deletions src/pvh.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use core::mem::size_of;

use crate::{
boot::{E820Entry, Info},
bootinfo::{EntryType, Info, MemoryEntry},
common,
};

Expand Down Expand Up @@ -30,6 +30,16 @@ struct MemMapEntry {
_pad: u32,
}

impl From<MemMapEntry> for MemoryEntry {
fn from(value: MemMapEntry) -> Self {
Self {
addr: value.addr,
size: value.size,
entry_type: EntryType::from(value.entry_type),
}
}
}

impl Info for StartInfo {
fn name(&self) -> &str {
"PVH Boot Protocol"
Expand All @@ -40,22 +50,18 @@ impl Info for StartInfo {
fn cmdline(&self) -> &[u8] {
unsafe { common::from_cstring(self.cmdline_paddr) }
}
fn num_entries(&self) -> u8 {
fn num_entries(&self) -> usize {
// memmap_paddr and memmap_entries only exist in version 1 or later
if self.version < 1 || self.memmap_paddr == 0 {
return 0;
}
self.memmap_entries as u8
self.memmap_entries as usize
}
fn entry(&self, idx: u8) -> E820Entry {
fn entry(&self, idx: usize) -> MemoryEntry {
assert!(idx < self.num_entries());
let ptr = self.memmap_paddr as *const MemMapEntry;
let entry = unsafe { *ptr.offset(idx as isize) };
E820Entry {
addr: entry.addr,
size: entry.size,
entry_type: entry.entry_type,
}
let entry = unsafe { *ptr.add(idx) };
MemoryEntry::from(entry)
}
}

Expand Down