diff --git a/BUILD.md b/BUILD.md index 67f6f8508..ddf271127 100644 --- a/BUILD.md +++ b/BUILD.md @@ -2,21 +2,6 @@ # Build BitBox02 firmware and bootloader -## Dependencies - -- [HIDAPI](https://github.com/signal11/hidapi) -- [GNU ARM Embedded Toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) -- SEGGER J-Link software - - [All packages and versions](https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack) - - Newer versions should work, but if not, go to "Older versions" and get version 6.34g - - [OSX package](https://www.segger.com/downloads/jlink/JLink_MacOSX_V630d.pkg) - - [Linux 64bit](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.tgz) - - [others](https://www.segger.com/downloads/jlink/) -- cmake -- git -- Install the pre-built [protobuf python binary](https://github.com/protocolbuffers/protobuf/releases) - - Then install the included [Python Protocol Buffers](https://github.com/protocolbuffers/protobuf/tree/master/python#installation) runtime library - ## Reporting issues @@ -25,99 +10,170 @@ For security related issues please see [SECURITY.md](SECURITY.md). ## Development environment -### Install development environment as a Docker container +There is a container image with all the build dependencies and there are some +`make` shortcuts to use it. -The container will contain all tools needed to build the project but it is still necessary to get -the J-Link software to flash the bootloader. Run the commands below to build the container and -execute a persistent one. +> [!TIP] +> It is highly recommended to use the container for development. -```sh -make dockerinit -make dockerdev -``` +Accessing USB devices, like the flashing tool and the bitbox, is easier outside +of the container. So it is recommended to install the J-Link Software on your +development machine to follow the instructions below. + +### Development Dependencies* + +| Dependency | Version** | +| ---------- | -------- | +| [Arm GNU Toolchain](https://developer.arm.com/downloads/-/gnu-rm) | 8-2018-q4 | +| [HIDAPI](https://github.com/signal11/hidapi) | 0.11.2 | +| [cmake](https://cmake.org/download/) | 3.10 | +| [git](https://git-scm.com/downloads) | 2.34 | +| [Protobuf Compiler](https://github.com/protocolbuffers/protobuf/releases) | 21.2 | +| [Python Probobuf Runtime](https://github.com/protocolbuffers/protobuf/tree/master/python#installation) | 5.27.3 | +| [SEGGER J-Link Software and Documentation Pack](https://www.segger.com/downloads/jlink) | 6.34g | +| Graphviz | 2.42.2 | +| Doxygen | 1.9.1 | +| [cmocka](https://cmocka.org/files/1.1/) | 1.1.5 | + +* See the complete list of dependences in the Dockerfile. + +** The versions here are known to be working. Newer versions should +work. + +### Setup containerized environment + +`make dockerpull` will use `docker pull` to fetch the current container image. +`make dockerdev` will use `docker run` and `docker exec` to run a container in +the background and enter it. + +> [!NOTE] +> The current development container is defined in the file `.containerversion` -If you do not want to build the docker image locally, or are not working on it, it may be more straightforward to -pull the image from docker instead of building it. This should be a bit faster and there should not be any issues with -`make dockerdev` expecting specific version of the image. +`make dockerdev` will mount the project root outside +the container to the same path inside the container so that you can use your +preferred editor/IDE outside the container and so that compiler errors have the +right file paths. + +> [!IMPORTANT] +> `make dockerdev` will enter an already running container if it exists. ```sh make dockerpull make dockerdev ``` +`make dockerinit` is a shortcut to run `docker build` if you need to update the +container image (`Dockerfile`). Don't forget to update the `.containerversion` +file. -The docker container will not allow you to access the hosts USB devices by default which means that -it is necessary to flash the device in a terminal not running in docker. - -> [!NOTE] -> Current development container is defined in the file `.containerversion` +```sh +make dockerinit +``` -The docker container mounts the repo it was launched from, so you can freely edit your fork in your preferred IDE and -the changes will be reflected in the docker container. +### Setup development environment on macOS with brew -**It is highly recommended you develop using this docker container as not all of local setup is completely up to date -with every Operating system.** +> [!CAUTION] +> Brew usually only supports the latest versions of software packages. It is +> not easy to get a working development environment using brew. CI uses the +> development container so it will be additional work getting CI to pass. -### Install development environment on macOS +> [!IMPORTANT] +> If you use compiler versions different from CI and everyone else you will not +> be able to reproducibly build the firmware. -Make sure you have [Homebrew](https://brew.sh) installed. -Install the dependencies with: +Make sure you have [Homebrew](https://brew.sh) installed. Install the +dependencies with: ```sh -brew install hidapi cmake protobuf -brew install automake libtool # for building some code in the external/ folder +brew install hidapi cmake protobuf@21 +brew install automake libtool brew tap osx-cross/arm brew install arm-gcc-bin ``` -## Simulator +## Contributor instructions -The Multi edition firmware can be built as a simulator for linux-amd64. To build it, run: +### Check out the repository - make -j simulator +#### 1. Fork the repository on github. -Run it with: +Go to [bitbox02-firmware](https://github.com/bitboxswiss/bitbox02-firmware) and fork the repository. - ./build-build/bin/simulator +#### 2. Check out your fork -This launches a server simulating the firmware. The send_message tool can connect to it with: +Run the following commands to check out your fork: - ./py/send_message.py --simulator +```sh +git clone --recurse-submodules git@github.com:/bitbox02-firmware.git +cd bitbox02-firmware +``` -If you choose to create a wallet by restoring a mnemonic, the simulator will automatically use this -mnemonic: +> [!TIP] +> If you have already cloned the repository without the `--recurse-submodules` +> argument, run: +> +> ```sh +> git submodule update --init --recursive +> ``` - boring mistake dish oyster truth pigeon viable emerge sort crash wire portion cannon couple enact box walk height pull today solid off enable tide +### Build the firmware -## Instructions +Run the following commands to enter the container and build the firmware: -Connect the J-Link to the debug pins on the BitBox02 prototype board. +```sh +make dockerdev +make firmware +``` + +> [!TIP] +> If you have multiple cores you can speed up compilation by passing `-j`, for example `-j8`. -Plug in both the J-Link hardware and the BitBox02 device into USB ports on your computer or a hub connected to your computer. +### Build the bootloader -Build the firmware: +Run the following commands to enter the container and build the bootloader: ```sh -git clone --recurse-submodules https://github.com/BitBoxSwiss/bitbox02-firmware && cd bitbox02-firmware -# or via ssh -git clone --recurse-submodules git@github.com:BitBoxSwiss/bitbox02-firmware.git && cd bitbox02-firmware -make firmware # requires a GNU ARM toolchain for cross-compiling +make dockerdev +make bootloader ``` -If you have already cloned the repository without the `--recurse-submodules` argument, run: +> [!NOTE] +> To create a bootloader for a development or a production device, use `make +> bootloader-devdevice` or `make bootloader-production` respectively. -```sh -git submodule update --init --recursive -``` +> [!NOTE] +> To run unsigned firmwares you need a development bootloader. -Build the bootloader: +### Build the simulator + +The Multi edition firmware can be built as a simulator for linux-amd64. To build it, run: ```sh -make bootloader +make simulator ``` -(to create a bootloader for a devdevice or a production device, use `make bootloader-devdevice` or -`make bootloader-production` respectively). +### Flash instructions + +#### Connect J-Link probe + +Connect the J-Link probe to the debug pins on the BitBox02 prototype board. The +pinout of the board and the Arm JTAG/SWD 10-pin connector can be seen in the +table below. + +| Signal | Bitbox02 # | Arm JTAG/SWD # | +| ------ | ---------- | -------------- | +| VCC | 1 | 1 | +| CLK | 2 | 4 | +| GND | 3 | 3, 5 | +| DIO | 4 | 2 | + +See [bitbox schematics](doc/bb02_v2.10_schematics.pdf) and [Arm JTAG/SWD +interface](https://developer.arm.com/documentation/101636/0100/Debug-and-Trace/JTAG-SWD-Interface) + +Plug **both** the J-Link probe and the BitBox02 into your development machine using +USB. + +#### Flash bootloader using J-Link Load the bootloader by JLink (requires JLinkExe in PATH). @@ -125,13 +181,11 @@ Load the bootloader by JLink (requires JLinkExe in PATH). make jlink-flash-bootloader ``` -You need to install the [BitBox02 Python Library](#BitBox02-Python-library) before you can flash the built firmware. - -Load the firmware by the bootloader (requires loading bootloader.bin by JLink, if not already loaded on the device): +> [!NOTE] +> To flash a bootloader for a development device +> `make jlink-flash-bootloader-development`. -```sh -make flash-dev-firmware -``` +#### Flash firmware using J-Link Load the firmware by JLink: @@ -139,15 +193,20 @@ Load the firmware by JLink: make jlink-flash-firmware ``` -### Build reference documentation (Doxygen) +#### Flash firmware using bootloader and python cli client + +> [!TIP] +> This method does not require a J-Link probe while developing. + +Install the [BitBox02 Python CLI client](#bitbox02-python-cli-client). -Dependencies: +Load the firmware through the bootloader: ```sh -brew install graphviz doxygen +make flash-dev-firmware ``` -Build: +### Build reference documentation (Doxygen) ```sh make docs @@ -155,48 +214,80 @@ make docs To view the results, open `build/docs/html/index.html` in a web browser. -### BitBox02 Python library +### Debugging -There is a Python api library in `py/bitbox02`. +#### Debugging using the simulator -Run `pip install -r py/requirements.txt` to install the deps (virtualenv recommended). - -`make -C py/bitbox02` to generate the protobuf files. - -To kick off some api calls: +Run it with: ```sh -./py/send_message.py +./build-build/bin/simulator ``` -### Unit tests +This launches a server simulating the firmware. The send_message tool can connect to it with: -We are using CMocka [https://cmocka.org/](https://cmocka.org/) for unit tests. To run the tests, the CMocka library -needs to be installed on your system. + ./py/send_message.py --simulator -If you're on a Mac, you can use the brew command to install it: +If you choose to create a wallet by restoring a mnemonic, the simulator will automatically use this +mnemonic: + + boring mistake dish oyster truth pigeon viable emerge sort crash wire portion cannon couple enact box walk height pull today solid off enable tide + + +#### Debugging using the J-Link probe and GDB + +The *debug firmware* enables pretty printing of panics over [RTT](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/). + +Run the following commands to build the debug firmware. ```sh -brew install cmocka +make dockerdev +make firmware-debug ``` -Alternatively, you can get CMocka by cloning the git repository and following these instructions: +Run the following command to run the J-Link GDB Server. ```sh -git clone git://git.cryptomilk.org/projects/cmocka.git -cd cmocka -mkdir build && cd build -cmake .. -make && sudo make install +make jlink-gdb-server ``` -By default, the library will be installed into /usr/local/lib64 directory under Linux x86\_64. -If the library is not on the library path by default, you might need to export the following environment variable: +> [!TIP] +> The J-Link GDB Server can be left running in the background. + +Run the following command to connect with telnet to the J-Link GDB Server to +see the RTT output. ```sh -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib64/ +make rtt-client ``` +Run the following command to run GDB. GDB will connect to the J-Link GDB +server, flash the debug firmware and then start execution from the bootloader +(as if the device was just plugged in). + +```sh +make run +``` + +> [!TIP] +> After rebuilding the firmware, exit GDB and rerun `make run` to flash and reset the device. + +### Unit tests + +CMocka [https://cmocka.org/](https://cmocka.org/) is used for mocking in the +unit tests. To compile the tests, the CMocka library needs to be installed on +your system. CMocka is available through most package managers, like *brew* and +*apt*. + +> [!NOTE] +> If you compiled it yourself from souce, the library will, by default, be +> installed into **/usr/local/** directory instead of **/usr/**. +> If the library is not on the library path by default, you might need to export +> the following environment variable: +> ```sh +> export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib64/ +> ``` + Then you can run the tests by executing ```sh @@ -220,9 +311,26 @@ make -C build-build coverage-lcovr ### SCCache / CCache -The build systems supports sccache/ccache, you just need to have it available in your path. You can -install it into your dev container with the following commands: +The build systems supports sccache/ccache, you just need to have it available +in your path. You can install it into your dev container with the following +commands: ``` docker exec -u 0 -it bitbox02-firmware-dev bash -c 'apt update && apt install -y libssl-dev && CARGO_HOME=/opt/cargo cargo install --locked sccache' ``` + +## BitBox02 Python Library + +There is a Python api library in `py/bitbox02`. + +### BitBox02 CLI client + +Run `pip install -r py/requirements.txt` to install the deps (virtualenv recommended). + +`make -C py/bitbox02` to generate the protobuf files. + +To kick off some api calls: + +```sh +./py/send_message.py +```