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