Skip to content

Commit d6cb731

Browse files
committed
gpu: nova-core: firmware: add support for common firmware header
Several firmware files loaded from userspace feature a common header that describes their payload. Add basic support for it so subsequent patches can leverage it. Acked-by: Danilo Krummrich <dakr@kernel.org> Link: https://lore.kernel.org/r/20250913-nova_firmware-v6-5-9007079548b0@nvidia.com Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
1 parent ebe6587 commit d6cb731

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

drivers/gpu/nova-core/firmware.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
//! to be loaded into a given execution unit.
55
66
use core::marker::PhantomData;
7+
use core::mem::size_of;
78

89
use kernel::device;
910
use kernel::firmware;
1011
use kernel::prelude::*;
1112
use kernel::str::CString;
13+
use kernel::transmute::FromBytes;
1214

1315
use crate::dma::DmaObject;
1416
use crate::falcon::FalconFirmware;
@@ -156,6 +158,66 @@ impl<F: FalconFirmware> FirmwareDmaObject<F, Unsigned> {
156158
}
157159
}
158160

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+
159221
pub(crate) struct ModInfoBuilder<const N: usize>(firmware::ModInfoBuilder<N>);
160222

161223
impl<const N: usize> ModInfoBuilder<N> {

0 commit comments

Comments
 (0)