File Index
Files and directories
Sign in
FILE

riscv.rs

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/nova-core/firmware/riscv.rs RUST
 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
 6use core::mem::size_of;
 7
 8use kernel::{
 9    device,
10    firmware::Firmware,
11    prelude::*,
12    transmute::FromBytes, //
13};
14
15use crate::{
16    dma::DmaObject,
17    firmware::BinFirmware,
18    num::FromSafeCast, //
19};
20
21/// Descriptor for microcode running on a RISC-V core.
22#[repr(C)]
23#[derive(Debug)]
24struct RmRiscvUCodeDesc {
25    version: u32,
26    bootloader_offset: u32,
27    bootloader_size: u32,
28    bootloader_param_offset: u32,
29    bootloader_param_size: u32,
30    riscv_elf_offset: u32,
31    riscv_elf_size: u32,
32    app_version: u32,
33    manifest_offset: u32,
34    manifest_size: u32,
35    monitor_data_offset: u32,
36    monitor_data_size: u32,
37    monitor_code_offset: u32,
38    monitor_code_size: u32,
39}
40
41// SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability.
42unsafe impl FromBytes for RmRiscvUCodeDesc {}
43
44impl RmRiscvUCodeDesc {
45    /// Interprets the header of `bin_fw` as a [`RmRiscvUCodeDesc`] and returns it.
46    ///
47    /// Fails if the header pointed at by `bin_fw` is not within the bounds of the firmware image.
48    fn new(bin_fw: &BinFirmware<'_>) -> Result<Self> {
49        let offset = usize::from_safe_cast(bin_fw.hdr.header_offset);
50
51        bin_fw
52            .fw
53            .get(offset..offset + size_of::<Self>())
54            .and_then(Self::from_bytes_copy)
55            .ok_or(EINVAL)
56    }
57}
58
59/// A parsed firmware for a RISC-V core, ready to be loaded and run.
60pub(crate) struct RiscvFirmware {
61    /// Offset at which the code starts in the firmware image.
62    pub(crate) code_offset: u32,
63    /// Offset at which the data starts in the firmware image.
64    pub(crate) data_offset: u32,
65    /// Offset at which the manifest starts in the firmware image.
66    pub(crate) manifest_offset: u32,
67    /// Application version.
68    pub(crate) app_version: u32,
69    /// Device-mapped firmware image.
70    pub(crate) ucode: DmaObject,
71}
72
73impl RiscvFirmware {
74    /// Parses the RISC-V firmware image contained in `fw`.
75    pub(crate) fn new(dev: &device::Device<device::Bound>, fw: &Firmware) -> Result<Self> {
76        let bin_fw = BinFirmware::new(fw)?;
77
78        let riscv_desc = RmRiscvUCodeDesc::new(&bin_fw)?;
79
80        let ucode = {
81            let start = usize::from_safe_cast(bin_fw.hdr.data_offset);
82            let len = usize::from_safe_cast(bin_fw.hdr.data_size);
83
84            DmaObject::from_data(dev, fw.data().get(start..start + len).ok_or(EINVAL)?)?
85        };
86
87        Ok(Self {
88            ucode,
89            code_offset: riscv_desc.monitor_code_offset,
90            data_offset: riscv_desc.monitor_data_offset,
91            manifest_offset: riscv_desc.manifest_offset,
92            app_version: riscv_desc.app_version,
93        })
94    }
95}
~/ Read-only file preview.