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