Skip to content

Commit

Permalink
rust: Add initial crates for rust support
Browse files Browse the repository at this point in the history
This commit adds three rust crates: `bitbox02-sys`, `bitbox02` and
`bitbox02-new`.

bitbox02-sys contains the generated unsafe rust functions that maps to
c-functions in the firmware. CMake will pass the sysroot and the include
paths to cargo when building.

bitbox02 contains the safe wrappers around the unsafe functions above.

bitbox02-rust contains new workflows/api endpoints that are implemented
in rust.

Functions from `bitbox02-rust` that have been declared "extern" can be
called from C. During compile time a header called "bitbox02_rust.h" is
generated with the correct declarations.

The only crate that actually is built by CMake is `bitbox02-rust`. Due to
dependency declarations in the Cargo.toml files cargo knows where to
find and how to build the other crates.

Unit tests can be run with `make -C build rust-test`
  • Loading branch information
NickeZ committed Nov 21, 2019
1 parent 81771a4 commit efbb7da
Show file tree
Hide file tree
Showing 26 changed files with 1,725 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .ci/ci
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

set -e

# Deny warnings in rust. CI will fail to compile any code with warnings in it.
export RUSTFLAGS="-Dwarnings"

# Check style

./.ci/check-style
Expand Down Expand Up @@ -47,4 +50,6 @@ make -C tools/go/src/atecc608a test
# Build device tests
make -j8 device-tests

# Don't generate graphics in CI
(cd build; cmake -DDOC_GRAPHS=NO ..)
make -j8 docs
2 changes: 1 addition & 1 deletion .ci/travis-ci
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -e
set -x

CONTAINER=shiftcrypto/firmware_v2:8
CONTAINER=shiftcrypto/firmware_v2:9

if [ "$1" == "pull" ] ; then
docker pull "$CONTAINER"
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ endif()
# Finds objcopy and other utilities for us
if(CMAKE_CROSSCOMPILING)
include(CMakeFindBinUtils)
find_program(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size" HINTS /usr/local/bin)
message(STATUS size: ${CMAKE_SIZE} ${TOOLCHAIN_PREFIX}size)
find_program(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size")
message(STATUS "size: ${CMAKE_SIZE} ${TOOLCHAIN_PREFIX}size")
endif()


Expand Down
13 changes: 12 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ RUN cd ~/Downloads &&\
# Tools for building
RUN apt-get update && apt-get install -y \
build-essential \
llvm \
gcc-8 \
binutils \
valgrind \
Expand All @@ -68,7 +69,8 @@ RUN apt-get update && apt-get install -y \
libhidapi-dev

RUN apt-get update && apt-get install -y \
doxygen
doxygen \
graphviz

# Set gcc-8 as the default gcc
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100
Expand Down Expand Up @@ -127,5 +129,14 @@ RUN go get -v -u github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc
RUN cd /opt && wget https://github.com/linux-test-project/lcov/releases/download/v1.14/lcov-1.14.tar.gz && tar -xf lcov-1.14.tar.gz
ENV PATH /opt/lcov-1.14/bin:$PATH

# Install rust compiler
ENV PATH /opt/cargo/bin:$PATH
ENV RUSTUP_HOME=/opt/rustup
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | CARGO_HOME=/opt/cargo sh -s -- --default-toolchain 1.38.0 -y
RUN rustup target add thumbv7em-none-eabi
RUN rustup component add rustfmt
RUN rustup component add clippy
RUN CARGO_HOME=/opt/cargo cargo install cbindgen

# Clean temporary files to reduce image size
RUN rm -rf /var/lib/apt/lists/*
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@ bootloader-bitboxbase-production: | build
$(MAKE) -C build bootloader-bitboxbase-production.elf
factory-setup: | build
$(MAKE) -C build factory-setup.elf
docs: | build-build
$(MAKE) -C build-build doc
docs: | build
$(MAKE) -C build doc
unit-test: | build-build
$(MAKE) -C build-build
device-tests: | build
${MAKE} -C build device-tests
# Must compile tests before running them
run-unit-tests: | build-build
# Must compile C tests before running them
run-unit-tests: | build build-build
$(MAKE) -C build-build test
${MAKE} -C build rust-test
# Must run tests before creating coverage report
coverage: | build-build
${MAKE} -C build-build coverage
Expand Down Expand Up @@ -118,5 +119,6 @@ ci:
prepare-tidy: | build build-build
make -C build generate-protobufs
make -C build-build generate-protobufs
make -C build rust-bindgen
clean:
rm -rf build build-build
4 changes: 3 additions & 1 deletion arm.cmake
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
set(CMAKE_SYSTEM_NAME "Generic")
set(CMAKE_SYSTEM_PROCESSOR "arm")

set(TOOLCHAIN_PREFIX "arm-none-eabi-")
set(TOOLCHAIN_PREFIX_PREFIX "arm-none-eabi")
set(TOOLCHAIN_PREFIX "${TOOLCHAIN_PREFIX_PREFIX}-")
set(CMAKE_C_COMPILER "/usr/local/bin/${TOOLCHAIN_PREFIX}gcc")
set(CMAKE_SYSROOT "/usr/local/${TOOLCHAIN_PREFIX_PREFIX}")

# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
Expand Down
6 changes: 3 additions & 3 deletions external/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,9 @@ if(CMAKE_CROSSCOMPILING)
asf4-drivers/diskio
)

find_library(QTOUCHLIB_A qtm_acq_samd51_0x000f PATHS asf4-drivers/qtouch/lib/gcc)
find_library(QTOUCHLIB_B qtm_binding_layer_cm4_0x0005 PATHS asf4-drivers/qtouch/lib/gcc)
find_library(QTOUCHLIB_T qtm_touch_key_cm4_0x0002 PATHS asf4-drivers/qtouch/lib/gcc)
find_library(QTOUCHLIB_A qtm_acq_samd51_0x000f PATHS asf4-drivers/qtouch/lib/gcc NO_CMAKE_FIND_ROOT_PATH)
find_library(QTOUCHLIB_B qtm_binding_layer_cm4_0x0005 PATHS asf4-drivers/qtouch/lib/gcc NO_CMAKE_FIND_ROOT_PATH)
find_library(QTOUCHLIB_T qtm_touch_key_cm4_0x0002 PATHS asf4-drivers/qtouch/lib/gcc NO_CMAKE_FIND_ROOT_PATH)

add_library(cryptoauthlib
cryptoauthlib/lib/atca_cfgs.c
Expand Down
58 changes: 58 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,10 @@ set(SYSTEMINCLUDES ${SYSTEMINCLUDES} PARENT_SCOPE)


# TODO: Not needed when building bootlaoder..
# Since the nanopb is included in the source tree and not in the sysroot (/usr/local/arm-none-eabi) we have to disable searching in the sysroot.
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
find_package(Nanopb REQUIRED)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(FIRMWARE-SOURCES
${DBB-FIRMWARE-SOURCES}
Expand All @@ -232,6 +235,58 @@ set_source_files_properties(
)

if(CMAKE_CROSSCOMPILING)
get_property(SAMD51A_INCLUDES TARGET samd51a-ds PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
get_property(ASF4_MIN_INCLUDES TARGET asf4-drivers-min PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
get_property(ASF4_INCLUDES TARGET asf4-drivers PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
get_property(CMSIS_INCLUDES TARGET CMSIS PROPERTY INTERFACE_INCLUDE_DIRECTORIES)

set(RUST_INCLUDES ${INCLUDES} ${SAMD51A_INCLUDES} ${ASF4_INCLUDES} ${ASF4_MIN_INCLUDES} ${CMSIS_INCLUDES})

if(CMAKE_BUILD_TYPE STREQUAL "DEBUG")
set(RUST_PROFILE "debug")
else()
set(RUST_PROFILE "release")
set(RUST_CARGO_FLAG "--release")
endif()

set(LIBBITBOX02_RUST_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/rust/bitbox02-rust)
set(LIBBITBOX02_RUST_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/rust/bitbox02-rust/target)
set(LIBBITBOX02_RUST ${CMAKE_CURRENT_BINARY_DIR}/rust/bitbox02-rust/target/thumbv7em-none-eabi/${RUST_PROFILE}/libbitbox02_rust.a)

find_program(CBINDGEN cbindgen)
find_program(CARGO cargo)

add_custom_target(rust
# Build rust library
COMMAND
${CMAKE_COMMAND} -E env SYSROOT=${CMAKE_SYSROOT} INCLUDES="${RUST_INCLUDES}" ${CARGO} build --manifest-path ${LIBBITBOX02_RUST_SOURCE_DIR}/Cargo.toml --target-dir ${LIBBITBOX02_RUST_BINARY_DIR} ${RUST_CARGO_FLAG} --target thumbv7em-none-eabi
# Rust packages stdlib functions which we must remove/weaken
COMMAND
${CMAKE_OBJCOPY} -N memset -N memcpy -N memmove -W memcmp ${LIBBITBOX02_RUST}
BYPRODUCTS
${LIBBITBOX02_RUST}
)

add_custom_target(rust-test
COMMAND
${CMAKE_COMMAND} -E env INCLUDES="${RUST_INCLUDES}" ${CARGO} test --manifest-path ${CMAKE_CURRENT_SOURCE_DIR}/rust/bitbox02-sys/Cargo.toml --target-dir ${LIBBITBOX02_RUST_BINARY_DIR} ${RUST_CARGO_FLAG}
COMMAND
${CMAKE_COMMAND} -E env INCLUDES="${RUST_INCLUDES}" ${CARGO} test --manifest-path ${CMAKE_CURRENT_SOURCE_DIR}/rust/bitbox02/Cargo.toml --target-dir ${LIBBITBOX02_RUST_BINARY_DIR} ${RUST_CARGO_FLAG}
COMMAND
${CMAKE_COMMAND} -E env INCLUDES="${RUST_INCLUDES}" ${CARGO} test --manifest-path ${LIBBITBOX02_RUST_SOURCE_DIR}/Cargo.toml --target-dir ${LIBBITBOX02_RUST_BINARY_DIR} ${RUST_CARGO_FLAG}
)

add_custom_target(rust-bindgen
# Generate c-headers for the rust library
COMMAND
${CBINDGEN} --config ${CMAKE_CURRENT_SOURCE_DIR}/rust/cbindgen.toml --output ${CMAKE_CURRENT_BINARY_DIR}/rust/bitbox02_rust.h ${LIBBITBOX02_RUST_SOURCE_DIR}
BYPRODUCTS
${CMAKE_CURRENT_BINARY_DIR}/rust/bitbox02_rust.h
)

add_library(bitbox02_rust STATIC IMPORTED)
set_property(TARGET bitbox02_rust PROPERTY IMPORTED_LOCATION ${LIBBITBOX02_RUST})

set(STACK_SIZE "0x10000" CACHE STRING "Specify stack size for bootloader/firmware")
set(STACK_SIZE ${STACK_SIZE} PARENT_SCOPE)
set(HEAP_SIZE "0x18000" CACHE STRING "Specify heap size for bootloader/firmware")
Expand Down Expand Up @@ -398,6 +453,9 @@ if(CMAKE_CROSSCOMPILING)
target_compile_definitions(firmware-bitboxbase-semihosting.elf PRIVATE PRODUCT_BITBOX_BASE SEMIHOSTING)
target_sources(firmware-bitboxbase-semihosting.elf PRIVATE ${PLATFORM-BITBOXBASE-SOURCES})

target_link_libraries(firmware-bitboxbase.elf PRIVATE bitbox02_rust)
add_dependencies(firmware-bitboxbase.elf rust rust-bindgen)

target_sources(factory-setup.elf PRIVATE factorysetup.c)
target_compile_definitions(factory-setup.elf PRIVATE FACTORYSETUP)
target_sources(factory-setup.elf PRIVATE ${PLATFORM-BITBOX02-SOURCES})
Expand Down
9 changes: 9 additions & 0 deletions src/rust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Enums

arm-none-eabi-gcc compiles with -fshort-enums by defualt. This means that if all variants of an
enum fits in a small type (such as `uint8_t`), then the enum will be backed by such a small type.


With `-fno-short-enums` (the default on other platforms) all enums will be `int32_t` sized as long
as they fit, otherwise `int64_t`. `repr(C)` in rust also follows this and can therefore not be
used. Instead all enums that are exported must have an explicit size using `repr(u8)` for example.
2 changes: 2 additions & 0 deletions src/rust/bitbox02-rust/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target = "thumbv7em-none-eabi"
Loading

0 comments on commit efbb7da

Please sign in to comment.