diff --git a/docs/building.md b/docs/building.md index 0b498af..64e9d0b 100644 --- a/docs/building.md +++ b/docs/building.md @@ -5,7 +5,7 @@ There exists a development board [NUCLEO-L432KC](https://www.st.com/en/evaluatio # Prerequisites -Install the [latest ARM compiler toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) for your system. +Install the [latest ARM compiler toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) for your system. We recommend getting the latest compilers from ARM. You can also install the ARM toolchain using a package manage like `apt-get` or `pacman`, but be warned they might be out of date. Typically it will be called `gcc-arm-none-eabi binutils-arm-none-eabi`. @@ -30,117 +30,131 @@ Build the cbor library. make cbor ``` -Now build the Solo bootloader. +Now build Solo. ``` -make clean -make boot -# Or to make a Solo Hacker build: -# make boot-hacker +make build-hacker ``` -Now build the Solo application. +The `build-hacker` recipe does a few things. First it builds the bootloader, with +signature checking disabled. Then it builds the Solo application with "hacker" features +enabled, like being able to jump to the bootloader on command. It then merges bootloader +and solo builds into the same binary. I.e. it combines `bootloader.hex` and `solo.hex` +into `all.hex`. + +If you're just planning to do development, please don't try to reprogram the bootloader, +as this can be risky if done often. Just use `solo.hex`. + +### Building with debug messages + +If you're developing, you probably want to see debug messages! Solo has a USB +Serial port that it will send debug messages through (from `printf`). You can read them using +a normal serial terminal like `picocom` or `putty`. + +Just add `DEBUG=1` or `DEBUG=2` to your build recipe, like this. ``` -make clean -make -# Or to make a Solo Hacker build: -# make all-hacker +make build-hacker DEBUG=1 ``` -Note that for hacker builds, the bootloader must be built using the `boot-hacker` recipe. +If you use `DEBUG=2`, that means Solo will not boot until something starts reading +it's debug messages. So it basically it waits to tether to a serial terminal so that you don't +miss any debug messages. -Merge the two files together. This script also patches a spot in memory to -allow the bootloader to boot the application. This memory spot is later used for -signed firmware updates. +We recommend using our `solotool.py` as a serial emulator since it will automatically +reconnect each time you program Solo. ``` -python merge_hex.py solo.hex bootloader.hex all.hex +python tools/solotool.py monitor ``` -You can now program Solo with `all.hex`. +### Building a Solo release -# Solo Hacker +If you want to build a release of Solo, we recommend trying a Hacker build first +just to make sure that it's working. Otherwise it may not be as easy or possible to +fix any mistakes. -A Solo Hacker build is more friendly for development. If you just want to test your -solo build or do any sort of development, you should start with this. +If you're ready to program a full release, run this recipe to build. -It is the same build as a production Solo, but it has extra commands available. +``` +make build-release-locked +``` -* Allows updates at any time without pressing button. -* Opens a USB emulated serial port for printing. -* Doesn't lock the flash or debugger at all. +Programming `all.hex` will cause the device to permanently lock itself. -You if build with Solo Hacker, you can always completely overwrite it and start over. -If it's not a hacker build, you cannot reprogram Solo as easily. - -* `all-hacker`: can be reprogrammed again over USB or via wire with a programmer. -* `all`: can be reprogrammed using only signed updates or via wire with a programmer. -* `all-locked`: Can only be reprogrammed via signed updates unless they are disabled. # Programming It's recommended to test a debug/hacker build first to make sure Solo is working as expected. Then you can switch to a locked down build, which cannot be reprogrammed as easily (or not at all!). +We recommend using our `solotool.py` to manage programming. It is cross platform. First you must +install the prerequisites: + +``` +pip3 install -r tools/requirements.txt +``` + +If you're on Windows, you must also install [libusb](https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/1.2.6.0/). + +## Pre-programmed Solo Hacker + +If your Solo device is already programmed (it flashes green when powered), we recommend +programming it using the Solo bootloader. + +``` +python tools/solotool.py program solo.hex +``` + +Make sure to program `solo.hex` and not `all.hex`. Nothing bad would happen, but you'd +see errors. + +If something bad happens, you can always boot the Solo bootloader by doing the following. + +1. Unplug device. +2. Hold down button. +3. Plug in device while holding down button. +4. Wait about 2 seconds for flashing yellow light. Release button. + +If you hold the button for an additional 5 seconds, it will boot to the ST DFU (device firmware update). +Don't use the ST DFU unless you know what you're doing. + ## ST USB DFU -If your Solo has never been programmed, it will boot the ST USB DFU. You can program -it via USB. After you program it, it will still be in ST USB DFU mode. You additionally -need to supply a command to tell the DFU program to "detach" and boot the application. +If your Solo has never been programmed, it will boot the ST USB DFU. The LED is turned +off and it enumerates as "STM BOOTLOADER". -If you power cycle Solo, it will return to DFU mode so you can reprogram it. If you don't -want it to do this, you must set the option bytes bit `nBOOT0=1`. Now it will always boot the application. - -Example using STM32CubeProg. +You can program it by running the following. ``` -# Program all.hex -STM32_Programmer_CLI -c port=usb1 -halt -d all.hex - -# If you want it to always boot application, set nBOOT0=1 -STM32_Programmer_CLI -c port=usb1 -ob nBOOT0=1 +python tools/solotool.py program all.hex --use-dfu --detach ``` -If Solo has been programmed with a hacker build, you can return it to ST DFU mode using just USB. +Make sure to program `all.hex`, as this contains both the bootloader and the Solo application. -``` -# Use our programmer script +If all goes well, you should see a slow-flashing green light. -# Makes it boot to ST DFU once -python tools/programmer.py --st-dfu - -# OR -# Make it boot to ST DFU every boot (initial state basically) -python tools/programmer.py --enter-bootloader -python tools/programmer.py --st-dfu -``` - -## Solo / Solo Hacker updates - -To program a Solo Hacker device, run the following. Note you should only specify the application -firmware, not the combined bootloader+application! I.e. not `all.hex` from above. - -```bash -python tools/programmer.py target/stm32l442/solo.hex -``` +## Solo Hacker vs Solo A Solo hacker device doesn't need to be in bootloader mode to be programmed, it will automatically switch. -If the application gets bricked, you can hold down the button for 2 seconds while -plugging it in the token make it stay in the bootloader. Holding the button an additional 5 seconds -will return it to the ST DFU. + +Solo (locked) needs the button to be held down when plugged in to boot to the bootloader. + +A locked Solo will only accept signed updates. + +## Signed updates If this is not a device with a hacker build, you can only program signed updates. ``` -python tools/programmer.py /path/to/firmware.json +python tools/solotool.py program /path/to/firmware.json ``` If you've provisioned the Solo bootloader with your own secp256r1 public key, you can sign your firmware by running the following command. ``` -python tools/sign_firmware.py /path/to/signing-key.pem /path/to/solo.hex /output-path/to/firmware.json +python tools/solotool.py sign /path/to/signing-key.pem /path/to/solo.hex /output-path/to/firmware.json ``` If your Solo isn't locked, you can always reprogram it using a debugger connected directly @@ -151,13 +165,9 @@ to the token. If you plan to be using your Solo for real, you should lock it permanently. This prevents someone from connecting a debugger to your token and stealing credentials. -To do this, build the non-hacker bootloader and locked version of the firmware. +To do this, build the locked release firmware. ``` -make clean -make boot -make clean -make all-locked -python merge_hex.py solo.hex bootloader.hex all.hex +make build-release-locked ``` Now when you program `all.hex`, the device will lock itself when it first boots. You can only update it @@ -166,6 +176,6 @@ with signed updates. If you'd like to also permanently disable signed updates, plug in your programmed Solo and run the following: ``` -# No more signed updates. +# WARNING: No more signed updates. python tools/programmer.py --disable ``` diff --git a/targets/stm32l442/Makefile b/targets/stm32l442/Makefile index 76d24d6..6463634 100644 --- a/targets/stm32l442/Makefile +++ b/targets/stm32l442/Makefile @@ -22,13 +22,14 @@ debugboot-boot: LDSCRIPT=linker/bootloader_stm32l4xx_extra.ld EXTRA_DEFINES='-DAPPLICATION_START_PAGE=16 -DSOLO_HACKER' boot-sig-checking: - $(MAKE) -f bootloader.mk -j8 bootloader.hex + $(MAKE) -f bootloader.mk -j8 bootloader.hex DEBUG=0 boot-no-sig: - $(MAKE) -f bootloader.mk -j8 bootloader.hex EXTRA_DEFINES='-DSOLO_HACKER' + $(MAKE) -f bootloader.mk -j8 bootloader.hex EXTRA_DEFINES='-DSOLO_HACKER' DEBUG=0 build-release-locked: clean2 boot-sig-checking clean all-locked $(merge_hex) solo.hex bootloader.hex all.hex + rm -f solo.hex bootloader.hex # don't program solo.hex ... build-release: clean2 boot-sig-checking clean all $(merge_hex) solo.hex bootloader.hex all.hex