mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02:00
gpu: nova-core: transition gen_bootloader to TLV images
Switch the generic bootloader firmware loader from the legacy binary format to the TLV format. This change requires the new TLV versions of the r570.144 firmware images. Signed-off-by: Timur Tabi <ttabi@nvidia.com> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Tested-by: Alexandre Courbot <acourbot@nvidia.com> Link: https://patch.msgid.link/20260731201017.2580713-7-ttabi@nvidia.com Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
parent
ccdcefb71a
commit
ebc053cf0b
|
|
@ -11,8 +11,7 @@
|
|||
device,
|
||||
firmware,
|
||||
prelude::*,
|
||||
str::CString,
|
||||
transmute::FromBytes, //
|
||||
str::CString, //
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -344,27 +343,6 @@ fn no_patch_signature(self) -> FirmwareObject<F, Signed> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Header common to most firmware files.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
struct BinHdr {
|
||||
/// Magic number, must be `0x10de`.
|
||||
bin_magic: u32,
|
||||
/// Version of the header.
|
||||
bin_ver: u32,
|
||||
/// Size in bytes of the binary (to be ignored).
|
||||
bin_size: u32,
|
||||
/// Offset of the start of the application-specific header.
|
||||
header_offset: u32,
|
||||
/// Offset of the start of the data payload.
|
||||
data_offset: u32,
|
||||
/// Size in bytes of the data payload.
|
||||
data_size: u32,
|
||||
}
|
||||
|
||||
// SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability.
|
||||
unsafe impl FromBytes for BinHdr {}
|
||||
|
||||
pub(crate) struct ModInfoBuilder<const N: usize>(firmware::ModInfoBuilder<N>);
|
||||
|
||||
impl<const N: usize> ModInfoBuilder<N> {
|
||||
|
|
|
|||
|
|
@ -19,10 +19,7 @@
|
|||
Alignment, //
|
||||
},
|
||||
sizes,
|
||||
transmute::{
|
||||
AsBytes,
|
||||
FromBytes, //
|
||||
},
|
||||
transmute::AsBytes,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -42,38 +39,16 @@
|
|||
},
|
||||
firmware::{
|
||||
fwsec::FwsecFirmware,
|
||||
request_firmware,
|
||||
BinHdr,
|
||||
FIRMWARE_VERSION, //
|
||||
tlv::{
|
||||
request_tlv, //
|
||||
Tlv,
|
||||
},
|
||||
},
|
||||
gpu::Chipset,
|
||||
num::FromSafeCast, //
|
||||
regs,
|
||||
};
|
||||
|
||||
/// Descriptor used by RM to figure out the requirements of the boot loader.
|
||||
///
|
||||
/// Most of its fields appear to be legacy and carry incorrect values, so they are left unused.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
struct BootloaderDesc {
|
||||
/// Starting tag of bootloader.
|
||||
start_tag: u32,
|
||||
/// DMEM load offset - unused here as we always load at offset `0`.
|
||||
_dmem_load_off: u32,
|
||||
/// Offset of code section in the image. Unused as there is only one section in the bootloader
|
||||
/// binary.
|
||||
_code_off: u32,
|
||||
/// Size of code section in the image.
|
||||
code_size: u32,
|
||||
/// Offset of data section in the image. Unused as we build the data section ourselves.
|
||||
_data_off: u32,
|
||||
/// Size of data section in the image. Unused as we build the data section ourselves.
|
||||
_data_size: u32,
|
||||
}
|
||||
// SAFETY: any byte sequence is valid for this struct.
|
||||
unsafe impl FromBytes for BootloaderDesc {}
|
||||
|
||||
/// Structure used by the boot-loader to load the rest of the code.
|
||||
///
|
||||
/// This has to be filled by the GPU driver and copied into DMEM at offset
|
||||
|
|
@ -146,38 +121,24 @@ pub(crate) fn new(
|
|||
dev: &Device<device::Bound>,
|
||||
chipset: Chipset,
|
||||
) -> Result<Self> {
|
||||
let fw = request_firmware(dev, chipset, "gen_bootloader", FIRMWARE_VERSION)?;
|
||||
let hdr = fw
|
||||
.data()
|
||||
.get(0..size_of::<BinHdr>())
|
||||
.and_then(BinHdr::from_bytes_copy)
|
||||
.ok_or(EINVAL)?;
|
||||
|
||||
let desc = {
|
||||
let desc_offset = usize::from_safe_cast(hdr.header_offset);
|
||||
|
||||
fw.data()
|
||||
.get(desc_offset..)
|
||||
.and_then(BootloaderDesc::from_bytes_copy_prefix)
|
||||
.ok_or(EINVAL)?
|
||||
.0
|
||||
};
|
||||
let fw = request_tlv(dev, chipset, "gen_bootloader")?;
|
||||
let tlv = Tlv::new(fw.data())?;
|
||||
dev_dbg!(
|
||||
dev,
|
||||
"loaded generic bootloader firmware v{}\n",
|
||||
tlv.get_string(b"VERS")?
|
||||
);
|
||||
|
||||
let ucode = {
|
||||
let ucode_start = usize::from_safe_cast(hdr.data_offset);
|
||||
let code_size = usize::from_safe_cast(desc.code_size);
|
||||
// Align to falcon block size (256 bytes).
|
||||
let blob = tlv.get_bytes(b"BLOB")?;
|
||||
let code_size = usize::from_safe_cast(tlv.get_u32(b"CDSZ")?);
|
||||
let code = blob.get(..code_size).ok_or(EINVAL)?;
|
||||
let aligned_code_size = code_size
|
||||
.align_up(Alignment::new::<{ falcon::MEM_BLOCK_ALIGNMENT }>())
|
||||
.ok_or(EINVAL)?;
|
||||
|
||||
let mut ucode = KVec::with_capacity(aligned_code_size, GFP_KERNEL)?;
|
||||
ucode.extend_from_slice(
|
||||
fw.data()
|
||||
.get(ucode_start..ucode_start + code_size)
|
||||
.ok_or(EINVAL)?,
|
||||
GFP_KERNEL,
|
||||
)?;
|
||||
ucode.extend_from_slice(code, GFP_KERNEL)?;
|
||||
ucode.resize(aligned_code_size, 0, GFP_KERNEL)?;
|
||||
|
||||
ucode
|
||||
|
|
@ -258,13 +219,15 @@ pub(crate) fn new(
|
|||
.checked_sub(ucode.len())
|
||||
.ok_or(EOVERFLOW)?;
|
||||
|
||||
let start_tag = u16::try_from(tlv.get_u32(b"STRT")?)?;
|
||||
|
||||
Ok(Self {
|
||||
_firmware_dma: firmware_dma,
|
||||
ucode,
|
||||
dmem_desc,
|
||||
brom_params: firmware.brom_params(),
|
||||
imem_dst_start: u16::try_from(imem_dst_start)?,
|
||||
start_tag: u16::try_from(desc.start_tag)?,
|
||||
start_tag,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user