Skip to content

Commit cc3ba73

Browse files
committed
Support dumping Turin data structures and Milan data structures at the same time.
Fixes <#135>.
1 parent db77d47 commit cc3ba73

File tree

7 files changed

+160
-43
lines changed

7 files changed

+160
-43
lines changed

rust-toolchain

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[toolchain]
22
channel = "nightly-2024-06-19"
3-
components = [ "rustfmt", "rust-src" ]
3+
components = [ "rustfmt", "rust-src", "rust-analyzer" ]

src/apcb.rs

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
use crate::types::{Error, FileSystemError, PtrMut, Result};
5+
use crate::types::{Context, Error, FileSystemError, PtrMut, Result};
66

77
use crate::entry::EntryItemBody;
88
use crate::group::{GroupItem, GroupMutItem};
@@ -50,29 +50,41 @@ use std::borrow::Cow;
5050
#[derive(Clone)]
5151
pub struct ApcbIoOptions {
5252
pub check_checksum: bool,
53+
pub context: Context,
5354
}
5455

5556
impl Default for ApcbIoOptions {
5657
fn default() -> Self {
57-
Self { check_checksum: true }
58+
Self { check_checksum: true, context: Context::default() }
5859
}
5960
}
6061

6162
impl ApcbIoOptions {
6263
pub fn builder() -> Self {
6364
Self::default()
6465
}
66+
pub fn check_checksum(&self) -> bool {
67+
self.check_checksum
68+
}
69+
pub fn context(&self) -> Context {
70+
self.context
71+
}
6572
pub fn with_check_checksum(&mut self, value: bool) -> &mut Self {
6673
self.check_checksum = value;
6774
self
6875
}
76+
pub fn with_context(&mut self, value: Context) -> &mut Self {
77+
self.context = value;
78+
self
79+
}
6980
pub fn build(&self) -> Self {
7081
self.clone()
7182
}
7283
}
7384

7485
#[cfg_attr(feature = "std", derive(Clone))]
7586
pub struct Apcb<'a> {
87+
context: Context,
7688
used_size: usize,
7789
pub backing_store: PtrMut<'a, [u8]>,
7890
}
@@ -83,6 +95,10 @@ pub struct Apcb<'a> {
8395
#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
8496
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
8597
pub struct SerdeApcb {
98+
/// This field is out-of-band information. At the cost of slight redundancy
99+
/// in user config and another extra field that isn't actually in the blob,
100+
/// we can actually handle the out-of-band information quite natually.
101+
pub context: Context,
86102
pub version: String,
87103
pub header: V2_HEADER,
88104
pub v3_header_ext: Option<V3_HEADER_EXT>,
@@ -110,11 +126,15 @@ impl<'a> schemars::JsonSchema for Apcb<'a> {
110126
use core::convert::TryFrom;
111127

112128
#[cfg(feature = "serde")]
113-
impl<'a> TryFrom<SerdeApcb> for Apcb<'a> {
114-
type Error = Error;
129+
impl<'a> Apcb<'a> {
130+
// type Error = Error;
115131
fn try_from(serde_apcb: SerdeApcb) -> Result<Self> {
116132
let buf = Cow::from(vec![0xFFu8; Self::MAX_SIZE]);
117-
let mut apcb = Apcb::create(buf, 42, &ApcbIoOptions::default())?;
133+
let mut apcb = Apcb::create(
134+
buf,
135+
42,
136+
&ApcbIoOptions::default().with_context(serde_apcb.context).build(),
137+
)?;
118138
*apcb.header_mut()? = serde_apcb.header;
119139
match serde_apcb.v3_header_ext {
120140
Some(v3) => {
@@ -217,11 +237,13 @@ impl<'de> Deserialize<'de> for Apcb<'_> {
217237
}
218238

219239
pub struct ApcbIterMut<'a> {
240+
context: Context,
220241
buf: &'a mut [u8],
221242
remaining_used_size: usize,
222243
}
223244

224245
pub struct ApcbIter<'a> {
246+
context: Context,
225247
buf: &'a [u8],
226248
remaining_used_size: usize,
227249
}
@@ -230,7 +252,10 @@ impl<'a> ApcbIterMut<'a> {
230252
/// It's useful to have some way of NOT mutating self.buf. This is what
231253
/// this function does. Note: The caller needs to manually decrease
232254
/// remaining_used_size for each call if desired.
233-
fn next_item<'b>(buf: &mut &'b mut [u8]) -> Result<GroupMutItem<'b>> {
255+
fn next_item<'b>(
256+
context: Context,
257+
buf: &mut &'b mut [u8],
258+
) -> Result<GroupMutItem<'b>> {
234259
if buf.is_empty() {
235260
return Err(Error::FileSystem(
236261
FileSystemError::InconsistentHeader,
@@ -256,7 +281,7 @@ impl<'a> ApcbIterMut<'a> {
256281
))?;
257282
let body_len = body.len();
258283

259-
Ok(GroupMutItem { header, buf: body, used_size: body_len })
284+
Ok(GroupMutItem { context, header, buf: body, used_size: body_len })
260285
}
261286

262287
/// Moves the point to the group with the given GROUP_ID. Returns (offset,
@@ -273,12 +298,12 @@ impl<'a> ApcbIterMut<'a> {
273298
if buf.is_empty() {
274299
break;
275300
}
276-
let group = ApcbIterMut::next_item(&mut buf)?;
301+
let group = ApcbIterMut::next_item(self.context, &mut buf)?;
277302
let group_size = group.header.group_size.get();
278303
if group.header.group_id.get() == group_id {
279304
return Ok((offset, group_size as usize));
280305
}
281-
let group = ApcbIterMut::next_item(&mut self.buf)?;
306+
let group = ApcbIterMut::next_item(self.context, &mut self.buf)?;
282307
let group_size = group.header.group_size.get() as usize;
283308
offset = offset
284309
.checked_add(group_size)
@@ -295,7 +320,7 @@ impl<'a> ApcbIterMut<'a> {
295320

296321
pub(crate) fn next1(&mut self) -> Result<GroupMutItem<'a>> {
297322
assert!(self.remaining_used_size != 0, "Internal error");
298-
let item = Self::next_item(&mut self.buf)?;
323+
let item = Self::next_item(self.context, &mut self.buf)?;
299324
let group_size = item.header.group_size.get() as usize;
300325
if group_size <= self.remaining_used_size {
301326
self.remaining_used_size -= group_size;
@@ -324,7 +349,10 @@ impl<'a> ApcbIter<'a> {
324349
/// It's useful to have some way of NOT mutating self.buf. This is what
325350
/// this function does. Note: The caller needs to manually decrease
326351
/// remaining_used_size for each call if desired.
327-
fn next_item<'b>(buf: &mut &'b [u8]) -> Result<GroupItem<'b>> {
352+
fn next_item<'b>(
353+
context: Context,
354+
buf: &mut &'b [u8],
355+
) -> Result<GroupItem<'b>> {
328356
if buf.is_empty() {
329357
return Err(Error::FileSystem(
330358
FileSystemError::InconsistentHeader,
@@ -351,12 +379,12 @@ impl<'a> ApcbIter<'a> {
351379

352380
let body_len = body.len();
353381

354-
Ok(GroupItem { header, buf: body, used_size: body_len })
382+
Ok(GroupItem { context, header, buf: body, used_size: body_len })
355383
}
356384

357385
pub(crate) fn next1(&mut self) -> Result<GroupItem<'a>> {
358386
assert!(self.remaining_used_size != 0, "Internal error");
359-
let item = Self::next_item(&mut self.buf)?;
387+
let item = Self::next_item(self.context, &mut self.buf)?;
360388
let group_size = item.header.group_size.get() as usize;
361389
if group_size <= self.remaining_used_size {
362390
self.remaining_used_size -= group_size;
@@ -369,7 +397,7 @@ impl<'a> ApcbIter<'a> {
369397
}
370398
}
371399
/// Validates the entries (recursively). Also consumes iterator.
372-
pub(crate) fn validate(mut self) -> Result<()> {
400+
pub(crate) fn validate(mut self, context: Context) -> Result<()> {
373401
while self.remaining_used_size > 0 {
374402
let item = self.next1()?;
375403
GroupId::from_u16(item.header.group_id.get()).ok_or(
@@ -509,6 +537,7 @@ impl<'a> Apcb<'a> {
509537

510538
pub fn groups(&self) -> Result<ApcbIter<'_>> {
511539
Ok(ApcbIter {
540+
context: self.context,
512541
buf: self.beginning_of_groups()?,
513542
remaining_used_size: self.used_size,
514543
})
@@ -522,13 +551,14 @@ impl<'a> Apcb<'a> {
522551
/// If ABL0_VERSION is Some, also validates against that AGESA
523552
/// bootloader version.
524553
pub fn validate(&self, abl0_version: Option<u32>) -> Result<()> {
525-
self.groups()?.validate()?;
554+
self.groups()?.validate(self.context)?;
526555
self.ensure_abl0_compatibility(abl0_version)
527556
}
528557

529558
pub fn groups_mut(&mut self) -> Result<ApcbIterMut<'_>> {
530559
let used_size = self.used_size;
531560
Ok(ApcbIterMut {
561+
context: self.context,
532562
buf: &mut *self.beginning_of_groups_mut()?,
533563
remaining_used_size: used_size,
534564
})
@@ -1030,6 +1060,7 @@ impl<'a> Apcb<'a> {
10301060
signature: [u8; 4],
10311061
) -> Result<GroupMutItem<'_>> {
10321062
// TODO: insert sorted.
1063+
let context = self.context;
10331064

10341065
if !match group_id {
10351066
GroupId::Psp => signature == *b"PSPG",
@@ -1090,7 +1121,7 @@ impl<'a> Apcb<'a> {
10901121
))?;
10911122
let body_len = body.len();
10921123

1093-
Ok(GroupMutItem { header, buf: body, used_size: body_len })
1124+
Ok(GroupMutItem { context, header, buf: body, used_size: body_len })
10941125
}
10951126

10961127
pub(crate) fn calculate_checksum(
@@ -1263,9 +1294,11 @@ impl<'a> Apcb<'a> {
12631294
));
12641295
}
12651296
}
1266-
let result = Self { backing_store: bs, used_size };
1297+
let result =
1298+
Self { context: options.context(), backing_store: bs, used_size };
12671299

1268-
match result.groups()?.validate() {
1300+
let context = options.context();
1301+
match result.groups()?.validate(context) {
12691302
Ok(_) => {}
12701303
Err(e) => {
12711304
return Err(e);

src/entry.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::ondisk::{
1212
};
1313
use crate::ondisk::{Parameters, ParametersIter};
1414
use crate::tokens_entry::TokensEntryBodyItem;
15-
use crate::types::{Error, FileSystemError, Result};
15+
use crate::types::{Context, Error, FileSystemError, Result};
1616
use core::marker::PhantomData;
1717
use core::mem::size_of;
1818
use num_traits::FromPrimitive;
@@ -46,6 +46,7 @@ impl<'a> EntryItemBody<&'a mut [u8]> {
4646
pub(crate) fn from_slice(
4747
header: &ENTRY_HEADER,
4848
b: &'a mut [u8],
49+
context: Context,
4950
) -> Result<EntryItemBody<&'a mut [u8]>> {
5051
let context_type = ContextType::from_u8(header.context_type).ok_or(
5152
Error::FileSystem(
@@ -66,7 +67,7 @@ impl<'a> EntryItemBody<&'a mut [u8]> {
6667
ContextType::Tokens => {
6768
let used_size = b.len();
6869
Ok(Self::Tokens(TokensEntryBodyItem::<&mut [u8]>::new(
69-
header, b, used_size,
70+
header, b, used_size, context,
7071
)?))
7172
}
7273
ContextType::Parameters => Err(Error::EntryTypeMismatch),
@@ -78,6 +79,7 @@ impl<'a> EntryItemBody<&'a [u8]> {
7879
pub(crate) fn from_slice(
7980
header: &ENTRY_HEADER,
8081
b: &'a [u8],
82+
context: Context,
8183
) -> Result<EntryItemBody<&'a [u8]>> {
8284
let context_type = ContextType::from_u8(header.context_type).ok_or(
8385
Error::FileSystem(
@@ -98,7 +100,7 @@ impl<'a> EntryItemBody<&'a [u8]> {
98100
ContextType::Tokens => {
99101
let used_size = b.len();
100102
Ok(Self::Tokens(TokensEntryBodyItem::<&[u8]>::new(
101-
header, b, used_size,
103+
header, b, used_size, context,
102104
)?))
103105
}
104106
ContextType::Parameters => Err(Error::EntryTypeMismatch),
@@ -117,6 +119,7 @@ impl<'a> EntryItemBody<&'a [u8]> {
117119

118120
#[derive(Debug)]
119121
pub struct EntryMutItem<'a> {
122+
pub(crate) context: Context,
120123
pub(crate) header: &'a mut ENTRY_HEADER,
121124
pub body: EntryItemBody<&'a mut [u8]>,
122125
}
@@ -420,6 +423,7 @@ use std::fmt;
420423

421424
#[derive(Clone)]
422425
pub struct EntryItem<'a> {
426+
pub(crate) context: Context,
423427
pub(crate) header: &'a ENTRY_HEADER,
424428
pub body: EntryItemBody<&'a [u8]>,
425429
}
@@ -677,12 +681,6 @@ impl<'a> Serialize for EntryItem<'a> {
677681
} else if let Some(s) = self.body_as_struct_array::<memory::Ddr5CaPinMapElement>() {
678682
let v = s.iter().collect::<Vec<_>>();
679683
state.serialize_field("Ddr5CaPinMapElement", &v)?;
680-
// } else if let Some(s) = self.body_as_struct_array::<memory::MemDfeSearchElement32>() { // UH OH
681-
// let v = s.iter().collect::<Vec<_>>();
682-
// state.serialize_field("MemDfeSearchElement32", &v)?;
683-
} else if let Some(s) = self.body_as_struct_array::<memory::MemDfeSearchElement36>() {
684-
let v = s.iter().collect::<Vec<_>>();
685-
state.serialize_field("MemDfeSearchElement36", &v)?;
686684
} else if let Some(s) = self.body_as_struct_array::<memory::DdrDqPinMapElement>() {
687685
let v = s.iter().collect::<Vec<_>>();
688686
state.serialize_field("DdrDqPinMapElement", &v)?;
@@ -747,7 +745,27 @@ self.body_as_struct_sequence::<memory::platform_tuning::ElementRef<'_>>() {
747745
let v = parameters.collect::<Vec<_>>();
748746
state.serialize_field("parameters", &v)?;
749747
} else {
750-
state.serialize_field("struct_body", &buf)?;
748+
match self.context.mem_dfe_search_version() {
749+
Some(MemDfeSearchVersion::Genoa2) => { // UH OH
750+
if let Some(s) = self.body_as_struct_array::<memory::MemDfeSearchElement32>() {
751+
let v = s.iter().collect::<Vec<_>>();
752+
state.serialize_field("MemDfeSearchElement32", &v)?;
753+
} else {
754+
state.serialize_field("struct_body", &buf)?;
755+
}
756+
},
757+
Some(MemDfeSearchVersion::Turin) => {
758+
if let Some(s) = self.body_as_struct_array::<memory::MemDfeSearchElement36>() {
759+
let v = s.iter().collect::<Vec<_>>();
760+
state.serialize_field("MemDfeSearchElement36", &v)?;
761+
} else {
762+
state.serialize_field("struct_body", &buf)?;
763+
}
764+
}
765+
_ => {
766+
state.serialize_field("struct_body", &buf)?;
767+
}
768+
}
751769
}
752770
}
753771
}

0 commit comments

Comments
 (0)