From 557e702c63d03d73d4d6688914e0e39340c71e55 Mon Sep 17 00:00:00 2001 From: "Surply, Pierre" Date: Tue, 7 Jul 2026 14:16:05 +0200 Subject: [PATCH] app: make info command dispaly extra CPER sections When the input file contains extra CPER sections (eg. other than FERs containing Intel Crash Log records), the info command now displays an additional table listing the section's GUID and descriptions: $ iclg info cper.whea # Record Type Rev. Product Size Skt Checksum Die ----- ------------ ----- -------- ----- ---- --------- ---- 0-0 Punit 16 0x017 28 0 1-0 PMC 3 0x00c 2560 0 2-0 PMC_TRACE 1 0x00c 512 0 # CPER Section GUID Length Description -- ------------------------------------- ------- ------------------------------------------------------------- 0 81212a96-09ed-4996-9471-8d729c8e69ed 4128 Firmware Error Record - 26d769a7-c31a-43d0-9378-3c6c872eea4d 1 81212a96-09ed-4996-9471-8d729c8e69ed 3552 Firmware Error Record - 024508e0-d564-42ed-b236-580d542bc9d6 Signed-off-by: Surply, Pierre --- app/src/info.rs | 103 +++++++++++++++++++----------------- app/src/table.rs | 33 ++++++++++++ lib/src/cper/section.rs | 13 ++++- lib/src/cper/section/fer.rs | 13 ++++- 4 files changed, 111 insertions(+), 51 deletions(-) diff --git a/app/src/info.rs b/app/src/info.rs index 8cfc1e4..bd97847 100644 --- a/app/src/info.rs +++ b/app/src/info.rs @@ -69,46 +69,32 @@ fn compact(cm: &CollateralManager, input: &Path) -> Result table.render(); + if !crashlog.metadata.extra_cper_sections.is_empty() { + println!(); + + let mut table = Table::from(["#", "CPER Section GUID", "Length", "Description"]); + + for (i, section) in crashlog.metadata.extra_cper_sections.iter().enumerate() { + table.append_row(Row::from([ + i.to_string(), + section.guid().to_string(), + section.len().to_string(), + section.to_string(), + ])); + } + + table.render(); + } + Ok(()) } fn markdown(cm: &CollateralManager, input: &Path) -> Result<(), Error> { let crashlog = CrashLog::from_slice(&std::fs::read(input)?)?; - // Column widths - let region_idx_width = 8; - let record_idx_width = 8; - let record_type_width = 16; - let revision_width = 8; - let product_width = 14; - let size_width = 10; - let skt_width = 8; - let checksum_width = 12; - let die_width = 10; - - // Header - println!( - "| {1:(cm: &CollateralManager, input: &Path) -> Resul "Socket", "Checksum", "Die", - ); + ]); for (i, region) in crashlog.regions.iter().enumerate() { for (j, record) in region.records.iter().enumerate() { @@ -137,7 +123,8 @@ fn markdown(cm: &CollateralManager, input: &Path) -> Resul let checksum = record .checksum() - .map_or("", |check| if check { "Valid" } else { "Invalid" }); + .map_or("", |check| if check { "Valid" } else { "Invalid" }) + .to_string(); let die = if let Some(die_id) = record.header.die(cm) { die_id @@ -152,21 +139,39 @@ fn markdown(cm: &CollateralManager, input: &Path) -> Resul let record_size = record.header.record_size(); let socket_id = record.header.socket_id(); - // Populate the table - println!( - "| {i:width$}|", " ", width = column.width + 2); + } + println!(); + + for row in self.rows.iter() { + print!("|"); + for (i, cell) in row.cells.iter().enumerate() { + let Some(column) = self.columns.get(i) else { + break; + }; + + let width = column.width + 2; + print!(" "); + match column.alignment { + Alignment::Left => print!("{:width$}", cell), + Alignment::Right => print!("{:>width$} ", cell, width = width - 1), + Alignment::Center => print!("{:^width$}", cell), + } + print!("|"); + } + println!(); + } + } } diff --git a/lib/src/cper/section.rs b/lib/src/cper/section.rs index ae553f1..a37b0ce 100644 --- a/lib/src/cper/section.rs +++ b/lib/src/cper/section.rs @@ -4,7 +4,9 @@ pub mod fer; #[cfg(not(feature = "std"))] -use alloc::vec::Vec; +use alloc::{fmt, vec::Vec}; +#[cfg(feature = "std")] +use std::fmt; use super::descr::CperSectionDescriptor; use crate::region::Region; @@ -63,6 +65,15 @@ impl CperSectionBody { } } +impl fmt::Display for CperSectionBody { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::FirmwareErrorRecord(fer) => write!(f, "Firmware Error Record - {fer}"), + Self::Unknown(_, _) => write!(f, "Unknown"), + } + } +} + /// The descriptor and the body of the CPER Section. pub struct CperSection { pub descriptor: CperSectionDescriptor, diff --git a/lib/src/cper/section/fer.rs b/lib/src/cper/section/fer.rs index f448f50..f01ed86 100644 --- a/lib/src/cper/section/fer.rs +++ b/lib/src/cper/section/fer.rs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: MIT #[cfg(not(feature = "std"))] -use alloc::vec::Vec; +use alloc::{fmt, vec::Vec}; +#[cfg(feature = "std")] +use std::fmt; use uguid::Guid; use crate::region::Region; @@ -34,6 +36,15 @@ pub struct FirmwareErrorRecord { pub payload: Vec, } +impl fmt::Display for FirmwareErrorRecord { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.header.guid { + guids::RECORD_ID_CRASHLOG => write!(f, "Intel Crash Log Region"), + _ => write!(f, "{}", self.header.guid), + } + } +} + impl FirmwareErrorRecordHeader { /// Parses the section header from a slice. pub fn from_slice(s: &[u8]) -> Option {