falcon.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. // SPDX-License-Identifier: GPL-2.0
  2. //! Falcon microprocessor base support
  3. use core::ops::Deref;
  4. use hal::FalconHal;
  5. use kernel::{
  6. device,
  7. dma::{
  8. DmaAddress,
  9. DmaMask, //
  10. },
  11. io::poll::read_poll_timeout,
  12. prelude::*,
  13. sync::aref::ARef,
  14. time::{
  15. Delta, //
  16. },
  17. };
  18. use crate::{
  19. dma::DmaObject,
  20. driver::Bar0,
  21. falcon::hal::LoadMethod,
  22. gpu::Chipset,
  23. num::{
  24. FromSafeCast,
  25. IntoSafeCast, //
  26. },
  27. regs,
  28. regs::macros::RegisterBase, //
  29. };
  30. pub(crate) mod gsp;
  31. mod hal;
  32. pub(crate) mod sec2;
  33. // TODO[FPRI]: Replace with `ToPrimitive`.
  34. macro_rules! impl_from_enum_to_u8 {
  35. ($enum_type:ty) => {
  36. impl From<$enum_type> for u8 {
  37. fn from(value: $enum_type) -> Self {
  38. value as u8
  39. }
  40. }
  41. };
  42. }
  43. /// Revision number of a falcon core, used in the [`crate::regs::NV_PFALCON_FALCON_HWCFG1`]
  44. /// register.
  45. #[repr(u8)]
  46. #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
  47. pub(crate) enum FalconCoreRev {
  48. #[default]
  49. Rev1 = 1,
  50. Rev2 = 2,
  51. Rev3 = 3,
  52. Rev4 = 4,
  53. Rev5 = 5,
  54. Rev6 = 6,
  55. Rev7 = 7,
  56. }
  57. impl_from_enum_to_u8!(FalconCoreRev);
  58. // TODO[FPRI]: replace with `FromPrimitive`.
  59. impl TryFrom<u8> for FalconCoreRev {
  60. type Error = Error;
  61. fn try_from(value: u8) -> Result<Self> {
  62. use FalconCoreRev::*;
  63. let rev = match value {
  64. 1 => Rev1,
  65. 2 => Rev2,
  66. 3 => Rev3,
  67. 4 => Rev4,
  68. 5 => Rev5,
  69. 6 => Rev6,
  70. 7 => Rev7,
  71. _ => return Err(EINVAL),
  72. };
  73. Ok(rev)
  74. }
  75. }
  76. /// Revision subversion number of a falcon core, used in the
  77. /// [`crate::regs::NV_PFALCON_FALCON_HWCFG1`] register.
  78. #[repr(u8)]
  79. #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
  80. pub(crate) enum FalconCoreRevSubversion {
  81. #[default]
  82. Subversion0 = 0,
  83. Subversion1 = 1,
  84. Subversion2 = 2,
  85. Subversion3 = 3,
  86. }
  87. impl_from_enum_to_u8!(FalconCoreRevSubversion);
  88. // TODO[FPRI]: replace with `FromPrimitive`.
  89. impl TryFrom<u8> for FalconCoreRevSubversion {
  90. type Error = Error;
  91. fn try_from(value: u8) -> Result<Self> {
  92. use FalconCoreRevSubversion::*;
  93. let sub_version = match value & 0b11 {
  94. 0 => Subversion0,
  95. 1 => Subversion1,
  96. 2 => Subversion2,
  97. 3 => Subversion3,
  98. _ => return Err(EINVAL),
  99. };
  100. Ok(sub_version)
  101. }
  102. }
  103. /// Security model of a falcon core, used in the [`crate::regs::NV_PFALCON_FALCON_HWCFG1`]
  104. /// register.
  105. #[repr(u8)]
  106. #[derive(Debug, Default, Copy, Clone)]
  107. /// Security mode of the Falcon microprocessor.
  108. ///
  109. /// See `falcon.rst` for more details.
  110. pub(crate) enum FalconSecurityModel {
  111. /// Non-Secure: runs unsigned code without privileges.
  112. #[default]
  113. None = 0,
  114. /// Light-Secured (LS): Runs signed code with some privileges.
  115. /// Entry into this mode is only possible from 'Heavy-secure' mode, which verifies the code's
  116. /// signature.
  117. ///
  118. /// Also known as Low-Secure, Privilege Level 2 or PL2.
  119. Light = 2,
  120. /// Heavy-Secured (HS): Runs signed code with full privileges.
  121. /// The code's signature is verified by the Falcon Boot ROM (BROM).
  122. ///
  123. /// Also known as High-Secure, Privilege Level 3 or PL3.
  124. Heavy = 3,
  125. }
  126. impl_from_enum_to_u8!(FalconSecurityModel);
  127. // TODO[FPRI]: replace with `FromPrimitive`.
  128. impl TryFrom<u8> for FalconSecurityModel {
  129. type Error = Error;
  130. fn try_from(value: u8) -> Result<Self> {
  131. use FalconSecurityModel::*;
  132. let sec_model = match value {
  133. 0 => None,
  134. 2 => Light,
  135. 3 => Heavy,
  136. _ => return Err(EINVAL),
  137. };
  138. Ok(sec_model)
  139. }
  140. }
  141. /// Signing algorithm for a given firmware, used in the [`crate::regs::NV_PFALCON2_FALCON_MOD_SEL`]
  142. /// register. It is passed to the Falcon Boot ROM (BROM) as a parameter.
  143. #[repr(u8)]
  144. #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
  145. pub(crate) enum FalconModSelAlgo {
  146. /// AES.
  147. #[expect(dead_code)]
  148. Aes = 0,
  149. /// RSA3K.
  150. #[default]
  151. Rsa3k = 1,
  152. }
  153. impl_from_enum_to_u8!(FalconModSelAlgo);
  154. // TODO[FPRI]: replace with `FromPrimitive`.
  155. impl TryFrom<u8> for FalconModSelAlgo {
  156. type Error = Error;
  157. fn try_from(value: u8) -> Result<Self> {
  158. match value {
  159. 1 => Ok(FalconModSelAlgo::Rsa3k),
  160. _ => Err(EINVAL),
  161. }
  162. }
  163. }
  164. /// Valid values for the `size` field of the [`crate::regs::NV_PFALCON_FALCON_DMATRFCMD`] register.
  165. #[repr(u8)]
  166. #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
  167. pub(crate) enum DmaTrfCmdSize {
  168. /// 256 bytes transfer.
  169. #[default]
  170. Size256B = 0x6,
  171. }
  172. impl_from_enum_to_u8!(DmaTrfCmdSize);
  173. // TODO[FPRI]: replace with `FromPrimitive`.
  174. impl TryFrom<u8> for DmaTrfCmdSize {
  175. type Error = Error;
  176. fn try_from(value: u8) -> Result<Self> {
  177. match value {
  178. 0x6 => Ok(Self::Size256B),
  179. _ => Err(EINVAL),
  180. }
  181. }
  182. }
  183. /// Currently active core on a dual falcon/riscv (Peregrine) controller.
  184. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
  185. pub(crate) enum PeregrineCoreSelect {
  186. /// Falcon core is active.
  187. #[default]
  188. Falcon = 0,
  189. /// RISC-V core is active.
  190. Riscv = 1,
  191. }
  192. impl From<bool> for PeregrineCoreSelect {
  193. fn from(value: bool) -> Self {
  194. match value {
  195. false => PeregrineCoreSelect::Falcon,
  196. true => PeregrineCoreSelect::Riscv,
  197. }
  198. }
  199. }
  200. impl From<PeregrineCoreSelect> for bool {
  201. fn from(value: PeregrineCoreSelect) -> Self {
  202. match value {
  203. PeregrineCoreSelect::Falcon => false,
  204. PeregrineCoreSelect::Riscv => true,
  205. }
  206. }
  207. }
  208. /// Different types of memory present in a falcon core.
  209. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  210. pub(crate) enum FalconMem {
  211. /// Secure Instruction Memory.
  212. ImemSecure,
  213. /// Non-Secure Instruction Memory.
  214. #[expect(unused)]
  215. ImemNonSecure,
  216. /// Data Memory.
  217. Dmem,
  218. }
  219. /// Defines the Framebuffer Interface (FBIF) aperture type.
  220. /// This determines the memory type for external memory access during a DMA transfer, which is
  221. /// performed by the Falcon's Framebuffer DMA (FBDMA) engine. See falcon.rst for more details.
  222. #[derive(Debug, Clone, Default)]
  223. pub(crate) enum FalconFbifTarget {
  224. /// VRAM.
  225. #[default]
  226. /// Local Framebuffer (GPU's VRAM memory).
  227. LocalFb = 0,
  228. /// Coherent system memory (System DRAM).
  229. CoherentSysmem = 1,
  230. /// Non-coherent system memory (System DRAM).
  231. NoncoherentSysmem = 2,
  232. }
  233. impl_from_enum_to_u8!(FalconFbifTarget);
  234. // TODO[FPRI]: replace with `FromPrimitive`.
  235. impl TryFrom<u8> for FalconFbifTarget {
  236. type Error = Error;
  237. fn try_from(value: u8) -> Result<Self> {
  238. let res = match value {
  239. 0 => Self::LocalFb,
  240. 1 => Self::CoherentSysmem,
  241. 2 => Self::NoncoherentSysmem,
  242. _ => return Err(EINVAL),
  243. };
  244. Ok(res)
  245. }
  246. }
  247. /// Type of memory addresses to use.
  248. #[derive(Debug, Clone, Default)]
  249. pub(crate) enum FalconFbifMemType {
  250. /// Virtual memory addresses.
  251. #[default]
  252. Virtual = 0,
  253. /// Physical memory addresses.
  254. Physical = 1,
  255. }
  256. /// Conversion from a single-bit register field.
  257. impl From<bool> for FalconFbifMemType {
  258. fn from(value: bool) -> Self {
  259. match value {
  260. false => Self::Virtual,
  261. true => Self::Physical,
  262. }
  263. }
  264. }
  265. impl From<FalconFbifMemType> for bool {
  266. fn from(value: FalconFbifMemType) -> Self {
  267. match value {
  268. FalconFbifMemType::Virtual => false,
  269. FalconFbifMemType::Physical => true,
  270. }
  271. }
  272. }
  273. /// Type used to represent the `PFALCON` registers address base for a given falcon engine.
  274. pub(crate) struct PFalconBase(());
  275. /// Type used to represent the `PFALCON2` registers address base for a given falcon engine.
  276. pub(crate) struct PFalcon2Base(());
  277. /// Trait defining the parameters of a given Falcon engine.
  278. ///
  279. /// Each engine provides one base for `PFALCON` and `PFALCON2` registers. The `ID` constant is used
  280. /// to identify a given Falcon instance with register I/O methods.
  281. pub(crate) trait FalconEngine:
  282. Send + Sync + RegisterBase<PFalconBase> + RegisterBase<PFalcon2Base> + Sized
  283. {
  284. /// Singleton of the engine, used to identify it with register I/O methods.
  285. const ID: Self;
  286. }
  287. /// Represents a portion of the firmware to be loaded into a particular memory (e.g. IMEM or DMEM).
  288. #[derive(Debug, Clone)]
  289. pub(crate) struct FalconLoadTarget {
  290. /// Offset from the start of the source object to copy from.
  291. pub(crate) src_start: u32,
  292. /// Offset from the start of the destination memory to copy into.
  293. pub(crate) dst_start: u32,
  294. /// Number of bytes to copy.
  295. pub(crate) len: u32,
  296. }
  297. /// Parameters for the falcon boot ROM.
  298. #[derive(Debug, Clone)]
  299. pub(crate) struct FalconBromParams {
  300. /// Offset in `DMEM`` of the firmware's signature.
  301. pub(crate) pkc_data_offset: u32,
  302. /// Mask of engines valid for this firmware.
  303. pub(crate) engine_id_mask: u16,
  304. /// ID of the ucode used to infer a fuse register to validate the signature.
  305. pub(crate) ucode_id: u8,
  306. }
  307. /// Trait for providing load parameters of falcon firmwares.
  308. pub(crate) trait FalconLoadParams {
  309. /// Returns the load parameters for Secure `IMEM`.
  310. fn imem_sec_load_params(&self) -> FalconLoadTarget;
  311. /// Returns the load parameters for Non-Secure `IMEM`,
  312. /// used only on Turing and GA100.
  313. fn imem_ns_load_params(&self) -> Option<FalconLoadTarget>;
  314. /// Returns the load parameters for `DMEM`.
  315. fn dmem_load_params(&self) -> FalconLoadTarget;
  316. /// Returns the parameters to write into the BROM registers.
  317. fn brom_params(&self) -> FalconBromParams;
  318. /// Returns the start address of the firmware.
  319. fn boot_addr(&self) -> u32;
  320. }
  321. /// Trait for a falcon firmware.
  322. ///
  323. /// A falcon firmware can be loaded on a given engine, and is presented in the form of a DMA
  324. /// object.
  325. pub(crate) trait FalconFirmware: FalconLoadParams + Deref<Target = DmaObject> {
  326. /// Engine on which this firmware is to be loaded.
  327. type Target: FalconEngine;
  328. }
  329. /// Contains the base parameters common to all Falcon instances.
  330. pub(crate) struct Falcon<E: FalconEngine> {
  331. hal: KBox<dyn FalconHal<E>>,
  332. dev: ARef<device::Device>,
  333. }
  334. impl<E: FalconEngine + 'static> Falcon<E> {
  335. /// Create a new falcon instance.
  336. pub(crate) fn new(dev: &device::Device, chipset: Chipset) -> Result<Self> {
  337. Ok(Self {
  338. hal: hal::falcon_hal(chipset)?,
  339. dev: dev.into(),
  340. })
  341. }
  342. /// Resets DMA-related registers.
  343. pub(crate) fn dma_reset(&self, bar: &Bar0) {
  344. regs::NV_PFALCON_FBIF_CTL::update(bar, &E::ID, |v| v.set_allow_phys_no_ctx(true));
  345. regs::NV_PFALCON_FALCON_DMACTL::default().write(bar, &E::ID);
  346. }
  347. /// Reset the controller, select the falcon core, and wait for memory scrubbing to complete.
  348. pub(crate) fn reset(&self, bar: &Bar0) -> Result {
  349. self.hal.reset_eng(bar)?;
  350. self.hal.select_core(self, bar)?;
  351. self.hal.reset_wait_mem_scrubbing(bar)?;
  352. regs::NV_PFALCON_FALCON_RM::default()
  353. .set_value(regs::NV_PMC_BOOT_0::read(bar).into())
  354. .write(bar, &E::ID);
  355. Ok(())
  356. }
  357. /// Perform a DMA write according to `load_offsets` from `dma_handle` into the falcon's
  358. /// `target_mem`.
  359. ///
  360. /// `sec` is set if the loaded firmware is expected to run in secure mode.
  361. fn dma_wr<F: FalconFirmware<Target = E>>(
  362. &self,
  363. bar: &Bar0,
  364. fw: &F,
  365. target_mem: FalconMem,
  366. load_offsets: FalconLoadTarget,
  367. ) -> Result {
  368. const DMA_LEN: u32 = 256;
  369. // For IMEM, we want to use the start offset as a virtual address tag for each page, since
  370. // code addresses in the firmware (and the boot vector) are virtual.
  371. //
  372. // For DMEM we can fold the start offset into the DMA handle.
  373. let (src_start, dma_start) = match target_mem {
  374. FalconMem::ImemSecure | FalconMem::ImemNonSecure => {
  375. (load_offsets.src_start, fw.dma_handle())
  376. }
  377. FalconMem::Dmem => (
  378. 0,
  379. fw.dma_handle_with_offset(load_offsets.src_start.into_safe_cast())?,
  380. ),
  381. };
  382. if dma_start % DmaAddress::from(DMA_LEN) > 0 {
  383. dev_err!(
  384. self.dev,
  385. "DMA transfer start addresses must be a multiple of {}\n",
  386. DMA_LEN
  387. );
  388. return Err(EINVAL);
  389. }
  390. // The DMATRFBASE/1 register pair only supports a 49-bit address.
  391. if dma_start > DmaMask::new::<49>().value() {
  392. dev_err!(self.dev, "DMA address {:#x} exceeds 49 bits\n", dma_start);
  393. return Err(ERANGE);
  394. }
  395. // DMA transfers can only be done in units of 256 bytes. Compute how many such transfers we
  396. // need to perform.
  397. let num_transfers = load_offsets.len.div_ceil(DMA_LEN);
  398. // Check that the area we are about to transfer is within the bounds of the DMA object.
  399. // Upper limit of transfer is `(num_transfers * DMA_LEN) + load_offsets.src_start`.
  400. match num_transfers
  401. .checked_mul(DMA_LEN)
  402. .and_then(|size| size.checked_add(load_offsets.src_start))
  403. {
  404. None => {
  405. dev_err!(self.dev, "DMA transfer length overflow\n");
  406. return Err(EOVERFLOW);
  407. }
  408. Some(upper_bound) if usize::from_safe_cast(upper_bound) > fw.size() => {
  409. dev_err!(self.dev, "DMA transfer goes beyond range of DMA object\n");
  410. return Err(EINVAL);
  411. }
  412. Some(_) => (),
  413. };
  414. // Set up the base source DMA address.
  415. regs::NV_PFALCON_FALCON_DMATRFBASE::default()
  416. // CAST: `as u32` is used on purpose since we do want to strip the upper bits, which
  417. // will be written to `NV_PFALCON_FALCON_DMATRFBASE1`.
  418. .set_base((dma_start >> 8) as u32)
  419. .write(bar, &E::ID);
  420. regs::NV_PFALCON_FALCON_DMATRFBASE1::default()
  421. // CAST: `as u16` is used on purpose since the remaining bits are guaranteed to fit
  422. // within a `u16`.
  423. .set_base((dma_start >> 40) as u16)
  424. .write(bar, &E::ID);
  425. let cmd = regs::NV_PFALCON_FALCON_DMATRFCMD::default()
  426. .set_size(DmaTrfCmdSize::Size256B)
  427. .with_falcon_mem(target_mem);
  428. for pos in (0..num_transfers).map(|i| i * DMA_LEN) {
  429. // Perform a transfer of size `DMA_LEN`.
  430. regs::NV_PFALCON_FALCON_DMATRFMOFFS::default()
  431. .set_offs(load_offsets.dst_start + pos)
  432. .write(bar, &E::ID);
  433. regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default()
  434. .set_offs(src_start + pos)
  435. .write(bar, &E::ID);
  436. cmd.write(bar, &E::ID);
  437. // Wait for the transfer to complete.
  438. // TIMEOUT: arbitrarily large value, no DMA transfer to the falcon's small memories
  439. // should ever take that long.
  440. read_poll_timeout(
  441. || Ok(regs::NV_PFALCON_FALCON_DMATRFCMD::read(bar, &E::ID)),
  442. |r| r.idle(),
  443. Delta::ZERO,
  444. Delta::from_secs(2),
  445. )?;
  446. }
  447. Ok(())
  448. }
  449. /// Perform a DMA load into `IMEM` and `DMEM` of `fw`, and prepare the falcon to run it.
  450. fn dma_load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F) -> Result {
  451. // The Non-Secure section only exists on firmware used by Turing and GA100, and
  452. // those platforms do not use DMA.
  453. if fw.imem_ns_load_params().is_some() {
  454. debug_assert!(false);
  455. return Err(EINVAL);
  456. }
  457. self.dma_reset(bar);
  458. regs::NV_PFALCON_FBIF_TRANSCFG::update(bar, &E::ID, 0, |v| {
  459. v.set_target(FalconFbifTarget::CoherentSysmem)
  460. .set_mem_type(FalconFbifMemType::Physical)
  461. });
  462. self.dma_wr(bar, fw, FalconMem::ImemSecure, fw.imem_sec_load_params())?;
  463. self.dma_wr(bar, fw, FalconMem::Dmem, fw.dmem_load_params())?;
  464. self.hal.program_brom(self, bar, &fw.brom_params())?;
  465. // Set `BootVec` to start of non-secure code.
  466. regs::NV_PFALCON_FALCON_BOOTVEC::default()
  467. .set_value(fw.boot_addr())
  468. .write(bar, &E::ID);
  469. Ok(())
  470. }
  471. /// Wait until the falcon CPU is halted.
  472. pub(crate) fn wait_till_halted(&self, bar: &Bar0) -> Result<()> {
  473. // TIMEOUT: arbitrarily large value, firmwares should complete in less than 2 seconds.
  474. read_poll_timeout(
  475. || Ok(regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID)),
  476. |r| r.halted(),
  477. Delta::ZERO,
  478. Delta::from_secs(2),
  479. )?;
  480. Ok(())
  481. }
  482. /// Start the falcon CPU.
  483. pub(crate) fn start(&self, bar: &Bar0) -> Result<()> {
  484. match regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID).alias_en() {
  485. true => regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::default()
  486. .set_startcpu(true)
  487. .write(bar, &E::ID),
  488. false => regs::NV_PFALCON_FALCON_CPUCTL::default()
  489. .set_startcpu(true)
  490. .write(bar, &E::ID),
  491. }
  492. Ok(())
  493. }
  494. /// Writes values to the mailbox registers if provided.
  495. pub(crate) fn write_mailboxes(&self, bar: &Bar0, mbox0: Option<u32>, mbox1: Option<u32>) {
  496. if let Some(mbox0) = mbox0 {
  497. regs::NV_PFALCON_FALCON_MAILBOX0::default()
  498. .set_value(mbox0)
  499. .write(bar, &E::ID);
  500. }
  501. if let Some(mbox1) = mbox1 {
  502. regs::NV_PFALCON_FALCON_MAILBOX1::default()
  503. .set_value(mbox1)
  504. .write(bar, &E::ID);
  505. }
  506. }
  507. /// Reads the value from `mbox0` register.
  508. pub(crate) fn read_mailbox0(&self, bar: &Bar0) -> u32 {
  509. regs::NV_PFALCON_FALCON_MAILBOX0::read(bar, &E::ID).value()
  510. }
  511. /// Reads the value from `mbox1` register.
  512. pub(crate) fn read_mailbox1(&self, bar: &Bar0) -> u32 {
  513. regs::NV_PFALCON_FALCON_MAILBOX1::read(bar, &E::ID).value()
  514. }
  515. /// Reads values from both mailbox registers.
  516. pub(crate) fn read_mailboxes(&self, bar: &Bar0) -> (u32, u32) {
  517. let mbox0 = self.read_mailbox0(bar);
  518. let mbox1 = self.read_mailbox1(bar);
  519. (mbox0, mbox1)
  520. }
  521. /// Start running the loaded firmware.
  522. ///
  523. /// `mbox0` and `mbox1` are optional parameters to write into the `MBOX0` and `MBOX1` registers
  524. /// prior to running.
  525. ///
  526. /// Wait up to two seconds for the firmware to complete, and return its exit status read from
  527. /// the `MBOX0` and `MBOX1` registers.
  528. pub(crate) fn boot(
  529. &self,
  530. bar: &Bar0,
  531. mbox0: Option<u32>,
  532. mbox1: Option<u32>,
  533. ) -> Result<(u32, u32)> {
  534. self.write_mailboxes(bar, mbox0, mbox1);
  535. self.start(bar)?;
  536. self.wait_till_halted(bar)?;
  537. Ok(self.read_mailboxes(bar))
  538. }
  539. /// Returns the fused version of the signature to use in order to run a HS firmware on this
  540. /// falcon instance. `engine_id_mask` and `ucode_id` are obtained from the firmware header.
  541. pub(crate) fn signature_reg_fuse_version(
  542. &self,
  543. bar: &Bar0,
  544. engine_id_mask: u16,
  545. ucode_id: u8,
  546. ) -> Result<u32> {
  547. self.hal
  548. .signature_reg_fuse_version(self, bar, engine_id_mask, ucode_id)
  549. }
  550. /// Check if the RISC-V core is active.
  551. ///
  552. /// Returns `true` if the RISC-V core is active, `false` otherwise.
  553. pub(crate) fn is_riscv_active(&self, bar: &Bar0) -> bool {
  554. self.hal.is_riscv_active(bar)
  555. }
  556. // Load a firmware image into Falcon memory
  557. pub(crate) fn load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F) -> Result {
  558. match self.hal.load_method() {
  559. LoadMethod::Dma => self.dma_load(bar, fw),
  560. LoadMethod::Pio => Err(ENOTSUPP),
  561. }
  562. }
  563. /// Write the application version to the OS register.
  564. pub(crate) fn write_os_version(&self, bar: &Bar0, app_version: u32) {
  565. regs::NV_PFALCON_FALCON_OS::default()
  566. .set_value(app_version)
  567. .write(bar, &E::ID);
  568. }
  569. }