Skip to content

Commit

Permalink
bootinfo: Add architecture-independent memory entry
Browse files Browse the repository at this point in the history
`E820Entry` is used in `boot::Info` trait, which is x86_64-dependent
memory entry data structure. It's confusing if e820 is used in other
architectures. This commit introduces an architecture-independent memory
entry `bootinfo::MemoryEntry` and replaces `boot::Info` with
`bootinfo::Info`. This change is suggested in [1].

[1]
#205 (comment)

Signed-off-by: Akira Moroo <retrage01@gmail.com>
  • Loading branch information
retrage committed Nov 28, 2022
1 parent 1ff4dc8 commit a91205b
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 55 deletions.
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

0 comments on commit a91205b

Please sign in to comment.