// SPDX-License-Identifier: GPL-2.0 //! Contains structures and functions dedicated to the parsing, building and patching of firmwares //! to be loaded into a given execution unit. use kernel::device; use kernel::firmware; use kernel::prelude::*; use kernel::str::CString; use crate::gpu; use crate::gpu::Chipset; pub(crate) const FIRMWARE_VERSION: &str = "535.113.01"; /// Structure encapsulating the firmware blobs required for the GPU to operate. #[expect(dead_code)] pub(crate) struct Firmware { booter_load: firmware::Firmware, booter_unload: firmware::Firmware, bootloader: firmware::Firmware, gsp: firmware::Firmware, } impl Firmware { pub(crate) fn new(dev: &device::Device, chipset: Chipset, ver: &str) -> Result { let mut chip_name = CString::try_from_fmt(fmt!("{}", chipset))?; chip_name.make_ascii_lowercase(); let request = |name_| { CString::try_from_fmt(fmt!("nvidia/{}/gsp/{}-{}.bin", &*chip_name, name_, ver)) .and_then(|path| firmware::Firmware::request(&path, dev)) }; Ok(Firmware { booter_load: request("booter_load")?, booter_unload: request("booter_unload")?, bootloader: request("bootloader")?, gsp: request("gsp")?, }) } } pub(crate) struct ModInfoBuilder(firmware::ModInfoBuilder); impl ModInfoBuilder { const fn make_entry_file(self, chipset: &str, fw: &str) -> Self { ModInfoBuilder( self.0 .new_entry() .push("nvidia/") .push(chipset) .push("/gsp/") .push(fw) .push("-") .push(FIRMWARE_VERSION) .push(".bin"), ) } const fn make_entry_chipset(self, chipset: &str) -> Self { self.make_entry_file(chipset, "booter_load") .make_entry_file(chipset, "booter_unload") .make_entry_file(chipset, "bootloader") .make_entry_file(chipset, "gsp") } pub(crate) const fn create( module_name: &'static kernel::str::CStr, ) -> firmware::ModInfoBuilder { let mut this = Self(firmware::ModInfoBuilder::new(module_name)); let mut i = 0; while i < gpu::Chipset::NAMES.len() { this = this.make_entry_chipset(gpu::Chipset::NAMES[i]); i += 1; } this.0 } }