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 let chip_name = &*chip_name; 30 31 let request = |name_| { 32 CString::try_from_fmt(fmt!("nvidia/{chip_name}/gsp/{name_}-{ver}.bin")) 33 .and_then(|path| firmware::Firmware::request(&path, dev)) 34 }; 35 36 Ok(Firmware { 37 booter_load: request("booter_load")?, 38 booter_unload: request("booter_unload")?, 39 bootloader: request("bootloader")?, 40 gsp: request("gsp")?, 41 }) 42 } 43 } 44 45 pub(crate) struct ModInfoBuilder<const N: usize>(firmware::ModInfoBuilder<N>); 46 47 impl<const N: usize> ModInfoBuilder<N> { 48 const fn make_entry_file(self, chipset: &str, fw: &str) -> Self { 49 ModInfoBuilder( 50 self.0 51 .new_entry() 52 .push("nvidia/") 53 .push(chipset) 54 .push("/gsp/") 55 .push(fw) 56 .push("-") 57 .push(FIRMWARE_VERSION) 58 .push(".bin"), 59 ) 60 } 61 62 const fn make_entry_chipset(self, chipset: &str) -> Self { 63 self.make_entry_file(chipset, "booter_load") 64 .make_entry_file(chipset, "booter_unload") 65 .make_entry_file(chipset, "bootloader") 66 .make_entry_file(chipset, "gsp") 67 } 68 69 pub(crate) const fn create( 70 module_name: &'static kernel::str::CStr, 71 ) -> firmware::ModInfoBuilder<N> { 72 let mut this = Self(firmware::ModInfoBuilder::new(module_name)); 73 let mut i = 0; 74 75 while i < gpu::Chipset::NAMES.len() { 76 this = this.make_entry_chipset(gpu::Chipset::NAMES[i]); 77 i += 1; 78 } 79 80 this.0 81 } 82 } 83