Skip to content

Commit

Permalink
feat(core): Add Rust bindings to MicroPython and trezorhal
Browse files Browse the repository at this point in the history
core: Remove dangling module decls

core: Use new Cargo feature resolver, use external MacOS debug info

core: Rust docs improvements

core: Upgrade bindgen

core: Add test target to Rust

ci: build rust sources

build(core): .ARM.exidx.text.__aeabi_ui2f in t1 firmware size

It's an unwind table for softfloat function inserted by rustc, probably
can be removed to save 8 bytes:
/~https://github.com/rust-embedded/cortex-m-rt/blob/599c58db70c5dd4eb1dfb92e1dad7c80ed848937/link.x.in#L175-L182

scons: Remove dead code

core: Move Rust target to build/rust

core: Replace extern with a FFI version

core: Add some explanatory Rust comments

core: Use correct path for the Rust lib

core: Remove Buffer::as_mut()

Mutable buffer access needs MP_BUFFER_WRITE flag. TBD in the Protobuf PR.

core: Improve docs for micropython::Buffer

core: Minor Rust docs changes

core: Rewrite trezor_obj_get_ll_checked

core: Fix incorrect doc comment

core: Remove cc from deps

fixup! core: Rewrite trezor_obj_get_ll_checked

core: update safety comments
  • Loading branch information
jpochyla authored and matejcik committed May 5, 2021
1 parent 77d0020 commit 6257584
Show file tree
Hide file tree
Showing 38 changed files with 2,151 additions and 15 deletions.
35 changes: 25 additions & 10 deletions ci/shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,35 @@
, hardwareTest ? false
}:

# the last successful build of nixpkgs-unstable as of 2021-03-25
with import (builtins.fetchTarball {
url = "/~https://github.com/NixOS/nixpkgs/archive/c0e881852006b132236cbf0301bd1939bb50867e.tar.gz";
sha256 = "0fy7z7yxk5n7yslsvx5cyc6h21qwi4bhxf3awhirniszlbvaazy2";
})
{ };

let
moneroTests = fetchurl {
mozillaOverlay = import (builtins.fetchTarball {
url = "/~https://github.com/mozilla/nixpkgs-mozilla/archive/8c007b60731c07dd7a052cce508de3bb1ae849b4.tar.gz";
sha256 = "1zybp62zz0h077zm2zmqs2wcg3whg6jqaah9hcl1gv4x8af4zhs6";
});
# the last successful build of nixpkgs-unstable as of 2021-03-25
nixpkgs = import (builtins.fetchTarball {
url = "/~https://github.com/NixOS/nixpkgs/archive/c0e881852006b132236cbf0301bd1939bb50867e.tar.gz";
sha256 = "0fy7z7yxk5n7yslsvx5cyc6h21qwi4bhxf3awhirniszlbvaazy2";
}) { overlays = [ mozillaOverlay ]; };
moneroTests = nixpkgs.fetchurl {
url = "/~https://github.com/ph4r05/monero/releases/download/v0.17.1.9-tests/trezor_tests";
sha256 = "410bc4ff2ff1edc65e17f15b549bd1bf8a3776cf67abdea86aed52cf4bce8d9d";
};
moneroTestsPatched = runCommandCC "monero_trezor_tests" {} ''
moneroTestsPatched = nixpkgs.runCommandCC "monero_trezor_tests" {} ''
cp ${moneroTests} $out
chmod +wx $out
${patchelf}/bin/patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$out"
${nixpkgs.patchelf}/bin/patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$out"
chmod -w $out
'';
rustNightly = (nixpkgs.rustChannelOf { date = "2021-03-29"; channel = "nightly"; }).rust.override {
targets = [
"x86_64-unknown-linux-gnu" # emulator
"thumbv7em-none-eabihf" # TT
"thumbv7em-none-eabi" # T1
];
};
in
with nixpkgs;
stdenv.mkDerivation ({
name = "trezor-firmware-env";
buildInputs = lib.optionals fullDeps [
Expand All @@ -38,6 +48,7 @@ stdenv.mkDerivation ({
bash
check
clang-tools
clang
editorconfig-checker
gcc
gcc-arm-embedded
Expand All @@ -52,6 +63,8 @@ stdenv.mkDerivation ({
pkgconfig
poetry
protobuf3_6
rustfmt
rustNightly
wget
zlib
] ++ lib.optionals (!stdenv.isDarwin) [
Expand Down Expand Up @@ -80,6 +93,8 @@ stdenv.mkDerivation ({
# Fix bdist-wheel problem by setting source date epoch to a more recent date
SOURCE_DATE_EPOCH = 1600000000;

# Used by rust bindgen
LIBCLANG_PATH = "${llvmPackages.libclang}/lib";
} // (lib.optionalAttrs fullDeps) {
TREZOR_MONERO_TESTS_PATH = moneroTestsPatched;
})
1 change: 1 addition & 0 deletions core/.changelog.d/1540.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Rust FFI for MicroPython.
5 changes: 3 additions & 2 deletions core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ PRODTEST_BUILD_DIR = $(BUILD_DIR)/prodtest
REFLASH_BUILD_DIR = $(BUILD_DIR)/reflash
FIRMWARE_BUILD_DIR = $(BUILD_DIR)/firmware
UNIX_BUILD_DIR = $(BUILD_DIR)/unix
RUST_BUILD_DIR = $(BUILD_DIR)/rust

UNAME_S := $(shell uname -s)
UNIX_PORT_OPTS ?=
Expand Down Expand Up @@ -179,10 +180,10 @@ clean_reflash: ## clean reflash build
rm -rf $(REFLASH_BUILD_DIR)

clean_firmware: ## clean firmware build
rm -rf $(FIRMWARE_BUILD_DIR)
rm -rf $(FIRMWARE_BUILD_DIR) $(RUST_BUILD_DIR)

clean_unix: ## clean unix build
rm -rf $(UNIX_BUILD_DIR)
rm -rf $(UNIX_BUILD_DIR) $(RUST_BUILD_DIR)

clean_cross: ## clean mpy-cross build
$(MAKE) -C vendor/micropython/mpy-cross clean $(CROSS_PORT_OPTS)
Expand Down
36 changes: 35 additions & 1 deletion core/SConscript.firmware
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# pylint: disable=E0602
# fmt: off

import os

Expand Down Expand Up @@ -49,6 +50,7 @@ CPPDEFINES_MOD += [
('USE_EOS', '1' if EVERYTHING else '0'),
]
SOURCE_MOD += [
'embed/extmod/trezorobj.c',
'embed/extmod/modtrezorcrypto/crc.c',
'embed/extmod/modtrezorcrypto/modtrezorcrypto.c',
'embed/extmod/modtrezorcrypto/rand.c',
Expand Down Expand Up @@ -394,11 +396,13 @@ if TREZOR_MODEL == 'T':
CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx'
LD_VARIANT = '_zkp' if FEATURE_FLAGS["SECP256K1_ZKP"] else ''
RUST_TARGET = 'thumbv7em-none-eabihf'
elif TREZOR_MODEL == '1':
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx'
LD_VARIANT = '' if EVERYTHING else '_min'
RUST_TARGET = 'thumbv7em-none-eabi'
else:
raise ValueError('Unknown Trezor model')

Expand All @@ -416,6 +420,7 @@ env.Replace(
LINKFLAGS='-T embed/firmware/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,-Map=build/firmware/firmware.map -Wl,--warn-common' % LD_VARIANT,
CPPPATH=[
'.',
'embed/rust',
'embed/firmware',
'embed/trezorhal',
'embed/extmod/modtrezorui',
Expand Down Expand Up @@ -616,6 +621,33 @@ if FEATURE_FLAGS["SECP256K1_ZKP"]:
action='cd ${SOURCE.dir}; ./gen_context',
)

#
# Rust library
#

RUST_PROFILE = 'release'
RUST_LIB = 'trezor_lib'
RUST_LIBDIR = f'build/rust/{RUST_TARGET}/{RUST_PROFILE}'
RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a'

def cargo_build():
# Determine the profile build flags.
if RUST_PROFILE == 'release':
profile = '--release'
else:
profile = ''
return f'cd embed/rust; cargo build {profile} --target={RUST_TARGET}'

rust = env.Command(
target=RUST_LIBPATH,
source='',
action=cargo_build(), )

env.Depends(rust, qstr_generated)

env.Append(LINKFLAGS=f' -L{RUST_LIBDIR}')
env.Append(LINKFLAGS=f' -l{RUST_LIB}')

#
# Program objects
#
Expand Down Expand Up @@ -658,9 +690,11 @@ program_elf = env.Command(
target='firmware.elf',
source=obj_program,
action=
'$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES -lc_nano -lm -lgcc',
'$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc',
)

env.Depends(program_elf, rust)

if TREZOR_MODEL == 'T':
action_bin=[
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data --pad-to 0x08100000 $SOURCE ${TARGET}.p1',
Expand Down
32 changes: 32 additions & 0 deletions core/SConscript.unix
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# pylint: disable=E0602
# fmt: off

import os

Expand Down Expand Up @@ -48,6 +49,7 @@ CPPDEFINES_MOD += [
('USE_EOS', '1' if EVERYTHING else '0'),
]
SOURCE_MOD += [
'embed/extmod/trezorobj.c',
'embed/extmod/modtrezorcrypto/modtrezorcrypto.c',
'embed/extmod/modtrezorcrypto/crc.c',
'vendor/trezor-crypto/address.c',
Expand Down Expand Up @@ -367,6 +369,7 @@ env.Replace(
LIBS=['m'],
CPPPATH=[
'.',
'embed/rust',
'embed/unix',
'embed/extmod/modtrezorui',
'vendor/micropython',
Expand Down Expand Up @@ -567,6 +570,33 @@ if FEATURE_FLAGS["SECP256K1_ZKP"]:
action='cd ${SOURCE.dir}; ./gen_context',
)

#
# Rust library
#

RUST_PROFILE = 'release'
RUST_LIB = 'trezor_lib'
RUST_LIBDIR = f'build/rust/{RUST_PROFILE}'
RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a'

def cargo_build():
# Determine the profile build flags.
if RUST_PROFILE == 'release':
profile = '--release'
else:
profile = ''
return f'cd embed/rust; cargo build {profile}'

rust = env.Command(
target=RUST_LIBPATH,
source='',
action=cargo_build(), )

env.Depends(rust, qstr_generated)

env.Append(LINKFLAGS=f'-L{RUST_LIBDIR}')
env.Append(LINKFLAGS=f'-l{RUST_LIB}')

#
# Program objects
#
Expand All @@ -588,3 +618,5 @@ program = env.Command(
target='trezor-emu-core',
source=obj_program,
action='$CC -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $LINKFLAGS', )

env.Depends(program, rust)
64 changes: 64 additions & 0 deletions core/embed/extmod/trezorobj.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* This file is part of the Trezor project, https://trezor.io/
*
* Copyright (c) SatoshiLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <string.h>

#include "memzero.h"
#include "py/objint.h"

static bool mpz_as_ll_checked(const mpz_t *i, long long *value) {
// Analogue of `mpz_as_int_checked` from mpz.c

unsigned long long val = 0;
mpz_dig_t *d = i->dig + i->len;

while (d-- > i->dig) {
if (val > (~0x8000000000000000 >> MPZ_DIG_SIZE)) {
// will overflow
*value = 0;
return false;
}
val = (val << MPZ_DIG_SIZE) | *d;
}

if (i->neg != 0) {
val = -val;
}

*value = val;
return true;
}

bool trezor_obj_get_ll_checked(mp_obj_t obj, long long *value) {
if (mp_obj_is_small_int(obj)) {
// Value is fitting in a small int range. Return it directly.
*value = MP_OBJ_SMALL_INT_VALUE(obj);
return true;

} else if (mp_obj_is_type(obj, &mp_type_int)) {
// Value is not fitting into small int range, but is an integer.
mp_obj_int_t *self = MP_OBJ_TO_PTR(obj);
// Try to get the long long value out of the MPZ struct.
return mpz_as_ll_checked(&self->mpz, value);
} else {
// Value is not integer.
*value = 0;
return false;
}
}
2 changes: 2 additions & 0 deletions core/embed/extmod/trezorobj.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,6 @@ static inline uint8_t trezor_obj_get_uint8(mp_obj_t obj) {
return u;
}

bool trezor_obj_get_ll_checked(mp_obj_t obj, long long *value);

#endif
3 changes: 2 additions & 1 deletion core/embed/firmware/memory_1.ld
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ sram_end = ORIGIN(SRAM) + LENGTH(SRAM);
_ram_start = sram_start;
_ram_end = sram_end;

_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.ARM.exidx);
/* .ARM.exidx.text.__aeabi_ui2f is probably not needed as long as we are using panic = "abort" */
_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.ARM.exidx) + SIZEOF(.ARM.exidx.text.__aeabi_ui2f);
_flash_start = ORIGIN(FLASH);
_flash_end = ORIGIN(FLASH) + LENGTH(FLASH);
_heap_start = ADDR(.heap);
Expand Down
3 changes: 2 additions & 1 deletion core/embed/firmware/memory_1_min.ld
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ sram_end = ORIGIN(SRAM) + LENGTH(SRAM);
_ram_start = sram_start;
_ram_end = sram_end;

_codelen = SIZEOF(.flash) + SIZEOF(.data);
/* .ARM.exidx.text.__aeabi_ui2f is probably not needed as long as we are using panic = "abort" */
_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.ARM.exidx.text.__aeabi_ui2f);
_flash_start = ORIGIN(FLASH);
_flash_end = ORIGIN(FLASH) + LENGTH(FLASH);
_heap_start = ADDR(.heap);
Expand Down
2 changes: 2 additions & 0 deletions core/embed/rust/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target-dir = "../../build/rust"
Loading

0 comments on commit 6257584

Please sign in to comment.