Skip to content

Commit 4368845

Browse files
GnurouDanilo Krummrich
authored andcommitted
gpu: nova-core: add types for patching firmware binaries
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. Reviewed-by: Lyude Paul <[email protected]> Signed-off-by: Alexandre Courbot <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Danilo Krummrich <[email protected]>
1 parent 8021393 commit 4368845

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

drivers/gpu/nova-core/firmware.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33
//! Contains structures and functions dedicated to the parsing, building and patching of firmwares
44
//! to be loaded into a given execution unit.
55
6+
use core::marker::PhantomData;
7+
68
use kernel::device;
79
use kernel::firmware;
810
use kernel::prelude::*;
911
use kernel::str::CString;
1012

13+
use crate::dma::DmaObject;
14+
use crate::falcon::FalconFirmware;
1115
use crate::gpu;
1216
use crate::gpu::Chipset;
1317

@@ -84,6 +88,66 @@ impl FalconUCodeDescV3 {
8488
}
8589
}
8690

91+
/// Trait implemented by types defining the signed state of a firmware.
92+
trait SignedState {}
93+
94+
/// Type indicating that the firmware must be signed before it can be used.
95+
struct Unsigned;
96+
impl SignedState for Unsigned {}
97+
98+
/// Type indicating that the firmware is signed and ready to be loaded.
99+
struct Signed;
100+
impl SignedState for Signed {}
101+
102+
/// A [`DmaObject`] containing a specific microcode ready to be loaded into a falcon.
103+
///
104+
/// This is module-local and meant for sub-modules to use internally.
105+
///
106+
/// After construction, a firmware is [`Unsigned`], and must generally be patched with a signature
107+
/// before it can be loaded (with an exception for development hardware). The
108+
/// [`Self::patch_signature`] and [`Self::no_patch_signature`] methods are used to transition the
109+
/// firmware to its [`Signed`] state.
110+
struct FirmwareDmaObject<F: FalconFirmware, S: SignedState>(DmaObject, PhantomData<(F, S)>);
111+
112+
/// Trait for signatures to be patched directly into a given firmware.
113+
///
114+
/// This is module-local and meant for sub-modules to use internally.
115+
trait FirmwareSignature<F: FalconFirmware>: AsRef<[u8]> {}
116+
117+
#[expect(unused)]
118+
impl<F: FalconFirmware> FirmwareDmaObject<F, Unsigned> {
119+
/// Patches the firmware at offset `sig_base_img` with `signature`.
120+
fn patch_signature<S: FirmwareSignature<F>>(
121+
mut self,
122+
signature: &S,
123+
sig_base_img: usize,
124+
) -> Result<FirmwareDmaObject<F, Signed>> {
125+
let signature_bytes = signature.as_ref();
126+
if sig_base_img + signature_bytes.len() > self.0.size() {
127+
return Err(EINVAL);
128+
}
129+
130+
// SAFETY: We are the only user of this object, so there cannot be any race.
131+
let dst = unsafe { self.0.start_ptr_mut().add(sig_base_img) };
132+
133+
// SAFETY: `signature` and `dst` are valid, properly aligned, and do not overlap.
134+
unsafe {
135+
core::ptr::copy_nonoverlapping(signature_bytes.as_ptr(), dst, signature_bytes.len())
136+
};
137+
138+
Ok(FirmwareDmaObject(self.0, PhantomData))
139+
}
140+
141+
/// Mark the firmware as signed without patching it.
142+
///
143+
/// This method is used to explicitly confirm that we do not need to sign the firmware, while
144+
/// allowing us to continue as if it was. This is typically only needed for development
145+
/// hardware.
146+
fn no_patch_signature(self) -> FirmwareDmaObject<F, Signed> {
147+
FirmwareDmaObject(self.0, PhantomData)
148+
}
149+
}
150+
87151
pub(crate) struct ModInfoBuilder<const N: usize>(firmware::ModInfoBuilder<N>);
88152

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

0 commit comments

Comments
 (0)