Some of the firmwares need to be patched at load-time with a signature. Add a couple of types and traits that sub-modules can use to implement this behavior, while ensuring that the correct kind of signature is applied to the firmware.
Signed-off-by: Alexandre Courbot <acour...@nvidia.com> --- drivers/gpu/nova-core/dma.rs | 3 --- drivers/gpu/nova-core/firmware.rs | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/nova-core/dma.rs b/drivers/gpu/nova-core/dma.rs index 4b063aaef65ec4e2f476fc5ce9dc25341b6660ca..1f1f8c378d8e2cf51edc772e7afe392e9c9c8831 100644 --- a/drivers/gpu/nova-core/dma.rs +++ b/drivers/gpu/nova-core/dma.rs @@ -2,9 +2,6 @@ //! Simple DMA object wrapper. -// To be removed when all code is used. -#![expect(dead_code)] - use core::ops::{Deref, DerefMut}; use kernel::device; diff --git a/drivers/gpu/nova-core/firmware.rs b/drivers/gpu/nova-core/firmware.rs index c5d0f16d0de0e29f9f68f2e0b37e1e997a72782d..3909ceec6ffd28466d8b2930a0116ac73629d967 100644 --- a/drivers/gpu/nova-core/firmware.rs +++ b/drivers/gpu/nova-core/firmware.rs @@ -3,11 +3,15 @@ //! Contains structures and functions dedicated to the parsing, building and patching of firmwares //! to be loaded into a given execution unit. +use core::marker::PhantomData; + use kernel::device; use kernel::firmware; use kernel::prelude::*; use kernel::str::CString; +use crate::dma::DmaObject; +use crate::falcon::FalconFirmware; use crate::gpu; use crate::gpu::Chipset; @@ -82,6 +86,46 @@ pub(crate) fn size(&self) -> usize { } } +/// A [`DmaObject`] containing a specific microcode ready to be loaded into a falcon. +/// +/// This is module-local and meant for sub-modules to use internally. +struct FirmwareDmaObject<F: FalconFirmware>(DmaObject, PhantomData<F>); + +/// Trait for signatures to be patched directly into a given firmware. +/// +/// This is module-local and meant for sub-modules to use internally. +trait FirmwareSignature<F: FalconFirmware>: AsRef<[u8]> {} + +#[expect(unused)] +impl<F: FalconFirmware> FirmwareDmaObject<F> { + /// Creates a new `UcodeDmaObject` containing `data`. + fn new(dev: &device::Device<device::Bound>, data: &[u8]) -> Result<Self> { + DmaObject::from_data(dev, data).map(|dmaobj| Self(dmaobj, PhantomData)) + } + + /// Patches the firmware at offset `sig_base_img` with `signature`. + fn patch_signature<S: FirmwareSignature<F>>( + &mut self, + signature: &S, + sig_base_img: usize, + ) -> Result<()> { + let signature_bytes = signature.as_ref(); + if sig_base_img + signature_bytes.len() > self.0.size() { + return Err(EINVAL); + } + + // SAFETY: we are the only user of this object, so there cannot be any race. + let dst = unsafe { self.0.start_ptr_mut().add(sig_base_img) }; + + // SAFETY: `signature` and `dst` are valid, properly aligned, and do not overlap. + unsafe { + core::ptr::copy_nonoverlapping(signature_bytes.as_ptr(), dst, signature_bytes.len()) + }; + + Ok(()) + } +} + pub(crate) struct ModInfoBuilder<const N: usize>(firmware::ModInfoBuilder<N>); impl<const N: usize> ModInfoBuilder<N> { -- 2.49.0