On 1/21/2026 8:45 PM, Joel Fernandes wrote:
> 
> 
> On 1/21/2026 6:53 PM, Timur Tabi wrote:
>> The FRTS firmware in Turing and GA100 VBIOS has an older header
>> format (v2 instead of v3).  To support both v2 and v3 at runtime,
>> add the FalconUCodeDescV2 struct, and update code that references
>> the FalconUCodeDescV3 directly with a FalconUCodeDesc enum that
>> encapsulates both.
>>
>> Signed-off-by: Timur Tabi <[email protected]>
>> ---
>>  drivers/gpu/nova-core/firmware.rs       |  203 ++++-
>>  drivers/gpu/nova-core/firmware/fwsec.rs |   46 +-
>>  drivers/gpu/nova-core/vbios.rs          |   64 +-
>>  drivers/gpu/nova-core/vbios.rs.orig     | 1105 +++++++++++++++++++++++
>>  4 files changed, 1354 insertions(+), 64 deletions(-)
>>  create mode 100644 drivers/gpu/nova-core/vbios.rs.orig
>>
>> diff --git a/drivers/gpu/nova-core/firmware.rs 
>> b/drivers/gpu/nova-core/firmware.rs
>> index 2d2008b33fb4..68779540aa28 100644
>> --- a/drivers/gpu/nova-core/firmware.rs
>> +++ b/drivers/gpu/nova-core/firmware.rs
>> @@ -4,6 +4,7 @@
>>  //! to be loaded into a given execution unit.
>>  
>>  use core::marker::PhantomData;
>> +use core::ops::Deref;
>>  
>>  use kernel::{
>>      device,
>> @@ -15,7 +16,10 @@
>>  
>>  use crate::{
>>      dma::DmaObject,
>> -    falcon::FalconFirmware,
>> +    falcon::{
>> +        FalconFirmware,
>> +        FalconLoadTarget, //
>> +    },
>>      gpu,
>>      num::{
>>          FromSafeCast,
>> @@ -43,6 +47,46 @@ fn request_firmware(
>>          .and_then(|path| firmware::Firmware::request(&path, dev))
>>  }
>>  
>> +/// Structure used to describe some firmwares, notably FWSEC-FRTS.
>> +#[repr(C)]
>> +#[derive(Debug, Clone)]
>> +pub(crate) struct FalconUCodeDescV2 {
>> +    /// Header defined by 'NV_BIT_FALCON_UCODE_DESC_HEADER_VDESC*' in 
>> OpenRM.
>> +    hdr: u32,
>> +    /// Stored size of the ucode after the header, compressed or 
>> uncompressed
>> +    stored_size: u32,
>> +    /// Uncompressed size of the ucode.  If store_size == 
>> uncompressed_size, then the ucode
>> +    /// is not compressed.
>> +    pub(crate) uncompressed_size: u32,
>> +    /// Code entry point
>> +    pub(crate) virtual_entry: u32,
>> +    /// Offset after the code segment at which the Application Interface 
>> Table headers are located.
>> +    pub(crate) interface_offset: u32,
>> +    /// Base address at which to load the code segment into 'IMEM'.
>> +    pub(crate) imem_phys_base: u32,
>> +    /// Size in bytes of the code to copy into 'IMEM'.
>> +    pub(crate) imem_load_size: u32,
>> +    /// Virtual 'IMEM' address (i.e. 'tag') at which the code should start.
>> +    pub(crate) imem_virt_base: u32,
>> +    /// Virtual address of secure IMEM segment.
>> +    pub(crate) imem_sec_base: u32,
>> +    /// Size of secure IMEM segment.
>> +    pub(crate) imem_sec_size: u32,
>> +    /// Offset into stored (uncompressed) image at which DMEM begins.
>> +    pub(crate) dmem_offset: u32,
>> +    /// Base address at which to load the data segment into 'DMEM'.
>> +    pub(crate) dmem_phys_base: u32,
>> +    /// Size in bytes of the data to copy into 'DMEM'.
>> +    pub(crate) dmem_load_size: u32,
>> +    /// "Alternate" Size of data to load into IMEM.
>> +    pub(crate) alt_imem_load_size: u32,
>> +    /// "Alternate" Size of data to load into DMEM.
>> +    pub(crate) alt_dmem_load_size: u32,
>> +}
>> +
>> +// SAFETY: all bit patterns are valid for this type, and it doesn't use 
>> interior mutability.
>> +unsafe impl FromBytes for FalconUCodeDescV2 {}
>> +
>>  /// Structure used to describe some firmwares, notably FWSEC-FRTS.
>>  #[repr(C)]
>>  #[derive(Debug, Clone)]
>> @@ -76,13 +120,164 @@ pub(crate) struct FalconUCodeDescV3 {
>>      _reserved: u16,
>>  }
>>  
>> -impl FalconUCodeDescV3 {
>> +// SAFETY: all bit patterns are valid for this type, and it doesn't use
>> +// interior mutability.
>> +unsafe impl FromBytes for FalconUCodeDescV3 {}
>> +
>> +/// Enum wrapping the different versions of Falcon microcode descriptors.
>> +///
>> +/// This allows handling both V2 and V3 descriptor formats through a
>> +/// unified type, providing version-agnostic access to firmware metadata
>> +/// via the [`FalconUCodeDescriptor`] trait.
>> +#[derive(Debug, Clone)]
>> +pub(crate) enum FalconUCodeDesc {
>> +    V2(FalconUCodeDescV2),
>> +    V3(FalconUCodeDescV3),
>> +}
>> +
>> +impl Deref for FalconUCodeDesc {
>> +    type Target = dyn FalconUCodeDescriptor;
>> +
>> +    fn deref(&self) -> &Self::Target {
>> +        match self {
>> +            FalconUCodeDesc::V2(v2) => v2,
>> +            FalconUCodeDesc::V3(v3) => v3,
>> +        }
>> +    }
> 
> I guess we still need to decide if we want to use 'dyn' for
> FalconUCodeDescriptor or function wrappers with separate match statements. 
> John
> also recently felt, I think, that 'dyn' here is more complicated (I was the 
> one
> who suggested 'dyn' in v2 or so, but hey - in my defense, I am learning Rust 
> too
> ;-)).
> 
> After seeing this patch, I think I realized 'dyn' *for this case* does add 
> more
> boilerplate, because now you have duplicated functions which almost do exactly
> the same thing (seems much worse than duplicate match arms).
> 
> 'dyn' would benefit a lot though if the match arms were large. But in this
> patch, most of the match arms are just accessing fields.
> 
> For my -mm patches, where I am routing between version 2 and version 3 of the
> page table/directory formats, I actually went with match arms instead of dyn
> which was cleaner.
> 

Since this is not something we can easily fix though in a follow-up patch:

Reviewed-by: Joel Fernandes <[email protected]>

-- 
Joel Fernandes

Reply via email to