From: John Hubbard Date: Tue, 2 Jun 2026 03:20:57 +0000 (-0700) Subject: gpu: nova-core: add auto-detection of 32-bit, 64-bit firmware images X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ad5f9977a9a0070526d3d7f8f18e4652877a9def;p=thirdparty%2Fkernel%2Flinux.git gpu: nova-core: add auto-detection of 32-bit, 64-bit firmware images A firmware image may be either a 32-bit or a 64-bit ELF, and callers should not have to know which. Detect the ELF class from the image header at parse time and dispatch to the matching parser, so a single entry point handles both layouts. Signed-off-by: John Hubbard Reviewed-by: Eliot Courtney Link: https://patch.msgid.link/20260602032111.224790-10-jhubbard@nvidia.com Signed-off-by: Alexandre Courbot --- diff --git a/drivers/gpu/nova-core/firmware.rs b/drivers/gpu/nova-core/firmware.rs index e4dcc9a87b7e7..87588cb24f11a 100644 --- a/drivers/gpu/nova-core/firmware.rs +++ b/drivers/gpu/nova-core/firmware.rs @@ -629,14 +629,33 @@ mod elf { }) } - /// Tries to extract section with name `name` from the ELF64 image `elf`, and returns it. - pub(super) fn elf64_section<'a>(elf: &'a [u8], name: &str) -> Option<&'a [u8]> { + /// Extract the section with name `name` from the ELF64 image `elf`. + fn elf64_section<'a>(elf: &'a [u8], name: &str) -> Option<&'a [u8]> { elf_section_generic::(elf, name) } /// Extract the section with name `name` from the ELF32 image `elf`. - #[expect(dead_code)] - pub(super) fn elf32_section<'a>(elf: &'a [u8], name: &str) -> Option<&'a [u8]> { + fn elf32_section<'a>(elf: &'a [u8], name: &str) -> Option<&'a [u8]> { elf_section_generic::(elf, name) } + + /// Automatically detects ELF32 vs ELF64 based on the ELF header. + pub(super) fn elf_section<'a>(elf: &'a [u8], name: &str) -> Option<&'a [u8]> { + // ELF identification: a 4-byte magic followed by a class byte (32- vs 64-bit). + const ELFMAG: &[u8] = b"\x7fELF"; + const SELFMAG: usize = ELFMAG.len(); + const EI_CLASS: usize = 4; + const ELFCLASS32: u8 = 1; + const ELFCLASS64: u8 = 2; + + if elf.get(0..SELFMAG) != Some(ELFMAG) { + return None; + } + + match *elf.get(EI_CLASS)? { + ELFCLASS32 => elf32_section(elf, name), + ELFCLASS64 => elf64_section(elf, name), + _ => None, + } + } } diff --git a/drivers/gpu/nova-core/firmware/gsp.rs b/drivers/gpu/nova-core/firmware/gsp.rs index e576bc8a9b1cd..99a302bae5676 100644 --- a/drivers/gpu/nova-core/firmware/gsp.rs +++ b/drivers/gpu/nova-core/firmware/gsp.rs @@ -88,7 +88,7 @@ impl GspFirmware { pin_init::pin_init_scope(move || { let firmware = super::request_firmware(dev, chipset, "gsp", ver)?; - let fw_section = elf::elf64_section(firmware.data(), ".fwimage").ok_or(EINVAL)?; + let fw_section = elf::elf_section(firmware.data(), ".fwimage").ok_or(EINVAL)?; let size = fw_section.len(); @@ -148,7 +148,7 @@ impl GspFirmware { signatures: { let sigs_section = Self::find_gsp_sigs_section(chipset); - elf::elf64_section(firmware.data(), sigs_section) + elf::elf_section(firmware.data(), sigs_section) .ok_or(EINVAL) .and_then(|data| Coherent::from_slice(dev, data, GFP_KERNEL))? },