55
66#[ cfg( feature = "collateral_manager" ) ]
77use crate :: collateral:: { CollateralManager , CollateralTree , ItemPath , PVSS } ;
8+ use crate :: errata:: Errata ;
89use crate :: error:: Error ;
910use crate :: node:: Node ;
1011#[ cfg( not( feature = "std" ) ) ]
@@ -78,6 +79,16 @@ pub enum HeaderType {
7879 completion_status : Vec < u32 > ,
7980 collection_complete : bool ,
8081 } ,
82+
83+ Type0LegacyServer {
84+ timestamp : u64 ,
85+ agent_version : u32 ,
86+ reason : u32 ,
87+ die_id : u8 ,
88+ socket_id : u8 ,
89+ completion_status : u32 ,
90+ collection_complete : bool ,
91+ } ,
8192}
8293
8394impl HeaderType {
@@ -177,6 +188,36 @@ impl HeaderType {
177188 } )
178189 }
179190
191+ fn type0_legacy_server_from_slice ( slice : & [ u8 ] ) -> Option < Self > {
192+ let reason = u32:: from_le_bytes ( slice. get ( 4 ..8 ) ?. try_into ( ) . ok ( ) ?) ;
193+ let timestamp = u64:: from_le_bytes ( slice. get ( 8 ..16 ) ?. try_into ( ) . ok ( ) ?) ;
194+ let agent_version = u32:: from_le_bytes ( slice. get ( 20 ..24 ) ?. try_into ( ) . ok ( ) ?) ;
195+ let socket_id = slice[ 24 ] ;
196+ let cs_data = u32:: from_le_bytes ( slice. get ( 28 ..32 ) ?. try_into ( ) . ok ( ) ?) ;
197+ let completion_status = cs_data & 0x7FFFFFFF ;
198+ let collection_complete = ( cs_data >> 31 ) != 0 ;
199+
200+ // Encoded die_id
201+ let revision = slice[ 0 ] ;
202+ let die_idx = revision & 0x3 ;
203+
204+ let die_id = if ( ( revision >> 7 ) & 1 ) == 1 {
205+ die_idx + 9
206+ } else {
207+ die_idx << 2
208+ } ;
209+
210+ Some ( HeaderType :: Type0LegacyServer {
211+ timestamp,
212+ agent_version,
213+ reason,
214+ die_id,
215+ socket_id,
216+ completion_status,
217+ collection_complete,
218+ } )
219+ }
220+
180221 pub fn from_slice ( header_type_value : u16 , slice : & [ u8 ] ) -> Result < Self , Error > {
181222 match header_type_value {
182223 0 => Ok ( HeaderType :: Type0 ) ,
@@ -189,6 +230,10 @@ impl HeaderType {
189230 type_value => Err ( Error :: InvalidHeaderType ( type_value) ) ,
190231 }
191232 }
233+
234+ pub fn from_slice_type0_legacy_server ( slice : & [ u8 ] ) -> Result < Self , Error > {
235+ Self :: type0_legacy_server_from_slice ( slice) . ok_or ( Error :: InvalidHeader )
236+ }
192237}
193238
194239/// Header of a Crash Log record
@@ -209,8 +254,19 @@ impl Header {
209254 // Termination marker
210255 return Ok ( None ) ;
211256 } ;
212- let size = RecordSize :: from_slice ( slice) . ok_or ( Error :: InvalidHeader ) ?;
213- let header_type = HeaderType :: from_slice ( version. header_type , slice) ?;
257+ let errata = Errata :: from_version ( & version) ;
258+
259+ let size = if errata. type0_legacy_server {
260+ RecordSize :: from_slice_type0_legacy_server ( slice) . ok_or ( Error :: InvalidHeader ) ?
261+ } else {
262+ RecordSize :: from_slice ( slice) . ok_or ( Error :: InvalidHeader ) ?
263+ } ;
264+
265+ let header_type = if errata. type0_legacy_server {
266+ HeaderType :: from_slice_type0_legacy_server ( slice) ?
267+ } else {
268+ HeaderType :: from_slice ( version. header_type , slice) ?
269+ } ;
214270
215271 Ok ( Some ( Header {
216272 version,
@@ -280,19 +336,19 @@ impl Header {
280336
281337 /// Returns the ID of the socket that generated the record.
282338 pub fn socket_id ( & self ) -> u8 {
283- if let HeaderType :: Type6 { socket_id , .. } = self . header_type {
284- socket_id
285- } else {
286- 0
339+ match self . header_type {
340+ HeaderType :: Type6 { socket_id, .. } => socket_id ,
341+ HeaderType :: Type0LegacyServer { socket_id , .. } => socket_id ,
342+ _ => 0 ,
287343 }
288344 }
289345
290346 /// Returns the ID of the die that generated the record.
291347 pub fn die_id ( & self ) -> Option < u8 > {
292- if let HeaderType :: Type6 { die_id , .. } = self . header_type {
293- Some ( die_id)
294- } else {
295- None
348+ match self . header_type {
349+ HeaderType :: Type6 { die_id , .. } => Some ( die_id) ,
350+ HeaderType :: Type0LegacyServer { die_id , .. } => Some ( die_id ) ,
351+ _ => None ,
296352 }
297353 }
298354
@@ -372,6 +428,7 @@ impl Header {
372428 completion_status_size,
373429 ..
374430 } => 28 + completion_status_size as usize * 4 ,
431+ HeaderType :: Type0LegacyServer { .. } => 32 ,
375432 }
376433 }
377434
@@ -380,25 +437,28 @@ impl Header {
380437 & self ,
381438 cm : & CollateralManager < T > ,
382439 ) -> Option < String > {
383- if let HeaderType :: Type6 { socket_id, .. } = self . header_type {
384- if let Some ( die) = self . die ( cm) {
385- Some ( format ! ( "processors.cpu{socket_id}.{die}" ) )
386- } else {
387- self . get_root_path ( )
440+ match self . header_type {
441+ HeaderType :: Type6 { socket_id, .. }
442+ | HeaderType :: Type0LegacyServer { socket_id, .. } => {
443+ if let Some ( die) = self . die ( cm) {
444+ Some ( format ! ( "processors.cpu{socket_id}.{die}" ) )
445+ } else {
446+ self . get_root_path ( )
447+ }
388448 }
389- } else {
390- None
449+ _ => None ,
391450 }
392451 }
393452
394453 pub ( super ) fn get_root_path ( & self ) -> Option < String > {
395- if let HeaderType :: Type6 {
396- socket_id, die_id, ..
397- } = self . header_type
398- {
399- Some ( format ! ( "processors.cpu{socket_id}.die{die_id}" ) )
400- } else {
401- None
454+ match self . header_type {
455+ HeaderType :: Type6 {
456+ socket_id, die_id, ..
457+ }
458+ | HeaderType :: Type0LegacyServer {
459+ socket_id, die_id, ..
460+ } => Some ( format ! ( "processors.cpu{socket_id}.die{die_id}" ) ) ,
461+ _ => None ,
402462 }
403463 }
404464}
@@ -412,8 +472,13 @@ impl fmt::Display for Header {
412472 ) ;
413473 let header_type = match self . header_type {
414474 HeaderType :: Type6 {
415- die_id, socket_id, ..
416- } => format ! ( "die_id={die_id}, socket_id={socket_id}" ) ,
475+ socket_id, die_id, ..
476+ }
477+ | HeaderType :: Type0LegacyServer {
478+ socket_id, die_id, ..
479+ } => {
480+ format ! ( "die_id={die_id}, socket_id={socket_id}" )
481+ }
417482 _ => ".." . to_string ( ) ,
418483 } ;
419484
@@ -512,6 +577,14 @@ impl RecordSize {
512577 extended_record_size : u16:: from_le_bytes ( slice. get ( 6 ..8 ) ?. try_into ( ) . ok ( ) ?) ,
513578 } )
514579 }
580+
581+ /// Creates a [RecordSize] from the raw record of a server product with legacy header type0
582+ pub fn from_slice_type0_legacy_server ( slice : & [ u8 ] ) -> Option < Self > {
583+ Some ( RecordSize {
584+ record_size : u16:: from_le_bytes ( slice. get ( 16 ..18 ) ?. try_into ( ) . ok ( ) ?) ,
585+ extended_record_size : 0 ,
586+ } )
587+ }
515588}
516589
517590impl From < & RecordSize > for Node {
@@ -641,6 +714,26 @@ impl From<&Header> for Node {
641714 ) ) ;
642715 }
643716 }
717+ HeaderType :: Type0LegacyServer {
718+ timestamp,
719+ agent_version,
720+ reason,
721+ die_id,
722+ socket_id,
723+ completion_status,
724+ collection_complete,
725+ } => {
726+ node. add ( Node :: field ( "timestamp" , timestamp) ) ;
727+ node. add ( Node :: field ( "agent_version" , agent_version as u64 ) ) ;
728+ node. add ( Node :: field ( "reason" , reason as u64 ) ) ;
729+ node. add ( Node :: field ( "die_id" , die_id as u64 ) ) ;
730+ node. add ( Node :: field ( "socket_id" , socket_id as u64 ) ) ;
731+ node. add ( Node :: field ( "completion_status" , completion_status as u64 ) ) ;
732+ node. add ( Node :: field (
733+ "record_collection_completed" ,
734+ collection_complete as u64 ,
735+ ) ) ;
736+ }
644737 _ => ( ) ,
645738 }
646739
0 commit comments