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