|
4 | 4 | //! to be loaded into a given execution unit. |
5 | 5 |
|
6 | 6 | use core::marker::PhantomData; |
| 7 | +use core::mem::size_of; |
7 | 8 |
|
8 | 9 | use kernel::device; |
9 | 10 | use kernel::firmware; |
10 | 11 | use kernel::prelude::*; |
11 | 12 | use kernel::str::CString; |
| 13 | +use kernel::transmute::FromBytes; |
12 | 14 |
|
13 | 15 | use crate::dma::DmaObject; |
14 | 16 | use crate::falcon::FalconFirmware; |
@@ -156,6 +158,66 @@ impl<F: FalconFirmware> FirmwareDmaObject<F, Unsigned> { |
156 | 158 | } |
157 | 159 | } |
158 | 160 |
|
| 161 | +/// Header common to most firmware files. |
| 162 | +#[repr(C)] |
| 163 | +#[derive(Debug, Clone)] |
| 164 | +struct BinHdr { |
| 165 | + /// Magic number, must be `0x10de`. |
| 166 | + bin_magic: u32, |
| 167 | + /// Version of the header. |
| 168 | + bin_ver: u32, |
| 169 | + /// Size in bytes of the binary (to be ignored). |
| 170 | + bin_size: u32, |
| 171 | + /// Offset of the start of the application-specific header. |
| 172 | + header_offset: u32, |
| 173 | + /// Offset of the start of the data payload. |
| 174 | + data_offset: u32, |
| 175 | + /// Size in bytes of the data payload. |
| 176 | + data_size: u32, |
| 177 | +} |
| 178 | + |
| 179 | +// SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability. |
| 180 | +unsafe impl FromBytes for BinHdr {} |
| 181 | + |
| 182 | +// A firmware blob starting with a `BinHdr`. |
| 183 | +struct BinFirmware<'a> { |
| 184 | + hdr: BinHdr, |
| 185 | + fw: &'a [u8], |
| 186 | +} |
| 187 | + |
| 188 | +#[expect(dead_code)] |
| 189 | +impl<'a> BinFirmware<'a> { |
| 190 | + /// Interpret `fw` as a firmware image starting with a [`BinHdr`], and returns the |
| 191 | + /// corresponding [`BinFirmware`] that can be used to extract its payload. |
| 192 | + fn new(fw: &'a firmware::Firmware) -> Result<Self> { |
| 193 | + const BIN_MAGIC: u32 = 0x10de; |
| 194 | + let fw = fw.data(); |
| 195 | + |
| 196 | + fw.get(0..size_of::<BinHdr>()) |
| 197 | + // Extract header. |
| 198 | + .and_then(BinHdr::from_bytes_copy) |
| 199 | + // Validate header. |
| 200 | + .and_then(|hdr| { |
| 201 | + if hdr.bin_magic == BIN_MAGIC { |
| 202 | + Some(hdr) |
| 203 | + } else { |
| 204 | + None |
| 205 | + } |
| 206 | + }) |
| 207 | + .map(|hdr| Self { hdr, fw }) |
| 208 | + .ok_or(EINVAL) |
| 209 | + } |
| 210 | + |
| 211 | + /// Returns the data payload of the firmware, or `None` if the data range is out of bounds of |
| 212 | + /// the firmware image. |
| 213 | + fn data(&self) -> Option<&[u8]> { |
| 214 | + let fw_start = self.hdr.data_offset as usize; |
| 215 | + let fw_size = self.hdr.data_size as usize; |
| 216 | + |
| 217 | + self.fw.get(fw_start..fw_start + fw_size) |
| 218 | + } |
| 219 | +} |
| 220 | + |
159 | 221 | pub(crate) struct ModInfoBuilder<const N: usize>(firmware::ModInfoBuilder<N>); |
160 | 222 |
|
161 | 223 | impl<const N: usize> ModInfoBuilder<N> { |
|
0 commit comments