On Thu, 2025-12-18 at 21:59 +0900, Alexandre Courbot wrote:
> So `FwsecFirmware` could have an optional member that contains both the
> generic bootloader and the `BootloaderDmemDescV2` corresponding to it.
> If that optional member is `Some`, then it returns the `FalconLoadTarget`s
> corresponding to the generic bootloader. Otherwise, it behaves as
> before.

Unfortunately, this won't work because the BootloaderDmemDescV2() depends on 
properties of the
FwsecFirmware, i.e. it is self-referential.  

So I tried this:

pub(crate) struct GenericBootloader {
    pub desc: BootloaderDesc,
    pub desc2: BootloaderDmemDescV2,   <--- new field
    pub ucode: Vec<u8, kernel::alloc::allocator::Kmalloc>,
}

and we already have this:

pub(crate) struct FwsecFirmware {
    /// Descriptor of the firmware.
    desc: FalconUCodeDesc,
    /// GPU-accessible DMA object containing the firmware.
    ucode: FirmwareDmaObject<Self, Signed>,
    /// Generic bootloader
    gen_bootloader: Option<GenericBootloader>,
}

So in the constructor for FwsecFirmware, I tried to do this:

                let imem_sec = self.imem_sec_load_params();
                let imem_ns = self.imem_ns_load_params().ok_or(EINVAL)?;
                let dmem = self.dmem_load_params();

                // This structure tells the generic bootloader where to find the
                // FWSEC image.
                let desc2 = BootloaderDmemDescV2 {
                    reserved: [0; 4],
                    signature: [0; 4],
                    ctx_dma: 4, // FALCON_DMAIDX_PHYS_SYS_NCOH
                    code_dma_base: ucode_dma.0.dma_handle(),
                    non_sec_code_off: imem_ns.dst_start,
                    non_sec_code_size: imem_ns.len,
                    sec_code_off: imem_sec.dst_start,
                    sec_code_size: imem_sec.len,
                    code_entry_point: 0,
                    data_dma_base: fw.dma_handle() + u64::from(dmem.src_start),
                    data_size: dmem.len,
                    argc: 0,
                    argv: 0,
                };

This obviously doesn't work because `self` doesn't exist it.  It is the output 
of the contructor
(FwsecFirmware::new()), so I can't use it in the constructor.  The 
self.imem_sec_load_params(), etc
functions all depend on whether it's a v2 or a v3 descriptor (local variable 
`desc` in ::new()).  I
would need to dismantle all that code and manually re-implement it in this 
constructor.  The truth
of the matter is that the BootloaderDmemDescV2 object needs to be built *after* 
the FwsecFirmware
object exists, because it references several fields inside FwsecFirmware 
descriptor, which could
technically be either a v2 or a v3.

Now I could assume that it's always a v2 descriptor, but that would just ignore 
the entire
infrastructure we created to support both versions transparently.

I will post a v5 that has only your minor suggestions.  I recommend that we 
collaborate offline to
implement the major ones, if you still feel they are necessary.  However, I 
would prefer that we
implement them as follow-on patches, in order to have Turing support make the 
6.20-rc6 deadline.

Reply via email to