From c1f2551d0d246c4170079140c1196d1689a0ce7a Mon Sep 17 00:00:00 2001 From: Jean-Michel Picod Date: Fri, 10 Sep 2021 08:32:34 +0200 Subject: [PATCH] Bump Tock kernel version (#374) * Bump Tock kernel version * Update boards to new kernel * Update patches to new kernel * Update PR template * Bump libtock-rs * Use new layout from libtock-rs * Fix clippy warnings due to updated toolchain * Fix new toolchain file format * Bump elf2tab to v0.7.0 * Fix worklow and setup.sh script to use the TOML rust-toolchain file * New libtock-rs style of declaring the stack. * Fix padding in layout file. The layout from libtock-rs generates invalid flash padding. The value is 32-bit and therefore setting padding to 0xff yields 0xff000000 instead of 0xffffffff that we want. * adds tock patch for app break hard fault * sets in deploy, removed patch 04-mpu-fix * fixed the if deploy * fixes indentation * updates board names in install.md * fix docs and deploy style Co-authored-by: Fabian Kaczmarczyck Co-authored-by: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com> --- .github/PULL_REQUEST_TEMPLATE.md | 9 +- .github/workflows/boards_build.yml | 5 +- .github/workflows/cargo_audit.yml | 5 +- .github/workflows/cargo_check.yml | 5 +- .github/workflows/cargo_clippy.yml | 6 +- .github/workflows/cargo_fmt.yml | 6 +- .github/workflows/cargo_fuzz.yml | 5 +- .github/workflows/cbor_test.yml | 5 +- .github/workflows/coveralls.yml | 13 +- .github/workflows/crypto_test.yml | 5 +- .github/workflows/opensk_build.yml | 5 +- .github/workflows/opensk_test.yml | 5 +- .github/workflows/persistent_store_test.yml | 6 +- .github/workflows/reproducible.yml | 5 +- .../nordic/nrf52840_dongle_opensk/src/io.rs | 9 +- .../nordic/nrf52840_dongle_opensk/src/main.rs | 167 +++++++++++------ boards/nordic/nrf52840_mdk_dfu/src/io.rs | 9 +- boards/nordic/nrf52840_mdk_dfu/src/main.rs | 144 +++++++-------- boards/nordic/nrf52840dk_opensk/src/io.rs | 12 +- boards/nordic/nrf52840dk_opensk/src/main.rs | 158 ++++++++++------ deploy.py | 35 +++- docs/install.md | 16 +- examples/console_test.rs | 2 + examples/crypto_bench.rs | 2 + examples/erase_storage.rs | 2 + examples/nfct_test.rs | 3 + examples/oom_test.rs | 2 + examples/panic_test.rs | 2 + examples/store_latency.rs | 12 +- layout.ld | 62 +++---- patches/tock/01-persistent-storage.patch | 43 ++--- patches/tock/02-usb.patch | 172 +----------------- patches/tock/03-additional-boards.patch | 6 +- patches/tock/04-mpu-fix.patch | 12 -- ...update-uicr.patch => 04-update-uicr.patch} | 52 +++++- ...rotect.patch => 05-firmware-protect.patch} | 117 ++---------- patches/tock/06-upgrade-partitions.patch | 56 ++++++ patches/tock/07-app-break-fix.patch | 13 ++ patches/tock/07-upgrade-partitions.patch | 92 ---------- setup.sh | 5 +- src/ctap/apdu.rs | 34 ++-- src/ctap/config_command.rs | 6 +- src/ctap/ctap1.rs | 4 +- src/ctap/hid/send.rs | 7 +- src/embedded_flash/helper.rs | 2 +- src/main.rs | 2 + third_party/libtock-rs | 2 +- third_party/tock | 2 +- 48 files changed, 617 insertions(+), 732 deletions(-) delete mode 100644 patches/tock/04-mpu-fix.patch rename patches/tock/{05-update-uicr.patch => 04-update-uicr.patch} (67%) rename patches/tock/{06-firmware-protect.patch => 05-firmware-protect.patch} (74%) create mode 100644 patches/tock/06-upgrade-partitions.patch create mode 100644 patches/tock/07-app-break-fix.patch delete mode 100644 patches/tock/07-upgrade-partitions.patch diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0787bd9..80261f5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,5 +2,10 @@ Fixes # > It's a good idea to open an issue first for discussion. -- [ ] Tests pass -- [ ] Appropriate changes to README are included in PR \ No newline at end of file +- [ ] Local tests pass (running `run_desktop_tests.sh`) +- [ ] Tested against boards + - [ ] Nordic nRF52840 DK + - [ ] Nordic nRF52840 Dongle (JTAG programmed) + - [ ] Nordic nRF52840 Dongle (DFU programmed) + - [ ] Makerdiary nRF52840 MDK USB Dongle +- [ ] Appropriate changes to README are included in PR diff --git a/.github/workflows/boards_build.yml b/.github/workflows/boards_build.yml index b48429b..002922c 100644 --- a/.github/workflows/boards_build.yml +++ b/.github/workflows/boards_build.yml @@ -18,9 +18,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/cargo_audit.yml b/.github/workflows/cargo_audit.yml index 4ff71b0..ca2457b 100644 --- a/.github/workflows/cargo_audit.yml +++ b/.github/workflows/cargo_audit.yml @@ -11,9 +11,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/cargo_check.yml b/.github/workflows/cargo_check.yml index 7151806..5681368 100644 --- a/.github/workflows/cargo_check.yml +++ b/.github/workflows/cargo_check.yml @@ -19,9 +19,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/cargo_clippy.yml b/.github/workflows/cargo_clippy.yml index 25aa63d..7d10e1c 100644 --- a/.github/workflows/cargo_clippy.yml +++ b/.github/workflows/cargo_clippy.yml @@ -12,10 +12,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi - components: clippy + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/cargo_fmt.yml b/.github/workflows/cargo_fmt.yml index 6e38687..b17f60c 100644 --- a/.github/workflows/cargo_fmt.yml +++ b/.github/workflows/cargo_fmt.yml @@ -20,10 +20,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi - components: rustfmt + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/cargo_fuzz.yml b/.github/workflows/cargo_fuzz.yml index b71b10a..999d5d5 100644 --- a/.github/workflows/cargo_fuzz.yml +++ b/.github/workflows/cargo_fuzz.yml @@ -12,9 +12,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/cbor_test.yml b/.github/workflows/cbor_test.yml index 7d341dc..32c81f7 100644 --- a/.github/workflows/cbor_test.yml +++ b/.github/workflows/cbor_test.yml @@ -14,9 +14,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/coveralls.yml b/.github/workflows/coveralls.yml index bab8255..4efcf00 100644 --- a/.github/workflows/coveralls.yml +++ b/.github/workflows/coveralls.yml @@ -17,15 +17,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - override: true - - name: Install grcov - run: if [[ ! -e ~/.cargo/bin/grcov ]]; then cargo +nightly install grcov; fi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 @@ -34,6 +27,8 @@ jobs: - name: Set up OpenSK run: ./setup.sh + - name: Install grcov + run: if [[ ! -e ~/.cargo/bin/grcov ]]; then cargo +stable install grcov; fi - uses: actions-rs/cargo@v1 with: command: test diff --git a/.github/workflows/crypto_test.yml b/.github/workflows/crypto_test.yml index 5abfce9..8734927 100644 --- a/.github/workflows/crypto_test.yml +++ b/.github/workflows/crypto_test.yml @@ -16,9 +16,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/opensk_build.yml b/.github/workflows/opensk_build.yml index cb2fb6f..f7e73ae 100644 --- a/.github/workflows/opensk_build.yml +++ b/.github/workflows/opensk_build.yml @@ -15,9 +15,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/opensk_test.yml b/.github/workflows/opensk_test.yml index 406a7f3..1de22f4 100644 --- a/.github/workflows/opensk_test.yml +++ b/.github/workflows/opensk_test.yml @@ -16,9 +16,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/.github/workflows/persistent_store_test.yml b/.github/workflows/persistent_store_test.yml index c40d262..20a33af 100644 --- a/.github/workflows/persistent_store_test.yml +++ b/.github/workflows/persistent_store_test.yml @@ -13,10 +13,8 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - override: true + - name: Install Rust toolchain + run: rustup show - name: Unit testing of Persistent store library (release mode) uses: actions-rs/cargo@v1 diff --git a/.github/workflows/reproducible.yml b/.github/workflows/reproducible.yml index fa82a0b..4934d78 100644 --- a/.github/workflows/reproducible.yml +++ b/.github/workflows/reproducible.yml @@ -16,9 +16,8 @@ jobs: - uses: actions/checkout@v2 with: submodules: "true" - - uses: actions-rs/toolchain@v1 - with: - target: thumbv7em-none-eabi + - name: Install Rust toolchain + run: rustup show - uses: actions/setup-python@v1 with: python-version: 3.7 diff --git a/boards/nordic/nrf52840_dongle_opensk/src/io.rs b/boards/nordic/nrf52840_dongle_opensk/src/io.rs index e8bafa5..f242235 100644 --- a/boards/nordic/nrf52840_dongle_opensk/src/io.rs +++ b/boards/nordic/nrf52840_dongle_opensk/src/io.rs @@ -25,7 +25,10 @@ impl Write for Writer { impl IoWrite for Writer { fn write(&mut self, buf: &[u8]) { - let uart = unsafe { &mut nrf52840::uart::UARTE0 }; + // Here, we create a second instance of the Uarte struct. + // This is okay because we only call this during a panic, and + // we will never actually process the interrupts + let uart = nrf52840::uart::Uarte::new(); if !self.initialized { self.initialized = true; uart.configure(uart::Parameters { @@ -51,8 +54,8 @@ impl IoWrite for Writer { /// Panic handler pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! { // The nRF52840 Dongle LEDs (see back of board) - const LED1_PIN: Pin = Pin::P0_06; - let led = &mut led::LedLow::new(&mut nrf52840::gpio::PORT[LED1_PIN]); + let led_kernel_pin = &nrf52840::gpio::GPIOPin::new(Pin::P0_06); + let led = &mut led::LedLow::new(led_kernel_pin); let writer = &mut WRITER; debug::panic( &mut [led], diff --git a/boards/nordic/nrf52840_dongle_opensk/src/main.rs b/boards/nordic/nrf52840_dongle_opensk/src/main.rs index f9c1042..a10207c 100644 --- a/boards/nordic/nrf52840_dongle_opensk/src/main.rs +++ b/boards/nordic/nrf52840_dongle_opensk/src/main.rs @@ -12,9 +12,12 @@ use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState}; use kernel::component::Component; +use kernel::hil::led::LedLow; +use kernel::hil::time::Counter; #[allow(unused_imports)] use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init}; use nrf52840::gpio::Pin; +use nrf52840::interrupt_service::Nrf52840DefaultPeripherals; use nrf52_components::{self, UartChannel, UartPins}; // The nRF52840 Dongle LEDs @@ -40,6 +43,17 @@ const _SPI_CLK: Pin = Pin::P1_04; /// UART Writer pub mod io; +const VENDOR_ID: u16 = 0x1915; // Nordic Semiconductor +const PRODUCT_ID: u16 = 0x521f; // nRF52840 Dongle (PCA10059) +static STRINGS: &'static [&'static str] = &[ + // Manufacturer + "Nordic Semiconductor ASA", + // Product + "OpenSK", + // Serial number + "v1.0", +]; + // State for loading and holding applications. // How should the kernel respond when a process faults. const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic; @@ -53,10 +67,11 @@ static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROC static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 1] = [kernel::StorageLocation { address: 0xC0000, size: 0x40000, + storage_type: kernel::StorageType::STORE, }]; // Static reference to chip for panic dumps -static mut CHIP: Option<&'static nrf52840::chip::Chip> = None; +static mut CHIP: Option<&'static nrf52840::chip::NRF52> = None; /// Dummy buffer that causes the linker to reserve enough space for the stack. #[no_mangle] @@ -72,9 +87,12 @@ pub struct Platform { >, console: &'static capsules::console::Console<'static>, gpio: &'static capsules::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>, - led: &'static capsules::led::LED<'static, nrf52840::gpio::GPIOPin<'static>>, + led: &'static capsules::led::LedDriver< + 'static, + LedLow<'static, nrf52840::gpio::GPIOPin<'static>>, + >, rng: &'static capsules::rng::RngDriver<'static>, - ipc: kernel::ipc::IPC, + ipc: kernel::ipc::IPC, analog_comparator: &'static capsules::analog_comparator::AnalogComparator< 'static, nrf52840::acomp::Comparator<'static>, @@ -84,6 +102,12 @@ pub struct Platform { capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>, >, nvmc: &'static nrf52840::nvmc::SyscallDriver, + usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver< + 'static, + 'static, + nrf52840::usbd::Usbd<'static>, + >, + crp: &'static capsules::firmware_protection::FirmwareProtection, } impl kernel::Platform for Platform { @@ -100,6 +124,8 @@ impl kernel::Platform for Platform { capsules::rng::DRIVER_NUM => f(Some(self.rng)), capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)), nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)), + capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)), + capsules::firmware_protection::DRIVER_NUM => f(Some(self.crp)), kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), _ => f(None), } @@ -131,6 +157,17 @@ pub unsafe fn reset_handler() { // Loads relocations and clears BSS nrf52840::init(); + let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new()); + // Initialize chip peripheral drivers + let nrf52840_peripherals = static_init!( + Nrf52840DefaultPeripherals, + Nrf52840DefaultPeripherals::new(ppi) + ); + + // set up circular peripheral dependencies + nrf52840_peripherals.init(); + let base_peripherals = &nrf52840_peripherals.nrf52; + let board_kernel = static_init!( kernel::Kernel, kernel::Kernel::new_with_storage(&PROCESSES, &STORAGE_LOCATIONS) @@ -142,32 +179,32 @@ pub unsafe fn reset_handler() { components::gpio_component_helper!( nrf52840::gpio::GPIOPin, // left side of the USB plug - 0 => &nrf52840::gpio::PORT[Pin::P0_13], - 1 => &nrf52840::gpio::PORT[Pin::P0_15], - 2 => &nrf52840::gpio::PORT[Pin::P0_17], - 3 => &nrf52840::gpio::PORT[Pin::P0_20], - 4 => &nrf52840::gpio::PORT[Pin::P0_22], - 5 => &nrf52840::gpio::PORT[Pin::P0_24], - 6 => &nrf52840::gpio::PORT[Pin::P1_00], - 7 => &nrf52840::gpio::PORT[Pin::P0_09], - 8 => &nrf52840::gpio::PORT[Pin::P0_10], + 0 => &nrf52840_peripherals.gpio_port[Pin::P0_13], + 1 => &nrf52840_peripherals.gpio_port[Pin::P0_15], + 2 => &nrf52840_peripherals.gpio_port[Pin::P0_17], + 3 => &nrf52840_peripherals.gpio_port[Pin::P0_20], + 4 => &nrf52840_peripherals.gpio_port[Pin::P0_22], + 5 => &nrf52840_peripherals.gpio_port[Pin::P0_24], + 6 => &nrf52840_peripherals.gpio_port[Pin::P1_00], + 7 => &nrf52840_peripherals.gpio_port[Pin::P0_09], + 8 => &nrf52840_peripherals.gpio_port[Pin::P0_10], // right side of the USB plug - 9 => &nrf52840::gpio::PORT[Pin::P0_31], - 10 => &nrf52840::gpio::PORT[Pin::P0_29], - 11 => &nrf52840::gpio::PORT[Pin::P0_02], - 12 => &nrf52840::gpio::PORT[Pin::P1_15], - 13 => &nrf52840::gpio::PORT[Pin::P1_13], - 14 => &nrf52840::gpio::PORT[Pin::P1_10], + 9 => &nrf52840_peripherals.gpio_port[Pin::P0_31], + 10 => &nrf52840_peripherals.gpio_port[Pin::P0_29], + 11 => &nrf52840_peripherals.gpio_port[Pin::P0_02], + 12 => &nrf52840_peripherals.gpio_port[Pin::P1_15], + 13 => &nrf52840_peripherals.gpio_port[Pin::P1_13], + 14 => &nrf52840_peripherals.gpio_port[Pin::P1_10], // Below the PCB - 15 => &nrf52840::gpio::PORT[Pin::P0_26], - 16 => &nrf52840::gpio::PORT[Pin::P0_04], - 17 => &nrf52840::gpio::PORT[Pin::P0_11], - 18 => &nrf52840::gpio::PORT[Pin::P0_14], - 19 => &nrf52840::gpio::PORT[Pin::P1_11], - 20 => &nrf52840::gpio::PORT[Pin::P1_07], - 21 => &nrf52840::gpio::PORT[Pin::P1_01], - 22 => &nrf52840::gpio::PORT[Pin::P1_04], - 23 => &nrf52840::gpio::PORT[Pin::P1_02] + 15 => &nrf52840_peripherals.gpio_port[Pin::P0_26], + 16 => &nrf52840_peripherals.gpio_port[Pin::P0_04], + 17 => &nrf52840_peripherals.gpio_port[Pin::P0_11], + 18 => &nrf52840_peripherals.gpio_port[Pin::P0_14], + 19 => &nrf52840_peripherals.gpio_port[Pin::P1_11], + 20 => &nrf52840_peripherals.gpio_port[Pin::P1_07], + 21 => &nrf52840_peripherals.gpio_port[Pin::P1_01], + 22 => &nrf52840_peripherals.gpio_port[Pin::P1_04], + 23 => &nrf52840_peripherals.gpio_port[Pin::P1_02] ), ) .finalize(components::gpio_component_buf!(nrf52840::gpio::GPIOPin)); @@ -177,7 +214,7 @@ pub unsafe fn reset_handler() { components::button_component_helper!( nrf52840::gpio::GPIOPin, ( - &nrf52840::gpio::PORT[BUTTON_PIN], + &nrf52840_peripherals.gpio_port[BUTTON_PIN], kernel::hil::gpio::ActivationMode::ActiveLow, kernel::hil::gpio::FloatingState::PullUp ) @@ -186,33 +223,27 @@ pub unsafe fn reset_handler() { .finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin)); let led = components::led::LedsComponent::new(components::led_component_helper!( - nrf52840::gpio::GPIOPin, - ( - &nrf52840::gpio::PORT[LED1_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ), - ( - &nrf52840::gpio::PORT[LED2_R_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ), - ( - &nrf52840::gpio::PORT[LED2_G_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ), - ( - &nrf52840::gpio::PORT[LED2_B_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ) + LedLow<'static, nrf52840::gpio::GPIOPin>, + LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]), + LedLow::new(&nrf52840_peripherals.gpio_port[LED2_R_PIN]), + LedLow::new(&nrf52840_peripherals.gpio_port[LED2_G_PIN]), + LedLow::new(&nrf52840_peripherals.gpio_port[LED2_B_PIN]), )) - .finalize(components::led_component_buf!(nrf52840::gpio::GPIOPin)); + .finalize(components::led_component_buf!( + LedLow<'static, nrf52840::gpio::GPIOPin> + )); - let chip = static_init!(nrf52840::chip::Chip, nrf52840::chip::new()); + let chip = static_init!( + nrf52840::chip::NRF52, + nrf52840::chip::NRF52::new(nrf52840_peripherals) + ); CHIP = Some(chip); nrf52_components::startup::NrfStartupComponent::new( false, BUTTON_RST_PIN, nrf52840::uicr::Regulator0Output::V3_0, + &base_peripherals.nvmc, ) .finalize(()); @@ -223,7 +254,7 @@ pub unsafe fn reset_handler() { let main_loop_capability = create_capability!(capabilities::MainLoopCapability); let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability); - let gpio_port = &nrf52840::gpio::PORT; + let gpio_port = &nrf52840_peripherals.gpio_port; // Configure kernel debug gpios as early as possible kernel::debug::assign_gpios( @@ -232,17 +263,22 @@ pub unsafe fn reset_handler() { Some(&gpio_port[LED2_B_PIN]), ); - let rtc = &nrf52840::rtc::RTC; + let rtc = &base_peripherals.rtc; rtc.start(); let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc) .finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc)); let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm) .finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc)); let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)); - let channel = nrf52_components::UartChannelComponent::new(uart_channel, mux_alarm).finalize(()); + let channel = nrf52_components::UartChannelComponent::new( + uart_channel, + mux_alarm, + &base_peripherals.uarte0, + ) + .finalize(()); let dynamic_deferred_call_clients = - static_init!([DynamicDeferredCallClientState; 2], Default::default()); + static_init!([DynamicDeferredCallClientState; 3], Default::default()); let dynamic_deferred_caller = static_init!( DynamicDeferredCall, DynamicDeferredCall::new(dynamic_deferred_call_clients) @@ -263,12 +299,12 @@ pub unsafe fn reset_handler() { // Create the debugger object that handles calls to `debug!()`. components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(()); - let rng = components::rng::RngComponent::new(board_kernel, &nrf52840::trng::TRNG).finalize(()); + let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(()); // Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02) // These are hardcoded pin assignments specified in the driver let analog_comparator = components::analog_comparator::AcComponent::new( - &nrf52840::acomp::ACOMP, + &base_peripherals.acomp, components::acomp_component_helper!( nrf52840::acomp::Channel, &nrf52840::acomp::CHANNEL_AC0 @@ -281,7 +317,7 @@ pub unsafe fn reset_handler() { let nvmc = static_init!( nrf52840::nvmc::SyscallDriver, nrf52840::nvmc::SyscallDriver::new( - &nrf52840::nvmc::NVMC, + &base_peripherals.nvmc, board_kernel.create_grant(&memory_allocation_capability), dynamic_deferred_caller, ) @@ -292,7 +328,26 @@ pub unsafe fn reset_handler() { .expect("no deferred call slot available for nvmc"), ); - nrf52_components::NrfClockComponent::new().finalize(()); + // Configure USB controller + let usb = components::usb_ctap::UsbCtapComponent::new( + board_kernel, + &nrf52840_peripherals.usbd, + capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840, + VENDOR_ID, + PRODUCT_ID, + STRINGS, + ) + .finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd)); + + let crp = components::firmware_protection::FirmwareProtectionComponent::new( + board_kernel, + nrf52840::uicr::Uicr::new(), + ) + .finalize(components::firmware_protection_component_helper!( + nrf52840::uicr::Uicr + )); + + nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(()); let platform = Platform { button, @@ -304,6 +359,8 @@ pub unsafe fn reset_handler() { alarm, analog_comparator, nvmc, + usb, + crp, ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), }; diff --git a/boards/nordic/nrf52840_mdk_dfu/src/io.rs b/boards/nordic/nrf52840_mdk_dfu/src/io.rs index 1f5f5a6..dc25d10 100644 --- a/boards/nordic/nrf52840_mdk_dfu/src/io.rs +++ b/boards/nordic/nrf52840_mdk_dfu/src/io.rs @@ -25,7 +25,10 @@ impl Write for Writer { impl IoWrite for Writer { fn write(&mut self, buf: &[u8]) { - let uart = unsafe { &mut nrf52840::uart::UARTE0 }; + // Here, we create a second instance of the Uarte struct. + // This is okay because we only call this during a panic, and + // we will never actually process the interrupts + let uart = nrf52840::uart::Uarte::new(); if !self.initialized { self.initialized = true; uart.configure(uart::Parameters { @@ -51,8 +54,8 @@ impl IoWrite for Writer { /// Panic handler pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! { // The nRF52840 Dongle LEDs (see back of board) - const LED1_PIN: Pin = Pin::P0_23; - let led = &mut led::LedLow::new(&mut nrf52840::gpio::PORT[LED1_PIN]); + let led_kernel_pin = &nrf52840::gpio::GPIOPin::new(Pin::P0_23); + let led = &mut led::LedLow::new(led_kernel_pin); let writer = &mut WRITER; debug::panic( &mut [led], diff --git a/boards/nordic/nrf52840_mdk_dfu/src/main.rs b/boards/nordic/nrf52840_mdk_dfu/src/main.rs index 25bd614..a92a82d 100644 --- a/boards/nordic/nrf52840_mdk_dfu/src/main.rs +++ b/boards/nordic/nrf52840_mdk_dfu/src/main.rs @@ -12,10 +12,12 @@ use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState}; use kernel::component::Component; +use kernel::hil::led::LedLow; +use kernel::hil::time::Counter; #[allow(unused_imports)] use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init}; -use kernel::hil::usb::UsbController; use nrf52840::gpio::Pin; +use nrf52840::interrupt_service::Nrf52840DefaultPeripherals; use nrf52_components::{self, UartChannel, UartPins}; // The nRF52840 MDK USB Dongle LEDs @@ -25,7 +27,7 @@ const LED1_B_PIN: Pin = Pin::P0_24; // The nRF52840 Dongle button const BUTTON_PIN: Pin = Pin::P0_18; -const BUTTON_RST_PIN: Pin = Pin::P0_02; +const _BUTTON_RST_PIN: Pin = Pin::P0_02; const UART_RTS: Option = Some(Pin::P0_21); const UART_TXD: Pin = Pin::P0_20; @@ -59,10 +61,11 @@ static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROC static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 1] = [kernel::StorageLocation { address: 0xC0000, size: 0x40000, + storage_type: kernel::StorageType::STORE, }]; // Static reference to chip for panic dumps -static mut CHIP: Option<&'static nrf52840::chip::Chip> = None; +static mut CHIP: Option<&'static nrf52840::chip::NRF52> = None; /// Dummy buffer that causes the linker to reserve enough space for the stack. #[no_mangle] @@ -78,9 +81,12 @@ pub struct Platform { >, console: &'static capsules::console::Console<'static>, gpio: &'static capsules::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>, - led: &'static capsules::led::LED<'static, nrf52840::gpio::GPIOPin<'static>>, + led: &'static capsules::led::LedDriver< + 'static, + LedLow<'static, nrf52840::gpio::GPIOPin<'static>>, + >, rng: &'static capsules::rng::RngDriver<'static>, - ipc: kernel::ipc::IPC, + ipc: kernel::ipc::IPC, analog_comparator: &'static capsules::analog_comparator::AnalogComparator< 'static, nrf52840::acomp::Comparator<'static>, @@ -143,6 +149,17 @@ pub unsafe fn reset_handler() { // Loads relocations and clears BSS nrf52840::init(); + let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new()); + // Initialize chip peripheral drivers + let nrf52840_peripherals = static_init!( + Nrf52840DefaultPeripherals, + Nrf52840DefaultPeripherals::new(ppi) + ); + + // set up circular peripheral dependencies + nrf52840_peripherals.init(); + let base_peripherals = &nrf52840_peripherals.nrf52; + let board_kernel = static_init!( kernel::Kernel, kernel::Kernel::new_with_storage(&PROCESSES, &STORAGE_LOCATIONS) @@ -153,20 +170,21 @@ pub unsafe fn reset_handler() { components::gpio_component_helper!( nrf52840::gpio::GPIOPin, // left side of the USB plug. Right side is used for UART - 0 => &nrf52840::gpio::PORT[Pin::P0_04], - 1 => &nrf52840::gpio::PORT[Pin::P0_05], - 2 => &nrf52840::gpio::PORT[Pin::P0_06], - 3 => &nrf52840::gpio::PORT[Pin::P0_07], - 4 => &nrf52840::gpio::PORT[Pin::P0_08] + 0 => &nrf52840_peripherals.gpio_port[Pin::P0_04], + 1 => &nrf52840_peripherals.gpio_port[Pin::P0_05], + 2 => &nrf52840_peripherals.gpio_port[Pin::P0_06], + 3 => &nrf52840_peripherals.gpio_port[Pin::P0_07], + 4 => &nrf52840_peripherals.gpio_port[Pin::P0_08] ), - ).finalize(components::gpio_component_buf!(nrf52840::gpio::GPIOPin)); + ) + .finalize(components::gpio_component_buf!(nrf52840::gpio::GPIOPin)); let button = components::button::ButtonComponent::new( board_kernel, components::button_component_helper!( nrf52840::gpio::GPIOPin, ( - &nrf52840::gpio::PORT[BUTTON_PIN], + &nrf52840_peripherals.gpio_port[BUTTON_PIN], kernel::hil::gpio::ActivationMode::ActiveLow, kernel::hil::gpio::FloatingState::PullUp ) @@ -175,32 +193,21 @@ pub unsafe fn reset_handler() { .finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin)); let led = components::led::LedsComponent::new(components::led_component_helper!( - nrf52840::gpio::GPIOPin, - ( - &nrf52840::gpio::PORT[LED1_R_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ), - ( - &nrf52840::gpio::PORT[LED1_G_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ), - ( - &nrf52840::gpio::PORT[LED1_B_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ) + LedLow<'static, nrf52840::gpio::GPIOPin>, + LedLow::new(&nrf52840_peripherals.gpio_port[LED1_R_PIN]), + LedLow::new(&nrf52840_peripherals.gpio_port[LED1_G_PIN]), + LedLow::new(&nrf52840_peripherals.gpio_port[LED1_B_PIN]), )) - .finalize(components::led_component_buf!(nrf52840::gpio::GPIOPin)); + .finalize(components::led_component_buf!( + LedLow<'static, nrf52840::gpio::GPIOPin> + )); - let chip = static_init!(nrf52840::chip::Chip, nrf52840::chip::new()); + let chip = static_init!( + nrf52840::chip::NRF52, + nrf52840::chip::NRF52::new(nrf52840_peripherals) + ); CHIP = Some(chip); - nrf52_components::startup::NrfStartupComponent::new( - false, - BUTTON_RST_PIN, - nrf52840::uicr::Regulator0Output::V3_0, - ) - .finalize(()); - // Create capabilities that the board needs to call certain protected kernel // functions. let process_management_capability = @@ -208,7 +215,7 @@ pub unsafe fn reset_handler() { let main_loop_capability = create_capability!(capabilities::MainLoopCapability); let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability); - let gpio_port = &nrf52840::gpio::PORT; + let gpio_port = &nrf52840_peripherals.gpio_port; // Configure kernel debug gpios as early as possible kernel::debug::assign_gpios( @@ -217,14 +224,19 @@ pub unsafe fn reset_handler() { Some(&gpio_port[LED1_B_PIN]), ); - let rtc = &nrf52840::rtc::RTC; + let rtc = &base_peripherals.rtc; rtc.start(); let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc) .finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc)); let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm) .finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc)); let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)); - let channel = nrf52_components::UartChannelComponent::new(uart_channel, mux_alarm).finalize(()); + let channel = nrf52_components::UartChannelComponent::new( + uart_channel, + mux_alarm, + &base_peripherals.uarte0, + ) + .finalize(()); let dynamic_deferred_call_clients = static_init!([DynamicDeferredCallClientState; 2], Default::default()); @@ -248,12 +260,12 @@ pub unsafe fn reset_handler() { // Create the debugger object that handles calls to `debug!()`. components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(()); - let rng = components::rng::RngComponent::new(board_kernel, &nrf52840::trng::TRNG).finalize(()); + let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(()); // Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02) // These are hardcoded pin assignments specified in the driver let analog_comparator = components::analog_comparator::AcComponent::new( - &nrf52840::acomp::ACOMP, + &base_peripherals.acomp, components::acomp_component_helper!( nrf52840::acomp::Channel, &nrf52840::acomp::CHANNEL_AC0 @@ -266,7 +278,7 @@ pub unsafe fn reset_handler() { let nvmc = static_init!( nrf52840::nvmc::SyscallDriver, nrf52840::nvmc::SyscallDriver::new( - &nrf52840::nvmc::NVMC, + &base_peripherals.nvmc, board_kernel.create_grant(&memory_allocation_capability), dynamic_deferred_caller, ) @@ -278,49 +290,17 @@ pub unsafe fn reset_handler() { ); // Configure USB controller - let usb: - &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver< - 'static, - 'static, - nrf52840::usbd::Usbd<'static>, - > = { - let usb_ctap = static_init!( - capsules::usb::usbc_ctap_hid::ClientCtapHID< - 'static, - 'static, - nrf52840::usbd::Usbd<'static>, - >, - capsules::usb::usbc_ctap_hid::ClientCtapHID::new( - &nrf52840::usbd::USBD, - capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840, - VENDOR_ID, - PRODUCT_ID, - STRINGS, - ) - ); - nrf52840::usbd::USBD.set_client(usb_ctap); + let usb = components::usb_ctap::UsbCtapComponent::new( + board_kernel, + &nrf52840_peripherals.usbd, + capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840, + VENDOR_ID, + PRODUCT_ID, + STRINGS, + ) + .finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd)); - // Enable power events to be sent to USB controller - nrf52840::power::POWER.set_usb_client(&nrf52840::usbd::USBD); - nrf52840::power::POWER.enable_interrupts(); - - // Configure the USB userspace driver - let usb_driver = static_init!( - capsules::usb::usb_ctap::CtapUsbSyscallDriver< - 'static, - 'static, - nrf52840::usbd::Usbd<'static>, - >, - capsules::usb::usb_ctap::CtapUsbSyscallDriver::new( - usb_ctap, - board_kernel.create_grant(&memory_allocation_capability) - ) - ); - usb_ctap.set_client(usb_driver); - usb_driver as &'static _ - }; - - nrf52_components::NrfClockComponent::new().finalize(()); + nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(()); let platform = Platform { button, diff --git a/boards/nordic/nrf52840dk_opensk/src/io.rs b/boards/nordic/nrf52840dk_opensk/src/io.rs index 88a697d..bd4d455 100644 --- a/boards/nordic/nrf52840dk_opensk/src/io.rs +++ b/boards/nordic/nrf52840dk_opensk/src/io.rs @@ -4,7 +4,8 @@ use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; -use kernel::hil::uart::{self, Configure}; +use kernel::hil::uart; +use kernel::hil::uart::Configure; use nrf52840::gpio::Pin; use crate::CHIP; @@ -41,7 +42,10 @@ impl IoWrite for Writer { fn write(&mut self, buf: &[u8]) { match self { Writer::WriterUart(ref mut initialized) => { - let uart = unsafe { &mut nrf52840::uart::UARTE0 }; + // Here, we create a second instance of the Uarte struct. + // This is okay because we only call this during a panic, and + // we will never actually process the interrupts + let uart = nrf52840::uart::Uarte::new(); if !*initialized { *initialized = true; uart.configure(uart::Parameters { @@ -88,8 +92,8 @@ impl IoWrite for Writer { /// Panic handler pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! { // The nRF52840DK LEDs (see back of board) - const LED1_PIN: Pin = Pin::P0_13; - let led = &mut led::LedLow::new(&mut nrf52840::gpio::PORT[LED1_PIN]); + let led_kernel_pin = &nrf52840::gpio::GPIOPin::new(Pin::P0_13); + let led = &mut led::LedLow::new(led_kernel_pin); let writer = &mut WRITER; debug::panic( &mut [led], diff --git a/boards/nordic/nrf52840dk_opensk/src/main.rs b/boards/nordic/nrf52840dk_opensk/src/main.rs index c80732f..4503ebd 100644 --- a/boards/nordic/nrf52840dk_opensk/src/main.rs +++ b/boards/nordic/nrf52840dk_opensk/src/main.rs @@ -69,9 +69,12 @@ use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState}; use kernel::component::Component; +use kernel::hil::led::LedLow; +use kernel::hil::time::Counter; #[allow(unused_imports)] use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init}; use nrf52840::gpio::Pin; +use nrf52840::interrupt_service::Nrf52840DefaultPeripherals; use nrf52_components::{self, UartChannel, UartPins}; // The nRF52840DK LEDs (see back of board) @@ -104,6 +107,17 @@ pub mod io; // - Set to true to use Segger RTT over USB. const USB_DEBUGGING: bool = true; +const VENDOR_ID: u16 = 0x1915; // Nordic Semiconductor +const PRODUCT_ID: u16 = 0x521f; // nRF52840 Dongle (PCA10059) +static STRINGS: &'static [&'static str] = &[ + // Manufacturer + "Nordic Semiconductor ASA", + // Product + "OpenSK", + // Serial number + "v1.0", +]; + // State for loading and holding applications. // How should the kernel respond when a process faults. const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic; @@ -117,9 +131,10 @@ static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROC static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 1] = [kernel::StorageLocation { address: 0xC0000, size: 0x40000, + storage_type: kernel::StorageType::STORE, }]; -static mut CHIP: Option<&'static nrf52840::chip::Chip> = None; +static mut CHIP: Option<&'static nrf52840::chip::NRF52> = None; /// Dummy buffer that causes the linker to reserve enough space for the stack. #[no_mangle] @@ -135,9 +150,12 @@ pub struct Platform { >, console: &'static capsules::console::Console<'static>, gpio: &'static capsules::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>, - led: &'static capsules::led::LED<'static, nrf52840::gpio::GPIOPin<'static>>, + led: &'static capsules::led::LedDriver< + 'static, + kernel::hil::led::LedLow<'static, nrf52840::gpio::GPIOPin<'static>>, + >, rng: &'static capsules::rng::RngDriver<'static>, - ipc: kernel::ipc::IPC, + ipc: kernel::ipc::IPC, analog_comparator: &'static capsules::analog_comparator::AnalogComparator< 'static, nrf52840::acomp::Comparator<'static>, @@ -147,6 +165,12 @@ pub struct Platform { capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>, >, nvmc: &'static nrf52840::nvmc::SyscallDriver, + usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver< + 'static, + 'static, + nrf52840::usbd::Usbd<'static>, + >, + crp: &'static capsules::firmware_protection::FirmwareProtection, } impl kernel::Platform for Platform { @@ -163,6 +187,8 @@ impl kernel::Platform for Platform { capsules::rng::DRIVER_NUM => f(Some(self.rng)), capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)), nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)), + capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)), + capsules::firmware_protection::DRIVER_NUM => f(Some(self.crp)), kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), _ => f(None), } @@ -193,6 +219,16 @@ impl kernel::Platform for Platform { pub unsafe fn reset_handler() { // Loads relocations and clears BSS nrf52840::init(); + let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new()); + // Initialize chip peripheral drivers + let nrf52840_peripherals = static_init!( + Nrf52840DefaultPeripherals, + Nrf52840DefaultPeripherals::new(ppi) + ); + + // set up circular peripheral dependencies + nrf52840_peripherals.init(); + let base_peripherals = &nrf52840_peripherals.nrf52; let uart_channel = if USB_DEBUGGING { // Initialize early so any panic beyond this point can use the RTT memory object. @@ -218,22 +254,22 @@ pub unsafe fn reset_handler() { board_kernel, components::gpio_component_helper!( nrf52840::gpio::GPIOPin, - 0 => &nrf52840::gpio::PORT[Pin::P1_01], - 1 => &nrf52840::gpio::PORT[Pin::P1_02], - 2 => &nrf52840::gpio::PORT[Pin::P1_03], - 3 => &nrf52840::gpio::PORT[Pin::P1_04], - 4 => &nrf52840::gpio::PORT[Pin::P1_05], - 5 => &nrf52840::gpio::PORT[Pin::P1_06], - 6 => &nrf52840::gpio::PORT[Pin::P1_07], - 7 => &nrf52840::gpio::PORT[Pin::P1_08], - 8 => &nrf52840::gpio::PORT[Pin::P1_10], - 9 => &nrf52840::gpio::PORT[Pin::P1_11], - 10 => &nrf52840::gpio::PORT[Pin::P1_12], - 11 => &nrf52840::gpio::PORT[Pin::P1_13], - 12 => &nrf52840::gpio::PORT[Pin::P1_14], - 13 => &nrf52840::gpio::PORT[Pin::P1_15], - 14 => &nrf52840::gpio::PORT[Pin::P0_26], - 15 => &nrf52840::gpio::PORT[Pin::P0_27] + 0 => &nrf52840_peripherals.gpio_port[Pin::P1_01], + 1 => &nrf52840_peripherals.gpio_port[Pin::P1_02], + 2 => &nrf52840_peripherals.gpio_port[Pin::P1_03], + 3 => &nrf52840_peripherals.gpio_port[Pin::P1_04], + 4 => &nrf52840_peripherals.gpio_port[Pin::P1_05], + 5 => &nrf52840_peripherals.gpio_port[Pin::P1_06], + 6 => &nrf52840_peripherals.gpio_port[Pin::P1_07], + 7 => &nrf52840_peripherals.gpio_port[Pin::P1_08], + 8 => &nrf52840_peripherals.gpio_port[Pin::P1_10], + 9 => &nrf52840_peripherals.gpio_port[Pin::P1_11], + 10 => &nrf52840_peripherals.gpio_port[Pin::P1_12], + 11 => &nrf52840_peripherals.gpio_port[Pin::P1_13], + 12 => &nrf52840_peripherals.gpio_port[Pin::P1_14], + 13 => &nrf52840_peripherals.gpio_port[Pin::P1_15], + 14 => &nrf52840_peripherals.gpio_port[Pin::P0_26], + 15 => &nrf52840_peripherals.gpio_port[Pin::P0_27] ), ) .finalize(components::gpio_component_buf!(nrf52840::gpio::GPIOPin)); @@ -243,22 +279,22 @@ pub unsafe fn reset_handler() { components::button_component_helper!( nrf52840::gpio::GPIOPin, ( - &nrf52840::gpio::PORT[BUTTON1_PIN], + &nrf52840_peripherals.gpio_port[BUTTON1_PIN], kernel::hil::gpio::ActivationMode::ActiveLow, kernel::hil::gpio::FloatingState::PullUp ), //13 ( - &nrf52840::gpio::PORT[BUTTON2_PIN], + &nrf52840_peripherals.gpio_port[BUTTON2_PIN], kernel::hil::gpio::ActivationMode::ActiveLow, kernel::hil::gpio::FloatingState::PullUp ), //14 ( - &nrf52840::gpio::PORT[BUTTON3_PIN], + &nrf52840_peripherals.gpio_port[BUTTON3_PIN], kernel::hil::gpio::ActivationMode::ActiveLow, kernel::hil::gpio::FloatingState::PullUp ), //15 ( - &nrf52840::gpio::PORT[BUTTON4_PIN], + &nrf52840_peripherals.gpio_port[BUTTON4_PIN], kernel::hil::gpio::ActivationMode::ActiveLow, kernel::hil::gpio::FloatingState::PullUp ) //16 @@ -267,33 +303,27 @@ pub unsafe fn reset_handler() { .finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin)); let led = components::led::LedsComponent::new(components::led_component_helper!( - nrf52840::gpio::GPIOPin, - ( - &nrf52840::gpio::PORT[LED1_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ), - ( - &nrf52840::gpio::PORT[LED2_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ), - ( - &nrf52840::gpio::PORT[LED3_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ), - ( - &nrf52840::gpio::PORT[LED4_PIN], - kernel::hil::gpio::ActivationMode::ActiveLow - ) + LedLow<'static, nrf52840::gpio::GPIOPin>, + LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]), + LedLow::new(&nrf52840_peripherals.gpio_port[LED2_PIN]), + LedLow::new(&nrf52840_peripherals.gpio_port[LED3_PIN]), + LedLow::new(&nrf52840_peripherals.gpio_port[LED4_PIN]), )) - .finalize(components::led_component_buf!(nrf52840::gpio::GPIOPin)); + .finalize(components::led_component_buf!( + LedLow<'static, nrf52840::gpio::GPIOPin> + )); - let chip = static_init!(nrf52840::chip::Chip, nrf52840::chip::new()); + let chip = static_init!( + nrf52840::chip::NRF52, + nrf52840::chip::NRF52::new(nrf52840_peripherals) + ); CHIP = Some(chip); nrf52_components::startup::NrfStartupComponent::new( false, BUTTON_RST_PIN, nrf52840::uicr::Regulator0Output::DEFAULT, + &base_peripherals.nvmc, ) .finalize(()); @@ -303,7 +333,7 @@ pub unsafe fn reset_handler() { create_capability!(capabilities::ProcessManagementCapability); let main_loop_capability = create_capability!(capabilities::MainLoopCapability); let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability); - let gpio_port = &nrf52840::gpio::PORT; + let gpio_port = &nrf52840_peripherals.gpio_port; // Configure kernel debug gpios as early as possible kernel::debug::assign_gpios( Some(&gpio_port[LED1_PIN]), @@ -311,17 +341,22 @@ pub unsafe fn reset_handler() { Some(&gpio_port[LED3_PIN]), ); - let rtc = &nrf52840::rtc::RTC; + let rtc = &base_peripherals.rtc; rtc.start(); let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc) .finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc)); let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm) .finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc)); - let channel = nrf52_components::UartChannelComponent::new(uart_channel, mux_alarm).finalize(()); + let channel = nrf52_components::UartChannelComponent::new( + uart_channel, + mux_alarm, + &base_peripherals.uarte0, + ) + .finalize(()); let dynamic_deferred_call_clients = - static_init!([DynamicDeferredCallClientState; 2], Default::default()); + static_init!([DynamicDeferredCallClientState; 3], Default::default()); let dynamic_deferred_caller = static_init!( DynamicDeferredCall, DynamicDeferredCall::new(dynamic_deferred_call_clients) @@ -342,9 +377,9 @@ pub unsafe fn reset_handler() { // Create the debugger object that handles calls to `debug!()`. components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(()); - let rng = components::rng::RngComponent::new(board_kernel, &nrf52840::trng::TRNG).finalize(()); + let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(()); - nrf52840::spi::SPIM0.configure( + base_peripherals.spim0.configure( nrf52840::pinmux::Pinmux::new(SPI_MOSI as u32), nrf52840::pinmux::Pinmux::new(SPI_MISO as u32), nrf52840::pinmux::Pinmux::new(SPI_CLK as u32), @@ -353,7 +388,7 @@ pub unsafe fn reset_handler() { // Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02) // These are hardcoded pin assignments specified in the driver let analog_comparator = components::analog_comparator::AcComponent::new( - &nrf52840::acomp::ACOMP, + &base_peripherals.acomp, components::acomp_component_helper!( nrf52840::acomp::Channel, &nrf52840::acomp::CHANNEL_AC0 @@ -366,7 +401,7 @@ pub unsafe fn reset_handler() { let nvmc = static_init!( nrf52840::nvmc::SyscallDriver, nrf52840::nvmc::SyscallDriver::new( - &nrf52840::nvmc::NVMC, + &base_peripherals.nvmc, board_kernel.create_grant(&memory_allocation_capability), dynamic_deferred_caller, ) @@ -377,7 +412,26 @@ pub unsafe fn reset_handler() { .expect("no deferred call slot available for nvmc"), ); - nrf52_components::NrfClockComponent::new().finalize(()); + // Configure USB controller + let usb = components::usb_ctap::UsbCtapComponent::new( + board_kernel, + &nrf52840_peripherals.usbd, + capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840, + VENDOR_ID, + PRODUCT_ID, + STRINGS, + ) + .finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd)); + + let crp = components::firmware_protection::FirmwareProtectionComponent::new( + board_kernel, + nrf52840::uicr::Uicr::new(), + ) + .finalize(components::firmware_protection_component_helper!( + nrf52840::uicr::Uicr + )); + + nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(()); let platform = Platform { button, @@ -389,6 +443,8 @@ pub unsafe fn reset_handler() { alarm, analog_comparator, nvmc, + usb, + crp, ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), }; diff --git a/deploy.py b/deploy.py index 18e1ed9..dc8b267 100755 --- a/deploy.py +++ b/deploy.py @@ -162,11 +162,6 @@ SUPPORTED_BOARDS = { ), } -# The STACK_SIZE value below must match the one used in the linker script -# used by the board. -# e.g. for Nordic nRF52840 boards the file is `nrf52840_layout.ld`. -STACK_SIZE = 0x4000 - # The following value must match the one used in the file # `src/entry_point.rs` APP_HEAP_SIZE = 90000 @@ -309,7 +304,16 @@ class OpenSKInstaller: def update_rustc_if_needed(self): target_toolchain_fullstring = "stable" with open("rust-toolchain", "r", encoding="utf-8") as f: - target_toolchain_fullstring = f.readline().strip() + content = f.readlines() + if len(content) == 1: + # Old format, only the build is stored + target_toolchain_fullstring = content[0].strip() + else: + # New format + for line in content: + if line.startswith("channel"): + channel = line.strip().split("=", maxsplit=1)[1].strip() + target_toolchain_fullstring = channel.strip('"') target_toolchain = target_toolchain_fullstring.split("-", maxsplit=1) if len(target_toolchain) == 1: # If we target the stable version of rust, we won't have a date @@ -419,10 +423,10 @@ class OpenSKInstaller: elf2tab_ver = self.checked_command_output( ["elf2tab/bin/elf2tab", "--version"]).split( "\n", maxsplit=1)[0] - if elf2tab_ver != "elf2tab 0.6.0": + if elf2tab_ver != "elf2tab 0.7.0": error( ("Detected unsupported elf2tab version {!a}. The following " - "commands may fail. Please use 0.6.0 instead.").format(elf2tab_ver)) + "commands may fail. Please use 0.7.0 instead.").format(elf2tab_ver)) os.makedirs(self.tab_folder, exist_ok=True) tab_filename = os.path.join(self.tab_folder, "{}.tab".format(self.args.application)) @@ -432,14 +436,25 @@ class OpenSKInstaller: ] if self.args.verbose_build: elf2tab_args.append("--verbose") + stack_sizes = set() for arch, app_file in binaries.items(): dest_file = os.path.join(self.tab_folder, "{}.elf".format(arch)) shutil.copyfile(app_file, dest_file) elf2tab_args.append(dest_file) + # extract required stack size directly from binary + nm = self.checked_command_output( + ["nm", "--print-size", "--radix=x", app_file]) + for line in nm.splitlines(): + if "STACK_MEMORY" in line: + required_stack_size = int(line.split(" ", maxsplit=2)[1], 16) + stack_sizes.add(required_stack_size) + if len(stack_sizes) != 1: + error("Detected different stack sizes across tab files.") elf2tab_args.extend([ - "--stack={}".format(STACK_SIZE), "--app-heap={}".format(APP_HEAP_SIZE), - "--kernel-heap=1024", "--protected-region-size=64" + "--stack={}".format(stack_sizes.pop()), + "--app-heap={}".format(APP_HEAP_SIZE), "--kernel-heap=1024", + "--protected-region-size=64" ]) if self.args.elf2tab_output: output = self.checked_command_output(elf2tab_args) diff --git a/docs/install.md b/docs/install.md index 487acc3..d5ee73f 100644 --- a/docs/install.md +++ b/docs/install.md @@ -220,7 +220,7 @@ the board in order to see your OpenSK device on your system. (_output may differ_): ```shell - $ ./deploy.py os --board=nrf52840_dongle --programmer=jlink + $ ./deploy.py os --board=nrf52840_dongle_opensk --programmer=jlink info: Updating rust toolchain to nightly-2020-02-03 info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu' info: checking for self-updates @@ -261,13 +261,15 @@ the board in order to see your OpenSK device on your system. Although flashing using a Segger JLink probe is the officially supported way, our tool, `deploy.py` also supports other methods: -* OpenOCD: `./deploy.py --board=nrf52840_dongle --opensk --programmer=openocd` -* pyOCD: `./deploy.py --board=nrf52840_dongle --opensk --programmer=pyocd` -* Nordic DFU: `./deploy.py --board=nrf52840_dongle --opensk +* OpenOCD: `./deploy.py --board=nrf52840_dongle_opensk --opensk + --programmer=openocd` +* pyOCD: `./deploy.py --board=nrf52840_dongle_opensk --opensk + --programmer=pyocd` +* Nordic DFU: `./deploy.py --board=nrf52840_dongle_dfu --opensk --programmer=nordicdfu` -* Custom: `./deploy.py --board=nrf52840_dongle --opensk --programmer=none`. In - this case, an IntelHex file will be created and how to program a board is - left to the user. +* Custom: `./deploy.py --board=nrf52840_dongle_opensk --opensk + --programmer=none`. In this case, an IntelHex file will be created and how + to program a board is left to the user. If your board is already flashed with Tock OS, you may skip installing it: `./deploy.py --board=nrf52840dk_opensk --opensk --no-tockos` diff --git a/examples/console_test.rs b/examples/console_test.rs index c6de0cf..a9ed8da 100644 --- a/examples/console_test.rs +++ b/examples/console_test.rs @@ -18,6 +18,8 @@ extern crate lang_items; use libtock_drivers::console::{Console, BUFFER_SIZE}; +libtock_core::stack_size! {0x800} + fn main() { // Write messages of length up to the console driver's buffer size. let mut buf = [0; BUFFER_SIZE]; diff --git a/examples/crypto_bench.rs b/examples/crypto_bench.rs index 6106ae2..a6208d7 100644 --- a/examples/crypto_bench.rs +++ b/examples/crypto_bench.rs @@ -29,6 +29,8 @@ use libtock_drivers::timer; use libtock_drivers::timer::Timer; use libtock_drivers::timer::Timestamp; +libtock_core::stack_size! {0x800} + fn main() { let mut console = Console::new(); // Setup the timer with a dummy callback (we only care about reading the current time, but the diff --git a/examples/erase_storage.rs b/examples/erase_storage.rs index 6076348..6d102db 100644 --- a/examples/erase_storage.rs +++ b/examples/erase_storage.rs @@ -23,6 +23,8 @@ use libtock_drivers::led; use libtock_drivers::result::FlexUnwrap; use persistent_store::{Storage, StorageIndex}; +libtock_core::stack_size! {0x800} + fn is_page_erased(storage: &dyn Storage, page: usize) -> bool { let index = StorageIndex { page, byte: 0 }; let length = storage.page_size(); diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index 924237d..6efbce3 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -7,6 +7,8 @@ extern crate libtock_drivers; use core::fmt::Write; use libtock_drivers::console::Console; +libtock_core::stack_size! {0x4000} + #[cfg(not(feature = "with_nfc"))] mod example { use super::Console; @@ -31,6 +33,7 @@ mod example { use libtock_drivers::timer::Timestamp; #[derive(Copy, Clone, Debug, PartialEq)] + #[allow(clippy::upper_case_acronyms)] enum ReturnCode { /// Operation completed successfully SUCCESS, diff --git a/examples/oom_test.rs b/examples/oom_test.rs index a7074e8..2248abc 100644 --- a/examples/oom_test.rs +++ b/examples/oom_test.rs @@ -17,6 +17,8 @@ extern crate alloc; extern crate lang_items; +libtock_core::stack_size! {0x800} + use alloc::vec::Vec; use core::fmt::Write; use libtock_drivers::console::Console; diff --git a/examples/panic_test.rs b/examples/panic_test.rs index e646149..e98314c 100644 --- a/examples/panic_test.rs +++ b/examples/panic_test.rs @@ -16,6 +16,8 @@ extern crate lang_items; +libtock_core::stack_size! {0x800} + fn main() { panic!("Bye world!") } diff --git a/examples/store_latency.rs b/examples/store_latency.rs index b6d0156..3571cf4 100644 --- a/examples/store_latency.rs +++ b/examples/store_latency.rs @@ -26,6 +26,8 @@ use libtock_drivers::console::Console; use libtock_drivers::timer::{self, Duration, Timer, Timestamp}; use persistent_store::Store; +libtock_core::stack_size! {0x800} + fn timestamp(timer: &Timer) -> Timestamp { Timestamp::::from_clock_value(timer.get_current_clock().ok().unwrap()) } @@ -66,10 +68,12 @@ fn compute_latency( key_increment: usize, word_length: usize, ) -> Stat { - let mut stat = Stat::default(); - stat.num_pages = num_pages; - stat.key_increment = key_increment; - stat.entry_length = word_length; + let mut stat = Stat { + num_pages, + key_increment, + entry_length: word_length, + ..Default::default() + }; let mut console = Console::new(); writeln!( diff --git a/layout.ld b/layout.ld index fde1c40..64aab2a 100644 --- a/layout.ld +++ b/layout.ld @@ -14,7 +14,6 @@ * FLASH (rx) : ORIGIN = 0x10030, LENGTH = 0x0FFD0 * SRAM (RWX) : ORIGIN = 0x20000, LENGTH = 0x10000 * } - * STACK_SIZE = 2048; * MPU_MIN_ALIGN = 8K; * INCLUDE ../libtock-rs/layout.ld */ @@ -25,9 +24,15 @@ SECTIONS { /* Section for just the app crt0 header. * This must be first so that the app can find it. */ - .crt0_header : + /* Runtime setup logic. The crt0_header symbol is used by the entry point + * assembly. We have to include start here rather than .text because + * otherwise elf2tab fails to recognize that the process binary's flash + * region should start at the beginning of .start. + */ + .start : { _beginning = .; /* Start of the app in flash. */ + crt0_header = .; /** * Populate the header expected by `crt0`: * @@ -64,35 +69,44 @@ SECTIONS { * .rel.data section */ LONG(LOADADDR(.endflash) - _beginning); /* The size of the stack requested by this application */ - LONG(STACK_SIZE); + LONG(_stack_top_aligned - _sstack); /* Pad the header out to a multiple of 32 bytes so there is not a gap * between the header and subsequent .data section. It's unclear why, * but LLD is aligning sections to a multiple of 32 bytes. */ . = ALIGN(32); - } > FLASH =0xFF + + *(.start) + } > FLASH =0xFFFFFFFF /* Text section, Code! */ .text : { . = ALIGN(4); _text = .; - KEEP (*(.start)) *(.text*) *(.rodata*) KEEP (*(.syscalls)) *(.ARM.extab*) . = ALIGN(4); /* Make sure we're word-aligned here */ _etext = .; - } > FLASH =0xFF + } > FLASH =0xFFFFFFFF /* Application stack */ - .stack : + .stack (NOLOAD) : { - . = . + STACK_SIZE; - - _stack_top_unaligned = .; + /* elf2tab requires that the `_sram_origin` symbol be present to + * mark the first address in the SRAM memory. Since ELF files do + * not really need to specify this address as they only care about + * loading into flash, we need to manually mark this address for + * elf2tab. elf2tab will use it to add a fixed address header in the + * TBF header if needed. + */ + _sram_origin = .; + _sstack = .; + KEEP(*(.stack_buffer)) + _stack_top_unaligned = .; . = ALIGN(8); - _stack_top_aligned = .; + _stack_top_aligned = .; } > SRAM /* Data section, static initialized variables @@ -104,6 +118,7 @@ SECTIONS { . = ALIGN(4); /* Make sure we're word-aligned here */ _data = .; KEEP(*(.data*)) + *(.sdata*) /* RISC-V small-pointer data section */ . = ALIGN(4); /* Make sure we're word-aligned at the end of flash */ } > SRAM @@ -122,7 +137,7 @@ SECTIONS { { . = ALIGN(4); /* Make sure we're word-aligned here */ _bss = .; - KEEP(*(.bss*)) + KEEP(*(.bss* .sbss*)) *(COMMON) . = ALIGN(4); } > SRAM @@ -132,26 +147,11 @@ SECTIONS { { } > FLASH - /* ARM Exception support - * - * This contains compiler-generated support for unwinding the stack, - * consisting of key-value pairs of function addresses and information on - * how to unwind stack frames. - * https://wiki.linaro.org/KenWerner/Sandbox/libunwind?action=AttachFile&do=get&target=libunwind-LDS.pdf - * - * .ARM.exidx is sorted, so has to go in its own output section. - * - * __NOTE__: It's at the end because we currently don't actually serialize - * it to the binary in elf2tbf. If it was before the RAM sections, it would - * through off our calculations of the header. - */ - PROVIDE_HIDDEN (__exidx_start = .); - .ARM.exidx : + /* Sections we do not need. */ + /DISCARD/ : { - /* (C++) Index entries for section unwinding */ - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - PROVIDE_HIDDEN (__exidx_end = .); + *(.ARM.exidx .eh_frame) + } } ASSERT((_stack_top_aligned - _stack_top_unaligned) == 0, " diff --git a/patches/tock/01-persistent-storage.patch b/patches/tock/01-persistent-storage.patch index 629fd6d..aed7581 100644 --- a/patches/tock/01-persistent-storage.patch +++ b/patches/tock/01-persistent-storage.patch @@ -1,5 +1,5 @@ diff --git a/chips/nrf52/src/nvmc.rs b/chips/nrf52/src/nvmc.rs -index b70162cae..9934f3a31 100644 +index adbc2a2b5..7594ec867 100644 --- a/chips/nrf52/src/nvmc.rs +++ b/chips/nrf52/src/nvmc.rs @@ -3,15 +3,19 @@ @@ -37,37 +37,38 @@ index b70162cae..9934f3a31 100644 /// This is a wrapper around a u8 array that is sized to a single page for the /// nrf. Users of this module must pass an object of this type to use the -@@ -219,6 +229,11 @@ impl Nvmc { +@@ -217,6 +227,10 @@ impl Nvmc { } } + pub fn configure_readonly(&self) { -+ let regs = &*self.registers; -+ regs.config.write(Configuration::WEN::Ren); ++ self.registers.config.write(Configuration::WEN::Ren); + } + /// Configure the NVMC to allow writes to flash. pub fn configure_writeable(&self) { - let regs = &*self.registers; -@@ -234,7 +249,7 @@ impl Nvmc { - let regs = &*self.registers; - regs.config.write(Configuration::WEN::Een); + self.registers.config.write(Configuration::WEN::Wen); +@@ -229,9 +243,7 @@ impl Nvmc { + pub fn erase_uicr(&self) { + self.registers.config.write(Configuration::WEN::Een); while !self.is_ready() {} -- regs.erasepage.write(ErasePage::ERASEPAGE.val(0x10001000)); -+ regs.eraseuicr.write(EraseUicr::ERASEUICR::ERASE); +- self.registers +- .erasepage +- .write(ErasePage::ERASEPAGE.val(0x10001000)); ++ self.registers.eraseuicr.write(EraseUicr::ERASEUICR::ERASE); while !self.is_ready() {} } -@@ -326,7 +341,7 @@ impl Nvmc { +@@ -319,7 +331,7 @@ impl Nvmc { // Put the NVMC in write mode. - regs.config.write(Configuration::WEN::Wen); + self.registers.config.write(Configuration::WEN::Wen); - for i in (0..data.len()).step_by(4) { + for i in (0..data.len()).step_by(WORD_SIZE) { let word: u32 = (data[i + 0] as u32) << 0 | (data[i + 1] as u32) << 8 | (data[i + 2] as u32) << 16 -@@ -394,3 +409,236 @@ impl hil::flash::Flash for Nvmc { +@@ -387,3 +399,236 @@ impl hil::flash::Flash for Nvmc { self.erase_page(page_number) } } @@ -305,10 +306,10 @@ index b70162cae..9934f3a31 100644 + } +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs -index dbe503515..428d90c29 100644 +index 49e1e5182..807170195 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs -@@ -123,7 +123,7 @@ pub use crate::sched::cooperative::{CoopProcessNode, CooperativeSched}; +@@ -122,7 +122,7 @@ pub use crate::sched::cooperative::{CoopProcessNode, CooperativeSched}; pub use crate::sched::mlfq::{MLFQProcessNode, MLFQSched}; pub use crate::sched::priority::PrioritySched; pub use crate::sched::round_robin::{RoundRobinProcessNode, RoundRobinSched}; @@ -348,10 +349,10 @@ index 348c746a5..5465c95f4 100644 } } diff --git a/kernel/src/process.rs b/kernel/src/process.rs -index 4dfde3b4f..8380af673 100644 +index c52754be3..ae6a58341 100644 --- a/kernel/src/process.rs +++ b/kernel/src/process.rs -@@ -360,6 +360,15 @@ pub trait ProcessType { +@@ -359,6 +359,15 @@ pub trait ProcessType { /// writeable flash region. fn get_writeable_flash_region(&self, region_index: usize) -> (u32, u32); @@ -367,7 +368,7 @@ index 4dfde3b4f..8380af673 100644 /// Debug function to update the kernel on where the stack starts for this /// process. Processes are not required to call this through the memop /// system call, but it aids in debugging the process. -@@ -1015,6 +1024,35 @@ impl ProcessType for Process<'_, C> { +@@ -1048,6 +1057,35 @@ impl ProcessType for Process<'_, C> { self.header.get_writeable_flash_region(region_index) } @@ -403,7 +404,7 @@ index 4dfde3b4f..8380af673 100644 fn update_stack_start_pointer(&self, stack_pointer: *const u8) { if stack_pointer >= self.mem_start() && stack_pointer < self.mem_end() { self.debug.map(|debug| { -@@ -1664,6 +1702,33 @@ impl Process<'_, C> { +@@ -1751,6 +1789,33 @@ impl Process<'_, C> { return Err(ProcessLoadError::MpuInvalidFlashLength); } @@ -438,7 +439,7 @@ index 4dfde3b4f..8380af673 100644 // memory space just for kernel and grant state. We need to make // sure we allocate enough memory just for that. diff --git a/kernel/src/sched.rs b/kernel/src/sched.rs -index 88eea4042..ed3ae8260 100644 +index 10626a2e1..8844bc6c3 100644 --- a/kernel/src/sched.rs +++ b/kernel/src/sched.rs @@ -118,6 +118,12 @@ pub enum SchedulingDecision { @@ -482,7 +483,7 @@ index 88eea4042..ed3ae8260 100644 process_identifier_max: Cell::new(0), grant_counter: Cell::new(0), grants_finalized: Cell::new(false), -@@ -899,4 +916,8 @@ impl Kernel { +@@ -900,4 +917,8 @@ impl Kernel { (return_reason, time_executed_us) } diff --git a/patches/tock/02-usb.patch b/patches/tock/02-usb.patch index 0350e1c..78f7a7b 100644 --- a/patches/tock/02-usb.patch +++ b/patches/tock/02-usb.patch @@ -1,11 +1,11 @@ diff --git a/boards/components/src/lib.rs b/boards/components/src/lib.rs -index dc56c94d2..917497af4 100644 +index 64fe46b7b..a3bbe724b 100644 --- a/boards/components/src/lib.rs +++ b/boards/components/src/lib.rs -@@ -36,3 +36,4 @@ pub mod spi; - pub mod st7735; - pub mod temperature; +@@ -52,3 +52,4 @@ pub mod tickv; pub mod touch; + pub mod udp_driver; + pub mod udp_mux; +pub mod usb_ctap; diff --git a/boards/components/src/usb_ctap.rs b/boards/components/src/usb_ctap.rs new file mode 100644 @@ -101,152 +101,8 @@ index 000000000..69e95c3c7 + usb_driver + } +} -diff --git a/boards/nordic/nrf52840_dongle_opensk/src/main.rs b/boards/nordic/nrf52840_dongle_opensk/src/main.rs -index f9c104251..115e17280 100644 ---- a/boards/nordic/nrf52840_dongle_opensk/src/main.rs -+++ b/boards/nordic/nrf52840_dongle_opensk/src/main.rs -@@ -40,6 +40,17 @@ const _SPI_CLK: Pin = Pin::P1_04; - /// UART Writer - pub mod io; - -+const VENDOR_ID: u16 = 0x1915; // Nordic Semiconductor -+const PRODUCT_ID: u16 = 0x521f; // nRF52840 Dongle (PCA10059) -+static STRINGS: &'static [&'static str] = &[ -+ // Manufacturer -+ "Nordic Semiconductor ASA", -+ // Product -+ "OpenSK", -+ // Serial number -+ "v1.0", -+]; -+ - // State for loading and holding applications. - // How should the kernel respond when a process faults. - const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic; -@@ -84,6 +95,11 @@ pub struct Platform { - capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>, - >, - nvmc: &'static nrf52840::nvmc::SyscallDriver, -+ usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver< -+ 'static, -+ 'static, -+ nrf52840::usbd::Usbd<'static>, -+ >, - } - - impl kernel::Platform for Platform { -@@ -100,6 +116,7 @@ impl kernel::Platform for Platform { - capsules::rng::DRIVER_NUM => f(Some(self.rng)), - capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)), - nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)), -+ capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)), - kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), - _ => f(None), - } -@@ -292,6 +309,21 @@ pub unsafe fn reset_handler() { - .expect("no deferred call slot available for nvmc"), - ); - -+ // Enable power events to be sent to USB controller -+ nrf52840::power::POWER.set_usb_client(&nrf52840::usbd::USBD); -+ nrf52840::power::POWER.enable_interrupts(); -+ -+ // Configure USB controller -+ let usb = components::usb_ctap::UsbCtapComponent::new( -+ board_kernel, -+ &nrf52840::usbd::USBD, -+ capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840, -+ VENDOR_ID, -+ PRODUCT_ID, -+ STRINGS, -+ ) -+ .finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd)); -+ - nrf52_components::NrfClockComponent::new().finalize(()); - - let platform = Platform { -@@ -304,6 +336,7 @@ pub unsafe fn reset_handler() { - alarm, - analog_comparator, - nvmc, -+ usb, - ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), - }; - -diff --git a/boards/nordic/nrf52840dk_opensk/src/main.rs b/boards/nordic/nrf52840dk_opensk/src/main.rs -index c80732f8d..41047a390 100644 ---- a/boards/nordic/nrf52840dk_opensk/src/main.rs -+++ b/boards/nordic/nrf52840dk_opensk/src/main.rs -@@ -104,6 +104,17 @@ pub mod io; - // - Set to true to use Segger RTT over USB. - const USB_DEBUGGING: bool = true; - -+const VENDOR_ID: u16 = 0x1915; // Nordic Semiconductor -+const PRODUCT_ID: u16 = 0x521f; // nRF52840 Dongle (PCA10059) -+static STRINGS: &'static [&'static str] = &[ -+ // Manufacturer -+ "Nordic Semiconductor ASA", -+ // Product -+ "OpenSK", -+ // Serial number -+ "v1.0", -+]; -+ - // State for loading and holding applications. - // How should the kernel respond when a process faults. - const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic; -@@ -147,6 +158,11 @@ pub struct Platform { - capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>, - >, - nvmc: &'static nrf52840::nvmc::SyscallDriver, -+ usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver< -+ 'static, -+ 'static, -+ nrf52840::usbd::Usbd<'static>, -+ >, - } - - impl kernel::Platform for Platform { -@@ -163,6 +179,7 @@ impl kernel::Platform for Platform { - capsules::rng::DRIVER_NUM => f(Some(self.rng)), - capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)), - nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)), -+ capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)), - kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), - _ => f(None), - } -@@ -377,6 +394,21 @@ pub unsafe fn reset_handler() { - .expect("no deferred call slot available for nvmc"), - ); - -+ // Enable power events to be sent to USB controller -+ nrf52840::power::POWER.set_usb_client(&nrf52840::usbd::USBD); -+ nrf52840::power::POWER.enable_interrupts(); -+ -+ // Configure USB controller -+ let usb = components::usb_ctap::UsbCtapComponent::new( -+ board_kernel, -+ &nrf52840::usbd::USBD, -+ capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840, -+ VENDOR_ID, -+ PRODUCT_ID, -+ STRINGS, -+ ) -+ .finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd)); -+ - nrf52_components::NrfClockComponent::new().finalize(()); - - let platform = Platform { -@@ -389,6 +421,7 @@ pub unsafe fn reset_handler() { - alarm, - analog_comparator, - nvmc, -+ usb, - ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), - }; - diff --git a/capsules/src/driver.rs b/capsules/src/driver.rs -index 256fc0e9d..ae458b309 100644 +index 3dad0f50b..b6124c4c0 100644 --- a/capsules/src/driver.rs +++ b/capsules/src/driver.rs @@ -26,6 +26,7 @@ pub enum NUM { @@ -258,11 +114,12 @@ index 256fc0e9d..ae458b309 100644 // Radio BleAdvertising = 0x30000, diff --git a/capsules/src/usb/mod.rs b/capsules/src/usb/mod.rs -index 767f5de83..3f3a4f646 100644 +index 6d5daa444..17cab4c23 100644 --- a/capsules/src/usb/mod.rs +++ b/capsules/src/usb/mod.rs -@@ -1,5 +1,7 @@ +@@ -1,6 +1,8 @@ pub mod cdc; + pub mod ctap; pub mod descriptors; +pub mod usb_ctap; pub mod usb_user; @@ -1005,16 +862,3 @@ index 000000000..642039120 + self.client.map(|client| client.packet_transmitted()); + } +} -diff --git a/chips/nrf52840/src/lib.rs b/chips/nrf52840/src/lib.rs -index 942d0288f..ce73e1f82 100644 ---- a/chips/nrf52840/src/lib.rs -+++ b/chips/nrf52840/src/lib.rs -@@ -2,7 +2,7 @@ - - pub use nrf52::{ - acomp, adc, aes, ble_radio, clock, constants, crt1, ficr, i2c, ieee802154_radio, init, nvmc, -- pinmux, ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr, usbd, -+ pinmux, power, ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr, usbd, - }; - pub mod chip; - pub mod gpio; diff --git a/patches/tock/03-additional-boards.patch b/patches/tock/03-additional-boards.patch index ff6055e..d6f605a 100644 --- a/patches/tock/03-additional-boards.patch +++ b/patches/tock/03-additional-boards.patch @@ -1,10 +1,10 @@ diff --git a/Cargo.toml b/Cargo.toml -index 83c48558e..75b1abacc 100644 +index 06acc26d2..e5db0740b 100644 --- a/Cargo.toml +++ b/Cargo.toml -@@ -12,7 +12,11 @@ members = [ - "boards/imix", +@@ -20,7 +20,11 @@ members = [ "boards/msp_exp432p401r", + "boards/microbit_v2", "boards/nordic/nrf52840dk", + "boards/nordic/nrf52840dk_opensk", "boards/nordic/nrf52840_dongle", diff --git a/patches/tock/04-mpu-fix.patch b/patches/tock/04-mpu-fix.patch deleted file mode 100644 index 4a3c4e4..0000000 --- a/patches/tock/04-mpu-fix.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/kernel/src/sched.rs b/kernel/src/sched.rs -index ed3ae8260..f109960d3 100644 ---- a/kernel/src/sched.rs -+++ b/kernel/src/sched.rs -@@ -632,6 +632,7 @@ impl Kernel { - let context_switch_reason = process.switch_to(); - scheduler_timer.disarm(); - chip.mpu().disable_app_mpu(); -+ chip.mpu().clear_mpu(); - - // Now the process has returned back to the kernel. Check - // why and handle the process as appropriate. diff --git a/patches/tock/05-update-uicr.patch b/patches/tock/04-update-uicr.patch similarity index 67% rename from patches/tock/05-update-uicr.patch rename to patches/tock/04-update-uicr.patch index 0b518a9..55e176c 100644 --- a/patches/tock/05-update-uicr.patch +++ b/patches/tock/04-update-uicr.patch @@ -1,13 +1,38 @@ +diff --git a/boards/nordic/nrf52_components/src/startup.rs b/boards/nordic/nrf52_components/src/startup.rs +index e6cf3ff56..7b3ea5a59 100644 +--- a/boards/nordic/nrf52_components/src/startup.rs ++++ b/boards/nordic/nrf52_components/src/startup.rs +@@ -53,6 +53,9 @@ impl<'a> Component for NrfStartupComponent<'a> { + erase_uicr |= !uicr.is_nfc_pins_protection_enabled(); + } + ++ // Avoid killing the DFU bootloader if present ++ let (dfu_start_addr, dfu_settings_addr) = uicr.get_dfu_params(); ++ + if erase_uicr { + self.nvmc.erase_uicr(); + } +@@ -62,6 +65,11 @@ impl<'a> Component for NrfStartupComponent<'a> { + + let mut needs_soft_reset: bool = false; + ++ // Restore DFU bootloader settings if we erased ++ if erase_uicr { ++ uicr.set_dfu_params(dfu_start_addr, dfu_settings_addr); ++ } ++ + // Configure reset pins + if uicr + .get_psel0_reset_pin() diff --git a/chips/nrf52/src/uicr.rs b/chips/nrf52/src/uicr.rs -index 6bb6c86b7..3bb8b5a7d 100644 +index 4924bbd44..788533210 100644 --- a/chips/nrf52/src/uicr.rs +++ b/chips/nrf52/src/uicr.rs -@@ -1,38 +1,45 @@ +@@ -1,38 +1,44 @@ //! User information configuration registers -//! -//! Minimal implementation to support activation of the reset button on -//! nRF52-DK. -+ use enum_primitive::cast::FromPrimitive; -use kernel::common::registers::{register_bitfields, ReadWrite}; @@ -75,7 +100,7 @@ index 6bb6c86b7..3bb8b5a7d 100644 } register_bitfields! [u32, -@@ -58,6 +65,21 @@ register_bitfields! [u32, +@@ -58,6 +64,21 @@ register_bitfields! [u32, DISABLED = 0xff ] ], @@ -97,3 +122,22 @@ index 6bb6c86b7..3bb8b5a7d 100644 /// Setting of pins dedicated to NFC functionality: NFC antenna or GPIO NfcPins [ /// Setting pins dedicated to NFC functionality +@@ -172,6 +193,18 @@ impl Uicr { + self.registers.nfcpins.matches_all(NfcPins::PROTECT::NFC) + } + ++ pub fn get_dfu_params(&self) -> (u32, u32) { ++ ( ++ self.registers.nrffw[0].get(), // DFU start address ++ self.registers.nrffw[1].get(), // DFU settings address ++ ) ++ } ++ ++ pub fn set_dfu_params(&self, dfu_start_addr: u32, dfu_settings_addr: u32) { ++ self.registers.nrffw[0].set(dfu_start_addr); ++ self.registers.nrffw[1].set(dfu_settings_addr); ++ } ++ + pub fn is_ap_protect_enabled(&self) -> bool { + // Here we compare to DISABLED value because any other value should enable the protection. + !self diff --git a/patches/tock/06-firmware-protect.patch b/patches/tock/05-firmware-protect.patch similarity index 74% rename from patches/tock/06-firmware-protect.patch rename to patches/tock/05-firmware-protect.patch index 063185d..3322080 100644 --- a/patches/tock/06-firmware-protect.patch +++ b/patches/tock/05-firmware-protect.patch @@ -75,105 +75,19 @@ index 000000000..58695af81 + } +} diff --git a/boards/components/src/lib.rs b/boards/components/src/lib.rs -index 917497af4..520408fcb 100644 +index a3bbe724b..95625f91f 100644 --- a/boards/components/src/lib.rs +++ b/boards/components/src/lib.rs -@@ -9,6 +9,7 @@ pub mod console; - pub mod crc; +@@ -13,6 +13,7 @@ pub mod crc; + pub mod ctap; pub mod debug_queue; pub mod debug_writer; +pub mod firmware_protection; pub mod ft6x06; + pub mod fxos8700; pub mod gpio; - pub mod hd44780; -diff --git a/boards/nordic/nrf52840_dongle_opensk/src/main.rs b/boards/nordic/nrf52840_dongle_opensk/src/main.rs -index 115e17280..3e35f7e90 100644 ---- a/boards/nordic/nrf52840_dongle_opensk/src/main.rs -+++ b/boards/nordic/nrf52840_dongle_opensk/src/main.rs -@@ -100,6 +100,7 @@ pub struct Platform { - 'static, - nrf52840::usbd::Usbd<'static>, - >, -+ crp: &'static capsules::firmware_protection::FirmwareProtection, - } - - impl kernel::Platform for Platform { -@@ -117,6 +118,7 @@ impl kernel::Platform for Platform { - capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)), - nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)), - capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)), -+ capsules::firmware_protection::DRIVER_NUM => f(Some(self.crp)), - kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), - _ => f(None), - } -@@ -324,6 +326,14 @@ pub unsafe fn reset_handler() { - ) - .finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd)); - -+ let crp = components::firmware_protection::FirmwareProtectionComponent::new( -+ board_kernel, -+ nrf52840::uicr::Uicr::new(), -+ ) -+ .finalize(components::firmware_protection_component_helper!( -+ nrf52840::uicr::Uicr -+ )); -+ - nrf52_components::NrfClockComponent::new().finalize(()); - - let platform = Platform { -@@ -337,6 +347,7 @@ pub unsafe fn reset_handler() { - analog_comparator, - nvmc, - usb, -+ crp, - ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), - }; - -diff --git a/boards/nordic/nrf52840dk_opensk/src/main.rs b/boards/nordic/nrf52840dk_opensk/src/main.rs -index 41047a390..05e19b821 100644 ---- a/boards/nordic/nrf52840dk_opensk/src/main.rs -+++ b/boards/nordic/nrf52840dk_opensk/src/main.rs -@@ -163,6 +163,7 @@ pub struct Platform { - 'static, - nrf52840::usbd::Usbd<'static>, - >, -+ crp: &'static capsules::firmware_protection::FirmwareProtection, - } - - impl kernel::Platform for Platform { -@@ -180,6 +181,7 @@ impl kernel::Platform for Platform { - capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)), - nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)), - capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)), -+ capsules::firmware_protection::DRIVER_NUM => f(Some(self.crp)), - kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), - _ => f(None), - } -@@ -409,6 +411,14 @@ pub unsafe fn reset_handler() { - ) - .finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd)); - -+ let crp = components::firmware_protection::FirmwareProtectionComponent::new( -+ board_kernel, -+ nrf52840::uicr::Uicr::new(), -+ ) -+ .finalize(components::firmware_protection_component_helper!( -+ nrf52840::uicr::Uicr -+ )); -+ - nrf52_components::NrfClockComponent::new().finalize(()); - - let platform = Platform { -@@ -422,6 +432,7 @@ pub unsafe fn reset_handler() { - analog_comparator, - nvmc, - usb, -+ crp, - ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), - }; - diff --git a/capsules/src/driver.rs b/capsules/src/driver.rs -index ae458b309..f536dad32 100644 +index b6124c4c0..90a18ea47 100644 --- a/capsules/src/driver.rs +++ b/capsules/src/driver.rs @@ -16,6 +16,7 @@ pub enum NUM { @@ -276,10 +190,10 @@ index 000000000..8cf63d6a4 + } +} diff --git a/capsules/src/lib.rs b/capsules/src/lib.rs -index e4423fe05..7538aad18 100644 +index 925b4ba41..919638c5d 100644 --- a/capsules/src/lib.rs +++ b/capsules/src/lib.rs -@@ -22,6 +22,7 @@ pub mod crc; +@@ -25,6 +25,7 @@ pub mod ctap; pub mod dac; pub mod debug_process_restart; pub mod driver; @@ -288,13 +202,12 @@ index e4423fe05..7538aad18 100644 pub mod ft6x06; pub mod fxos8700cq; diff --git a/chips/nrf52/src/uicr.rs b/chips/nrf52/src/uicr.rs -index 3bb8b5a7d..ea96cb2ae 100644 +index 788533210..655a98d5b 100644 --- a/chips/nrf52/src/uicr.rs +++ b/chips/nrf52/src/uicr.rs -@@ -1,13 +1,14 @@ +@@ -1,12 +1,14 @@ //! User information configuration registers -- use enum_primitive::cast::FromPrimitive; +use hil::firmware_protection::ProtectionLevel; use kernel::common::registers::{register_bitfields, register_structs, ReadWrite}; @@ -303,11 +216,11 @@ index 3bb8b5a7d..ea96cb2ae 100644 use kernel::ReturnCode; use crate::gpio::Pin; -+use crate::nvmc::NVMC; ++use crate::nvmc; const UICR_BASE: StaticRef = unsafe { StaticRef::new(0x10001000 as *const UicrRegisters) }; -@@ -210,3 +211,49 @@ impl Uicr { +@@ -217,3 +219,49 @@ impl Uicr { self.registers.approtect.write(ApProtect::PALL::ENABLED); } } @@ -335,7 +248,7 @@ index 3bb8b5a7d..ea96cb2ae 100644 + return ReturnCode::EALREADY; + } + -+ unsafe { NVMC.configure_writeable() }; ++ nvmc::Nvmc::new().configure_writeable(); + if level >= ProtectionLevel::JtagDisabled { + self.set_ap_protect(); + } @@ -348,7 +261,7 @@ index 3bb8b5a7d..ea96cb2ae 100644 + .write(DebugControl::CPUNIDEN::DISABLED + DebugControl::CPUFPBEN::DISABLED); + // TODO(jmichel): prevent returning into bootloader if present + } -+ unsafe { NVMC.configure_readonly() }; ++ nvmc::Nvmc::new().configure_readonly(); + + if self.get_protection() == level { + ReturnCode::SUCCESS @@ -412,10 +325,10 @@ index 000000000..de0824646 + fn set_protection(&self, level: ProtectionLevel) -> ReturnCode; +} diff --git a/kernel/src/hil/mod.rs b/kernel/src/hil/mod.rs -index 4f42afa02..83e7702ab 100644 +index f2d3629a9..d6eb39d2d 100644 --- a/kernel/src/hil/mod.rs +++ b/kernel/src/hil/mod.rs -@@ -8,6 +8,7 @@ pub mod dac; +@@ -9,6 +9,7 @@ pub mod dac; pub mod digest; pub mod eic; pub mod entropy; diff --git a/patches/tock/06-upgrade-partitions.patch b/patches/tock/06-upgrade-partitions.patch new file mode 100644 index 0000000..38defec --- /dev/null +++ b/patches/tock/06-upgrade-partitions.patch @@ -0,0 +1,56 @@ +diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs +index 807170195..a13413791 100644 +--- a/kernel/src/lib.rs ++++ b/kernel/src/lib.rs +@@ -122,7 +122,7 @@ pub use crate::sched::cooperative::{CoopProcessNode, CooperativeSched}; + pub use crate::sched::mlfq::{MLFQProcessNode, MLFQSched}; + pub use crate::sched::priority::PrioritySched; + pub use crate::sched::round_robin::{RoundRobinProcessNode, RoundRobinSched}; +-pub use crate::sched::{Kernel, Scheduler, StorageLocation}; ++pub use crate::sched::{Kernel, Scheduler, StorageLocation, StorageType}; + + // Export only select items from the process module. To remove the name conflict + // this cannot be called `process`, so we use a shortened version. These +diff --git a/kernel/src/memop.rs b/kernel/src/memop.rs +index 5465c95f4..e596648f7 100644 +--- a/kernel/src/memop.rs ++++ b/kernel/src/memop.rs +@@ -127,6 +127,14 @@ pub(crate) fn memop(process: &dyn ProcessType, op_type: usize, r1: usize) -> Ret + } + } + ++ // Op Type 15: The type of the storage location indexed by r1. ++ 15 => { ++ match process.get_storage_location(r1) { ++ None => ReturnCode::FAIL, ++ Some(x) => ReturnCode::SuccessWithValue { value: x.storage_type as usize } ++ } ++ } ++ + _ => ReturnCode::ENOSUPPORT, + } + } +diff --git a/kernel/src/sched.rs b/kernel/src/sched.rs +index 031159500..0cbfea929 100644 +--- a/kernel/src/sched.rs ++++ b/kernel/src/sched.rs +@@ -118,10 +118,19 @@ pub enum SchedulingDecision { + TrySleep, + } + ++/// Represents the type of a storage slice. ++#[derive(Copy, Clone)] ++pub enum StorageType { ++ STORE = 1, ++ PARTITION = 2, ++ METADATA = 3, ++} ++ + /// Represents a storage location in flash. + pub struct StorageLocation { + pub address: usize, + pub size: usize, ++ pub storage_type: StorageType, + } + + /// Main object for the kernel. Each board will need to create one. diff --git a/patches/tock/07-app-break-fix.patch b/patches/tock/07-app-break-fix.patch new file mode 100644 index 0000000..738cf23 --- /dev/null +++ b/patches/tock/07-app-break-fix.patch @@ -0,0 +1,13 @@ +diff --git a/arch/cortex-m/src/syscall.rs b/arch/cortex-m/src/syscall.rs +index c78b1c9fb..2769d0138 100644 +--- a/arch/cortex-m/src/syscall.rs ++++ b/arch/cortex-m/src/syscall.rs +@@ -65,7 +65,7 @@ impl kernel::syscall::UserspaceKernelBoundary for SysCall { + // + // The 1.x Tock kernel allocates at least 3 kB to processes, and we need + // to ensure that happens as userspace may expect it. +- 3 * 1024 ++ 16 * 1024 + + // TOCK 2.0 + // diff --git a/patches/tock/07-upgrade-partitions.patch b/patches/tock/07-upgrade-partitions.patch deleted file mode 100644 index 5e23a8f..0000000 --- a/patches/tock/07-upgrade-partitions.patch +++ /dev/null @@ -1,92 +0,0 @@ -diff --git a/boards/nordic/nrf52840_dongle_opensk/src/main.rs b/boards/nordic/nrf52840_dongle_opensk/src/main.rs -index 3e35f7e90..b624e19a2 100644 ---- a/boards/nordic/nrf52840_dongle_opensk/src/main.rs -+++ b/boards/nordic/nrf52840_dongle_opensk/src/main.rs -@@ -64,6 +64,7 @@ static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROC - static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 1] = [kernel::StorageLocation { - address: 0xC0000, - size: 0x40000, -+ storage_type: kernel::StorageType::STORE, - }]; - - // Static reference to chip for panic dumps -diff --git a/boards/nordic/nrf52840_mdk_dfu/src/main.rs b/boards/nordic/nrf52840_mdk_dfu/src/main.rs -index 25bd61460..84c7cff70 100644 ---- a/boards/nordic/nrf52840_mdk_dfu/src/main.rs -+++ b/boards/nordic/nrf52840_mdk_dfu/src/main.rs -@@ -59,6 +59,7 @@ static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROC - static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 1] = [kernel::StorageLocation { - address: 0xC0000, - size: 0x40000, -+ storage_type: kernel::StorageType::STORE, - }]; - - // Static reference to chip for panic dumps -diff --git a/boards/nordic/nrf52840dk_opensk/src/main.rs b/boards/nordic/nrf52840dk_opensk/src/main.rs -index 05e19b821..47b27bf0a 100644 ---- a/boards/nordic/nrf52840dk_opensk/src/main.rs -+++ b/boards/nordic/nrf52840dk_opensk/src/main.rs -@@ -128,6 +128,7 @@ static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROC - static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 1] = [kernel::StorageLocation { - address: 0xC0000, - size: 0x40000, -+ storage_type: kernel::StorageType::STORE, - }]; - - static mut CHIP: Option<&'static nrf52840::chip::Chip> = None; -diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs -index 428d90c29..2109a207e 100644 ---- a/kernel/src/lib.rs -+++ b/kernel/src/lib.rs -@@ -123,7 +123,7 @@ pub use crate::sched::cooperative::{CoopProcessNode, CooperativeSched}; - pub use crate::sched::mlfq::{MLFQProcessNode, MLFQSched}; - pub use crate::sched::priority::PrioritySched; - pub use crate::sched::round_robin::{RoundRobinProcessNode, RoundRobinSched}; --pub use crate::sched::{Kernel, Scheduler, StorageLocation}; -+pub use crate::sched::{Kernel, Scheduler, StorageLocation, StorageType}; - - // Export only select items from the process module. To remove the name conflict - // this cannot be called `process`, so we use a shortened version. These -diff --git a/kernel/src/memop.rs b/kernel/src/memop.rs -index 5465c95f4..e596648f7 100644 ---- a/kernel/src/memop.rs -+++ b/kernel/src/memop.rs -@@ -127,6 +127,14 @@ pub(crate) fn memop(process: &dyn ProcessType, op_type: usize, r1: usize) -> Ret - } - } - -+ // Op Type 15: The type of the storage location indexed by r1. -+ 15 => { -+ match process.get_storage_location(r1) { -+ None => ReturnCode::FAIL, -+ Some(x) => ReturnCode::SuccessWithValue { value: x.storage_type as usize } -+ } -+ } -+ - _ => ReturnCode::ENOSUPPORT, - } - } -diff --git a/kernel/src/sched.rs b/kernel/src/sched.rs -index f109960d3..9eaf98585 100644 ---- a/kernel/src/sched.rs -+++ b/kernel/src/sched.rs -@@ -118,10 +118,19 @@ pub enum SchedulingDecision { - TrySleep, - } - -+/// Represents the type of a storage slice. -+#[derive(Copy, Clone)] -+pub enum StorageType { -+ STORE = 1, -+ PARTITION = 2, -+ METADATA = 3, -+} -+ - /// Represents a storage location in flash. - pub struct StorageLocation { - pub address: usize, - pub size: usize, -+ pub storage_type: StorageType, - } - - /// Main object for the kernel. Each board will need to create one. diff --git a/setup.sh b/setup.sh index 90ee8c8..e3febf9 100755 --- a/setup.sh +++ b/setup.sh @@ -37,14 +37,13 @@ check_command pip3 source tools/gen_key_materials.sh generate_crypto_materials N -rustup install $(head -n 1 rust-toolchain) +rustup show pip3 install --user --upgrade 'tockloader==1.5' six intelhex -rustup target add thumbv7em-none-eabi # Install dependency to create applications. mkdir -p elf2tab rustup install stable -cargo +stable install elf2tab --version 0.6.0 --root elf2tab/ +cargo +stable install elf2tab --version 0.7.0 --root elf2tab/ # Install python dependencies to factory configure OpenSK (crypto, JTAG lockdown) pip3 install --user --upgrade colorama tqdm cryptography "fido2>=0.9.1" diff --git a/src/ctap/apdu.rs b/src/ctap/apdu.rs index 455e574..2c1cb23 100644 --- a/src/ctap/apdu.rs +++ b/src/ctap/apdu.rs @@ -93,7 +93,7 @@ pub enum ApduType { #[derive(Clone, Debug, PartialEq)] #[allow(dead_code)] -pub struct APDU { +pub struct Apdu { pub header: ApduHeader, pub lc: u16, pub data: Vec, @@ -101,7 +101,7 @@ pub struct APDU { pub case_type: ApduType, } -impl TryFrom<&[u8]> for APDU { +impl TryFrom<&[u8]> for Apdu { type Error = ApduStatusCode; fn try_from(frame: &[u8]) -> Result { @@ -115,7 +115,7 @@ impl TryFrom<&[u8]> for APDU { if payload.is_empty() { // Lc is zero-bytes in length - return Ok(APDU { + return Ok(Apdu { header: array_ref!(header, 0, APDU_HEADER_LEN).into(), lc: 0x00, data: Vec::new(), @@ -128,7 +128,7 @@ impl TryFrom<&[u8]> for APDU { if payload.len() == 1 { // There is only one byte in the payload, that byte cannot be Lc because that would // entail at *least* one another byte in the payload (for the command data) - return Ok(APDU { + return Ok(Apdu { header: array_ref!(header, 0, APDU_HEADER_LEN).into(), lc: 0x00, data: Vec::new(), @@ -144,7 +144,7 @@ impl TryFrom<&[u8]> for APDU { if payload.len() == 1 + (byte_0 as usize) && byte_0 != 0 { // Lc is one-byte long and since the size specified by Lc covers the rest of the // payload there's no Le at the end - return Ok(APDU { + return Ok(Apdu { header: array_ref!(header, 0, APDU_HEADER_LEN).into(), lc: byte_0.into(), data: payload[1..].to_vec(), @@ -156,7 +156,7 @@ impl TryFrom<&[u8]> for APDU { // Lc is one-byte long and since the size specified by Lc covers the rest of the // payload with ONE additional byte that byte must be Le let last_byte: u32 = (*payload.last().unwrap()).into(); - return Ok(APDU { + return Ok(Apdu { header: array_ref!(header, 0, APDU_HEADER_LEN).into(), lc: byte_0.into(), data: payload[1..(payload.len() - 1)].to_vec(), @@ -184,7 +184,7 @@ impl TryFrom<&[u8]> for APDU { // length that covers the rest of the block (plus few additional bytes for Le), we // have an extended-length APDU let last_byte: u32 = (*payload.last().unwrap()).into(); - return Ok(APDU { + return Ok(Apdu { header: array_ref!(header, 0, APDU_HEADER_LEN).into(), lc: extended_apdu_lc as u16, data: payload[3..(payload.len() - extended_apdu_le_len)].to_vec(), @@ -239,8 +239,8 @@ impl TryFrom<&[u8]> for APDU { mod test { use super::*; - fn pass_frame(frame: &[u8]) -> Result { - APDU::try_from(frame) + fn pass_frame(frame: &[u8]) -> Result { + Apdu::try_from(frame) } #[test] @@ -248,7 +248,7 @@ mod test { let frame: [u8; 4] = [0x00, 0x12, 0x00, 0x80]; let response = pass_frame(&frame); assert!(response.is_ok()); - let expected = APDU { + let expected = Apdu { header: ApduHeader { cla: 0x00, ins: 0x12, @@ -267,7 +267,7 @@ mod test { fn test_case_type_2_short() { let frame: [u8; 5] = [0x00, 0xb0, 0x00, 0x00, 0x0f]; let response = pass_frame(&frame); - let expected = APDU { + let expected = Apdu { header: ApduHeader { cla: 0x00, ins: 0xb0, @@ -286,7 +286,7 @@ mod test { fn test_case_type_2_short_le() { let frame: [u8; 5] = [0x00, 0xb0, 0x00, 0x00, 0x00]; let response = pass_frame(&frame); - let expected = APDU { + let expected = Apdu { header: ApduHeader { cla: 0x00, ins: 0xb0, @@ -306,7 +306,7 @@ mod test { let frame: [u8; 7] = [0x00, 0xa4, 0x00, 0x0c, 0x02, 0xe1, 0x04]; let payload = [0xe1, 0x04]; let response = pass_frame(&frame); - let expected = APDU { + let expected = Apdu { header: ApduHeader { cla: 0x00, ins: 0xa4, @@ -328,7 +328,7 @@ mod test { ]; let payload = [0xd2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01]; let response = pass_frame(&frame); - let expected = APDU { + let expected = Apdu { header: ApduHeader { cla: 0x00, ins: 0xa4, @@ -350,7 +350,7 @@ mod test { ]; let payload = [0xd2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01]; let response = pass_frame(&frame); - let expected = APDU { + let expected = Apdu { header: ApduHeader { cla: 0x00, ins: 0xa4, @@ -392,7 +392,7 @@ mod test { ]; let payload: &[u8] = &frame[7..frame.len() - 2]; let response = pass_frame(&frame); - let expected = APDU { + let expected = Apdu { header: ApduHeader { cla: 0x00, ins: 0x02, @@ -419,7 +419,7 @@ mod test { ]; let payload: &[u8] = &frame[7..frame.len() - 2]; let response = pass_frame(&frame); - let expected = APDU { + let expected = Apdu { header: ApduHeader { cla: 0x00, ins: 0x01, diff --git a/src/ctap/config_command.rs b/src/ctap/config_command.rs index 54daeba..6599220 100644 --- a/src/ctap/config_command.rs +++ b/src/ctap/config_command.rs @@ -86,10 +86,8 @@ pub fn process_config( pin_uv_auth_protocol, } = params; - let enforce_uv = match sub_command { - ConfigSubCommand::ToggleAlwaysUv => false, - _ => true, - } && persistent_store.has_always_uv()?; + let enforce_uv = !matches!(sub_command, ConfigSubCommand::ToggleAlwaysUv) + && persistent_store.has_always_uv()?; if persistent_store.pin_hash()?.is_some() || enforce_uv { let pin_uv_auth_param = pin_uv_auth_param.ok_or(Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED)?; diff --git a/src/ctap/ctap1.rs b/src/ctap/ctap1.rs index d5e60ee..1fc3b03 100644 --- a/src/ctap/ctap1.rs +++ b/src/ctap/ctap1.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::apdu::{ApduStatusCode, APDU}; +use super::apdu::{Apdu, ApduStatusCode}; use super::hid::ChannelID; use super::status_code::Ctap2StatusCode; use super::CtapState; @@ -81,7 +81,7 @@ impl TryFrom<&[u8]> for U2fCommand { type Error = Ctap1StatusCode; fn try_from(message: &[u8]) -> Result { - let apdu: APDU = match APDU::try_from(message) { + let apdu: Apdu = match Apdu::try_from(message) { Ok(apdu) => apdu, Err(apdu_status_code) => { return Err(Ctap1StatusCode::try_from(apdu_status_code).unwrap()) diff --git a/src/ctap/hid/send.rs b/src/ctap/hid/send.rs index 22f9c61..5ea2e1c 100644 --- a/src/ctap/hid/send.rs +++ b/src/ctap/hid/send.rs @@ -234,8 +234,6 @@ mod test { } // Sanity check for the length of the payload. - assert_eq!((64 - 7) + 128 * (64 - 5), 0x1db9); - assert_eq!(7609, 0x1db9); assert_eq!(payload.len(), 0x1db9); let message = Message { @@ -244,14 +242,13 @@ mod test { payload, }; - let mut expected_packets = Vec::new(); - expected_packets.push([ + let mut expected_packets: Vec = vec![[ 0x12, 0x34, 0x56, 0x78, 0xAB, 0x1D, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - ]); + ]]; for i in 0..128 { let mut packet: HidPacket = [0; 64]; packet[0] = 0x12; diff --git a/src/embedded_flash/helper.rs b/src/embedded_flash/helper.rs index 90168cb..a2a6feb 100644 --- a/src/embedded_flash/helper.rs +++ b/src/embedded_flash/helper.rs @@ -231,7 +231,7 @@ mod tests { let mut iter = ModRange::new(201, 99).aligned_iter(100); assert_eq!(iter.next(), None); let mut iter = ModRange::new(usize::MAX - 16, 20).aligned_iter(16); - assert_eq!(iter.next(), Some(0xf_fff_fff_fff_fff_ff0)); + assert_eq!(iter.next(), Some(0xffff_ffff_ffff_fff0)); assert_eq!(iter.next(), None); } } diff --git a/src/main.rs b/src/main.rs index 202a1ea..a471e55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,6 +47,8 @@ use libtock_drivers::timer::Timer; use libtock_drivers::timer::Timestamp; use libtock_drivers::usb_ctap_hid; +libtock_core::stack_size! {0x4000} + const KEEPALIVE_DELAY_MS: isize = 100; const KEEPALIVE_DELAY: Duration = Duration::from_ms(KEEPALIVE_DELAY_MS); const SEND_TIMEOUT: Duration = Duration::from_ms(1000); diff --git a/third_party/libtock-rs b/third_party/libtock-rs index 828c19d..15e837e 160000 --- a/third_party/libtock-rs +++ b/third_party/libtock-rs @@ -1 +1 @@ -Subproject commit 828c19de9292ddbca0e2da6a161c0c38124c5053 +Subproject commit 15e837e4495df2d7a39ae6d6c057fdec515cc430 diff --git a/third_party/tock b/third_party/tock index c5b7a4f..e916444 160000 --- a/third_party/tock +++ b/third_party/tock @@ -1 +1 @@ -Subproject commit c5b7a4f2c89a8c067f0f5786788f4037b32329fd +Subproject commit e916444378a3e683cde5b24f2cc166e5f056ff8c