trace_recorder_parser/streaming/
header_info.rs1use crate::streaming::Error;
2use crate::types::{
3 Endianness, KernelPortIdentity, KernelVersion, PlatformCfgVersion, TrimmedString,
4};
5use byteordered::ByteOrdered;
6use std::collections::VecDeque;
7use std::io::Read;
8use tracing::{debug, warn};
9
10#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
11pub struct HeaderInfo {
12 pub endianness: Endianness,
13 pub format_version: u16,
14 pub kernel_version: KernelVersion,
15 pub kernel_port: KernelPortIdentity,
16 pub options: u32,
17 pub irq_priority_order: u32,
18 pub num_cores: u32,
19 pub isr_tail_chaining_threshold: u32,
20 pub platform_cfg: String,
21 pub platform_cfg_version: PlatformCfgVersion,
22}
23
24impl HeaderInfo {
25 pub const WIRE_SIZE: usize = 24;
26 pub const PSF_LITTLE_ENDIAN: u32 = 0x50_53_46_00;
27 pub const PSF_BIG_ENDIAN: u32 = 0x00_46_53_50;
28
29 pub fn read_psf_word<R: Read>(r: &mut R) -> Result<Endianness, Error> {
30 let mut r = ByteOrdered::le(r);
31 let mut psf = [0; 4];
32 r.read_exact(&mut psf)?;
33 let endianness = match u32::from_le_bytes(psf) {
34 Self::PSF_LITTLE_ENDIAN => Endianness::Little,
35 Self::PSF_BIG_ENDIAN => Endianness::Big,
36 bad_psf => return Err(Error::PSFEndiannessIdentifier(bad_psf)),
37 };
38 Ok(endianness)
39 }
40
41 pub fn find<R: Read>(r: &mut R) -> Result<Self, Error> {
42 debug!("Searching for PSF word");
43 let mut offset = 0;
44 let mut r = ByteOrdered::native(r);
45 let mut psf_buf = VecDeque::with_capacity(4);
46 psf_buf.resize(4, 0_u8);
47 r.read_exact(psf_buf.make_contiguous())?;
48 loop {
49 match Self::read_psf_word(&mut psf_buf.clone()) {
50 Ok(endianness) => {
51 debug!(%endianness, offset, "Found PSF word");
52 return Self::read_with_endianness(endianness, &mut r.into_inner());
53 }
54 Err(Error::PSFEndiannessIdentifier(_)) => {
55 offset += 1;
56 psf_buf.push_back(r.read_u8()?);
57 psf_buf.pop_front();
58 continue;
59 }
60 Err(e) => {
61 debug!("Failed to find PSF word");
62 return Err(e);
63 }
64 }
65 }
66 }
67
68 pub fn read<R: Read>(r: &mut R) -> Result<Self, Error> {
69 let endianness = Self::read_psf_word(r)?;
70 Self::read_with_endianness(endianness, r)
71 }
72
73 pub fn read_with_endianness<R: Read>(endianness: Endianness, r: &mut R) -> Result<Self, Error> {
75 let mut r = ByteOrdered::new(r, byteordered::Endianness::from(endianness));
77
78 let format_version = r.read_u16()?;
79 debug!(format_version = format_version, "Found format version");
80 let platform = r.read_u16()?;
81 let kernel_version = KernelVersion(platform.to_le_bytes());
82 let kernel_port = kernel_version
83 .port_identity()
84 .map_err(|e| Error::KernelVersion(e.0))?;
85 debug!(kernel_version = %kernel_version, kernel_port = %kernel_port, endianness = ?endianness, "Found kernel version");
86
87 if kernel_port != KernelPortIdentity::FreeRtos {
88 warn!("Kernel port {kernel_port} is not officially supported");
89 }
90 if format_version != 10 && !(12..=14).contains(&format_version) {
91 warn!("Version {format_version} is not officially supported");
92 }
93
94 let options = r.read_u32()?;
96 let irq_priority_order = options & 0x01;
97 let num_cores = r.read_u32()? & 0xFF;
99 let isr_tail_chaining_threshold = r.read_u32()?;
100
101 let platform_cfg_version_patch;
102 let platform_cfg_version_minor;
103 let platform_cfg_version_major;
104 let mut platform_cfg_bytes: [u8; 8] = [0; 8];
105
106 if format_version == 10 || format_version == 12 {
107 r.read_exact(&mut platform_cfg_bytes)?;
108
109 platform_cfg_version_patch = r.read_u16()?;
110 platform_cfg_version_minor = r.read_u8()?;
111 platform_cfg_version_major = r.read_u8()?;
112 } else {
113 platform_cfg_version_patch = r.read_u16()?;
115 platform_cfg_version_minor = r.read_u8()?;
116 platform_cfg_version_major = r.read_u8()?;
117
118 r.read_exact(&mut platform_cfg_bytes)?;
119 }
120
121 let platform_cfg_version = PlatformCfgVersion {
122 major: platform_cfg_version_major,
123 minor: platform_cfg_version_minor,
124 patch: platform_cfg_version_patch,
125 };
126 let platform_cfg = TrimmedString::from_raw(&platform_cfg_bytes).into();
127
128 Ok(Self {
129 endianness,
130 format_version,
131 kernel_version,
132 kernel_port,
133 options,
134 irq_priority_order,
135 num_cores,
136 isr_tail_chaining_threshold,
137 platform_cfg,
138 platform_cfg_version,
139 })
140 }
141}