File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -28,6 +28,7 @@ use crate::{
2828} ;
2929
3030pub ( crate ) mod booter;
31+ pub ( crate ) mod fsp;
3132pub ( crate ) mod fwsec;
3233pub ( crate ) mod gsp;
3334pub ( crate ) mod riscv;
@@ -431,10 +432,16 @@ impl<const N: usize> ModInfoBuilder<N> {
431432 . make_entry_file ( name, "bootloader" )
432433 . make_entry_file ( name, "gsp" ) ;
433434
434- if chipset. needs_fwsec_bootloader ( ) {
435+ let this = if chipset. needs_fwsec_bootloader ( ) {
435436 this. make_entry_file ( name, "gen_bootloader" )
436437 } else {
437438 this
439+ } ;
440+
441+ if chipset. uses_fsp ( ) {
442+ this. make_entry_file ( name, "fmc" )
443+ } else {
444+ this
438445 }
439446 }
440447
Original file line number Diff line number Diff line change 1+ // SPDX-License-Identifier: GPL-2.0
2+ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
4+ //! FSP is a hardware unit that runs FMC firmware.
5+
6+ use kernel:: {
7+ device,
8+ dma:: Coherent ,
9+ firmware:: Firmware ,
10+ prelude:: * , //
11+ } ;
12+
13+ use crate :: {
14+ firmware:: elf,
15+ gpu:: Chipset , //
16+ } ;
17+
18+ pub ( crate ) struct FspFirmware {
19+ /// FMC firmware image data (only the "image" ELF section).
20+ #[ expect( dead_code) ]
21+ pub ( crate ) fmc_image : Coherent < [ u8 ] > ,
22+ /// Full FMC ELF for signature extraction.
23+ #[ expect( dead_code) ]
24+ pub ( crate ) fmc_elf : Firmware ,
25+ }
26+
27+ impl FspFirmware {
28+ pub ( crate ) fn new (
29+ dev : & device:: Device < device:: Bound > ,
30+ chipset : Chipset ,
31+ ver : & str ,
32+ ) -> Result < Self > {
33+ let fw = super :: request_firmware ( dev, chipset, "fmc" , ver) ?;
34+
35+ // FSP expects only the "image" section, not the entire ELF file.
36+ let fmc_image_data = elf:: elf_section ( fw. data ( ) , "image" ) . ok_or_else ( || {
37+ dev_err ! ( dev, "FMC ELF file missing 'image' section\n " ) ;
38+ EINVAL
39+ } ) ?;
40+ let fmc_image = Coherent :: from_slice ( dev, fmc_image_data, GFP_KERNEL ) ?;
41+
42+ Ok ( Self {
43+ fmc_image,
44+ fmc_elf : fw,
45+ } )
46+ }
47+ }
Original file line number Diff line number Diff line change @@ -137,6 +137,15 @@ impl Chipset {
137137 matches ! ( self . arch( ) , Architecture :: Turing ) || matches ! ( self , Self :: GA100 )
138138 }
139139
140+ /// Returns `true` if this chipset boots via FSP (Hopper and later), which requires the FMC
141+ /// firmware image.
142+ pub ( crate ) const fn uses_fsp ( self ) -> bool {
143+ matches ! (
144+ self . arch( ) ,
145+ Architecture :: Hopper | Architecture :: BlackwellGB10x | Architecture :: BlackwellGB20x
146+ )
147+ }
148+
140149 /// Returns the address range of the PCI config mirror space.
141150 pub ( crate ) fn pci_config_mirror_range ( self ) -> Range < u32 > {
142151 hal:: gpu_hal ( self ) . pci_config_mirror_range ( )
Original file line number Diff line number Diff line change @@ -16,6 +16,10 @@ use crate::{
1616 Falcon , //
1717 } ,
1818 fb:: FbLayout ,
19+ firmware:: {
20+ fsp:: FspFirmware ,
21+ FIRMWARE_VERSION , //
22+ } ,
1923 gpu:: Chipset ,
2024 gsp:: {
2125 boot:: BootUnloadGuard ,
@@ -35,14 +39,16 @@ impl GspHal for Gh100 {
3539 fn boot < ' a > (
3640 & self ,
3741 _gsp : & ' a Gsp ,
38- _dev : & ' a device:: Device < device:: Bound > ,
42+ dev : & ' a device:: Device < device:: Bound > ,
3943 _bar : & ' a Bar0 ,
40- _chipset : Chipset ,
44+ chipset : Chipset ,
4145 _fb_layout : & FbLayout ,
4246 _wpr_meta : & Coherent < GspFwWprMeta > ,
4347 _gsp_falcon : & ' a Falcon < GspEngine > ,
4448 _sec2_falcon : & ' a Falcon < Sec2 > ,
4549 ) -> Result < BootUnloadGuard < ' a > > {
50+ let _fsp_fw = FspFirmware :: new ( dev, chipset, FIRMWARE_VERSION ) ?;
51+
4652 Err ( ENOTSUPP )
4753 }
4854}
You can’t perform that action at this time.
0 commit comments