diff --git a/Cargo.toml b/Cargo.toml index a15e4714de..a9270dae24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ members = [ "boards/weact_f401ccu6/", "boards/configurations/nrf52840dk/nrf52840dk-test-appid-sha256", "boards/configurations/nrf52840dk/nrf52840dk-test-kernel", + "boards/tutorials/nrf52840dk-hotp-tutorial", "boards/tutorials/nrf52840dk-thread-tutorial", "capsules/aes_gcm", "capsules/core", diff --git a/boards/tutorials/nrf52840dk-hotp-tutorial/Cargo.toml b/boards/tutorials/nrf52840dk-hotp-tutorial/Cargo.toml new file mode 100644 index 0000000000..e3f37d8eff --- /dev/null +++ b/boards/tutorials/nrf52840dk-hotp-tutorial/Cargo.toml @@ -0,0 +1,19 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2024. + +[package] +name = "nrf52840dk-hotp-tutorial" +version.workspace = true +authors.workspace = true +build = "../../build.rs" +edition.workspace = true + +[dependencies] +kernel = { path = "../../../kernel" } +nrf52840 = { path = "../../../chips/nrf52840" } +nrf52840dk = { path = "../../nordic/nrf52840dk" } +capsules-core = { path = "../../../capsules/core" } +capsules-extra = { path = "../../../capsules/extra" } +capsules-system = { path = "../../../capsules/system" } +components = { path = "../../components" } diff --git a/boards/tutorials/nrf52840dk-hotp-tutorial/Makefile b/boards/tutorials/nrf52840dk-hotp-tutorial/Makefile new file mode 100644 index 0000000000..102ae2111c --- /dev/null +++ b/boards/tutorials/nrf52840dk-hotp-tutorial/Makefile @@ -0,0 +1,9 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2022. + +TARGET=thumbv7em-none-eabi +PLATFORM=nrf52840dk-hotp-tutorial + +include ../../Makefile.common +include ../../configurations/nrf52840dk/nrf52840dk.mk diff --git a/boards/tutorials/nrf52840dk-hotp-tutorial/README.md b/boards/tutorials/nrf52840dk-hotp-tutorial/README.md new file mode 100644 index 0000000000..9382ce5ab7 --- /dev/null +++ b/boards/tutorials/nrf52840dk-hotp-tutorial/README.md @@ -0,0 +1,9 @@ +nRF52840DK Board Definition for the Tock HOTP Tutorial +======================================================== + +This is the board definition for the nRF52840DK target used in the +[HOTP tutorial](https://book.tockos.org/course/usb-security-key/key-overview). + +Please follow the instructions in that tutorial. You may also want to look at +the documentation of the base nRF52840DK board definition +[here](../../nordic/nrf52840dk/README.md). diff --git a/boards/tutorials/nrf52840dk-hotp-tutorial/layout.ld b/boards/tutorials/nrf52840dk-hotp-tutorial/layout.ld new file mode 100644 index 0000000000..ece13c78e4 --- /dev/null +++ b/boards/tutorials/nrf52840dk-hotp-tutorial/layout.ld @@ -0,0 +1,6 @@ +/* Licensed under the Apache License, Version 2.0 or the MIT License. */ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* Copyright Tock Contributors 2023. */ + +INCLUDE ../../nordic/nrf52840_chip_layout.ld +INCLUDE ../../kernel_layout.ld diff --git a/boards/tutorials/nrf52840dk-hotp-tutorial/src/main.rs b/boards/tutorials/nrf52840dk-hotp-tutorial/src/main.rs new file mode 100644 index 0000000000..7a5a1f952a --- /dev/null +++ b/boards/tutorials/nrf52840dk-hotp-tutorial/src/main.rs @@ -0,0 +1,201 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2024. + +//! Tock kernel for the Nordic Semiconductor nRF52840 development kit (DK). + +#![no_std] +// Disable this attribute when documenting, as a workaround for +// https://github.com/rust-lang/rust/issues/62184. +#![cfg_attr(not(doc), no_main)] +#![deny(missing_docs)] + +use core::ptr::addr_of_mut; +use kernel::component::Component; +use kernel::debug; +use kernel::hil::usb::Client; +use kernel::platform::{KernelResources, SyscallDriverLookup}; +use kernel::static_init; +use kernel::{capabilities, create_capability}; +use nrf52840dk_lib::{self, PROCESSES}; + +// State for loading and holding applications. +// How should the kernel respond when a process faults. +const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy = + capsules_system::process_policies::PanicFaultPolicy {}; + +// USB Keyboard HID - for nRF52840dk +type UsbHw = nrf52840::usbd::Usbd<'static>; // For any nRF52840 board. +type KeyboardHidDriver = components::keyboard_hid::KeyboardHidComponentType; + +// HMAC +type HmacSha256Software = components::hmac::HmacSha256SoftwareComponentType< + capsules_extra::sha256::Sha256Software<'static>, +>; +type HmacDriver = components::hmac::HmacComponentType; + +struct Platform { + keyboard_hid_driver: &'static KeyboardHidDriver, + hmac: &'static HmacDriver, + base: nrf52840dk_lib::Platform, +} + +const KEYBOARD_HID_DRIVER_NUM: usize = capsules_core::driver::NUM::KeyboardHid as usize; + +impl SyscallDriverLookup for Platform { + fn with_driver(&self, driver_num: usize, f: F) -> R + where + F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R, + { + match driver_num { + capsules_extra::hmac::DRIVER_NUM => f(Some(self.hmac)), + KEYBOARD_HID_DRIVER_NUM => f(Some(self.keyboard_hid_driver)), + _ => self.base.with_driver(driver_num, f), + } + } +} + +type Chip = nrf52840dk_lib::Chip; + +impl KernelResources for Platform { + type SyscallDriverLookup = Self; + type SyscallFilter = >::SyscallFilter; + type ProcessFault = >::ProcessFault; + type Scheduler = >::Scheduler; + type SchedulerTimer = >::SchedulerTimer; + type WatchDog = >::WatchDog; + type ContextSwitchCallback = + >::ContextSwitchCallback; + + fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup { + self + } + fn syscall_filter(&self) -> &Self::SyscallFilter { + self.base.syscall_filter() + } + fn process_fault(&self) -> &Self::ProcessFault { + self.base.process_fault() + } + fn scheduler(&self) -> &Self::Scheduler { + self.base.scheduler() + } + fn scheduler_timer(&self) -> &Self::SchedulerTimer { + self.base.scheduler_timer() + } + fn watchdog(&self) -> &Self::WatchDog { + self.base.watchdog() + } + fn context_switch_callback(&self) -> &Self::ContextSwitchCallback { + self.base.context_switch_callback() + } +} + +/// Main function called after RAM initialized. +#[no_mangle] +pub unsafe fn main() { + let main_loop_capability = create_capability!(capabilities::MainLoopCapability); + + // Create the base board: + let (board_kernel, base_platform, chip, nrf52840_peripherals, _mux_alarm) = + nrf52840dk_lib::start(); + + //-------------------------------------------------------------------------- + // HMAC-SHA256 + //-------------------------------------------------------------------------- + + let sha256_sw = components::sha::ShaSoftware256Component::new() + .finalize(components::sha_software_256_component_static!()); + + let hmac_sha256_sw = components::hmac::HmacSha256SoftwareComponent::new(sha256_sw).finalize( + components::hmac_sha256_software_component_static!(capsules_extra::sha256::Sha256Software), + ); + + let hmac = components::hmac::HmacComponent::new( + board_kernel, + capsules_extra::hmac::DRIVER_NUM, + hmac_sha256_sw, + ) + .finalize(components::hmac_component_static!(HmacSha256Software, 32)); + + //-------------------------------------------------------------------------- + // KEYBOARD + //-------------------------------------------------------------------------- + + // Create the strings we include in the USB descriptor. + let strings = static_init!( + [&str; 3], + [ + "Nordic Semiconductor", // Manufacturer + "nRF52840dk - TockOS", // Product + "serial0001", // Serial number + ] + ); + + let usb_device = &nrf52840_peripherals.usbd; + + // Generic HID Keyboard component usage + let (keyboard_hid, keyboard_hid_driver) = components::keyboard_hid::KeyboardHidComponent::new( + board_kernel, + capsules_core::driver::NUM::KeyboardHid as usize, + usb_device, + 0x1915, // Nordic Semiconductor + 0x503a, + strings, + ) + .finalize(components::keyboard_hid_component_static!(UsbHw)); + + keyboard_hid.enable(); + keyboard_hid.attach(); + + //-------------------------------------------------------------------------- + // PLATFORM SETUP, SCHEDULER, AND START KERNEL LOOP + //-------------------------------------------------------------------------- + + let platform = Platform { + base: base_platform, + keyboard_hid_driver, + hmac, + }; + + // These symbols are defined in the linker script. + extern "C" { + /// Beginning of the ROM region containing app images. + static _sapps: u8; + /// End of the ROM region containing app images. + static _eapps: u8; + /// Beginning of the RAM region for app memory. + static mut _sappmem: u8; + /// End of the RAM region for app memory. + static _eappmem: u8; + } + + let process_management_capability = + create_capability!(capabilities::ProcessManagementCapability); + + kernel::process::load_processes( + board_kernel, + chip, + core::slice::from_raw_parts( + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, + ), + core::slice::from_raw_parts_mut( + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, + ), + &mut *addr_of_mut!(PROCESSES), + &FAULT_RESPONSE, + &process_management_capability, + ) + .unwrap_or_else(|err| { + debug!("Error loading processes!"); + debug!("{:?}", err); + }); + + board_kernel.kernel_loop( + &platform, + chip, + Some(&platform.base.ipc), + &main_loop_capability, + ); +}