Skip to content
Open
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
32 changes: 32 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ fdt = "0.1.5"
chrono = { version = "0.4", default-features = false }

[target.'cfg(target_arch = "x86_64")'.dependencies]
pvh = "0.1"
uart_16550 = "0.4.0"
x86_64 = { version = "0.15.4", default-features = false, features = [
"instructions",
Expand Down
15 changes: 0 additions & 15 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,6 @@ macro_rules! container_of_mut {
}};
}

// SAFETY: Requires that addr point to a static, null-terminated C-string.
// The returned slice does not include the null-terminator.
#[cfg(all(target_arch = "x86_64", not(feature = "coreboot")))]
pub unsafe fn from_cstring(addr: u64) -> &'static [u8] {
if addr == 0 {
return &[];
}
let start = addr as *const u8;
let mut size: usize = 0;
while start.add(size).read() != 0 {
size += 1;
}
core::slice::from_raw_parts(start, size)
}

pub fn ascii_strip(s: &[u8]) -> &str {
core::str::from_utf8(s).unwrap().trim_matches(char::from(0))
}
Expand Down
10 changes: 6 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,20 +179,22 @@ fn boot_from_device(

#[cfg(target_arch = "x86_64")]
#[no_mangle]
pub extern "C" fn rust64_start(#[cfg(not(feature = "coreboot"))] pvh_info: &pvh::StartInfo) -> ! {
pub extern "C" fn rust64_start(#[cfg(not(feature = "coreboot"))] start_info_paddr: u32) -> ! {
serial::PORT.borrow_mut().init();
logger::init();

arch::x86_64::sse::enable_sse();
arch::x86_64::paging::setup();

#[cfg(feature = "coreboot")]
let info = &coreboot::StartInfo::default();
let info = coreboot::StartInfo::default();

#[cfg(not(feature = "coreboot"))]
let info = pvh_info;
let info = unsafe {
::pvh::start_info::reader::StartInfoReader::from_paddr_identity(start_info_paddr).unwrap()
};

main(info)
main(&info)
}

#[cfg(target_arch = "aarch64")]
Expand Down
84 changes: 14 additions & 70 deletions src/pvh.rs
Original file line number Diff line number Diff line change
@@ -1,70 +1,41 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2020 Google LLC

use core::mem::size_of;
use pvh::start_info::{
reader::{MemMap, StartInfoReader},
MemmapTableEntry,
};

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

// Structures from xen/include/public/arch-x86/hvm/start_info.h
#[derive(Debug)]
#[repr(C)]
pub struct StartInfo {
magic: [u8; 4],
version: u32,
flags: u32,
nr_modules: u32,
modlist_paddr: u64,
cmdline_paddr: u64,
rsdp_paddr: u64,
memmap_paddr: u64,
memmap_entries: u32,
_pad: u32,
}

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

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

impl Info for StartInfo {
impl<M: MemMap> Info for StartInfoReader<'_, M> {
fn name(&self) -> &str {
"PVH Boot Protocol"
}
fn rsdp_addr(&self) -> Option<u64> {
Some(self.rsdp_paddr)
Some(self.raw().rsdp_paddr)
}
fn cmdline(&self) -> &[u8] {
unsafe { common::from_cstring(self.cmdline_paddr) }
self.cmdline().unwrap_or_default().to_bytes()
}
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 usize
self.memmap().len()
}
fn entry(&self, idx: usize) -> MemoryEntry {
assert!(idx < self.num_entries());
let ptr = self.memmap_paddr as *const MemMapEntry;
let entry = unsafe { *ptr.add(idx) };
let entry = self.memmap()[idx];
MemoryEntry::from(entry)
}
fn kernel_load_addr(&self) -> u64 {
Expand All @@ -77,34 +48,7 @@ impl Info for StartInfo {

// The PVH Boot Protocol starts at the 32-bit entrypoint to our firmware.
extern "C" {
fn ram32_start();
fn ram32_start() -> !;
}

// The kind/name/desc of the PHV ELF Note are from xen/include/public/elfnote.h.
// This is the "Physical entry point into the kernel".
const XEN_ELFNOTE_PHYS32_ENTRY: u32 = 18;
type Name = [u8; 4];
type Desc = unsafe extern "C" fn();

// We make sure our ELF Note has an alignment of 4 for maximum compatibility.
// Some software (QEMU) calculates padding incorectly if alignment != 4.
#[repr(C, packed(4))]
struct Note {
name_size: u32,
desc_size: u32,
kind: u32,
name: Name,
desc: Desc,
}

// This is: ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .quad ram32_start)
#[cfg(not(test))]
#[link_section = ".note"]
#[used]
static PVH_NOTE: Note = Note {
name_size: size_of::<Name>() as u32,
desc_size: size_of::<Desc>() as u32,
kind: XEN_ELFNOTE_PHYS32_ENTRY,
name: *b"Xen\0",
desc: ram32_start,
};
pvh::xen_elfnote_phys32_entry!(ram32_start);
2 changes: 1 addition & 1 deletion x86_64-unknown-none.ld
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ SECTIONS
/* Mapping the program headers and note into RAM makes the file smaller. */
. = ram_min;
. += SIZEOF_HEADERS;
.note : { *(.note) } :note :ram
.note : { *(.note .note.*) } :note :ram

/* These sections are mapped into RAM from the file. Omitting :ram from
later sections avoids emitting empty sections in the final binary. */
Expand Down