1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Contains structures and functions dedicated to the parsing, building and patching of firmwares 4 //! to be loaded into a given execution unit. 5 6 use kernel::device; 7 use kernel::firmware; 8 use kernel::prelude::*; 9 use kernel::str::CString; 10 11 use crate::gpu; 12 use crate::gpu::Chipset; 13 14 pub(crate) const FIRMWARE_VERSION: &str = "535.113.01"; 15 16 /// Structure encapsulating the firmware blobs required for the GPU to operate. 17 #[expect(dead_code)] 18 pub(crate) struct Firmware { 19 booter_load: firmware::Firmware, 20 booter_unload: firmware::Firmware, 21 bootloader: firmware::Firmware, 22 gsp: firmware::Firmware, 23 } 24 25 impl Firmware { 26 pub(crate) fn new(dev: &device::Device, chipset: Chipset, ver: &str) -> Result<Firmware> { 27 let mut chip_name = CString::try_from_fmt(fmt!("{}", chipset))?; 28 chip_name.make_ascii_lowercase(); 29 30 let request = |name_| { 31 CString::try_from_fmt(fmt!("nvidia/{}/gsp/{}-{}.bin", &*chip_name, name_, ver)) 32 .and_then(|path| firmware::Firmware::request(&path, dev)) 33 }; 34 35 Ok(Firmware { 36 booter_load: request("booter_load")?, 37 booter_unload: request("booter_unload")?, 38 bootloader: request("bootloader")?, 39 gsp: request("gsp")?, 40 }) 41 } 42 } 43 44 pub(crate) struct ModInfoBuilder<const N: usize>(firmware::ModInfoBuilder<N>); 45 46 impl<const N: usize> ModInfoBuilder<N> { 47 const fn make_entry_file(self, chipset: &str, fw: &str) -> Self { 48 ModInfoBuilder( 49 self.0 50 .new_entry() 51 .push("nvidia/") 52 .push(chipset) 53 .push("/gsp/") 54 .push(fw) 55 .push("-") 56 .push(FIRMWARE_VERSION) 57 .push(".bin"), 58 ) 59 } 60 61 const fn make_entry_chipset(self, chipset: &str) -> Self { 62 self.make_entry_file(chipset, "booter_load") 63 .make_entry_file(chipset, "booter_unload") 64 .make_entry_file(chipset, "bootloader") 65 .make_entry_file(chipset, "gsp") 66 } 67 68 pub(crate) const fn create( 69 module_name: &'static kernel::str::CStr, 70 ) -> firmware::ModInfoBuilder<N> { 71 let mut this = Self(firmware::ModInfoBuilder::new(module_name)); 72 let mut i = 0; 73 74 while i < gpu::Chipset::NAMES.len() { 75 this = this.make_entry_chipset(gpu::Chipset::NAMES[i]); 76 i += 1; 77 } 78 79 this.0 80 } 81 } 82