From 1f4b18a66d736273c26f6bdd1843915af5268f32 Mon Sep 17 00:00:00 2001 From: "Rivas Paz, Jose L" Date: Thu, 27 Aug 2026 16:07:45 +0200 Subject: [PATCH] header: include `Type0LegacyGpu` header This patch includes the Type0 Legacy GPU header. This header is introduced in order to properly support Intel(R) discrete graphics products that support Crash Log. Some of the legacy GPU products are using a Crash Log header Type0 legacy, which is different than the header used in server legacy products. Signed-off-by: Rivas Paz, Jose L --- lib/src/errata.rs | 24 ++++++++ lib/src/header.rs | 56 ++++++++++++++++-- lib/tests/header.rs | 24 +++++++- lib/tests/record.rs | 2 +- lib/tests/samples/legacy_type0_gpu.crashlog | Bin 0 -> 48 bytes ....crashlog => legacy_type0_server.crashlog} | Bin 6 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 lib/tests/samples/legacy_type0_gpu.crashlog rename lib/tests/samples/{legacy_type0.crashlog => legacy_type0_server.crashlog} (100%) diff --git a/lib/src/errata.rs b/lib/src/errata.rs index 686582a..230a658 100644 --- a/lib/src/errata.rs +++ b/lib/src/errata.rs @@ -29,6 +29,13 @@ pub struct Errata { /// The Crash Log headers have their sizes in DWORDs, but for some products that are using /// ECORE and PCORE Crash Log records, their sizes are written in bytes. pub core_record_size_bytes: bool, + + /// Type0 legacy header + /// + /// Some Intel(R) products in the discrete GPU segment are using legacy Crash Log record + /// headers with type0, which has a different layout compared with the currently defined Type0 + /// Header. + pub type0_legacy_gpu: bool, } const GNR_SP_PRODUCT_ID: u32 = 0x2f; @@ -38,10 +45,25 @@ const CWF_SP_PRODUCT_ID: u32 = 0x8e; const SERVER_LEGACY_PRODUCT_IDS: [u32; 3] = [GNR_SP_PRODUCT_ID, SRF_SP_PRODUCT_ID, CWF_SP_PRODUCT_ID]; +const BMG_X3_PRODUCT_ID: u32 = 0x5d; +const BMG_G31_PRODUCT_ID: u32 = 0x5e; +const BMG_X2_PRODUCT_ID: u32 = 0x5f; +const CRI_PRODUCT_ID: u32 = 0xb6; +const GPU_LEGACY_PRODUCT_IDS: [u32; 4] = [ + BMG_X3_PRODUCT_ID, + BMG_G31_PRODUCT_ID, + BMG_X2_PRODUCT_ID, + CRI_PRODUCT_ID, +]; + impl Errata { pub fn from_version(version: &Version) -> Self { let type0_legacy_server = version.header_type == 0 && SERVER_LEGACY_PRODUCT_IDS.contains(&version.product_id); + + let type0_legacy_gpu = + version.header_type == 0 && GPU_LEGACY_PRODUCT_IDS.contains(&version.product_id); + let type0_legacy_server_box = type0_legacy_server && version.record_type == record_types::PCORE; @@ -52,12 +74,14 @@ impl Errata { && (version.product_id < 0x71 || version.product_id == CGC_PRODUCT_ID); let core_record_size_bytes = !type0_legacy_server + && !type0_legacy_gpu && (ecore_record_with_size_in_bytes || pcore_record_with_size_in_bytes); Errata { type0_legacy_server, type0_legacy_server_box, core_record_size_bytes, + type0_legacy_gpu, } } } diff --git a/lib/src/header.rs b/lib/src/header.rs index 9e7fe33..9062f8f 100644 --- a/lib/src/header.rs +++ b/lib/src/header.rs @@ -89,6 +89,14 @@ pub enum HeaderType { completion_status: u32, collection_complete: bool, }, + + Type0LegacyGpu { + timestamp: u64, + agent_version: u32, + reason: u32, + completion_status: u32, + collection_complete: bool, + }, } impl HeaderType { @@ -218,6 +226,23 @@ impl HeaderType { }) } + fn type0_legacy_gpu_from_slice(slice: &[u8]) -> Option { + let reason = u32::from_le_bytes(slice.get(4..8)?.try_into().ok()?); + let timestamp = u64::from_le_bytes(slice.get(8..16)?.try_into().ok()?); + let agent_version = u32::from_le_bytes(slice.get(20..24)?.try_into().ok()?); + let cs_data = u32::from_le_bytes(slice.get(28..32)?.try_into().ok()?); + let completion_status = cs_data & 0x7FFFFFFF; + let collection_complete = (cs_data >> 31) != 0; + + Some(HeaderType::Type0LegacyGpu { + timestamp, + agent_version, + reason, + completion_status, + collection_complete, + }) + } + pub fn from_slice(header_type_value: u16, slice: &[u8]) -> Result { match header_type_value { 0 => Ok(HeaderType::Type0), @@ -234,6 +259,10 @@ impl HeaderType { pub fn from_slice_type0_legacy_server(slice: &[u8]) -> Result { Self::type0_legacy_server_from_slice(slice).ok_or(Error::InvalidHeader) } + + pub fn from_slice_type0_legacy_gpu(slice: &[u8]) -> Result { + Self::type0_legacy_gpu_from_slice(slice).ok_or(Error::InvalidHeader) + } } /// Header of a Crash Log record @@ -256,14 +285,16 @@ impl Header { }; let errata = Errata::from_version(&version); - let size = if errata.type0_legacy_server { - RecordSize::from_slice_type0_legacy_server(slice).ok_or(Error::InvalidHeader)? + let size = if errata.type0_legacy_server || errata.type0_legacy_gpu { + RecordSize::from_slice_type0_legacy(slice).ok_or(Error::InvalidHeader)? } else { RecordSize::from_slice(slice).ok_or(Error::InvalidHeader)? }; let header_type = if errata.type0_legacy_server { HeaderType::from_slice_type0_legacy_server(slice)? + } else if errata.type0_legacy_gpu { + HeaderType::from_slice_type0_legacy_gpu(slice)? } else { HeaderType::from_slice(version.header_type, slice)? }; @@ -428,6 +459,7 @@ impl Header { .. } => 28 + completion_status_size as usize * 4, HeaderType::Type0LegacyServer { .. } => 32, + HeaderType::Type0LegacyGpu { .. } => 32, } } @@ -580,8 +612,8 @@ impl RecordSize { }) } - /// Creates a [RecordSize] from the raw record of a server product with legacy header type0 - pub fn from_slice_type0_legacy_server(slice: &[u8]) -> Option { + /// Creates a [RecordSize] from the raw record of a product with legacy header type0 + pub fn from_slice_type0_legacy(slice: &[u8]) -> Option { Some(RecordSize { record_size: u16::from_le_bytes(slice.get(16..18)?.try_into().ok()?), extended_record_size: 0, @@ -736,6 +768,22 @@ impl From<&Header> for Node { collection_complete as u64, )); } + HeaderType::Type0LegacyGpu { + timestamp, + agent_version, + reason, + completion_status, + collection_complete, + } => { + node.add(Node::field("timestamp", timestamp)); + node.add(Node::field("agent_version", agent_version as u64)); + node.add(Node::field("reason", reason as u64)); + node.add(Node::field("completion_status", completion_status as u64)); + node.add(Node::field( + "record_collection_completed", + collection_complete as u64, + )); + } _ => (), } diff --git a/lib/tests/header.rs b/lib/tests/header.rs index 83540b4..d11f812 100644 --- a/lib/tests/header.rs +++ b/lib/tests/header.rs @@ -73,8 +73,8 @@ fn decode_die_id_header() { } #[test] -fn decode_legacy_header_type0() { - let data = fs::read("tests/samples/legacy_type0.crashlog").unwrap(); +fn decode_legacy_header_type0_server() { + let data = fs::read("tests/samples/legacy_type0_server.crashlog").unwrap(); let header = Header::from_slice(&data).unwrap().unwrap(); let socket_id = header.socket_id(); @@ -83,3 +83,23 @@ fn decode_legacy_header_type0() { let die_id = header.die_id().unwrap(); assert_eq!(die_id, 10); } + +#[test] +fn decode_legacy_header_type0_gpu() { + let data = fs::read("tests/samples/legacy_type0_gpu.crashlog").unwrap(); + let header = Header::from_slice(&data).unwrap().unwrap(); + + let socket_id = header.socket_id(); + assert_eq!(socket_id, 0); + + let die_id = header.die_id(); + assert_eq!(die_id, None); + + let node = Node::from(&header); + assert_eq!( + node.get_by_path("record_collection_completed") + .unwrap() + .kind, + NodeType::Field { value: 1 } + ); +} diff --git a/lib/tests/record.rs b/lib/tests/record.rs index b704dfd..383e832 100644 --- a/lib/tests/record.rs +++ b/lib/tests/record.rs @@ -240,7 +240,7 @@ fn box_header_type6() { #[test] fn header_type0_legacy_server() { let mut cm = CollateralManager::file_system_tree(Path::new(COLLATERAL_TREE_PATH)).unwrap(); - let data = fs::read("tests/samples/legacy_type0.crashlog").unwrap(); + let data = fs::read("tests/samples/legacy_type0_server.crashlog").unwrap(); let crashlog = CrashLog::from_slice(&data).unwrap(); diff --git a/lib/tests/samples/legacy_type0_gpu.crashlog b/lib/tests/samples/legacy_type0_gpu.crashlog new file mode 100644 index 0000000000000000000000000000000000000000..d59d51d8bdf1018015f82d9ad273ed37c649dccd GIT binary patch literal 48 gcmZp?z-q_Lz`zh(Zv2!9Nb>+O2rxpZ1_*^90i6T{2><{9 literal 0 HcmV?d00001 diff --git a/lib/tests/samples/legacy_type0.crashlog b/lib/tests/samples/legacy_type0_server.crashlog similarity index 100% rename from lib/tests/samples/legacy_type0.crashlog rename to lib/tests/samples/legacy_type0_server.crashlog