Skip to content

Commit cabb285

Browse files
mxu9jyao1
authored andcommitted
test-td-payload: Add ACPI test case
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>
1 parent 4ba6ac7 commit cabb285

File tree

4 files changed

+216
-2
lines changed

4 files changed

+216
-2
lines changed

tests/test-td-payload/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ scroll = { version = "0.10.0", default-features = false, features = ["derive"]}
2121
serde = { version = "1.0", default-features = false, features = ["derive"]}
2222
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
2323
x86 = { version = "0.44.0" }
24+
td-shim = { path = "../../td-shim" }
25+
zerocopy = "0.6.0"
2426

2527
[dependencies.lazy_static]
2628
version = "1.0"

tests/test-td-payload/src/main.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#[macro_use]
1010

1111
mod lib;
12+
mod testacpi;
1213
mod testiorw32;
1314
mod testiorw8;
1415
mod testtdinfo;
@@ -26,6 +27,7 @@ use linked_list_allocator::LockedHeap;
2627
use td_layout::memslice;
2728

2829
use crate::lib::{TestResult, TestSuite};
30+
use crate::testacpi::{TdAcpi, TestTdAcpi};
2931
use crate::testiorw32::Tdiorw32;
3032
use crate::testiorw8::Tdiorw8;
3133
use crate::testtdinfo::Tdinfo;
@@ -47,6 +49,7 @@ pub struct TestCases {
4749
pub tcs005: Tdiorw8,
4850
pub tcs006: Tdiorw32,
4951
pub tcs007: TdVE,
52+
pub tcs008: TdAcpi,
5053
}
5154

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

139142
// build test cases with test configuration data in CFV
140-
let tcs = build_testcases();
143+
let mut tcs = build_testcases();
141144

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

170+
if tcs.tcs008.run && tcs.tcs008.expected.num > 0 {
171+
let test_acpi = TestTdAcpi {
172+
hob_address: hob as usize,
173+
td_acpi: tcs.tcs008,
174+
};
175+
ts.testsuite.push(Box::new(test_acpi));
176+
}
177+
167178
if tcs.tcs007.run {
168179
ts.testsuite.push(Box::new(tcs.tcs007));
169180
}

tests/test-td-payload/src/test.json

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,27 @@
6363
"name": "testve",
6464
"result": "None",
6565
"run": true
66+
},
67+
"tcs008": {
68+
"name": "testacpi",
69+
"expected": {
70+
"num": 2,
71+
"tables":[
72+
{
73+
"name": "APIC",
74+
"signature": [65, 80, 73, 67],
75+
"valid": 1,
76+
"exist": 1
77+
},
78+
{
79+
"name": "TDEL",
80+
"signature": [84, 68, 69, 76],
81+
"valid": 1,
82+
"exist": 1
83+
}
84+
]
85+
},
86+
"result": "None",
87+
"run": true
6688
}
67-
}
89+
}

tests/test-td-payload/src/testacpi.rs

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Copyright (c) 2021 Intel Corporation
2+
//
3+
// SPDX-License-Identifier: BSD-2-Clause-Patent
4+
5+
#![no_std]
6+
extern crate alloc;
7+
8+
use crate::lib::{TestCase, TestResult};
9+
use alloc::string::{String, ToString};
10+
use alloc::vec::Vec;
11+
use core::ffi::c_void;
12+
use core::mem::size_of;
13+
use serde::{Deserialize, Serialize};
14+
use td_layout::memslice;
15+
use td_shim::acpi::GenericSdtHeader;
16+
use td_shim::TD_ACPI_TABLE_HOB_GUID;
17+
use td_uefi_pi::hob;
18+
use zerocopy::FromBytes;
19+
20+
#[derive(Debug, Serialize, Deserialize)]
21+
pub struct TdAcpiData {
22+
pub name: String,
23+
pub signature: [u8; 4],
24+
pub valid: u8,
25+
pub exist: u8,
26+
}
27+
28+
impl Default for TdAcpiData {
29+
fn default() -> TdAcpiData {
30+
TdAcpiData {
31+
name: String::default(),
32+
signature: [0, 0, 0, 0],
33+
valid: 0,
34+
exist: 0,
35+
}
36+
}
37+
}
38+
39+
#[derive(Debug, Serialize, Deserialize)]
40+
pub struct TdAcpiList {
41+
pub num: u32,
42+
pub tables: [TdAcpiData; 2],
43+
}
44+
45+
#[derive(Debug, Serialize, Deserialize)]
46+
pub struct TdAcpi {
47+
pub name: String,
48+
pub expected: TdAcpiList,
49+
pub result: TestResult,
50+
pub run: bool,
51+
}
52+
/**
53+
* Test ACPI
54+
*/
55+
// #[derive(Debug, Serialize, Deserialize)]
56+
pub struct TestTdAcpi {
57+
pub hob_address: usize,
58+
pub td_acpi: TdAcpi,
59+
}
60+
61+
impl TestTdAcpi {
62+
fn calculate_checksum(&self, data: &[u8]) -> u8 {
63+
(255 - data.iter().fold(0u8, |acc, x| acc.wrapping_add(*x))).wrapping_add(1)
64+
}
65+
66+
fn parse_hob(&self, hob_address: usize) -> Vec<TdAcpiData> {
67+
let mut tables: Vec<TdAcpiData> = Vec::new();
68+
69+
// Parse Hob to populate td_acpi_list
70+
let hob_buffer = unsafe {
71+
memslice::get_dynamic_mem_slice_mut(memslice::SliceType::PayloadHob, hob_address)
72+
};
73+
74+
let hob_size = hob::get_hob_total_size(hob_buffer).unwrap();
75+
let hob_list = &hob_buffer[..hob_size];
76+
77+
let mut next_hob = hob_list;
78+
while let Some(hob) = hob::get_next_extension_guid_hob(next_hob, &TD_ACPI_TABLE_HOB_GUID) {
79+
let table = hob::get_guid_data(hob).expect("Failed to get data from ACPI GUID HOB");
80+
let header = GenericSdtHeader::read_from(&table[..size_of::<GenericSdtHeader>()])
81+
.expect("Faile to read table header from ACPI GUID HOB");
82+
83+
let mut tbl = TdAcpiData {
84+
name: String::from_utf8(header.signature.to_ascii_uppercase()).unwrap(),
85+
signature: header.signature,
86+
valid: 1,
87+
exist: 1,
88+
};
89+
90+
// save it to tables
91+
tables.push(tbl);
92+
93+
// Then we go to next hob
94+
next_hob = hob::seek_to_next_hob(hob).unwrap();
95+
}
96+
97+
return tables;
98+
}
99+
100+
fn verify_tables(&self, acpi_tables: Vec<TdAcpiData>) -> TestResult {
101+
if acpi_tables.len() == 0 {
102+
log::info!("Not find ACPI tables in Hob\n");
103+
return TestResult::Fail;
104+
}
105+
106+
let mut cnt: usize = 0;
107+
while cnt < self.td_acpi.expected.num as usize {
108+
let expected_signature = self.td_acpi.expected.tables[cnt].signature;
109+
110+
let index = acpi_tables
111+
.iter()
112+
.position(|r| r.signature == expected_signature);
113+
// if the ACPI is not found
114+
if index.is_none() {
115+
log::info!(
116+
"ACPI {} is not found.",
117+
String::from_utf8_lossy(&expected_signature)
118+
);
119+
return TestResult::Fail;
120+
}
121+
122+
// valid?
123+
let idx = index.unwrap();
124+
125+
if acpi_tables[idx].valid == 0 {
126+
// This table is not valid
127+
log::info!(
128+
"ACPI {} is not valid.",
129+
String::from_utf8_lossy(&expected_signature)
130+
);
131+
return TestResult::Fail;
132+
}
133+
134+
cnt += 1;
135+
}
136+
137+
return TestResult::Pass;
138+
}
139+
}
140+
141+
/**
142+
* Implement the TestCase trait for ACPI
143+
*/
144+
impl TestCase for TestTdAcpi {
145+
/**
146+
* set up the Test case of Tdinfo
147+
*/
148+
fn setup(&mut self) {
149+
self.td_acpi.result = TestResult::Fail;
150+
}
151+
152+
/**
153+
* run the test case
154+
*/
155+
fn run(&mut self) {
156+
let acpi_tables = self.parse_hob(self.hob_address);
157+
158+
self.td_acpi.result = self.verify_tables(acpi_tables);
159+
}
160+
161+
/**
162+
* Tear down the test case.
163+
*/
164+
fn teardown(&mut self) {}
165+
166+
/**
167+
* get the name of the test case.
168+
*/
169+
fn get_name(&mut self) -> String {
170+
String::from(&self.td_acpi.name)
171+
}
172+
173+
/**
174+
* get the result of the test case.
175+
*/
176+
fn get_result(&mut self) -> TestResult {
177+
self.td_acpi.result
178+
}
179+
}

0 commit comments

Comments
 (0)