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