earlgrey_cw310/
main.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Board file for LowRISC OpenTitan RISC-V development platform.
6//!
7//! - <https://opentitan.org/>
8
9#![no_std]
10// Disable this attribute when documenting, as a workaround for
11// https://github.com/rust-lang/rust/issues/62184.
12#![cfg_attr(not(doc), no_main)]
13#![feature(custom_test_frameworks)]
14#![test_runner(test_runner)]
15#![reexport_test_harness_main = "test_main"]
16
17use crate::hil::symmetric_encryption::AES128_BLOCK_SIZE;
18use crate::otbn::OtbnComponent;
19use crate::pinmux_layout::BoardPinmuxLayout;
20use capsules_aes_gcm::aes_gcm;
21use capsules_core::virtualizers::virtual_aes_ccm;
22use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
23use core::ptr::{addr_of, addr_of_mut};
24use earlgrey::chip::EarlGreyDefaultPeripherals;
25use earlgrey::chip_config::EarlGreyConfig;
26use earlgrey::pinmux_config::EarlGreyPinmuxConfig;
27use kernel::capabilities;
28use kernel::component::Component;
29use kernel::hil;
30use kernel::hil::entropy::Entropy32;
31use kernel::hil::hasher::Hasher;
32use kernel::hil::i2c::I2CMaster;
33use kernel::hil::led::LedHigh;
34use kernel::hil::rng::Rng;
35use kernel::hil::symmetric_encryption::AES128;
36use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
37use kernel::platform::{KernelResources, SyscallDriverLookup, TbfHeaderFilterDefaultAllow};
38use kernel::scheduler::priority::PrioritySched;
39use kernel::utilities::registers::interfaces::ReadWriteable;
40use kernel::{create_capability, debug, static_init};
41use lowrisc::flash_ctrl::FlashMPConfig;
42use rv32i::csr;
43
44pub mod io;
45mod otbn;
46pub mod pinmux_layout;
47#[cfg(test)]
48mod tests;
49
50/// Chip configuration.
51///
52/// The `earlgrey` chip crate supports multiple targets with slightly different
53/// configurations, which are encoded through implementations of the
54/// `earlgrey::chip_config::EarlGreyConfig` trait. This type provides different
55/// implementations of the `EarlGreyConfig` trait, depending on Cargo's
56/// conditional compilation feature flags. If no feature is selected,
57/// compilation will error.
58pub enum ChipConfig {}
59
60#[cfg(feature = "fpga_cw310")]
61impl EarlGreyConfig for ChipConfig {
62    const NAME: &'static str = "fpga_cw310";
63
64    // Clock frequencies as of https://github.com/lowRISC/opentitan/pull/19479
65    const CPU_FREQ: u32 = 24_000_000;
66    const PERIPHERAL_FREQ: u32 = 6_000_000;
67    const AON_TIMER_FREQ: u32 = 250_000;
68    const UART_BAUDRATE: u32 = 115200;
69}
70
71#[cfg(feature = "sim_verilator")]
72impl EarlGreyConfig for ChipConfig {
73    const NAME: &'static str = "sim_verilator";
74
75    // Clock frequencies as of https://github.com/lowRISC/opentitan/pull/19368
76    const CPU_FREQ: u32 = 500_000;
77    const PERIPHERAL_FREQ: u32 = 125_000;
78    const AON_TIMER_FREQ: u32 = 125_000;
79    const UART_BAUDRATE: u32 = 7200;
80}
81
82// Whether to check for a proper ePMP handover configuration prior to ePMP
83// initialization:
84pub const EPMP_HANDOVER_CONFIG_CHECK: bool = false;
85
86// EarlGrey ePMP debug mode
87//
88// This type determines whether JTAG access shall be enabled. When JTAG access
89// is enabled, one less MPU region is available for use by userspace.
90//
91// Either
92// - `earlgrey::epmp::EPMPDebugEnable`, or
93// - `earlgrey::epmp::EPMPDebugDisable`.
94pub type EPMPDebugConfig = earlgrey::epmp::EPMPDebugEnable;
95
96// EarlGrey Chip type signature, including generic PMP argument and peripherals
97// type:
98pub type EarlGreyChip = earlgrey::chip::EarlGrey<
99    'static,
100    { <EPMPDebugConfig as earlgrey::epmp::EPMPDebugConfig>::TOR_USER_REGIONS },
101    EarlGreyDefaultPeripherals<'static, ChipConfig, BoardPinmuxLayout>,
102    ChipConfig,
103    BoardPinmuxLayout,
104    earlgrey::epmp::EarlGreyEPMP<{ EPMP_HANDOVER_CONFIG_CHECK }, EPMPDebugConfig>,
105>;
106
107const NUM_PROCS: usize = 4;
108
109//
110// Actual memory for holding the active process structures. Need an empty list
111// at least.
112static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; 4] = [None; NUM_PROCS];
113
114// Test access to the peripherals
115#[cfg(test)]
116static mut PERIPHERALS: Option<&'static EarlGreyDefaultPeripherals<ChipConfig, BoardPinmuxLayout>> =
117    None;
118// Test access to board
119#[cfg(test)]
120static mut BOARD: Option<&'static kernel::Kernel> = None;
121// Test access to platform
122#[cfg(test)]
123static mut PLATFORM: Option<&'static EarlGrey> = None;
124// Test access to main loop capability
125#[cfg(test)]
126static mut MAIN_CAP: Option<&dyn kernel::capabilities::MainLoopCapability> = None;
127// Test access to alarm
128static mut ALARM: Option<
129    &'static MuxAlarm<'static, earlgrey::timer::RvTimer<'static, ChipConfig>>,
130> = None;
131// Test access to TicKV
132static mut TICKV: Option<
133    &capsules_extra::tickv::TicKVSystem<
134        'static,
135        capsules_core::virtualizers::virtual_flash::FlashUser<
136            'static,
137            lowrisc::flash_ctrl::FlashCtrl<'static>,
138        >,
139        capsules_extra::sip_hash::SipHasher24<'static>,
140        2048,
141    >,
142> = None;
143// Test access to AES
144static mut AES: Option<
145    &aes_gcm::Aes128Gcm<
146        'static,
147        virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
148    >,
149> = None;
150// Test access to SipHash
151static mut SIPHASH: Option<&capsules_extra::sip_hash::SipHasher24<'static>> = None;
152// Test access to RSA
153static mut RSA_HARDWARE: Option<&lowrisc::rsa::OtbnRsa<'static>> = None;
154
155// Test access to a software SHA256
156#[cfg(test)]
157static mut SHA256SOFT: Option<&capsules_extra::sha256::Sha256Software<'static>> = None;
158
159static mut CHIP: Option<&'static EarlGreyChip> = None;
160static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
161    None;
162
163// How should the kernel respond when a process faults.
164const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
165    capsules_system::process_policies::PanicFaultPolicy {};
166
167/// Dummy buffer that causes the linker to reserve enough space for the stack.
168#[no_mangle]
169#[link_section = ".stack_buffer"]
170pub static mut STACK_MEMORY: [u8; 0x1400] = [0; 0x1400];
171
172/// A structure representing this platform that holds references to all
173/// capsules for this platform. We've included an alarm and console.
174struct EarlGrey {
175    led: &'static capsules_core::led::LedDriver<
176        'static,
177        LedHigh<'static, earlgrey::gpio::GpioPin<'static, earlgrey::pinmux::PadConfig>>,
178        8,
179    >,
180    gpio: &'static capsules_core::gpio::GPIO<
181        'static,
182        earlgrey::gpio::GpioPin<'static, earlgrey::pinmux::PadConfig>,
183    >,
184    console: &'static capsules_core::console::Console<'static>,
185    alarm: &'static capsules_core::alarm::AlarmDriver<
186        'static,
187        VirtualMuxAlarm<'static, earlgrey::timer::RvTimer<'static, ChipConfig>>,
188    >,
189    hmac: &'static capsules_extra::hmac::HmacDriver<'static, lowrisc::hmac::Hmac<'static>, 32>,
190    lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
191        'static,
192        capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
193    >,
194    i2c_master:
195        &'static capsules_core::i2c_master::I2CMasterDriver<'static, lowrisc::i2c::I2c<'static>>,
196    spi_controller: &'static capsules_core::spi_controller::Spi<
197        'static,
198        capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
199            'static,
200            lowrisc::spi_host::SpiHost<'static>,
201        >,
202    >,
203    rng: &'static capsules_core::rng::RngDriver<
204        'static,
205        capsules_core::rng::Entropy32ToRandom<'static, lowrisc::csrng::CsRng<'static>>,
206    >,
207    aes: &'static capsules_extra::symmetric_encryption::aes::AesDriver<
208        'static,
209        aes_gcm::Aes128Gcm<
210            'static,
211            virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
212        >,
213    >,
214    kv_driver: &'static capsules_extra::kv_driver::KVStoreDriver<
215        'static,
216        capsules_extra::virtual_kv::VirtualKVPermissions<
217            'static,
218            capsules_extra::kv_store_permissions::KVStorePermissions<
219                'static,
220                capsules_extra::tickv_kv_store::TicKVKVStore<
221                    'static,
222                    capsules_extra::tickv::TicKVSystem<
223                        'static,
224                        capsules_core::virtualizers::virtual_flash::FlashUser<
225                            'static,
226                            lowrisc::flash_ctrl::FlashCtrl<'static>,
227                        >,
228                        capsules_extra::sip_hash::SipHasher24<'static>,
229                        2048,
230                    >,
231                    [u8; 8],
232                >,
233            >,
234        >,
235    >,
236    syscall_filter: &'static TbfHeaderFilterDefaultAllow,
237    scheduler: &'static PrioritySched,
238    scheduler_timer: &'static VirtualSchedulerTimer<
239        VirtualMuxAlarm<'static, earlgrey::timer::RvTimer<'static, ChipConfig>>,
240    >,
241    watchdog: &'static lowrisc::aon_timer::AonTimer,
242}
243
244/// Mapping of integer syscalls to objects that implement syscalls.
245impl SyscallDriverLookup for EarlGrey {
246    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
247    where
248        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
249    {
250        match driver_num {
251            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
252            capsules_extra::hmac::DRIVER_NUM => f(Some(self.hmac)),
253            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
254            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
255            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
256            capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
257            capsules_core::i2c_master::DRIVER_NUM => f(Some(self.i2c_master)),
258            capsules_core::spi_controller::DRIVER_NUM => f(Some(self.spi_controller)),
259            capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
260            capsules_extra::symmetric_encryption::aes::DRIVER_NUM => f(Some(self.aes)),
261            capsules_extra::kv_driver::DRIVER_NUM => f(Some(self.kv_driver)),
262            _ => f(None),
263        }
264    }
265}
266
267impl KernelResources<EarlGreyChip> for EarlGrey {
268    type SyscallDriverLookup = Self;
269    type SyscallFilter = TbfHeaderFilterDefaultAllow;
270    type ProcessFault = ();
271    type Scheduler = PrioritySched;
272    type SchedulerTimer = VirtualSchedulerTimer<
273        VirtualMuxAlarm<'static, earlgrey::timer::RvTimer<'static, ChipConfig>>,
274    >;
275    type WatchDog = lowrisc::aon_timer::AonTimer;
276    type ContextSwitchCallback = ();
277
278    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
279        self
280    }
281    fn syscall_filter(&self) -> &Self::SyscallFilter {
282        self.syscall_filter
283    }
284    fn process_fault(&self) -> &Self::ProcessFault {
285        &()
286    }
287    fn scheduler(&self) -> &Self::Scheduler {
288        self.scheduler
289    }
290    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
291        self.scheduler_timer
292    }
293    fn watchdog(&self) -> &Self::WatchDog {
294        self.watchdog
295    }
296    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
297        &()
298    }
299}
300
301unsafe fn setup() -> (
302    &'static kernel::Kernel,
303    &'static EarlGrey,
304    &'static EarlGreyChip,
305    &'static EarlGreyDefaultPeripherals<'static, ChipConfig, BoardPinmuxLayout>,
306) {
307    // These symbols are defined in the linker script.
308    extern "C" {
309        /// Beginning of the ROM region containing app images.
310        static _sapps: u8;
311        /// End of the ROM region containing app images.
312        static _eapps: u8;
313        /// Beginning of the RAM region for app memory.
314        static mut _sappmem: u8;
315        /// End of the RAM region for app memory.
316        static _eappmem: u8;
317        /// The start of the kernel text (Included only for kernel PMP)
318        static _stext: u8;
319        /// The end of the kernel text (Included only for kernel PMP)
320        static _etext: u8;
321        /// The start of the kernel / app / storage flash (Included only for kernel PMP)
322        static _sflash: u8;
323        /// The end of the kernel / app / storage flash (Included only for kernel PMP)
324        static _eflash: u8;
325        /// The start of the kernel / app RAM (Included only for kernel PMP)
326        static _ssram: u8;
327        /// The end of the kernel / app RAM (Included only for kernel PMP)
328        static _esram: u8;
329        /// The start of the OpenTitan manifest
330        static _manifest: u8;
331    }
332
333    // Ibex-specific handler
334    earlgrey::chip::configure_trap_handler();
335
336    // Set up memory protection immediately after setting the trap handler, to
337    // ensure that much of the board initialization routine runs with ePMP
338    // protection.
339    let earlgrey_epmp = earlgrey::epmp::EarlGreyEPMP::new_debug(
340        earlgrey::epmp::FlashRegion(
341            rv32i::pmp::NAPOTRegionSpec::new(
342                core::ptr::addr_of!(_sflash),
343                core::ptr::addr_of!(_eflash) as usize - core::ptr::addr_of!(_sflash) as usize,
344            )
345            .unwrap(),
346        ),
347        earlgrey::epmp::RAMRegion(
348            rv32i::pmp::NAPOTRegionSpec::new(
349                core::ptr::addr_of!(_ssram),
350                core::ptr::addr_of!(_esram) as usize - core::ptr::addr_of!(_ssram) as usize,
351            )
352            .unwrap(),
353        ),
354        earlgrey::epmp::MMIORegion(
355            rv32i::pmp::NAPOTRegionSpec::new(
356                0x40000000 as *const u8, // start
357                0x10000000,              // size
358            )
359            .unwrap(),
360        ),
361        earlgrey::epmp::KernelTextRegion(
362            rv32i::pmp::TORRegionSpec::new(
363                core::ptr::addr_of!(_stext),
364                core::ptr::addr_of!(_etext),
365            )
366            .unwrap(),
367        ),
368        // RV Debug Manager memory region (required for JTAG debugging).
369        // This access can be disabled by changing the EarlGreyEPMP type
370        // parameter `EPMPDebugConfig` to `EPMPDebugDisable`, in which case
371        // this expects to be passed a unit (`()`) type.
372        earlgrey::epmp::RVDMRegion(
373            rv32i::pmp::NAPOTRegionSpec::new(
374                0x00010000 as *const u8, // start
375                0x00001000,              // size
376            )
377            .unwrap(),
378        ),
379    )
380    .unwrap();
381
382    // Configure board layout in pinmux
383    BoardPinmuxLayout::setup();
384
385    // initialize capabilities
386    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
387    let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
388
389    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
390
391    let peripherals = static_init!(
392        EarlGreyDefaultPeripherals<ChipConfig, BoardPinmuxLayout>,
393        EarlGreyDefaultPeripherals::new()
394    );
395    peripherals.init();
396
397    // Configure kernel debug gpios as early as possible
398    kernel::debug::assign_gpios(
399        Some(&peripherals.gpio_port[7]), // First LED
400        None,
401        None,
402    );
403
404    // Create a shared UART channel for the console and for kernel debug.
405    let uart_mux =
406        components::console::UartMuxComponent::new(&peripherals.uart0, ChipConfig::UART_BAUDRATE)
407            .finalize(components::uart_mux_component_static!());
408
409    // LEDs
410    // Start with half on and half off
411    let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
412        LedHigh<'static, earlgrey::gpio::GpioPin<earlgrey::pinmux::PadConfig>>,
413        LedHigh::new(&peripherals.gpio_port[8]),
414        LedHigh::new(&peripherals.gpio_port[9]),
415        LedHigh::new(&peripherals.gpio_port[10]),
416        LedHigh::new(&peripherals.gpio_port[11]),
417        LedHigh::new(&peripherals.gpio_port[12]),
418        LedHigh::new(&peripherals.gpio_port[13]),
419        LedHigh::new(&peripherals.gpio_port[14]),
420        LedHigh::new(&peripherals.gpio_port[15]),
421    ));
422
423    let gpio = components::gpio::GpioComponent::new(
424        board_kernel,
425        capsules_core::gpio::DRIVER_NUM,
426        components::gpio_component_helper!(
427            earlgrey::gpio::GpioPin<earlgrey::pinmux::PadConfig>,
428            0 => &peripherals.gpio_port[0],
429            1 => &peripherals.gpio_port[1],
430            2 => &peripherals.gpio_port[2],
431            3 => &peripherals.gpio_port[3],
432            4 => &peripherals.gpio_port[4],
433            5 => &peripherals.gpio_port[5],
434            6 => &peripherals.gpio_port[6],
435            7 => &peripherals.gpio_port[15]
436        ),
437    )
438    .finalize(components::gpio_component_static!(
439        earlgrey::gpio::GpioPin<earlgrey::pinmux::PadConfig>
440    ));
441
442    let hardware_alarm = static_init!(
443        earlgrey::timer::RvTimer<ChipConfig>,
444        earlgrey::timer::RvTimer::new()
445    );
446    hardware_alarm.setup();
447
448    // Create a shared virtualization mux layer on top of a single hardware
449    // alarm.
450    let mux_alarm = static_init!(
451        MuxAlarm<'static, earlgrey::timer::RvTimer<ChipConfig>>,
452        MuxAlarm::new(hardware_alarm)
453    );
454    hil::time::Alarm::set_alarm_client(hardware_alarm, mux_alarm);
455
456    ALARM = Some(mux_alarm);
457
458    // Alarm
459    let virtual_alarm_user = static_init!(
460        VirtualMuxAlarm<'static, earlgrey::timer::RvTimer<ChipConfig>>,
461        VirtualMuxAlarm::new(mux_alarm)
462    );
463    virtual_alarm_user.setup();
464
465    let scheduler_timer_virtual_alarm = static_init!(
466        VirtualMuxAlarm<'static, earlgrey::timer::RvTimer<ChipConfig>>,
467        VirtualMuxAlarm::new(mux_alarm)
468    );
469    scheduler_timer_virtual_alarm.setup();
470
471    let alarm = static_init!(
472        capsules_core::alarm::AlarmDriver<
473            'static,
474            VirtualMuxAlarm<'static, earlgrey::timer::RvTimer<ChipConfig>>,
475        >,
476        capsules_core::alarm::AlarmDriver::new(
477            virtual_alarm_user,
478            board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
479        )
480    );
481    hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
482
483    let scheduler_timer = static_init!(
484        VirtualSchedulerTimer<
485            VirtualMuxAlarm<'static, earlgrey::timer::RvTimer<'static, ChipConfig>>,
486        >,
487        VirtualSchedulerTimer::new(scheduler_timer_virtual_alarm)
488    );
489
490    let chip = static_init!(
491        EarlGreyChip,
492        earlgrey::chip::EarlGrey::new(peripherals, hardware_alarm, earlgrey_epmp)
493    );
494    CHIP = Some(chip);
495
496    // Need to enable all interrupts for Tock Kernel
497    chip.enable_plic_interrupts();
498    // enable interrupts globally
499    csr::CSR.mie.modify(
500        csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::CLEAR + csr::mie::mie::mext::SET,
501    );
502    csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
503
504    // Setup the console.
505    let console = components::console::ConsoleComponent::new(
506        board_kernel,
507        capsules_core::console::DRIVER_NUM,
508        uart_mux,
509    )
510    .finalize(components::console_component_static!());
511    // Create the debugger object that handles calls to `debug!()`.
512    components::debug_writer::DebugWriterComponent::new(uart_mux)
513        .finalize(components::debug_writer_component_static!());
514
515    let lldb = components::lldb::LowLevelDebugComponent::new(
516        board_kernel,
517        capsules_core::low_level_debug::DRIVER_NUM,
518        uart_mux,
519    )
520    .finalize(components::low_level_debug_component_static!());
521
522    let hmac = components::hmac::HmacComponent::new(
523        board_kernel,
524        capsules_extra::hmac::DRIVER_NUM,
525        &peripherals.hmac,
526    )
527    .finalize(components::hmac_component_static!(lowrisc::hmac::Hmac, 32));
528
529    let i2c_master_buffer = static_init!(
530        [u8; capsules_core::i2c_master::BUFFER_LENGTH],
531        [0; capsules_core::i2c_master::BUFFER_LENGTH]
532    );
533    let i2c_master = static_init!(
534        capsules_core::i2c_master::I2CMasterDriver<'static, lowrisc::i2c::I2c<'static>>,
535        capsules_core::i2c_master::I2CMasterDriver::new(
536            &peripherals.i2c0,
537            i2c_master_buffer,
538            board_kernel.create_grant(
539                capsules_core::i2c_master::DRIVER_NUM,
540                &memory_allocation_cap
541            )
542        )
543    );
544
545    peripherals.i2c0.set_master_client(i2c_master);
546
547    //SPI
548    let mux_spi = components::spi::SpiMuxComponent::new(&peripherals.spi_host0).finalize(
549        components::spi_mux_component_static!(lowrisc::spi_host::SpiHost),
550    );
551
552    let spi_controller = components::spi::SpiSyscallComponent::new(
553        board_kernel,
554        mux_spi,
555        lowrisc::spi_host::CS(0),
556        capsules_core::spi_controller::DRIVER_NUM,
557    )
558    .finalize(components::spi_syscall_component_static!(
559        lowrisc::spi_host::SpiHost
560    ));
561
562    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
563        .finalize(components::process_printer_text_component_static!());
564    PROCESS_PRINTER = Some(process_printer);
565
566    // USB support is currently broken in the OpenTitan hardware
567    // See https://github.com/lowRISC/opentitan/issues/2598 for more details
568    // let usb = components::usb::UsbComponent::new(
569    //     board_kernel,
570    //     capsules_extra::usb::usb_user::DRIVER_NUM,
571    //     &peripherals.usb,
572    // )
573    // .finalize(components::usb_component_static!(earlgrey::usbdev::Usb));
574
575    // Kernel storage region, allocated with the storage_volume!
576    // macro in common/utils.rs
577    extern "C" {
578        /// Beginning on the ROM region containing app images.
579        static _sstorage: u8;
580        static _estorage: u8;
581    }
582
583    // Flash setup memory protection for the ROM/Kernel
584    // Only allow reads for this region, any other ops will cause an MP fault
585    let mp_cfg = FlashMPConfig {
586        read_en: true,
587        write_en: false,
588        erase_en: false,
589        scramble_en: false,
590        ecc_en: false,
591        he_en: false,
592    };
593
594    // Allocate a flash protection region (associated cfg number: 0), for the code section.
595    if let Err(e) = peripherals.flash_ctrl.mp_set_region_perms(
596        core::ptr::addr_of!(_manifest) as usize,
597        core::ptr::addr_of!(_etext) as usize,
598        0,
599        &mp_cfg,
600    ) {
601        debug!("Failed to set flash memory protection: {:?}", e);
602    } else {
603        // Lock region 0, until next system reset.
604        if let Err(e) = peripherals.flash_ctrl.mp_lock_region_cfg(0) {
605            debug!("Failed to lock memory protection config: {:?}", e);
606        }
607    }
608
609    // Flash
610    let flash_ctrl_read_buf = static_init!(
611        [u8; lowrisc::flash_ctrl::PAGE_SIZE],
612        [0; lowrisc::flash_ctrl::PAGE_SIZE]
613    );
614    let page_buffer = static_init!(
615        lowrisc::flash_ctrl::LowRiscPage,
616        lowrisc::flash_ctrl::LowRiscPage::default()
617    );
618
619    let mux_flash = components::flash::FlashMuxComponent::new(&peripherals.flash_ctrl).finalize(
620        components::flash_mux_component_static!(lowrisc::flash_ctrl::FlashCtrl),
621    );
622
623    // SipHash
624    let sip_hash = static_init!(
625        capsules_extra::sip_hash::SipHasher24,
626        capsules_extra::sip_hash::SipHasher24::new()
627    );
628    kernel::deferred_call::DeferredCallClient::register(sip_hash);
629    SIPHASH = Some(sip_hash);
630
631    // TicKV
632    let tickv = components::tickv::TicKVComponent::new(
633        sip_hash,
634        mux_flash,                                     // Flash controller
635        lowrisc::flash_ctrl::FLASH_PAGES_PER_BANK - 1, // Region offset (End of Bank0/Use Bank1)
636        // Region Size
637        lowrisc::flash_ctrl::FLASH_PAGES_PER_BANK * lowrisc::flash_ctrl::PAGE_SIZE,
638        flash_ctrl_read_buf, // Buffer used internally in TicKV
639        page_buffer,         // Buffer used with the flash controller
640    )
641    .finalize(components::tickv_component_static!(
642        lowrisc::flash_ctrl::FlashCtrl,
643        capsules_extra::sip_hash::SipHasher24,
644        2048
645    ));
646    hil::flash::HasClient::set_client(&peripherals.flash_ctrl, mux_flash);
647    sip_hash.set_client(tickv);
648    TICKV = Some(tickv);
649
650    let kv_store = components::kv::TicKVKVStoreComponent::new(tickv).finalize(
651        components::tickv_kv_store_component_static!(
652            capsules_extra::tickv::TicKVSystem<
653                capsules_core::virtualizers::virtual_flash::FlashUser<
654                    lowrisc::flash_ctrl::FlashCtrl,
655                >,
656                capsules_extra::sip_hash::SipHasher24<'static>,
657                2048,
658            >,
659            capsules_extra::tickv::TicKVKeyType,
660        ),
661    );
662
663    let kv_store_permissions = components::kv::KVStorePermissionsComponent::new(kv_store).finalize(
664        components::kv_store_permissions_component_static!(
665            capsules_extra::tickv_kv_store::TicKVKVStore<
666                capsules_extra::tickv::TicKVSystem<
667                    capsules_core::virtualizers::virtual_flash::FlashUser<
668                        lowrisc::flash_ctrl::FlashCtrl,
669                    >,
670                    capsules_extra::sip_hash::SipHasher24<'static>,
671                    2048,
672                >,
673                capsules_extra::tickv::TicKVKeyType,
674            >
675        ),
676    );
677
678    let mux_kv = components::kv::KVPermissionsMuxComponent::new(kv_store_permissions).finalize(
679        components::kv_permissions_mux_component_static!(
680            capsules_extra::kv_store_permissions::KVStorePermissions<
681                capsules_extra::tickv_kv_store::TicKVKVStore<
682                    capsules_extra::tickv::TicKVSystem<
683                        capsules_core::virtualizers::virtual_flash::FlashUser<
684                            lowrisc::flash_ctrl::FlashCtrl,
685                        >,
686                        capsules_extra::sip_hash::SipHasher24<'static>,
687                        2048,
688                    >,
689                    capsules_extra::tickv::TicKVKeyType,
690                >,
691            >
692        ),
693    );
694
695    let virtual_kv_driver = components::kv::VirtualKVPermissionsComponent::new(mux_kv).finalize(
696        components::virtual_kv_permissions_component_static!(
697            capsules_extra::kv_store_permissions::KVStorePermissions<
698                capsules_extra::tickv_kv_store::TicKVKVStore<
699                    capsules_extra::tickv::TicKVSystem<
700                        capsules_core::virtualizers::virtual_flash::FlashUser<
701                            lowrisc::flash_ctrl::FlashCtrl,
702                        >,
703                        capsules_extra::sip_hash::SipHasher24<'static>,
704                        2048,
705                    >,
706                    capsules_extra::tickv::TicKVKeyType,
707                >,
708            >
709        ),
710    );
711
712    let kv_driver = components::kv::KVDriverComponent::new(
713        virtual_kv_driver,
714        board_kernel,
715        capsules_extra::kv_driver::DRIVER_NUM,
716    )
717    .finalize(components::kv_driver_component_static!(
718        capsules_extra::virtual_kv::VirtualKVPermissions<
719            capsules_extra::kv_store_permissions::KVStorePermissions<
720                capsules_extra::tickv_kv_store::TicKVKVStore<
721                    capsules_extra::tickv::TicKVSystem<
722                        capsules_core::virtualizers::virtual_flash::FlashUser<
723                            lowrisc::flash_ctrl::FlashCtrl,
724                        >,
725                        capsules_extra::sip_hash::SipHasher24<'static>,
726                        2048,
727                    >,
728                    capsules_extra::tickv::TicKVKeyType,
729                >,
730            >,
731        >
732    ));
733
734    let mux_otbn = crate::otbn::AccelMuxComponent::new(&peripherals.otbn)
735        .finalize(otbn_mux_component_static!());
736
737    let otbn = OtbnComponent::new(mux_otbn).finalize(crate::otbn_component_static!());
738
739    let otbn_rsa_internal_buf = static_init!([u8; 512], [0; 512]);
740
741    // Use the OTBN to create an RSA engine
742    if let Ok((rsa_imem_start, rsa_imem_length, rsa_dmem_start, rsa_dmem_length)) =
743        crate::otbn::find_app(
744            "otbn-rsa",
745            core::slice::from_raw_parts(
746                core::ptr::addr_of!(_sapps),
747                core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
748            ),
749        )
750    {
751        let rsa_hardware = static_init!(
752            lowrisc::rsa::OtbnRsa<'static>,
753            lowrisc::rsa::OtbnRsa::new(
754                otbn,
755                lowrisc::rsa::AppAddresses {
756                    imem_start: rsa_imem_start,
757                    imem_size: rsa_imem_length,
758                    dmem_start: rsa_dmem_start,
759                    dmem_size: rsa_dmem_length
760                },
761                otbn_rsa_internal_buf,
762            )
763        );
764        peripherals.otbn.set_client(rsa_hardware);
765        RSA_HARDWARE = Some(rsa_hardware);
766    } else {
767        debug!("Unable to find otbn-rsa, disabling RSA support");
768    }
769
770    // Convert hardware RNG to the Random interface.
771    let entropy_to_random = static_init!(
772        capsules_core::rng::Entropy32ToRandom<'static, lowrisc::csrng::CsRng<'static>>,
773        capsules_core::rng::Entropy32ToRandom::new(&peripherals.rng)
774    );
775    peripherals.rng.set_client(entropy_to_random);
776    // Setup RNG for userspace
777    let rng = static_init!(
778        capsules_core::rng::RngDriver<
779            'static,
780            capsules_core::rng::Entropy32ToRandom<'static, lowrisc::csrng::CsRng<'static>>,
781        >,
782        capsules_core::rng::RngDriver::new(
783            entropy_to_random,
784            board_kernel.create_grant(capsules_core::rng::DRIVER_NUM, &memory_allocation_cap)
785        )
786    );
787    entropy_to_random.set_client(rng);
788
789    const CRYPT_SIZE: usize = 7 * AES128_BLOCK_SIZE;
790
791    let ccm_mux = static_init!(
792        virtual_aes_ccm::MuxAES128CCM<'static, earlgrey::aes::Aes<'static>>,
793        virtual_aes_ccm::MuxAES128CCM::new(&peripherals.aes)
794    );
795    kernel::deferred_call::DeferredCallClient::register(ccm_mux);
796    peripherals.aes.set_client(ccm_mux);
797
798    let ccm_client = components::aes::AesVirtualComponent::new(ccm_mux).finalize(
799        components::aes_virtual_component_static!(earlgrey::aes::Aes<'static>),
800    );
801
802    let crypt_buf2 = static_init!([u8; CRYPT_SIZE], [0x00; CRYPT_SIZE]);
803    let gcm_client = static_init!(
804        aes_gcm::Aes128Gcm<
805            'static,
806            virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
807        >,
808        aes_gcm::Aes128Gcm::new(ccm_client, crypt_buf2)
809    );
810    ccm_client.set_client(gcm_client);
811
812    let aes = components::aes::AesDriverComponent::new(
813        board_kernel,
814        capsules_extra::symmetric_encryption::aes::DRIVER_NUM,
815        gcm_client,
816    )
817    .finalize(components::aes_driver_component_static!(
818        aes_gcm::Aes128Gcm<
819            'static,
820            virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
821        >,
822    ));
823
824    AES = Some(gcm_client);
825
826    #[cfg(test)]
827    {
828        use capsules_extra::sha256::Sha256Software;
829
830        let sha_soft = static_init!(Sha256Software<'static>, Sha256Software::new());
831        kernel::deferred_call::DeferredCallClient::register(sha_soft);
832
833        SHA256SOFT = Some(sha_soft);
834    }
835
836    hil::symmetric_encryption::AES128GCM::set_client(gcm_client, aes);
837    hil::symmetric_encryption::AES128::set_client(gcm_client, ccm_client);
838
839    let syscall_filter = static_init!(TbfHeaderFilterDefaultAllow, TbfHeaderFilterDefaultAllow {});
840    let scheduler = components::sched::priority::PriorityComponent::new(board_kernel)
841        .finalize(components::priority_component_static!());
842    let watchdog = &peripherals.watchdog;
843
844    let earlgrey = static_init!(
845        EarlGrey,
846        EarlGrey {
847            led,
848            gpio,
849            console,
850            alarm,
851            hmac,
852            lldb,
853            i2c_master,
854            spi_controller,
855            rng,
856            aes,
857            kv_driver,
858            syscall_filter,
859            scheduler,
860            scheduler_timer,
861            watchdog,
862        }
863    );
864
865    kernel::process::load_processes(
866        board_kernel,
867        chip,
868        core::slice::from_raw_parts(
869            core::ptr::addr_of!(_sapps),
870            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
871        ),
872        core::slice::from_raw_parts_mut(
873            core::ptr::addr_of_mut!(_sappmem),
874            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
875        ),
876        &mut *addr_of_mut!(PROCESSES),
877        &FAULT_RESPONSE,
878        &process_mgmt_cap,
879    )
880    .unwrap_or_else(|err| {
881        debug!("Error loading processes!");
882        debug!("{:?}", err);
883    });
884    debug!("OpenTitan initialisation complete. Entering main loop");
885
886    (board_kernel, earlgrey, chip, peripherals)
887}
888
889/// Main function.
890///
891/// This function is called from the arch crate after some very basic RISC-V
892/// setup and RAM initialization.
893#[no_mangle]
894pub unsafe fn main() {
895    #[cfg(test)]
896    test_main();
897
898    #[cfg(not(test))]
899    {
900        let (board_kernel, earlgrey, chip, _peripherals) = setup();
901
902        let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
903
904        board_kernel.kernel_loop(earlgrey, chip, None::<&kernel::ipc::IPC<0>>, &main_loop_cap);
905    }
906}
907
908#[cfg(test)]
909use kernel::platform::watchdog::WatchDog;
910
911#[cfg(test)]
912fn test_runner(tests: &[&dyn Fn()]) {
913    unsafe {
914        let (board_kernel, earlgrey, _chip, peripherals) = setup();
915
916        BOARD = Some(board_kernel);
917        PLATFORM = Some(&earlgrey);
918        PERIPHERALS = Some(peripherals);
919        MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
920
921        PLATFORM.map(|p| {
922            p.watchdog().setup();
923        });
924
925        for test in tests {
926            test();
927        }
928    }
929
930    // Exit QEMU with a return code of 0
931    crate::tests::semihost_command_exit_success()
932}