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