xref: /linux/drivers/gpu/nova-core/firmware/riscv.rs (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Support for firmware binaries designed to run on a RISC-V core. Such firmwares files have a
4 //! dedicated header.
5 
6 use kernel::{
7     device,
8     dma::Coherent,
9     firmware::Firmware,
10     prelude::*, //
11 };
12 
13 use crate::firmware::tlv::Tlv;
14 
15 /// A parsed firmware for a RISC-V core, ready to be loaded and run.
16 pub(crate) struct RiscvFirmware {
17     /// Offset at which the code starts in the firmware image.
18     pub(crate) code_offset: u32,
19     /// Offset at which the data starts in the firmware image.
20     pub(crate) data_offset: u32,
21     /// Offset at which the manifest starts in the firmware image.
22     pub(crate) manifest_offset: u32,
23     /// Application version.
24     pub(crate) app_version: u32,
25     /// Device-mapped firmware image.
26     pub(crate) ucode: Coherent<[u8]>,
27 }
28 
29 impl RiscvFirmware {
30     /// Parses the RISC-V firmware image contained in `fw`.
31     pub(crate) fn new(dev: &device::Device<device::Bound>, fw: &Firmware) -> Result<Self> {
32         let tlv = Tlv::new(fw.data())?;
33         dev_dbg!(
34             dev,
35             "loaded gsp bootloader firmware v{}\n",
36             tlv.get_string(b"VERS")?
37         );
38 
39         let code_offset = tlv.get_u32(b"CDOF")?;
40         let data_offset = tlv.get_u32(b"DAOF")?;
41         let manifest_offset = tlv.get_u32(b"MFOF")?;
42         let app_version = tlv.get_u32(b"APPV")?;
43 
44         let ucode = Coherent::from_slice(dev, tlv.get_bytes(b"BLOB")?, GFP_KERNEL)?;
45 
46         Ok(Self {
47             ucode,
48             code_offset,
49             data_offset,
50             manifest_offset,
51             app_version,
52         })
53     }
54 }
55