Skip to content

Commit ffe5c36

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

File tree

7 files changed

+214
-23
lines changed

7 files changed

+214
-23
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pre = { version = "0.2.1", default-features = false, features = [] }
2525
static_assertions = "1.1.0"
2626
zerocopy = "0.6.1"
2727
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
28+
serde_context = { path = "../serde_context" }
2829
serde-hex = { version = "0.1.0", optional = true }
2930
schemars = { version = "0.8.8", optional = true }
3031
parse_int = { version = "0.6.0", optional = true }

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: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ impl ApcbIoOptions {
7373

7474
#[cfg_attr(feature = "std", derive(Clone))]
7575
pub struct Apcb<'a> {
76+
context: u64,
7677
used_size: usize,
7778
pub backing_store: PtrMut<'a, [u8]>,
7879
}
@@ -83,6 +84,10 @@ pub struct Apcb<'a> {
8384
#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
8485
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
8586
pub struct SerdeApcb {
87+
/// This field is out-of-band information. At the cost of slight redundancy
88+
/// in user config and another extra field that isn't actually in the blob,
89+
/// we can actually handle the out-of-band information quite natually.
90+
pub context: u64,
8691
pub version: String,
8792
pub header: V2_HEADER,
8893
pub v3_header_ext: Option<V3_HEADER_EXT>,
@@ -110,11 +115,16 @@ impl<'a> schemars::JsonSchema for Apcb<'a> {
110115
use core::convert::TryFrom;
111116

112117
#[cfg(feature = "serde")]
113-
impl<'a> TryFrom<SerdeApcb> for Apcb<'a> {
114-
type Error = Error;
118+
impl<'a> Apcb<'a> {
119+
// type Error = Error;
115120
fn try_from(serde_apcb: SerdeApcb) -> Result<Self> {
116121
let buf = Cow::from(vec![0xFFu8; Self::MAX_SIZE]);
117-
let mut apcb = Apcb::create(buf, 42, &ApcbIoOptions::default())?;
122+
let mut apcb = Apcb::create(
123+
buf,
124+
42,
125+
&ApcbIoOptions::default(),
126+
serde_apcb.context,
127+
)?;
118128
*apcb.header_mut()? = serde_apcb.header;
119129
match serde_apcb.v3_header_ext {
120130
Some(v3) => {
@@ -217,11 +227,13 @@ impl<'de> Deserialize<'de> for Apcb<'_> {
217227
}
218228

219229
pub struct ApcbIterMut<'a> {
230+
context: u64,
220231
buf: &'a mut [u8],
221232
remaining_used_size: usize,
222233
}
223234

224235
pub struct ApcbIter<'a> {
236+
context: u64,
225237
buf: &'a [u8],
226238
remaining_used_size: usize,
227239
}
@@ -230,7 +242,10 @@ impl<'a> ApcbIterMut<'a> {
230242
/// It's useful to have some way of NOT mutating self.buf. This is what
231243
/// this function does. Note: The caller needs to manually decrease
232244
/// remaining_used_size for each call if desired.
233-
fn next_item<'b>(buf: &mut &'b mut [u8]) -> Result<GroupMutItem<'b>> {
245+
fn next_item<'b>(
246+
context: u64,
247+
buf: &mut &'b mut [u8],
248+
) -> Result<GroupMutItem<'b>> {
234249
if buf.is_empty() {
235250
return Err(Error::FileSystem(
236251
FileSystemError::InconsistentHeader,
@@ -256,7 +271,7 @@ impl<'a> ApcbIterMut<'a> {
256271
))?;
257272
let body_len = body.len();
258273

259-
Ok(GroupMutItem { header, buf: body, used_size: body_len })
274+
Ok(GroupMutItem { context, header, buf: body, used_size: body_len })
260275
}
261276

262277
/// Moves the point to the group with the given GROUP_ID. Returns (offset,
@@ -273,12 +288,12 @@ impl<'a> ApcbIterMut<'a> {
273288
if buf.is_empty() {
274289
break;
275290
}
276-
let group = ApcbIterMut::next_item(&mut buf)?;
291+
let group = ApcbIterMut::next_item(self.context, &mut buf)?;
277292
let group_size = group.header.group_size.get();
278293
if group.header.group_id.get() == group_id {
279294
return Ok((offset, group_size as usize));
280295
}
281-
let group = ApcbIterMut::next_item(&mut self.buf)?;
296+
let group = ApcbIterMut::next_item(self.context, &mut self.buf)?;
282297
let group_size = group.header.group_size.get() as usize;
283298
offset = offset
284299
.checked_add(group_size)
@@ -295,7 +310,7 @@ impl<'a> ApcbIterMut<'a> {
295310

296311
pub(crate) fn next1(&mut self) -> Result<GroupMutItem<'a>> {
297312
assert!(self.remaining_used_size != 0, "Internal error");
298-
let item = Self::next_item(&mut self.buf)?;
313+
let item = Self::next_item(self.context, &mut self.buf)?;
299314
let group_size = item.header.group_size.get() as usize;
300315
if group_size <= self.remaining_used_size {
301316
self.remaining_used_size -= group_size;
@@ -324,7 +339,10 @@ impl<'a> ApcbIter<'a> {
324339
/// It's useful to have some way of NOT mutating self.buf. This is what
325340
/// this function does. Note: The caller needs to manually decrease
326341
/// remaining_used_size for each call if desired.
327-
fn next_item<'b>(buf: &mut &'b [u8]) -> Result<GroupItem<'b>> {
342+
fn next_item<'b>(
343+
context: u64,
344+
buf: &mut &'b [u8],
345+
) -> Result<GroupItem<'b>> {
328346
if buf.is_empty() {
329347
return Err(Error::FileSystem(
330348
FileSystemError::InconsistentHeader,
@@ -351,12 +369,12 @@ impl<'a> ApcbIter<'a> {
351369

352370
let body_len = body.len();
353371

354-
Ok(GroupItem { header, buf: body, used_size: body_len })
372+
Ok(GroupItem { context, header, buf: body, used_size: body_len })
355373
}
356374

357375
pub(crate) fn next1(&mut self) -> Result<GroupItem<'a>> {
358376
assert!(self.remaining_used_size != 0, "Internal error");
359-
let item = Self::next_item(&mut self.buf)?;
377+
let item = Self::next_item(self.context, &mut self.buf)?;
360378
let group_size = item.header.group_size.get() as usize;
361379
if group_size <= self.remaining_used_size {
362380
self.remaining_used_size -= group_size;
@@ -509,6 +527,7 @@ impl<'a> Apcb<'a> {
509527

510528
pub fn groups(&self) -> Result<ApcbIter<'_>> {
511529
Ok(ApcbIter {
530+
context: self.context,
512531
buf: self.beginning_of_groups()?,
513532
remaining_used_size: self.used_size,
514533
})
@@ -529,6 +548,7 @@ impl<'a> Apcb<'a> {
529548
pub fn groups_mut(&mut self) -> Result<ApcbIterMut<'_>> {
530549
let used_size = self.used_size;
531550
Ok(ApcbIterMut {
551+
context: self.context,
532552
buf: &mut *self.beginning_of_groups_mut()?,
533553
remaining_used_size: used_size,
534554
})
@@ -1030,6 +1050,7 @@ impl<'a> Apcb<'a> {
10301050
signature: [u8; 4],
10311051
) -> Result<GroupMutItem<'_>> {
10321052
// TODO: insert sorted.
1053+
let context = self.context;
10331054

10341055
if !match group_id {
10351056
GroupId::Psp => signature == *b"PSPG",
@@ -1090,7 +1111,7 @@ impl<'a> Apcb<'a> {
10901111
))?;
10911112
let body_len = body.len();
10921113

1093-
Ok(GroupMutItem { header, buf: body, used_size: body_len })
1114+
Ok(GroupMutItem { context, header, buf: body, used_size: body_len })
10941115
}
10951116

10961117
pub(crate) fn calculate_checksum(
@@ -1136,6 +1157,7 @@ impl<'a> Apcb<'a> {
11361157
pub fn load(
11371158
#[allow(unused_mut)] mut bs: PtrMut<'a, [u8]>,
11381159
options: &ApcbIoOptions,
1160+
context: u64,
11391161
) -> Result<Self> {
11401162
let backing_store_len = bs.len();
11411163

@@ -1263,7 +1285,7 @@ impl<'a> Apcb<'a> {
12631285
));
12641286
}
12651287
}
1266-
let result = Self { backing_store: bs, used_size };
1288+
let result = Self { context, backing_store: bs, used_size };
12671289

12681290
match result.groups()?.validate() {
12691291
Ok(_) => {}
@@ -1309,6 +1331,7 @@ impl<'a> Apcb<'a> {
13091331
#[allow(unused_mut)] mut bs: PtrMut<'a, [u8]>,
13101332
initial_unique_apcb_instance: u32,
13111333
options: &ApcbIoOptions,
1334+
context: u64,
13121335
) -> Result<Self> {
13131336
#[cfg(not(feature = "std"))]
13141337
let backing_store: &mut [u8] = bs;
@@ -1354,7 +1377,7 @@ impl<'a> Apcb<'a> {
13541377

13551378
let (mut header, _) = LayoutVerified::<&'_ mut [u8], V2_HEADER>::new_unaligned_from_prefix(backing_store).unwrap();
13561379
header.checksum_byte = checksum_byte;
1357-
Self::load(bs, options)
1380+
Self::load(bs, options, context)
13581381
}
13591382
/// Note: Each modification in the APCB causes the value of
13601383
/// unique_apcb_instance to change.

src/entry.rs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use core::marker::PhantomData;
1717
use core::mem::size_of;
1818
use num_traits::FromPrimitive;
1919
use pre::pre;
20+
#[cfg(feature = "serde")]
21+
use serde_context::SerializeWithContext;
2022
use zerocopy::{AsBytes, FromBytes};
2123

2224
#[cfg(feature = "serde")]
@@ -117,6 +119,7 @@ impl<'a> EntryItemBody<&'a [u8]> {
117119

118120
#[derive(Debug)]
119121
pub struct EntryMutItem<'a> {
122+
pub(crate) context: u64,
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: u64,
423427
pub(crate) header: &'a ENTRY_HEADER,
424428
pub body: EntryItemBody<&'a [u8]>,
425429
}
@@ -613,6 +617,151 @@ impl schemars::JsonSchema for SerdeEntryItem {
613617
}
614618
}
615619

620+
#[cfg(feature = "serde")]
621+
impl<'a> SerializeWithContext for EntryItem<'a> {
622+
type Context = u64;
623+
fn serialize_with_context<S>(
624+
&self,
625+
serializer: S,
626+
context: Self::Context,
627+
) -> core::result::Result<S::Ok, S::Error>
628+
where
629+
S: Serializer,
630+
{
631+
use crate::df::SlinkConfig;
632+
use crate::fch;
633+
use crate::gnb;
634+
use crate::memory;
635+
use crate::psp;
636+
assert!(self.context == 42);
637+
let mut state = serializer.serialize_struct("EntryItem", 2)?;
638+
state.serialize_field("header", self.header)?;
639+
640+
// TODO: Automate this type determination instead of maintaining this
641+
// manually.
642+
match &self.body {
643+
EntryItemBody::<_>::Tokens(tokens) => {
644+
let v = tokens
645+
.iter()
646+
.map_err(|e| serde::ser::Error::custom(format!("{e:?}")))?
647+
.collect::<Vec<_>>();
648+
state.serialize_field("tokens", &v)?;
649+
}
650+
EntryItemBody::<_>::Struct(buf) => {
651+
if let Some(s) = self.body_as_struct_array::<memory::LrdimmDdr4OdtPatElement>() {
652+
let v = s.iter().collect::<Vec<_>>();
653+
state.serialize_field("LrdimmDdr4OdtPatElement", &v)?;
654+
} else if let Some(s) = self.body_as_struct_array::<memory::Ddr4OdtPatElement>() {
655+
let v = s.iter().collect::<Vec<_>>();
656+
state.serialize_field("Ddr4OdtPatElement", &v)?;
657+
} else if let Some(s) = self.body_as_struct_array::<memory::DdrPostPackageRepairElement>() {
658+
let v = s.iter().collect::<Vec<_>>();
659+
state.serialize_field("DdrPostPackageRepairElement", &v)?;
660+
} else if let Some(s) = self.body_as_struct_array::<memory::DimmInfoSmbusElement>() {
661+
let v = s.iter().collect::<Vec<_>>();
662+
state.serialize_field("DimmInfoSmbusElement", &v)?;
663+
} else if let Some(s) = self.body_as_struct_array::<memory::RdimmDdr4CadBusElement>() {
664+
let v = s.iter().collect::<Vec<_>>();
665+
state.serialize_field("RdimmDdr4CadBusElement", &v)?;
666+
} else if let Some(s) = self.body_as_struct_array::<memory::UdimmDdr4CadBusElement>() {
667+
let v = s.iter().collect::<Vec<_>>();
668+
state.serialize_field("UdimmDdr4CadBusElement", &v)?;
669+
} else if let Some(s) = self.body_as_struct_array::<memory::LrdimmDdr4CadBusElement>() {
670+
let v = s.iter().collect::<Vec<_>>();
671+
state.serialize_field("LrdimmDdr4CadBusElement", &v)?;
672+
} else if let Some(s) = self.body_as_struct_array::<memory::Ddr4DataBusElement>() {
673+
let v = s.iter().collect::<Vec<_>>();
674+
state.serialize_field("Ddr4DataBusElement", &v)?;
675+
} else if let Some(s) = self.body_as_struct_array::<memory::LrdimmDdr4DataBusElement>() {
676+
let v = s.iter().collect::<Vec<_>>();
677+
state.serialize_field("LrdimmDdr4DataBusElement", &v)?;
678+
} else if let Some(s) = self.body_as_struct_array::<memory::MaxFreqElement>() {
679+
let v = s.iter().collect::<Vec<_>>();
680+
state.serialize_field("MaxFreqElement", &v)?;
681+
} else if let Some(s) = self.body_as_struct_array::<memory::LrMaxFreqElement>() {
682+
let v = s.iter().collect::<Vec<_>>();
683+
state.serialize_field("LrMaxFreqElement", &v)?;
684+
} else if let Some(s) = self.body_as_struct_array::<memory::Ddr5CaPinMapElement>() {
685+
let v = s.iter().collect::<Vec<_>>();
686+
state.serialize_field("Ddr5CaPinMapElement", &v)?;
687+
// } else if let Some(s) = self.body_as_struct_array::<memory::MemDfeSearchElement32>() { // UH OH
688+
// let v = s.iter().collect::<Vec<_>>();
689+
// state.serialize_field("MemDfeSearchElement32", &v)?;
690+
} else if let Some(s) = self.body_as_struct_array::<memory::MemDfeSearchElement36>() {
691+
let v = s.iter().collect::<Vec<_>>();
692+
state.serialize_field("MemDfeSearchElement36", &v)?;
693+
} else if let Some(s) = self.body_as_struct_array::<memory::DdrDqPinMapElement>() {
694+
let v = s.iter().collect::<Vec<_>>();
695+
state.serialize_field("DdrDqPinMapElement", &v)?;
696+
} else if let Some(s) = self.body_as_struct_array::<memory::RdimmDdr5BusElement>() {
697+
let v = s.iter().collect::<Vec<_>>();
698+
state.serialize_field("RdimmDdr5BusElement", &v)?;
699+
} else if let Some((s, _)) = self.body_as_struct::<memory::ConsoleOutControl>() {
700+
state.serialize_field("ConsoleOutControl", &s)?;
701+
} else if let Some((s, _)) = self.body_as_struct::<memory::NaplesConsoleOutControl>() {
702+
state.serialize_field("NaplesConsoleOutControl", &s)?;
703+
} else if let Some((s, _)) = self.body_as_struct::<memory::ExtVoltageControl>() {
704+
state.serialize_field("ExtVoltageControl", &s)?;
705+
} else if let Some((s, _)) = self.body_as_struct::<memory::ErrorOutControl116>() {
706+
state.serialize_field("ErrorOutControl116", &s)?;
707+
} else if let Some((s, _)) = self.body_as_struct::<memory::ErrorOutControl112>() {
708+
state.serialize_field("ErrorOutControl112", &s)?;
709+
} else if let Some((s, _)) = self.body_as_struct::<SlinkConfig>() {
710+
state.serialize_field("SlinkConfig", &s)?;
711+
} else if let Some((header, s)) = self.body_as_struct::<psp::BoardIdGettingMethodGpio>() {
712+
let v = s.iter().collect::<Vec<_>>();
713+
let t = (header, v);
714+
state.serialize_field("BoardIdGettingMethodGpio", &t)?;
715+
} else if let Some((header, s)) = self.body_as_struct::<psp::BoardIdGettingMethodEeprom>() {
716+
let v = s.iter().collect::<Vec<_>>();
717+
let t = (header, v);
718+
state.serialize_field("BoardIdGettingMethodEeprom", &t)?;
719+
} else if let Some((header, s)) = self.body_as_struct::<psp::BoardIdGettingMethodSmbus>() {
720+
let v = s.iter().collect::<Vec<_>>();
721+
let t = (header, v);
722+
state.serialize_field("BoardIdGettingMethodSmbus", &t)?;
723+
} else if let Some((header, s)) = self.body_as_struct::<psp::BoardIdGettingMethodCustom>() {
724+
let v = s.iter().collect::<Vec<_>>();
725+
let t = (header, v);
726+
state.serialize_field("BoardIdGettingMethodCustom", &t)?;
727+
} else if let Some((header, _)) = self.body_as_struct::<fch::EspiInit>() {
728+
state.serialize_field("EspiInit", &header)?;
729+
} else if let Some(s) = self.body_as_struct_array::<memory::PmuBistVendorAlgorithmElement>() {
730+
let v = s.iter().collect::<Vec<_>>();
731+
state.serialize_field("PmuBistVendorAlgorithmElement", &v)?;
732+
} else if let Some(s) = self.body_as_struct_array::<memory::Ddr5RawCardConfigElement>() {
733+
let v = s.iter().collect::<Vec<_>>();
734+
state.serialize_field("Ddr5RawCardConfigElement", &v)?;
735+
} else if let Some(s) = self.body_as_struct_array::<fch::EspiSioInitElement>() { // TODO terminator, so variant
736+
let v = s.iter().collect::<Vec<_>>();
737+
state.serialize_field("EspiSioInitElement", &v)?;
738+
} else if let Some(s) = self.body_as_struct_array::<gnb::EarlyPcieConfigElement>() {
739+
let v = s.iter().collect::<Vec<_>>();
740+
state.serialize_field("EarlyPcieConfigElement", &v)?;
741+
} else if let Some(s) =
742+
self.body_as_struct_sequence::<memory::platform_specific_override::ElementRef<'_>>() {
743+
let i = s.iter().unwrap();
744+
let v = i.collect::<Vec<_>>();
745+
state.serialize_field("platform_specific_overrides", &v)?;
746+
} else if let Some(s) =
747+
self.body_as_struct_sequence::<memory::platform_tuning::ElementRef<'_>>() {
748+
let i = s.iter().unwrap();
749+
let v = i.collect::<Vec<_>>();
750+
state.serialize_field("platform_tuning", &v)?;
751+
} else if let Some((_, s)) = self.body_as_struct::<Parameters>() {
752+
let parameters = ParametersIter::new(s.into_slice())
753+
.map_err(|_| serde::ser::Error::custom("could not serialize Parameters"))?;
754+
let v = parameters.collect::<Vec<_>>();
755+
state.serialize_field("parameters", &v)?;
756+
} else {
757+
state.serialize_field("struct_body", &buf)?;
758+
}
759+
}
760+
}
761+
state.end()
762+
}
763+
}
764+
616765
#[cfg(feature = "serde")]
617766
impl<'a> Serialize for EntryItem<'a> {
618767
fn serialize<S>(

0 commit comments

Comments
 (0)