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>
This commit is contained in:
Alexandre Courbot
2025-09-13 23:12:18 +09:00
parent ebe658732c
commit d6cb7319e6

View File

@@ -4,11 +4,13 @@
//! to be loaded into a given execution unit.
use core::marker::PhantomData;
use core::mem::size_of;
use kernel::device;
use kernel::firmware;
use kernel::prelude::*;
use kernel::str::CString;
use kernel::transmute::FromBytes;
use crate::dma::DmaObject;
use crate::falcon::FalconFirmware;
@@ -156,6 +158,66 @@ fn no_patch_signature(self) -> FirmwareDmaObject<F, Signed> {
}
}
/// Header common to most firmware files.
#[repr(C)]
#[derive(Debug, Clone)]
struct BinHdr {
/// Magic number, must be `0x10de`.
bin_magic: u32,
/// Version of the header.
bin_ver: u32,
/// Size in bytes of the binary (to be ignored).
bin_size: u32,
/// Offset of the start of the application-specific header.
header_offset: u32,
/// Offset of the start of the data payload.
data_offset: u32,
/// Size in bytes of the data payload.
data_size: u32,
}
// SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability.
unsafe impl FromBytes for BinHdr {}
// A firmware blob starting with a `BinHdr`.
struct BinFirmware<'a> {
hdr: BinHdr,
fw: &'a [u8],
}
#[expect(dead_code)]
impl<'a> BinFirmware<'a> {
/// Interpret `fw` as a firmware image starting with a [`BinHdr`], and returns the
/// corresponding [`BinFirmware`] that can be used to extract its payload.
fn new(fw: &'a firmware::Firmware) -> Result<Self> {
const BIN_MAGIC: u32 = 0x10de;
let fw = fw.data();
fw.get(0..size_of::<BinHdr>())
// Extract header.
.and_then(BinHdr::from_bytes_copy)
// Validate header.
.and_then(|hdr| {
if hdr.bin_magic == BIN_MAGIC {
Some(hdr)
} else {
None
}
})
.map(|hdr| Self { hdr, fw })
.ok_or(EINVAL)
}
/// Returns the data payload of the firmware, or `None` if the data range is out of bounds of
/// the firmware image.
fn data(&self) -> Option<&[u8]> {
let fw_start = self.hdr.data_offset as usize;
let fw_size = self.hdr.data_size as usize;
self.fw.get(fw_start..fw_start + fw_size)
}
}
pub(crate) struct ModInfoBuilder<const N: usize>(firmware::ModInfoBuilder<N>);
impl<const N: usize> ModInfoBuilder<N> {