Skip to content

Commit

Permalink
test-td-payload: Add ACPI test case
Browse files Browse the repository at this point in the history
This is the initial version of ACPI test case. In this test case ACPI
tables will be checked whether they exist in payload hob or not. In the
next version more check will be added to the ACPI tables, such as the
validness of paticular fields.

Signed-off-by: Min Xu <min.m.xu@intel.com>
  • Loading branch information
mxu9 authored and jyao1 committed Mar 29, 2022
1 parent 4ba6ac7 commit cabb285
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 2 deletions.
2 changes: 2 additions & 0 deletions tests/test-td-payload/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ scroll = { version = "0.10.0", default-features = false, features = ["derive"]}
serde = { version = "1.0", default-features = false, features = ["derive"]}
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
x86 = { version = "0.44.0" }
td-shim = { path = "../../td-shim" }
zerocopy = "0.6.0"

[dependencies.lazy_static]
version = "1.0"
Expand Down
13 changes: 12 additions & 1 deletion tests/test-td-payload/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#[macro_use]

mod lib;
mod testacpi;
mod testiorw32;
mod testiorw8;
mod testtdinfo;
Expand All @@ -26,6 +27,7 @@ use linked_list_allocator::LockedHeap;
use td_layout::memslice;

use crate::lib::{TestResult, TestSuite};
use crate::testacpi::{TdAcpi, TestTdAcpi};
use crate::testiorw32::Tdiorw32;
use crate::testiorw8::Tdiorw8;
use crate::testtdinfo::Tdinfo;
Expand All @@ -47,6 +49,7 @@ pub struct TestCases {
pub tcs005: Tdiorw8,
pub tcs006: Tdiorw32,
pub tcs007: TdVE,
pub tcs008: TdAcpi,
}

pub const CFV_FFS_HEADER_TEST_CONFIG_GUID: Guid = Guid::from_fields(
Expand Down Expand Up @@ -137,7 +140,7 @@ extern "win64" fn _start(hob: *const c_void) -> ! {
};

// build test cases with test configuration data in CFV
let tcs = build_testcases();
let mut tcs = build_testcases();

// Add test cases in ts.testsuite
if tcs.tcs001.run {
Expand All @@ -164,6 +167,14 @@ extern "win64" fn _start(hob: *const c_void) -> ! {
ts.testsuite.push(Box::new(tcs.tcs006));
}

if tcs.tcs008.run && tcs.tcs008.expected.num > 0 {
let test_acpi = TestTdAcpi {
hob_address: hob as usize,
td_acpi: tcs.tcs008,
};
ts.testsuite.push(Box::new(test_acpi));
}

if tcs.tcs007.run {
ts.testsuite.push(Box::new(tcs.tcs007));
}
Expand Down
24 changes: 23 additions & 1 deletion tests/test-td-payload/src/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,27 @@
"name": "testve",
"result": "None",
"run": true
},
"tcs008": {
"name": "testacpi",
"expected": {
"num": 2,
"tables":[
{
"name": "APIC",
"signature": [65, 80, 73, 67],
"valid": 1,
"exist": 1
},
{
"name": "TDEL",
"signature": [84, 68, 69, 76],
"valid": 1,
"exist": 1
}
]
},
"result": "None",
"run": true
}
}
}
179 changes: 179 additions & 0 deletions tests/test-td-payload/src/testacpi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// Copyright (c) 2021 Intel Corporation
//
// SPDX-License-Identifier: BSD-2-Clause-Patent

#![no_std]
extern crate alloc;

use crate::lib::{TestCase, TestResult};
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::ffi::c_void;
use core::mem::size_of;
use serde::{Deserialize, Serialize};
use td_layout::memslice;
use td_shim::acpi::GenericSdtHeader;
use td_shim::TD_ACPI_TABLE_HOB_GUID;
use td_uefi_pi::hob;
use zerocopy::FromBytes;

#[derive(Debug, Serialize, Deserialize)]
pub struct TdAcpiData {
pub name: String,
pub signature: [u8; 4],
pub valid: u8,
pub exist: u8,
}

impl Default for TdAcpiData {
fn default() -> TdAcpiData {
TdAcpiData {
name: String::default(),
signature: [0, 0, 0, 0],
valid: 0,
exist: 0,
}
}
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TdAcpiList {
pub num: u32,
pub tables: [TdAcpiData; 2],
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TdAcpi {
pub name: String,
pub expected: TdAcpiList,
pub result: TestResult,
pub run: bool,
}
/**
* Test ACPI
*/
// #[derive(Debug, Serialize, Deserialize)]
pub struct TestTdAcpi {
pub hob_address: usize,
pub td_acpi: TdAcpi,
}

impl TestTdAcpi {
fn calculate_checksum(&self, data: &[u8]) -> u8 {
(255 - data.iter().fold(0u8, |acc, x| acc.wrapping_add(*x))).wrapping_add(1)
}

fn parse_hob(&self, hob_address: usize) -> Vec<TdAcpiData> {
let mut tables: Vec<TdAcpiData> = Vec::new();

// Parse Hob to populate td_acpi_list
let hob_buffer = unsafe {
memslice::get_dynamic_mem_slice_mut(memslice::SliceType::PayloadHob, hob_address)
};

let hob_size = hob::get_hob_total_size(hob_buffer).unwrap();
let hob_list = &hob_buffer[..hob_size];

let mut next_hob = hob_list;
while let Some(hob) = hob::get_next_extension_guid_hob(next_hob, &TD_ACPI_TABLE_HOB_GUID) {
let table = hob::get_guid_data(hob).expect("Failed to get data from ACPI GUID HOB");
let header = GenericSdtHeader::read_from(&table[..size_of::<GenericSdtHeader>()])
.expect("Faile to read table header from ACPI GUID HOB");

let mut tbl = TdAcpiData {
name: String::from_utf8(header.signature.to_ascii_uppercase()).unwrap(),
signature: header.signature,
valid: 1,
exist: 1,
};

// save it to tables
tables.push(tbl);

// Then we go to next hob
next_hob = hob::seek_to_next_hob(hob).unwrap();
}

return tables;
}

fn verify_tables(&self, acpi_tables: Vec<TdAcpiData>) -> TestResult {
if acpi_tables.len() == 0 {
log::info!("Not find ACPI tables in Hob\n");
return TestResult::Fail;
}

let mut cnt: usize = 0;
while cnt < self.td_acpi.expected.num as usize {
let expected_signature = self.td_acpi.expected.tables[cnt].signature;

let index = acpi_tables
.iter()
.position(|r| r.signature == expected_signature);
// if the ACPI is not found
if index.is_none() {
log::info!(
"ACPI {} is not found.",
String::from_utf8_lossy(&expected_signature)
);
return TestResult::Fail;
}

// valid?
let idx = index.unwrap();

if acpi_tables[idx].valid == 0 {
// This table is not valid
log::info!(
"ACPI {} is not valid.",
String::from_utf8_lossy(&expected_signature)
);
return TestResult::Fail;
}

cnt += 1;
}

return TestResult::Pass;
}
}

/**
* Implement the TestCase trait for ACPI
*/
impl TestCase for TestTdAcpi {
/**
* set up the Test case of Tdinfo
*/
fn setup(&mut self) {
self.td_acpi.result = TestResult::Fail;
}

/**
* run the test case
*/
fn run(&mut self) {
let acpi_tables = self.parse_hob(self.hob_address);

self.td_acpi.result = self.verify_tables(acpi_tables);
}

/**
* Tear down the test case.
*/
fn teardown(&mut self) {}

/**
* get the name of the test case.
*/
fn get_name(&mut self) -> String {
String::from(&self.td_acpi.name)
}

/**
* get the result of the test case.
*/
fn get_result(&mut self) -> TestResult {
self.td_acpi.result
}
}

0 comments on commit cabb285

Please sign in to comment.