Skip to content

Fixes #27

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

Merged
merged 4 commits into from
Nov 7, 2023
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
138 changes: 130 additions & 8 deletions src/aml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

extern crate alloc;

use crate::{Aml, AmlSink};
use crate::{gas, Aml, AmlSink};
use alloc::string::String;
use alloc::{vec, vec::Vec};

Expand Down Expand Up @@ -78,6 +78,7 @@ const ONESOP: u8 = 0xff;
// AML resouce data fields
const IOPORTDESC: u8 = 0x47;
const ENDTAG: u8 = 0x79;
const REGDESC: u8 = 0x82;
const MEMORY32FIXEDDESC: u8 = 0x86;
const DWORDADDRSPACEDESC: u8 = 0x87;
const WORDADDRSPACEDESC: u8 = 0x88;
Expand Down Expand Up @@ -298,14 +299,10 @@ pub struct PackageBuilder {

impl Aml for PackageBuilder {
fn to_aml_bytes(&self, sink: &mut dyn AmlSink) {
sink.byte(PACKAGEOP);

let mut pkg_length = create_pkg_length(self.data.len(), true);
pkg_length.reverse();
for byte in pkg_length {
sink.byte(byte);
}
let pkg_length = create_pkg_length(self.data.len() + 1, true);

sink.byte(PACKAGEOP);
sink.vec(&pkg_length);
sink.byte(self.elements as u8);
sink.vec(&self.data);
}
Expand Down Expand Up @@ -776,6 +773,25 @@ impl Aml for Interrupt {
}
}

/// Register resource object
pub struct Register {
reg: gas::GAS,
}

impl Register {
pub fn new(reg: gas::GAS) -> Self {
Self { reg }
}
}

impl Aml for Register {
fn to_aml_bytes(&self, sink: &mut dyn AmlSink) {
sink.byte(REGDESC); /* Register Descriptor */
sink.word(0x12); // length
self.reg.to_aml_bytes(sink);
}
}

/// Device object with its device name and children objects in it.
pub struct Device<'a> {
path: Path,
Expand Down Expand Up @@ -2549,4 +2565,110 @@ mod tests {
.to_aml_bytes(&mut aml);
assert_eq!(aml, data);
}

#[test]
fn test_packagebuilder() {
let expected = vec![0x12, 0x04, 0x01, 0x0A, 0x05];
{
let mut aml = Vec::new();

// Ensure Package and PackageBuilder produce the same output for a single element
Package::new(vec![&5u8]).to_aml_bytes(&mut aml);
assert_eq!(expected, aml);
}
{
let mut aml = Vec::new();
let mut builder = PackageBuilder::new();
builder.add_element(&5u8);
builder.to_aml_bytes(&mut aml);
assert_eq!(expected, aml);
}
}

#[test]
fn test_packagebuilder_multiple() {
let expected = vec![
0x12, 0x47, 0x9, 0x8, 0x12, 0x10, 0x4, 0xb, 0xff, 0xff, 0x0, 0x2e, 0x5f, 0x53, 0x42,
0x5f, 0x47, 0x53, 0x49, 0x30, 0x0, 0x12, 0x10, 0x4, 0xb, 0xff, 0xff, 0x1, 0x2e, 0x5f,
0x53, 0x42, 0x5f, 0x47, 0x53, 0x49, 0x31, 0x0, 0x12, 0x11, 0x4, 0xb, 0xff, 0xff, 0xa,
0x2, 0x2e, 0x5f, 0x53, 0x42, 0x5f, 0x47, 0x53, 0x49, 0x32, 0x0, 0x12, 0x11, 0x4, 0xb,
0xff, 0xff, 0xa, 0x3, 0x2e, 0x5f, 0x53, 0x42, 0x5f, 0x47, 0x53, 0x49, 0x33, 0x0, 0x12,
0x12, 0x4, 0xc, 0xff, 0xff, 0x1, 0x0, 0x0, 0x2e, 0x5f, 0x53, 0x42, 0x5f, 0x47, 0x53,
0x49, 0x31, 0x0, 0x12, 0x12, 0x4, 0xc, 0xff, 0xff, 0x1, 0x0, 0x1, 0x2e, 0x5f, 0x53,
0x42, 0x5f, 0x47, 0x53, 0x49, 0x32, 0x0, 0x12, 0x13, 0x4, 0xc, 0xff, 0xff, 0x1, 0x0,
0xa, 0x2, 0x2e, 0x5f, 0x53, 0x42, 0x5f, 0x47, 0x53, 0x49, 0x33, 0x0, 0x12, 0x13, 0x4,
0xc, 0xff, 0xff, 0x1, 0x0, 0xa, 0x3, 0x2e, 0x5f, 0x53, 0x42, 0x5f, 0x47, 0x53, 0x49,
0x30, 0x0,
];
{
let mut aml = Vec::new();
Package::new(vec![
&Package::new(vec![&0xffffu32, &0u32, &Path::new("_SB_.GSI0"), &0u32]),
&Package::new(vec![&0xffffu32, &1u32, &Path::new("_SB_.GSI1"), &0u32]),
&Package::new(vec![&0xffffu32, &2u32, &Path::new("_SB_.GSI2"), &0u32]),
&Package::new(vec![&0xffffu32, &3u32, &Path::new("_SB_.GSI3"), &0u32]),
&Package::new(vec![&0x1ffffu32, &0u32, &Path::new("_SB_.GSI1"), &0u32]),
&Package::new(vec![&0x1ffffu32, &1u32, &Path::new("_SB_.GSI2"), &0u32]),
&Package::new(vec![&0x1ffffu32, &2u32, &Path::new("_SB_.GSI3"), &0u32]),
&Package::new(vec![&0x1ffffu32, &3u32, &Path::new("_SB_.GSI0"), &0u32]),
])
.to_aml_bytes(&mut aml);
assert_eq!(expected, aml);
}

{
let mut aml = Vec::new();
let mut builder = PackageBuilder::new();
builder.add_element(&Package::new(vec![
&0xffffu32,
&0u32,
&Path::new("_SB_.GSI0"),
&0u32,
]));
builder.add_element(&Package::new(vec![
&0xffffu32,
&1u32,
&Path::new("_SB_.GSI1"),
&0u32,
]));
builder.add_element(&Package::new(vec![
&0xffffu32,
&2u32,
&Path::new("_SB_.GSI2"),
&0u32,
]));
builder.add_element(&Package::new(vec![
&0xffffu32,
&3u32,
&Path::new("_SB_.GSI3"),
&0u32,
]));
builder.add_element(&Package::new(vec![
&0x1ffffu32,
&0u32,
&Path::new("_SB_.GSI1"),
&0u32,
]));
builder.add_element(&Package::new(vec![
&0x1ffffu32,
&1u32,
&Path::new("_SB_.GSI2"),
&0u32,
]));
builder.add_element(&Package::new(vec![
&0x1ffffu32,
&2u32,
&Path::new("_SB_.GSI3"),
&0u32,
]));
builder.add_element(&Package::new(vec![
&0x1ffffu32,
&3u32,
&Path::new("_SB_.GSI0"),
&0u32,
]));
builder.to_aml_bytes(&mut aml);
assert_eq!(expected, aml);
}
}
}
63 changes: 63 additions & 0 deletions src/rhct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ impl RHCT {
IsaStringHandle(old_offset)
}

pub fn add_mmu_node(&mut self, scheme: VirtualAddressScheme) {
let node = MmuNode::new(scheme);

self.handle_offset += MmuNode::len() as u32;
self.update_header(node.u8sum(), MmuNode::len() as u32);
self.structures.push(Box::new(node));
}

pub fn add_cmo(&mut self, cmo: CmoNode) -> CmoHandle {
let old_offset = self.handle_offset;

Expand Down Expand Up @@ -142,6 +150,7 @@ impl Aml for RHCT {
enum RhctNodeType {
IsaString = 0,
Cmo = 1,
Mmu = 2,
HartInfo = 65535,
}

Expand Down Expand Up @@ -285,6 +294,44 @@ impl Aml for CmoNode {
}
}

#[repr(u8)]
pub enum VirtualAddressScheme {
Sv39 = 0,
Sv48 = 1,
Sv57 = 2,
}

pub struct MmuNode {
supported_type: u8,
}

impl MmuNode {
pub fn new(scheme: VirtualAddressScheme) -> Self {
Self {
supported_type: scheme as u8,
}
}

fn len() -> usize {
8
}

fn u8sum(&self) -> u8 {
u8sum(self)
}
}

impl Aml for MmuNode {
fn to_aml_bytes(&self, sink: &mut dyn AmlSink) {
let ty = RhctNodeType::Mmu as u16;
sink.word(ty);
sink.word(Self::len() as u16);
sink.word(1); // revision
sink.byte(0); // reserved
sink.byte(self.supported_type);
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -324,6 +371,22 @@ mod tests {
assert_eq!(sum, 0);
}

#[test]
fn test_mmu() {
let mut bytes = Vec::new();
let mut rhct = RHCT::new(*b"RIVOS_", *b"RIVOS___", 42u32, 0x1111_2222_3333_4444);

rhct.add_mmu_node(VirtualAddressScheme::Sv57);

rhct.to_aml_bytes(&mut bytes);
assert_eq!(
bytes[core::mem::size_of::<Header>() + MmuNode::len() - 1],
VirtualAddressScheme::Sv57 as u8
);
let sum = bytes.iter().fold(0u8, |acc, x| acc.wrapping_add(*x));
assert_eq!(sum, 0);
}

#[test]
fn test_hartinfo() {
let mut bytes = Vec::new();
Expand Down
12 changes: 5 additions & 7 deletions src/viot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,7 @@ impl VIOT {
/// past (e.g. IORT for ARM, DMAR for Intel, IVRS for AMD, etc.).
impl Aml for VIOT {
fn to_aml_bytes(&self, sink: &mut dyn AmlSink) {
for byte in self.header.as_bytes() {
sink.byte(*byte);
}

sink.vec(self.header.as_bytes());
sink.word(self.nodes.len() as u16);
sink.word(NODE_OFFSET);
sink.qword(0); // reserved
Expand Down Expand Up @@ -192,8 +189,8 @@ impl Aml for PciRange {
sink.byte(0); // reserved
sink.word(Self::len() as u16);
sink.dword(self.first.as_endpoint());
sink.word(self.first.as_segment());
sink.word(self.last.as_segment());
sink.word(self.first.segment);
sink.word(self.last.segment);
sink.word(self.first.as_bdf());
sink.word(self.last.as_bdf());
sink.word(self.translation_offset);
Expand Down Expand Up @@ -266,7 +263,8 @@ impl Aml for VirtIoPciIommu {
sink.byte(ViotEntryType::VirtIoPciIommu as u8);
sink.byte(0); // reserved
sink.word(Self::len() as u16);
sink.dword(self.device.as_endpoint());
sink.word(self.device.segment);
sink.word(self.device.as_bdf());
sink.qword(0); // reserved
}
}
Expand Down