Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19-rc5 95 lines 2.9 kB view raw
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}