earlgrey_cw310/
main.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Board file for LowRISC OpenTitan RISC-V development platform.
6//!
7//! - <https://opentitan.org/>
8
9#![no_std]
10#![no_main]
11#![feature(custom_test_frameworks)]
12#![test_runner(test_runner)]
13#![reexport_test_harness_main = "test_main"]
14
15use crate::hil::symmetric_encryption::AES128_BLOCK_SIZE;
16use crate::otbn::OtbnComponent;
17use crate::pinmux_layout::BoardPinmuxLayout;
18use capsules_aes_gcm::aes_gcm;
19use capsules_core::virtualizers::virtual_aes_ccm;
20use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
21use earlgrey::chip::EarlGreyDefaultPeripherals;
22use earlgrey::chip_config::EarlGreyConfig;
23use earlgrey::pinmux_config::EarlGreyPinmuxConfig;
24use kernel::capabilities;
25use kernel::component::Component;
26use kernel::hil;
27use kernel::hil::entropy::Entropy32;
28use kernel::hil::hasher::Hasher;
29use kernel::hil::i2c::I2CMaster;
30use kernel::hil::led::LedHigh;
31use kernel::hil::rng::Rng;
32use kernel::hil::symmetric_encryption::AES128;
33use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
34use kernel::platform::{KernelResources, SyscallDriverLookup, TbfHeaderFilterDefaultAllow};
35use kernel::process::ProcessArray;
36use kernel::scheduler::priority::PrioritySched;
37use kernel::utilities::registers::interfaces::ReadWriteable;
38use kernel::{create_capability, debug, static_init};
39use lowrisc::flash_ctrl::FlashMPConfig;
40use rv32i::csr;
41
42pub mod io;
43mod otbn;
44pub mod pinmux_layout;
45#[cfg(test)]
46mod tests;
47
48/// Chip configuration.
49///
50/// The `earlgrey` chip crate supports multiple targets with slightly different
51/// configurations, which are encoded through implementations of the
52/// `earlgrey::chip_config::EarlGreyConfig` trait. This type provides different
53/// implementations of the `EarlGreyConfig` trait, depending on Cargo's
54/// conditional compilation feature flags. If no feature is selected,
55/// compilation will error.
56pub enum ChipConfig {}
57
58#[cfg(feature = "fpga_cw310")]
59impl EarlGreyConfig for ChipConfig {
60    const NAME: &'static str = "fpga_cw310";
61
62    // Clock frequencies as of https://github.com/lowRISC/opentitan/pull/19479
63    const CPU_FREQ: u32 = 24_000_000;
64    const PERIPHERAL_FREQ: u32 = 6_000_000;
65    const AON_TIMER_FREQ: u32 = 250_000;
66    const UART_BAUDRATE: u32 = 115200;
67}
68
69#[cfg(feature = "sim_verilator")]
70impl EarlGreyConfig for ChipConfig {
71    const NAME: &'static str = "sim_verilator";
72
73    // Clock frequencies as of https://github.com/lowRISC/opentitan/pull/19368
74    const CPU_FREQ: u32 = 500_000;
75    const PERIPHERAL_FREQ: u32 = 125_000;
76    const AON_TIMER_FREQ: u32 = 125_000;
77    const UART_BAUDRATE: u32 = 7200;
78}
79
80// Whether to check for a proper ePMP handover configuration prior to ePMP
81// initialization:
82pub const EPMP_HANDOVER_CONFIG_CHECK: bool = false;
83
84// EarlGrey ePMP debug mode
85//
86// This type determines whether JTAG access shall be enabled. When JTAG access
87// is enabled, one less MPU region is available for use by userspace.
88//
89// Either
90// - `earlgrey::epmp::EPMPDebugEnable`, or
91// - `earlgrey::epmp::EPMPDebugDisable`.
92pub type EPMPDebugConfig = earlgrey::epmp::EPMPDebugEnable;
93
94// EarlGrey Chip type signature, including generic PMP argument and peripherals
95// type:
96pub type EarlGreyChip = earlgrey::chip::EarlGrey<
97    'static,
98    { <EPMPDebugConfig as earlgrey::epmp::EPMPDebugConfig>::TOR_USER_REGIONS },
99    EarlGreyDefaultPeripherals<'static, ChipConfig, BoardPinmuxLayout>,
100    ChipConfig,
101    BoardPinmuxLayout,
102    earlgrey::epmp::EarlGreyEPMP<{ EPMP_HANDOVER_CONFIG_CHECK }, EPMPDebugConfig>,
103>;
104
105const NUM_PROCS: usize = 4;
106
107/// Static variables used by io.rs.
108static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
109
110// Test access to the peripherals
111#[cfg(test)]
112static mut PERIPHERALS: Option<&'static EarlGreyDefaultPeripherals<ChipConfig, BoardPinmuxLayout>> =
113    None;
114// Test access to board
115#[cfg(test)]
116static mut BOARD: Option<&'static kernel::Kernel> = None;
117// Test access to platform
118#[cfg(test)]
119static mut PLATFORM: Option<&'static EarlGrey> = None;
120// Test access to main loop capability
121#[cfg(test)]
122static mut MAIN_CAP: Option<&dyn kernel::capabilities::MainLoopCapability> = None;
123// Test access to alarm
124static mut ALARM: Option<
125    &'static MuxAlarm<'static, earlgrey::timer::RvTimer<'static, ChipConfig>>,
126> = None;
127// Test access to TicKV
128static mut TICKV: Option<
129    &capsules_extra::tickv::TicKVSystem<
130        'static,
131        capsules_core::virtualizers::virtual_flash::FlashUser<
132            'static,
133            lowrisc::flash_ctrl::FlashCtrl<'static>,
134        >,
135        capsules_extra::sip_hash::SipHasher24<'static>,
136        2048,
137    >,
138> = None;
139// Test access to AES
140static mut AES: Option<
141    &aes_gcm::Aes128Gcm<
142        'static,
143        virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
144    >,
145> = None;
146// Test access to SipHash
147static mut SIPHASH: Option<&capsules_extra::sip_hash::SipHasher24<'static>> = None;
148// Test access to RSA
149static mut RSA_HARDWARE: Option<&lowrisc::rsa::OtbnRsa<'static>> = None;
150
151// Test access to a software SHA256
152#[cfg(test)]
153static mut SHA256SOFT: Option<&capsules_extra::sha256::Sha256Software<'static>> = None;
154
155static mut CHIP: Option<&'static EarlGreyChip> = None;
156static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
157    None;
158
159// How should the kernel respond when a process faults.
160const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
161    capsules_system::process_policies::PanicFaultPolicy {};
162
163/// Dummy buffer that causes the linker to reserve enough space for the stack.
164#[no_mangle]
165#[link_section = ".stack_buffer"]
166static mut STACK_MEMORY: [u8; 0x1400] = [0; 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::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(
515        uart_mux,
516        create_capability!(capabilities::SetDebugWriterCapability),
517    )
518    .finalize(components::debug_writer_component_static!());
519
520    let lldb = components::lldb::LowLevelDebugComponent::new(
521        board_kernel,
522        capsules_core::low_level_debug::DRIVER_NUM,
523        uart_mux,
524    )
525    .finalize(components::low_level_debug_component_static!());
526
527    let hmac = components::hmac::HmacComponent::new(
528        board_kernel,
529        capsules_extra::hmac::DRIVER_NUM,
530        &peripherals.hmac,
531    )
532    .finalize(components::hmac_component_static!(lowrisc::hmac::Hmac, 32));
533
534    let i2c_master_buffer = static_init!(
535        [u8; capsules_core::i2c_master::BUFFER_LENGTH],
536        [0; capsules_core::i2c_master::BUFFER_LENGTH]
537    );
538    let i2c_master = static_init!(
539        capsules_core::i2c_master::I2CMasterDriver<'static, lowrisc::i2c::I2c<'static>>,
540        capsules_core::i2c_master::I2CMasterDriver::new(
541            &peripherals.i2c0,
542            i2c_master_buffer,
543            board_kernel.create_grant(
544                capsules_core::i2c_master::DRIVER_NUM,
545                &memory_allocation_cap
546            )
547        )
548    );
549
550    peripherals.i2c0.set_master_client(i2c_master);
551
552    //SPI
553    let mux_spi = components::spi::SpiMuxComponent::new(&peripherals.spi_host0).finalize(
554        components::spi_mux_component_static!(lowrisc::spi_host::SpiHost),
555    );
556
557    let spi_controller = components::spi::SpiSyscallComponent::new(
558        board_kernel,
559        mux_spi,
560        lowrisc::spi_host::CS(0),
561        capsules_core::spi_controller::DRIVER_NUM,
562    )
563    .finalize(components::spi_syscall_component_static!(
564        lowrisc::spi_host::SpiHost
565    ));
566
567    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
568        .finalize(components::process_printer_text_component_static!());
569    PROCESS_PRINTER = Some(process_printer);
570
571    // USB support is currently broken in the OpenTitan hardware
572    // See https://github.com/lowRISC/opentitan/issues/2598 for more details
573    // let usb = components::usb::UsbComponent::new(
574    //     board_kernel,
575    //     capsules_extra::usb::usb_user::DRIVER_NUM,
576    //     &peripherals.usb,
577    // )
578    // .finalize(components::usb_component_static!(earlgrey::usbdev::Usb));
579
580    // Kernel storage region, allocated with the storage_volume!
581    // macro in common/utils.rs
582    extern "C" {
583        /// Beginning on the ROM region containing app images.
584        static _sstorage: u8;
585        static _estorage: u8;
586    }
587
588    // Flash setup memory protection for the ROM/Kernel
589    // Only allow reads for this region, any other ops will cause an MP fault
590    let mp_cfg = FlashMPConfig {
591        read_en: true,
592        write_en: false,
593        erase_en: false,
594        scramble_en: false,
595        ecc_en: false,
596        he_en: false,
597    };
598
599    // Allocate a flash protection region (associated cfg number: 0), for the code section.
600    if let Err(e) = peripherals.flash_ctrl.mp_set_region_perms(
601        core::ptr::addr_of!(_manifest) as usize,
602        core::ptr::addr_of!(_etext) as usize,
603        0,
604        &mp_cfg,
605    ) {
606        debug!("Failed to set flash memory protection: {:?}", e);
607    } else {
608        // Lock region 0, until next system reset.
609        if let Err(e) = peripherals.flash_ctrl.mp_lock_region_cfg(0) {
610            debug!("Failed to lock memory protection config: {:?}", e);
611        }
612    }
613
614    // Flash
615    let flash_ctrl_read_buf = static_init!(
616        [u8; lowrisc::flash_ctrl::PAGE_SIZE],
617        [0; lowrisc::flash_ctrl::PAGE_SIZE]
618    );
619    let page_buffer = static_init!(
620        lowrisc::flash_ctrl::LowRiscPage,
621        lowrisc::flash_ctrl::LowRiscPage::default()
622    );
623
624    let mux_flash = components::flash::FlashMuxComponent::new(&peripherals.flash_ctrl).finalize(
625        components::flash_mux_component_static!(lowrisc::flash_ctrl::FlashCtrl),
626    );
627
628    // SipHash
629    let sip_hash = static_init!(
630        capsules_extra::sip_hash::SipHasher24,
631        capsules_extra::sip_hash::SipHasher24::new()
632    );
633    kernel::deferred_call::DeferredCallClient::register(sip_hash);
634    SIPHASH = Some(sip_hash);
635
636    // TicKV
637    let tickv = components::tickv::TicKVComponent::new(
638        sip_hash,
639        mux_flash,                                     // Flash controller
640        lowrisc::flash_ctrl::FLASH_PAGES_PER_BANK - 1, // Region offset (End of Bank0/Use Bank1)
641        // Region Size
642        lowrisc::flash_ctrl::FLASH_PAGES_PER_BANK * lowrisc::flash_ctrl::PAGE_SIZE,
643        flash_ctrl_read_buf, // Buffer used internally in TicKV
644        page_buffer,         // Buffer used with the flash controller
645    )
646    .finalize(components::tickv_component_static!(
647        lowrisc::flash_ctrl::FlashCtrl,
648        capsules_extra::sip_hash::SipHasher24,
649        2048
650    ));
651    hil::flash::HasClient::set_client(&peripherals.flash_ctrl, mux_flash);
652    sip_hash.set_client(tickv);
653    TICKV = Some(tickv);
654
655    let kv_store = components::kv::TicKVKVStoreComponent::new(tickv).finalize(
656        components::tickv_kv_store_component_static!(
657            capsules_extra::tickv::TicKVSystem<
658                capsules_core::virtualizers::virtual_flash::FlashUser<
659                    lowrisc::flash_ctrl::FlashCtrl,
660                >,
661                capsules_extra::sip_hash::SipHasher24<'static>,
662                2048,
663            >,
664            capsules_extra::tickv::TicKVKeyType,
665        ),
666    );
667
668    let kv_store_permissions = components::kv::KVStorePermissionsComponent::new(kv_store).finalize(
669        components::kv_store_permissions_component_static!(
670            capsules_extra::tickv_kv_store::TicKVKVStore<
671                capsules_extra::tickv::TicKVSystem<
672                    capsules_core::virtualizers::virtual_flash::FlashUser<
673                        lowrisc::flash_ctrl::FlashCtrl,
674                    >,
675                    capsules_extra::sip_hash::SipHasher24<'static>,
676                    2048,
677                >,
678                capsules_extra::tickv::TicKVKeyType,
679            >
680        ),
681    );
682
683    let mux_kv = components::kv::KVPermissionsMuxComponent::new(kv_store_permissions).finalize(
684        components::kv_permissions_mux_component_static!(
685            capsules_extra::kv_store_permissions::KVStorePermissions<
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
700    let virtual_kv_driver = components::kv::VirtualKVPermissionsComponent::new(mux_kv).finalize(
701        components::virtual_kv_permissions_component_static!(
702            capsules_extra::kv_store_permissions::KVStorePermissions<
703                capsules_extra::tickv_kv_store::TicKVKVStore<
704                    capsules_extra::tickv::TicKVSystem<
705                        capsules_core::virtualizers::virtual_flash::FlashUser<
706                            lowrisc::flash_ctrl::FlashCtrl,
707                        >,
708                        capsules_extra::sip_hash::SipHasher24<'static>,
709                        2048,
710                    >,
711                    capsules_extra::tickv::TicKVKeyType,
712                >,
713            >
714        ),
715    );
716
717    let kv_driver = components::kv::KVDriverComponent::new(
718        virtual_kv_driver,
719        board_kernel,
720        capsules_extra::kv_driver::DRIVER_NUM,
721    )
722    .finalize(components::kv_driver_component_static!(
723        capsules_extra::virtual_kv::VirtualKVPermissions<
724            capsules_extra::kv_store_permissions::KVStorePermissions<
725                capsules_extra::tickv_kv_store::TicKVKVStore<
726                    capsules_extra::tickv::TicKVSystem<
727                        capsules_core::virtualizers::virtual_flash::FlashUser<
728                            lowrisc::flash_ctrl::FlashCtrl,
729                        >,
730                        capsules_extra::sip_hash::SipHasher24<'static>,
731                        2048,
732                    >,
733                    capsules_extra::tickv::TicKVKeyType,
734                >,
735            >,
736        >
737    ));
738
739    let mux_otbn = crate::otbn::AccelMuxComponent::new(&peripherals.otbn)
740        .finalize(otbn_mux_component_static!());
741
742    let otbn = OtbnComponent::new(mux_otbn).finalize(crate::otbn_component_static!());
743
744    let otbn_rsa_internal_buf = static_init!([u8; 512], [0; 512]);
745
746    // Use the OTBN to create an RSA engine
747    if let Ok((rsa_imem_start, rsa_imem_length, rsa_dmem_start, rsa_dmem_length)) =
748        crate::otbn::find_app(
749            "otbn-rsa",
750            core::slice::from_raw_parts(
751                core::ptr::addr_of!(_sapps),
752                core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
753            ),
754        )
755    {
756        let rsa_hardware = static_init!(
757            lowrisc::rsa::OtbnRsa<'static>,
758            lowrisc::rsa::OtbnRsa::new(
759                otbn,
760                lowrisc::rsa::AppAddresses {
761                    imem_start: rsa_imem_start,
762                    imem_size: rsa_imem_length,
763                    dmem_start: rsa_dmem_start,
764                    dmem_size: rsa_dmem_length
765                },
766                otbn_rsa_internal_buf,
767            )
768        );
769        peripherals.otbn.set_client(rsa_hardware);
770        RSA_HARDWARE = Some(rsa_hardware);
771    } else {
772        debug!("Unable to find otbn-rsa, disabling RSA support");
773    }
774
775    // Convert hardware RNG to the Random interface.
776    let entropy_to_random = static_init!(
777        capsules_core::rng::Entropy32ToRandom<'static, lowrisc::csrng::CsRng<'static>>,
778        capsules_core::rng::Entropy32ToRandom::new(&peripherals.rng)
779    );
780    peripherals.rng.set_client(entropy_to_random);
781    // Setup RNG for userspace
782    let rng = static_init!(
783        capsules_core::rng::RngDriver<
784            'static,
785            capsules_core::rng::Entropy32ToRandom<'static, lowrisc::csrng::CsRng<'static>>,
786        >,
787        capsules_core::rng::RngDriver::new(
788            entropy_to_random,
789            board_kernel.create_grant(capsules_core::rng::DRIVER_NUM, &memory_allocation_cap)
790        )
791    );
792    entropy_to_random.set_client(rng);
793
794    const CRYPT_SIZE: usize = 7 * AES128_BLOCK_SIZE;
795
796    let ccm_mux = static_init!(
797        virtual_aes_ccm::MuxAES128CCM<'static, earlgrey::aes::Aes<'static>>,
798        virtual_aes_ccm::MuxAES128CCM::new(&peripherals.aes)
799    );
800    kernel::deferred_call::DeferredCallClient::register(ccm_mux);
801    peripherals.aes.set_client(ccm_mux);
802
803    let ccm_client = components::aes::AesVirtualComponent::new(ccm_mux).finalize(
804        components::aes_virtual_component_static!(earlgrey::aes::Aes<'static>),
805    );
806
807    let crypt_buf2 = static_init!([u8; CRYPT_SIZE], [0x00; CRYPT_SIZE]);
808    let gcm_client = static_init!(
809        aes_gcm::Aes128Gcm<
810            'static,
811            virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
812        >,
813        aes_gcm::Aes128Gcm::new(ccm_client, crypt_buf2)
814    );
815    ccm_client.set_client(gcm_client);
816
817    let aes = components::aes::AesDriverComponent::new(
818        board_kernel,
819        capsules_extra::symmetric_encryption::aes::DRIVER_NUM,
820        gcm_client,
821    )
822    .finalize(components::aes_driver_component_static!(
823        aes_gcm::Aes128Gcm<
824            'static,
825            virtual_aes_ccm::VirtualAES128CCM<'static, earlgrey::aes::Aes<'static>>,
826        >,
827    ));
828
829    AES = Some(gcm_client);
830
831    #[cfg(test)]
832    {
833        use capsules_extra::sha256::Sha256Software;
834
835        let sha_soft = static_init!(Sha256Software<'static>, Sha256Software::new());
836        kernel::deferred_call::DeferredCallClient::register(sha_soft);
837
838        SHA256SOFT = Some(sha_soft);
839    }
840
841    hil::symmetric_encryption::AES128GCM::set_client(gcm_client, aes);
842    hil::symmetric_encryption::AES128::set_client(gcm_client, ccm_client);
843
844    let syscall_filter = static_init!(TbfHeaderFilterDefaultAllow, TbfHeaderFilterDefaultAllow {});
845    let scheduler = components::sched::priority::PriorityComponent::new(board_kernel)
846        .finalize(components::priority_component_static!());
847    let watchdog = &peripherals.watchdog;
848
849    let earlgrey = static_init!(
850        EarlGrey,
851        EarlGrey {
852            led,
853            gpio,
854            console,
855            alarm,
856            hmac,
857            lldb,
858            i2c_master,
859            spi_controller,
860            rng,
861            aes,
862            kv_driver,
863            syscall_filter,
864            scheduler,
865            scheduler_timer,
866            watchdog,
867        }
868    );
869
870    kernel::process::load_processes(
871        board_kernel,
872        chip,
873        core::slice::from_raw_parts(
874            core::ptr::addr_of!(_sapps),
875            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
876        ),
877        core::slice::from_raw_parts_mut(
878            core::ptr::addr_of_mut!(_sappmem),
879            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
880        ),
881        &FAULT_RESPONSE,
882        &process_mgmt_cap,
883    )
884    .unwrap_or_else(|err| {
885        debug!("Error loading processes!");
886        debug!("{:?}", err);
887    });
888    debug!("OpenTitan initialisation complete. Entering main loop");
889
890    (board_kernel, earlgrey, chip, peripherals)
891}
892
893/// Main function.
894///
895/// This function is called from the arch crate after some very basic RISC-V
896/// setup and RAM initialization.
897#[no_mangle]
898pub unsafe fn main() {
899    #[cfg(test)]
900    test_main();
901
902    #[cfg(not(test))]
903    {
904        let (board_kernel, earlgrey, chip, _peripherals) = setup();
905
906        let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
907
908        board_kernel.kernel_loop(earlgrey, chip, None::<&kernel::ipc::IPC<0>>, &main_loop_cap);
909    }
910}
911
912#[cfg(test)]
913use kernel::platform::watchdog::WatchDog;
914
915#[cfg(test)]
916fn test_runner(tests: &[&dyn Fn()]) {
917    unsafe {
918        let (board_kernel, earlgrey, _chip, peripherals) = setup();
919
920        BOARD = Some(board_kernel);
921        PLATFORM = Some(&earlgrey);
922        PERIPHERALS = Some(peripherals);
923        MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
924
925        PLATFORM.map(|p| {
926            p.watchdog().setup();
927        });
928
929        for test in tests {
930            test();
931        }
932    }
933
934    // Exit QEMU with a return code of 0
935    crate::tests::semihost_command_exit_success()
936}