[PATCH v11 11/22] gpu: nova-core: Hopper/Blackwell: add FMC firmware image
From: John Hubbard
Date: Fri May 29 2026 - 23:13:55 EST
FSP is the Falcon that runs FMC firmware on Hopper and Blackwell.
Load the FMC ELF in two forms: the image section that FSP boots from,
and the full Firmware object for later signature extraction during
Chain of Trust verification.
Co-developed-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx>
---
drivers/gpu/nova-core/firmware.rs | 1 +
drivers/gpu/nova-core/firmware/fsp.rs | 47 ++++++++++++++++++++++++++
drivers/gpu/nova-core/gsp/hal/gh100.rs | 5 +++
3 files changed, 53 insertions(+)
create mode 100644 drivers/gpu/nova-core/firmware/fsp.rs
diff --git a/drivers/gpu/nova-core/firmware.rs b/drivers/gpu/nova-core/firmware.rs
index 866bc9b3571e..6edb50b83a29 100644
--- a/drivers/gpu/nova-core/firmware.rs
+++ b/drivers/gpu/nova-core/firmware.rs
@@ -28,6 +28,7 @@
};
pub(crate) mod booter;
+pub(crate) mod fsp;
pub(crate) mod fwsec;
pub(crate) mod gsp;
pub(crate) mod riscv;
diff --git a/drivers/gpu/nova-core/firmware/fsp.rs b/drivers/gpu/nova-core/firmware/fsp.rs
new file mode 100644
index 000000000000..011be1e571c2
--- /dev/null
+++ b/drivers/gpu/nova-core/firmware/fsp.rs
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! FSP is a hardware unit that runs FMC firmware.
+
+use kernel::{
+ device,
+ dma::Coherent,
+ firmware::Firmware,
+ prelude::*, //
+};
+
+use crate::{
+ firmware::elf,
+ gpu::Chipset, //
+};
+
+pub(crate) struct FspFirmware {
+ /// FMC firmware image data (only the "image" ELF section).
+ #[expect(dead_code)]
+ pub(crate) fmc_image: Coherent<[u8]>,
+ /// Full FMC ELF for signature extraction.
+ #[expect(dead_code)]
+ pub(crate) fmc_elf: Firmware,
+}
+
+impl FspFirmware {
+ pub(crate) fn new(
+ dev: &device::Device<device::Bound>,
+ chipset: Chipset,
+ ver: &str,
+ ) -> Result<Self> {
+ let fw = super::request_firmware(dev, chipset, "fmc", ver)?;
+
+ // FSP expects only the "image" section, not the entire ELF file.
+ let fmc_image_data = elf::elf_section(fw.data(), "image").ok_or_else(|| {
+ dev_err!(dev, "FMC ELF file missing 'image' section\n");
+ EINVAL
+ })?;
+ let fmc_image = Coherent::from_slice(dev, fmc_image_data, GFP_KERNEL)?;
+
+ Ok(Self {
+ fmc_image,
+ fmc_elf: fw,
+ })
+ }
+}
diff --git a/drivers/gpu/nova-core/gsp/hal/gh100.rs b/drivers/gpu/nova-core/gsp/hal/gh100.rs
index fe2689764c8d..c38d88bc42b0 100644
--- a/drivers/gpu/nova-core/gsp/hal/gh100.rs
+++ b/drivers/gpu/nova-core/gsp/hal/gh100.rs
@@ -17,6 +17,10 @@
Falcon, //
},
fb::FbLayout,
+ firmware::{
+ fsp::FspFirmware,
+ FIRMWARE_VERSION, //
+ },
gpu::Chipset,
gsp::{
boot::BootUnloadGuard,
@@ -45,6 +49,7 @@ fn boot<'a>(
_sec2_falcon: &'a Falcon<Sec2>,
) -> Result<BootUnloadGuard<'a>> {
let _fsp_falcon = Falcon::<FspEngine>::new(dev, chipset)?;
+ let _fsp_fw = FspFirmware::new(dev, chipset, FIRMWARE_VERSION)?;
Err(ENOTSUPP)
}
--
2.54.0