| // 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<Firmware> { |
| 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<const N: usize>(firmware::ModInfoBuilder<N>); |
| |
| impl<const N: usize> ModInfoBuilder<N> { |
| 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<N> { |
| 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 |
| } |
| } |