From 48f32949bc0673900c75b0b0181a00c4756ab9db Mon Sep 17 00:00:00 2001 From: Matthew Mets Date: Mon, 24 Oct 2022 16:05:00 +0100 Subject: [PATCH 1/5] Add software reset example for the mta1 programmer --- hw/boards/mta1-usb-v1/test/reset.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 hw/boards/mta1-usb-v1/test/reset.py diff --git a/hw/boards/mta1-usb-v1/test/reset.py b/hw/boards/mta1-usb-v1/test/reset.py new file mode 100755 index 0000000..3bc9511 --- /dev/null +++ b/hw/boards/mta1-usb-v1/test/reset.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +import hid_test +import time + +def reset_mta1(): + """ Manipulate the GPIO lines on the MTA1-USB-CH552 Programmer to issue a hardware reset to the MTA1 """ + d = hid_test.ice40_flasher() + d.gpio_set_direction(14, True) + d.gpio_put(14, False) + d.gpio_set_direction(14, False) + d.close() + +reset_mta1() From 7af0fc67776706a1219d2c433f63eda6ef9505c5 Mon Sep 17 00:00:00 2001 From: Daniel Lublin Date: Tue, 25 Oct 2022 14:18:04 +0200 Subject: [PATCH 2/5] Make hid_test fail less confusingly when programming device is not connected Add requirements.txt --- hw/boards/mta1-usb-v1/test/hid_test.py | 3 +++ hw/boards/mta1-usb-v1/test/requirements.txt | 4 ++++ hw/boards/mta1-usb-v1/test/reset.py | 9 ++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 hw/boards/mta1-usb-v1/test/requirements.txt diff --git a/hw/boards/mta1-usb-v1/test/hid_test.py b/hw/boards/mta1-usb-v1/test/hid_test.py index f384b6d..ddadc1b 100644 --- a/hw/boards/mta1-usb-v1/test/hid_test.py +++ b/hw/boards/mta1-usb-v1/test/hid_test.py @@ -9,8 +9,11 @@ USB_VID = 0xcafe class ice40_flasher: def __init__(self): + self.dev = None for dict in hid.enumerate(USB_VID): self.dev = hid.Device(dict['vendor_id'], dict['product_id']) + if self.dev is None: + raise IOError("Couldn't find any hid device with vendor id 0x%x" % (USB_VID)) def close(self): self.dev.close() diff --git a/hw/boards/mta1-usb-v1/test/requirements.txt b/hw/boards/mta1-usb-v1/test/requirements.txt new file mode 100644 index 0000000..0987a4e --- /dev/null +++ b/hw/boards/mta1-usb-v1/test/requirements.txt @@ -0,0 +1,4 @@ +hid==1.0.5 +numpy==1.23.4 +pyserial==3.5 +pyusb==1.2.1 diff --git a/hw/boards/mta1-usb-v1/test/reset.py b/hw/boards/mta1-usb-v1/test/reset.py index 3bc9511..bd23fdc 100755 --- a/hw/boards/mta1-usb-v1/test/reset.py +++ b/hw/boards/mta1-usb-v1/test/reset.py @@ -2,12 +2,15 @@ import hid_test import time -def reset_mta1(): - """ Manipulate the GPIO lines on the MTA1-USB-CH552 Programmer to issue a hardware reset to the MTA1 """ + +def reset_tk1(): + """Manipulate the GPIO lines on the MTA1-USB-CH552 Programmer to issue a + hardware reset to the TK1. The result is that TK1 again will be in firmware + mode, so a new app can be loaded.""" d = hid_test.ice40_flasher() d.gpio_set_direction(14, True) d.gpio_put(14, False) d.gpio_set_direction(14, False) d.close() -reset_mta1() +reset_tk1() From fdda69745efc4e5734fba993fa24d6382650ae15 Mon Sep 17 00:00:00 2001 From: Daniel Lublin Date: Tue, 25 Oct 2022 15:14:45 +0200 Subject: [PATCH 3/5] Add wrapper script that runs reset.py using virtualenv --- .gitignore | 2 ++ doc/quickstart.md | 5 ++++- hw/application_fpga/tools/reset-tk1 | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100755 hw/application_fpga/tools/reset-tk1 diff --git a/.gitignore b/.gitignore index 2e7a69d..57a8473 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,5 @@ fp-info-cache *.net *.dsn *.ses + +__pycache__ diff --git a/doc/quickstart.md b/doc/quickstart.md index 6e7aef2..a1e17ff 100644 --- a/doc/quickstart.md +++ b/doc/quickstart.md @@ -35,7 +35,10 @@ the touch sensor is located (next to the LED). Note that connecting the USB stick to the computer is not required for programming it. Note also that with this setup, to reset the USB stick back to firmware mode after loading an app, you need to unplug both the USB cable to -the stick and the one to the programmer. +the stick and the one to the programmer. Alternatively, you can try +the script in `../hw/application_fpga/tools/reset-tk1` which pokes at +the TK1 that's sitting in the jig, leaving it in firmware mode so that +a new app can be loaded. On Linux, `lsusb` should list the connected programmer as `cafe:4004 Blinkinlabs ICE40 programmer`. If the USB stick is also connected it diff --git a/hw/application_fpga/tools/reset-tk1 b/hw/application_fpga/tools/reset-tk1 new file mode 100755 index 0000000..0b47639 --- /dev/null +++ b/hw/application_fpga/tools/reset-tk1 @@ -0,0 +1,15 @@ +#!/bin/sh +set -eu + +cd "${0%/*}" +cd ../../boards/mta1-usb-v1/test + +if [ ! -e venv ]; then + python3 -m venv venv + . ./venv/bin/activate + pip3 install -r requirements.txt +else + . ./venv/bin/activate +fi + +./reset.py From a14662c622deecf974c3d555ef6cf45a4aa3ecb1 Mon Sep 17 00:00:00 2001 From: Daniel Lublin Date: Mon, 31 Oct 2022 15:02:48 +0100 Subject: [PATCH 4/5] Change to max 100 KB app with 28 KB stack --- README.md | 5 +++-- doc/system_description/software.md | 10 ++++++---- hw/application_fpga/fw/tk1/main.c | 15 ++++++--------- hw/application_fpga/fw/tk1/start.S | 8 ++++---- hw/application_fpga/fw/tk1_mem.h | 6 +++++- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index f14acd7..77d2ed8 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,9 @@ user-provided seed, is used to derive key material unique to each application. This allows users to build and load their own apps, while ensuring that each app loaded will have its own cryptographic identity. The design is similar to TCG DICE. The Tillitis Key 1 -platform has 128 KB of RAM. The current firmware design allows for -applications up to 64 KB with a 64 KB stack. +platform has 128 KB of RAM. The current firmware is designed to load +an app that is up to 100 KB in size, and gives it a stack of 28 KB. A +smaller ap may move itself in memory, in order to have a larger stack. ![Tillitis Key 1 PCB, first implementation](doc/images/mta1-usb-v1.jpg) *Tillitis Key 1 PCB, first implementation* diff --git a/doc/system_description/software.md b/doc/system_description/software.md index 9e92ddf..3589912 100644 --- a/doc/system_description/software.md +++ b/doc/system_description/software.md @@ -63,7 +63,9 @@ between the host and the device. ## Firmware The device has 128 KB RAM. The current firmware loads the app at the -upper 64 KB. The lower 64 KB is currently set up as stack for the app. +upper 100 KB. The lower 28 KB is set up as stack for the app. A +smaller app that wants a larger stack could relocate itself on +startup. The firmware is part of FPGA bitstream (ROM), and is loaded at `0x0000_0000`. @@ -73,7 +75,7 @@ The firmware is part of FPGA bitstream (ROM), and is loaded at The PicoRV32 starts executing at `0x0000_0000`. Our firmware starts at `_start` from `start.S` which initializes the `.data`, and `.bss` at `0x4000_0000` and upwards. A stack is also initialized, starting at -0x4000_fff0 and downwards. When the initialization is finished, the +0x4000_6ff0 and downwards. When the initialization is finished, the firmware waits for incoming commands from the host, by busy-polling the `UART_RX_{STATUS,DATA}` registers. When a complete command is read, the firmware executes the command. @@ -355,8 +357,8 @@ Assigned core prefixes: | | | | | | | returns 0 if device is in firmware mode, 0xffffffff if in app mode. | | `LED` | w | w | 1B | u8 | | | | `GPIO` | | | | | | | -| `APP_ADDR` | r/w | r | 4B | u32 | | Application address (0x4000_0000) | -| `APP_SIZE` | r/w | r | 4B | u32 | | Application size | +| `APP_ADDR` | r/w | r | 4B | u32 | | Firmware stores app load address here, so app can read its own location| +| `APP_SIZE` | r/w | r | 4B | u32 | | Firmware stores app app size here, so app can read its own size | | `CDI_FIRST` | r/w | r | 32B | u8[32] | | Compound Device Identifier (CDI). UDS+measurement... | | `CDI_LAST` | | r | | | | Last word of CDI | diff --git a/hw/application_fpga/fw/tk1/main.c b/hw/application_fpga/fw/tk1/main.c index b8ea921..19de43d 100644 --- a/hw/application_fpga/fw/tk1/main.c +++ b/hw/application_fpga/fw/tk1/main.c @@ -9,10 +9,6 @@ #include "proto.h" #include "types.h" -// In RAM + above the stack (0x40010000) -#define APP_RAM_ADDR (TK1_RAM_BASE + 0x10000) -#define APP_MAX_SIZE 65536 - // clang-format off static volatile uint32_t *uds = (volatile uint32_t *)TK1_MMIO_UDS_FIRST; static volatile uint32_t *switch_app = (volatile uint32_t *)TK1_MMIO_TK1_SWITCH_APP; @@ -95,7 +91,7 @@ int main() struct frame_header hdr; // Used in both directions uint8_t cmd[CMDLEN_MAXBYTES]; uint8_t rsp[CMDLEN_MAXBYTES]; - uint8_t *loadaddr = (uint8_t *)APP_RAM_ADDR; + uint8_t *loadaddr = (uint8_t *)TK1_APP_ADDR; int left = 0; // Bytes left to receive uint8_t uss[32] = {0}; uint8_t digest[32] = {0}; @@ -177,7 +173,7 @@ int main() putinthex(local_app_size); lf(); - if (local_app_size > APP_MAX_SIZE) { + if (local_app_size > TK1_APP_MAX_SIZE) { rsp[0] = STATUS_BAD; fwreply(hdr, FW_RSP_LOAD_APP_SIZE, rsp); break; @@ -190,7 +186,7 @@ int main() memset(digest, 0, 32); // Reset where to start loading the program - loadaddr = (uint8_t *)APP_RAM_ADDR; + loadaddr = (uint8_t *)TK1_APP_ADDR; left = *app_size; rsp[0] = STATUS_OK; @@ -224,7 +220,7 @@ int main() putinthex(*app_size); lf(); - *app_addr = APP_RAM_ADDR; + *app_addr = TK1_APP_ADDR; // Get the Blake2S digest of the app - store it // for later queries blake2s_ctx ctx; @@ -266,8 +262,9 @@ int main() lf(); // clang-format off asm volatile( + // Clear the stack "li a0, 0x40000000;" // TK1_RAM_BASE - "li a1, 0x40010000;" + "li a1, 0x40007000;" // APP_RAM_ADDR "loop:;" "sw zero, 0(a0);" "addi a0, a0, 4;" diff --git a/hw/application_fpga/fw/tk1/start.S b/hw/application_fpga/fw/tk1/start.S index 2a327bb..0b7d139 100644 --- a/hw/application_fpga/fw/tk1/start.S +++ b/hw/application_fpga/fw/tk1/start.S @@ -39,15 +39,15 @@ _start: li x31,0 /* Clear all RAM */ - li a0, 0x40000000 // RAM base - li a1, 0x40020000 // To end of SRAM + li a0, 0x40000000 // TK1_RAM_BASE + li a1, 0x40020000 // TK1_RAM_BASE + TK1_RAM_SIZE clear: sw zero, 0(a0) addi a0, a0, 4 blt a0, a1, clear - /* init stack to right under where we load app at 0x40010000 */ - li sp, 0x4000fff0 + /* init stack below 0x40007000 (TK1_APP_ADDR) where we load app */ + li sp, 0x40006ff0 /* copy data section */ la a0, _sidata diff --git a/hw/application_fpga/fw/tk1_mem.h b/hw/application_fpga/fw/tk1_mem.h index 9567a5a..dcd341b 100644 --- a/hw/application_fpga/fw/tk1_mem.h +++ b/hw/application_fpga/fw/tk1_mem.h @@ -20,10 +20,14 @@ enum { TK1_ROM_BASE = 0x00000000, // 0b00000000... TK1_RAM_BASE = 0x40000000, // 0b01000000... + TK1_RAM_SIZE = 0x20000, // 128 KB TK1_RESERVED_BASE = 0x80000000, // 0b10000000... TK1_MMIO_BASE = 0xc0000000, // 0b11000000... TK1_MMIO_SIZE = 0xffffffff - TK1_MMIO_BASE, + TK1_APP_ADDR = TK1_RAM_BASE + 0x7000, // 28 KB of stack + TK1_APP_MAX_SIZE = TK1_RAM_SIZE - (TK1_APP_ADDR - TK1_RAM_BASE), + TK1_MMIO_TRNG_BASE = TK1_MMIO_BASE | 0x00000000, TK1_MMIO_TIMER_BASE = TK1_MMIO_BASE | 0x01000000, TK1_MMIO_UDS_BASE = TK1_MMIO_BASE | 0x02000000, @@ -81,7 +85,7 @@ enum { TK1_MMIO_TK1_GPIO2_BIT = 1, TK1_MMIO_TK1_GPIO3_BIT = 2, TK1_MMIO_TK1_GPIO4_BIT = 3, - TK1_MMIO_TK1_APP_ADDR = TK1_MMIO_TK1_BASE | 0x30, // 0x4000_0000 + TK1_MMIO_TK1_APP_ADDR = TK1_MMIO_TK1_BASE | 0x30, TK1_MMIO_TK1_APP_SIZE = TK1_MMIO_TK1_BASE | 0x34, TK1_MMIO_TK1_CDI_FIRST = TK1_MMIO_TK1_BASE | 0x80, TK1_MMIO_TK1_CDI_LAST = TK1_MMIO_TK1_BASE | 0x9c, // Address of last 32-bit word of CDI. From 254a3841810d4a946e29503feb0f784d30f28c21 Mon Sep 17 00:00:00 2001 From: Michael Cardell Widerkrantz Date: Thu, 3 Nov 2022 16:11:31 +0100 Subject: [PATCH 5/5] fw: Clarify and correct doc --- README.md | 3 ++- doc/system_description/software.md | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 77d2ed8..01e5bdf 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ ensuring that each app loaded will have its own cryptographic identity. The design is similar to TCG DICE. The Tillitis Key 1 platform has 128 KB of RAM. The current firmware is designed to load an app that is up to 100 KB in size, and gives it a stack of 28 KB. A -smaller ap may move itself in memory, in order to have a larger stack. +smaller app may want to move itself in memory to get larger continuous +memory. ![Tillitis Key 1 PCB, first implementation](doc/images/mta1-usb-v1.jpg) *Tillitis Key 1 PCB, first implementation* diff --git a/doc/system_description/software.md b/doc/system_description/software.md index 3589912..070fc33 100644 --- a/doc/system_description/software.md +++ b/doc/system_description/software.md @@ -64,8 +64,8 @@ between the host and the device. The device has 128 KB RAM. The current firmware loads the app at the upper 100 KB. The lower 28 KB is set up as stack for the app. A -smaller app that wants a larger stack could relocate itself on -startup. +smaller app that wants continuous memory may want to relocate itself +when starting. The firmware is part of FPGA bitstream (ROM), and is loaded at `0x0000_0000`. @@ -83,7 +83,7 @@ read, the firmware executes the command. ### Loading an application The purpose of the firmware is to bootstrap an application. The host -will send a raw binary targeted to be loaded at `0x4001_0000` in the +will send a raw binary targeted to be loaded at `0x4000_7000` in the device. 1. The host sends the User Supplied Secret (USS) by using the @@ -98,7 +98,7 @@ device. multiple `FW_CMD_LOAD_APP_DATA` commands, together containing the full application. 5. For each received `FW_CMD_LOAD_APP_DATA` command the firmware - places the data into `0x4001_0000` and upwards. The firmware + places the data into `0x4000_7000` and upwards. The firmware replies with a `FW_RSP_LOAD_APP_DATA` response to the host for each received block. 6. When the final block of the application image is received, we @@ -107,7 +107,7 @@ device. The Compound Device Identifier is computed by using the `UDS`, the measurement of the application, and the `USS`, and placed in - the `CDI` register. Then `0x4001_0000` is written to `APP_ADDR`. + the `CDI` register. Then `0x4000_7000` is written to `APP_ADDR`. The final `FW_RSP_LOAD_APP_DATA` response is sent to the host, completing the loading.