mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-26 09:52:34 +00:00
feat(core/prodtest): add prodtest emulator
[no changelog]
This commit is contained in:
parent
9e8f989c80
commit
9683efb5b9
@ -16,6 +16,7 @@ BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/bootloader
|
|||||||
BOOTLOADER_CI_BUILD_DIR = $(BUILD_DIR)/bootloader_ci
|
BOOTLOADER_CI_BUILD_DIR = $(BUILD_DIR)/bootloader_ci
|
||||||
BOOTLOADER_EMU_BUILD_DIR = $(BUILD_DIR)/bootloader_emu
|
BOOTLOADER_EMU_BUILD_DIR = $(BUILD_DIR)/bootloader_emu
|
||||||
PRODTEST_BUILD_DIR = $(BUILD_DIR)/prodtest
|
PRODTEST_BUILD_DIR = $(BUILD_DIR)/prodtest
|
||||||
|
PRODTEST_EMU_BUILD_DIR = $(BUILD_DIR)/prodtest_emu
|
||||||
REFLASH_BUILD_DIR = $(BUILD_DIR)/reflash
|
REFLASH_BUILD_DIR = $(BUILD_DIR)/reflash
|
||||||
KERNEL_BUILD_DIR = $(BUILD_DIR)/kernel
|
KERNEL_BUILD_DIR = $(BUILD_DIR)/kernel
|
||||||
FIRMWARE_BUILD_DIR = $(BUILD_DIR)/firmware
|
FIRMWARE_BUILD_DIR = $(BUILD_DIR)/firmware
|
||||||
@ -295,6 +296,9 @@ build_bootloader_emu_debug: ## build the unix bootloader emulator
|
|||||||
build_prodtest: ## build production test firmware
|
build_prodtest: ## build production test firmware
|
||||||
$(SCONS) $(PRODTEST_BUILD_DIR)/prodtest.bin
|
$(SCONS) $(PRODTEST_BUILD_DIR)/prodtest.bin
|
||||||
|
|
||||||
|
build_prodtest_emu: ## build the unix prodtest emulator
|
||||||
|
$(SCONS) $(PRODTEST_EMU_BUILD_DIR)/prodtest.elf
|
||||||
|
|
||||||
build_reflash: ## build reflash firmware + reflash image
|
build_reflash: ## build reflash firmware + reflash image
|
||||||
$(SCONS) $(REFLASH_BUILD_DIR)/reflash.bin
|
$(SCONS) $(REFLASH_BUILD_DIR)/reflash.bin
|
||||||
dd if=build/boardloader/boardloader.bin of=$(REFLASH_BUILD_DIR)/sdimage.bin bs=1 seek=0
|
dd if=build/boardloader/boardloader.bin of=$(REFLASH_BUILD_DIR)/sdimage.bin bs=1 seek=0
|
||||||
|
@ -132,6 +132,7 @@ FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_
|
|||||||
SOURCE_PRODTEST = [
|
SOURCE_PRODTEST = [
|
||||||
'embed/projects/prodtest/header.S',
|
'embed/projects/prodtest/header.S',
|
||||||
'embed/projects/prodtest/main.c',
|
'embed/projects/prodtest/main.c',
|
||||||
|
'embed/projects/prodtest/commands.c',
|
||||||
'embed/projects/prodtest/cmd/prodtest_boardloader.c',
|
'embed/projects/prodtest/cmd/prodtest_boardloader.c',
|
||||||
'embed/projects/prodtest/cmd/prodtest_ble.c',
|
'embed/projects/prodtest/cmd/prodtest_ble.c',
|
||||||
'embed/projects/prodtest/cmd/prodtest_bootloader.c',
|
'embed/projects/prodtest/cmd/prodtest_bootloader.c',
|
||||||
|
289
core/SConscript.prodtest_emu
Normal file
289
core/SConscript.prodtest_emu
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
# pylint: disable=E0602
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import tools, models, ui
|
||||||
|
|
||||||
|
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T2T1')
|
||||||
|
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||||
|
HW_REVISION = 'emulator'
|
||||||
|
|
||||||
|
FEATURE_FLAGS = {
|
||||||
|
"AES_GCM": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
if not models.has_emulator(TREZOR_MODEL):
|
||||||
|
# skip prodtest build
|
||||||
|
env = Environment()
|
||||||
|
def build_prodtest(target,source,env):
|
||||||
|
print(f'prodtest: nothing to build for Model {TREZOR_MODEL}')
|
||||||
|
program_bin = env.Command(
|
||||||
|
target='prodtest.elf',
|
||||||
|
source=None,
|
||||||
|
action=build_prodtest
|
||||||
|
)
|
||||||
|
Return()
|
||||||
|
|
||||||
|
FEATURES_WANTED = ["input", "rgb_led", "display", "tropic", "sd_card", "usb"]
|
||||||
|
|
||||||
|
CCFLAGS_MOD = ''
|
||||||
|
CPPPATH_MOD = []
|
||||||
|
CPPDEFINES_MOD = [
|
||||||
|
'KERNEL_MODE',
|
||||||
|
'AES_128',
|
||||||
|
'USE_INSECURE_PRNG',
|
||||||
|
]
|
||||||
|
SOURCE_MOD = []
|
||||||
|
SOURCE_MOD_CRYPTO = []
|
||||||
|
CPPDEFINES_HAL = []
|
||||||
|
SOURCE_HAL = []
|
||||||
|
PATH_HAL = []
|
||||||
|
RUST_UI_FEATURES = []
|
||||||
|
|
||||||
|
# modtrezorcrypto
|
||||||
|
CPPPATH_MOD += [
|
||||||
|
'vendor/trezor-crypto',
|
||||||
|
'vendor/trezor-storage',
|
||||||
|
]
|
||||||
|
SOURCE_MOD += [
|
||||||
|
'vendor/trezor-storage/flash_area.c',
|
||||||
|
]
|
||||||
|
SOURCE_MOD_CRYPTO += [
|
||||||
|
'vendor/trezor-crypto/aes/aes_modes.c',
|
||||||
|
'vendor/trezor-crypto/aes/aesccm.c',
|
||||||
|
'vendor/trezor-crypto/aes/aescrypt.c',
|
||||||
|
'vendor/trezor-crypto/aes/aeskey.c',
|
||||||
|
'vendor/trezor-crypto/aes/aestab.c',
|
||||||
|
'vendor/trezor-crypto/bignum.c',
|
||||||
|
'vendor/trezor-crypto/blake256.c',
|
||||||
|
'vendor/trezor-crypto/blake2b.c',
|
||||||
|
'vendor/trezor-crypto/buffer.c',
|
||||||
|
'vendor/trezor-crypto/chacha_drbg.c',
|
||||||
|
'vendor/trezor-crypto/chacha20poly1305/chacha_merged.c',
|
||||||
|
'vendor/trezor-crypto/der.c',
|
||||||
|
'vendor/trezor-crypto/ecdsa.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-scalarmult-base.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/ed25519-donna-32bit-tables.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/ed25519-donna-basepoint-table.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/ed25519-donna-impl-base.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/ed25519-keccak.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/ed25519-sha3.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/ed25519.c',
|
||||||
|
'vendor/trezor-crypto/ed25519-donna/modm-donna-32bit.c',
|
||||||
|
'vendor/trezor-crypto/groestl.c',
|
||||||
|
'vendor/trezor-crypto/hasher.c',
|
||||||
|
'vendor/trezor-crypto/hmac.c',
|
||||||
|
'vendor/trezor-crypto/hmac_drbg.c',
|
||||||
|
'vendor/trezor-crypto/memzero.c',
|
||||||
|
'vendor/trezor-crypto/nist256p1.c',
|
||||||
|
'vendor/trezor-crypto/rand.c',
|
||||||
|
'vendor/trezor-crypto/ripemd160.c',
|
||||||
|
'vendor/trezor-crypto/rfc6979.c',
|
||||||
|
'vendor/trezor-crypto/secp256k1.c',
|
||||||
|
'vendor/trezor-crypto/sha2.c',
|
||||||
|
'vendor/trezor-crypto/sha3.c',
|
||||||
|
'vendor/trezor-crypto/tls_prf.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
# AES-GCM
|
||||||
|
if FEATURE_FLAGS["AES_GCM"]:
|
||||||
|
CPPDEFINES_MOD += [
|
||||||
|
'USE_AES_GCM',
|
||||||
|
'AES_VAR',
|
||||||
|
]
|
||||||
|
SOURCE_MOD_CRYPTO += [
|
||||||
|
'vendor/trezor-crypto/aes/gf128mul.c',
|
||||||
|
'vendor/trezor-crypto/aes/aesgcm.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# modtrezorui
|
||||||
|
CPPPATH_MOD += [
|
||||||
|
'vendor/micropython/lib/uzlib'
|
||||||
|
]
|
||||||
|
|
||||||
|
SOURCE_MOD += [
|
||||||
|
'embed/gfx/bitblt/gfx_bitblt.c',
|
||||||
|
'embed/gfx/bitblt/gfx_bitblt_rgb565.c',
|
||||||
|
'embed/gfx/bitblt/gfx_bitblt_rgba8888.c',
|
||||||
|
'embed/gfx/bitblt/gfx_bitblt_mono8.c',
|
||||||
|
'embed/gfx/fonts/font_bitmap.c',
|
||||||
|
'embed/gfx/gfx_color.c',
|
||||||
|
'embed/gfx/gfx_draw.c',
|
||||||
|
'embed/gfx/terminal.c',
|
||||||
|
'embed/io/display/display_utils.c',
|
||||||
|
'embed/util/image/image.c',
|
||||||
|
'embed/util/rsod/rsod.c',
|
||||||
|
'embed/util/scm_revision/scm_revision.c',
|
||||||
|
'embed/rtl/cli.c',
|
||||||
|
'embed/rtl/error_handling.c',
|
||||||
|
'embed/rtl/mini_printf.c',
|
||||||
|
'embed/rtl/strutils.c',
|
||||||
|
'embed/rtl/unit_test.c',
|
||||||
|
'vendor/micropython/lib/uzlib/adler32.c',
|
||||||
|
'vendor/micropython/lib/uzlib/crc32.c',
|
||||||
|
'vendor/micropython/lib/uzlib/tinflate.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
ui.init_ui(TREZOR_MODEL, "prodtest", RUST_UI_FEATURES)
|
||||||
|
|
||||||
|
env = Environment(
|
||||||
|
ENV=os.environ,
|
||||||
|
CFLAGS=ARGUMENTS.get('CFLAGS', '') + f" -DCONFIDENTIAL= -DPRODUCTION={ARGUMENTS.get('PRODUCTION', '0')}",
|
||||||
|
CPPDEFPREFIX="-D'",
|
||||||
|
CPPDEFSUFFIX="'",
|
||||||
|
)
|
||||||
|
|
||||||
|
FEATURES_AVAILABLE = models.configure_board(TREZOR_MODEL, HW_REVISION, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL)
|
||||||
|
|
||||||
|
SOURCE_PRODTEST = [
|
||||||
|
'embed/projects/prodtest/main.c',
|
||||||
|
'embed/projects/prodtest/commands.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_boardloader.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_ble.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_bootloader.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_button.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_display.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_prodtest.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_backup_ram.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_get_cpuid.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_haptic.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_help.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_hw_revision.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_nfc.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_nrf.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_optiga.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_otp_batch.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_otp_variant.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_ping.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_power_manager.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_reboot.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_rgbled.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_sdcard.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_tamper.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_sbu.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_touch.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_tropic.c',
|
||||||
|
'embed/projects/prodtest/cmd/prodtest_wpc',
|
||||||
|
'embed/projects/prodtest/emulator.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
SOURCE_HAL += [
|
||||||
|
'embed/projects/unix/profile.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
env.Replace(
|
||||||
|
CAT='cat',
|
||||||
|
CP='cp',
|
||||||
|
AS='as',
|
||||||
|
AR='ar',
|
||||||
|
CC='gcc',
|
||||||
|
LINK='ld',
|
||||||
|
SIZE='size',
|
||||||
|
STRIP='strip',
|
||||||
|
OBJCOPY='objcopy',
|
||||||
|
PYTHON='python',
|
||||||
|
MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', )
|
||||||
|
|
||||||
|
MODEL_AS_NUMBER = str(models.get_hw_model_as_number(TREZOR_MODEL))
|
||||||
|
|
||||||
|
ALLPATHS = ['embed/rust',
|
||||||
|
'embed/projects/prodtest',
|
||||||
|
'embed/rtl/inc',
|
||||||
|
'embed/models',
|
||||||
|
'embed/projects/unix',
|
||||||
|
'embed/gfx/inc',
|
||||||
|
'embed/util/image/inc',
|
||||||
|
'embed/util/rsod/inc',
|
||||||
|
'embed/util/scm_revision/inc',
|
||||||
|
'embed/util/translations/inc',
|
||||||
|
] + CPPPATH_MOD + PATH_HAL
|
||||||
|
|
||||||
|
env.Replace(
|
||||||
|
COPT=env.get('ENV').get('OPTIMIZE', '-Os'),
|
||||||
|
CCFLAGS='$COPT '
|
||||||
|
'-g '
|
||||||
|
'-nostdlib '
|
||||||
|
'-std=gnu11 -Wall -Werror -Wpointer-arith -Wno-missing-braces -fno-common '
|
||||||
|
'-fdata-sections -ffunction-sections '
|
||||||
|
'-ffreestanding '
|
||||||
|
'-fstack-protector-all '
|
||||||
|
+ CCFLAGS_MOD,
|
||||||
|
LINKFLAGS='',
|
||||||
|
CPPPATH=ALLPATHS,
|
||||||
|
CPPDEFINES=[
|
||||||
|
'TREZOR_PRODTEST',
|
||||||
|
'TREZOR_EMULATOR',
|
||||||
|
'TREZOR_MODEL_'+TREZOR_MODEL,
|
||||||
|
] + CPPDEFINES_MOD + CPPDEFINES_HAL,
|
||||||
|
ASPPFLAGS='$CFLAGS $CCFLAGS', )
|
||||||
|
|
||||||
|
try:
|
||||||
|
env.ParseConfig('pkg-config --cflags --libs libjpeg')
|
||||||
|
except OSError:
|
||||||
|
print("libjpeg not installed, Emulator build is not possible")
|
||||||
|
|
||||||
|
try:
|
||||||
|
env.ParseConfig('pkg-config --cflags --libs sdl2 SDL2_image')
|
||||||
|
except OSError:
|
||||||
|
print("SDL2 not installed, Emulator build is not possible")
|
||||||
|
|
||||||
|
|
||||||
|
env.Replace(
|
||||||
|
ALLSOURCES=SOURCE_MOD + SOURCE_MOD_CRYPTO + SOURCE_PRODTEST + SOURCE_HAL,
|
||||||
|
ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES']))
|
||||||
|
|
||||||
|
cmake_gen = env.Command(
|
||||||
|
target='CMakeLists.txt',
|
||||||
|
source='',
|
||||||
|
action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS',
|
||||||
|
)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rust library
|
||||||
|
#
|
||||||
|
env.get("ENV")["RUST_TARGET"] = os.popen("rustc -vV | sed -n 's/host: //p'").read().strip()
|
||||||
|
features = ['prodtest',] + FEATURES_AVAILABLE + RUST_UI_FEATURES
|
||||||
|
if ARGUMENTS.get('TREZOR_EMULATOR_DEBUGGABLE', '0') == '1':
|
||||||
|
profile = 'dev'
|
||||||
|
else:
|
||||||
|
profile = 'release'
|
||||||
|
|
||||||
|
rust = tools.add_rust_lib(
|
||||||
|
env=env,
|
||||||
|
build='prodtest_emu',
|
||||||
|
profile=profile,
|
||||||
|
features=features,
|
||||||
|
all_paths=ALLPATHS,
|
||||||
|
build_dir=str(Dir('.').abspath),
|
||||||
|
)
|
||||||
|
|
||||||
|
env.Append(LINKFLAGS=['-lm'])
|
||||||
|
|
||||||
|
if env['PLATFORM'] == 'darwin':
|
||||||
|
env.Append(LINKFLAGS=['-Wl,-dead_strip'])
|
||||||
|
else:
|
||||||
|
env.Append(LINKFLAGS=['-Wl,--gc-sections'])
|
||||||
|
|
||||||
|
#
|
||||||
|
# Program objects
|
||||||
|
#
|
||||||
|
|
||||||
|
obj_program = []
|
||||||
|
obj_program += env.Object(source=SOURCE_MOD)
|
||||||
|
obj_program += env.Object(source=SOURCE_MOD_CRYPTO, CCFLAGS='$CCFLAGS -ftrivial-auto-var-init=zero')
|
||||||
|
obj_program += env.Object(source=SOURCE_PRODTEST)
|
||||||
|
obj_program += env.Object(source=SOURCE_HAL)
|
||||||
|
|
||||||
|
program_elf = env.Command(
|
||||||
|
target='prodtest.elf',
|
||||||
|
source=obj_program,
|
||||||
|
action=
|
||||||
|
'$CC -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $LINKFLAGS')
|
||||||
|
|
||||||
|
env.Depends(program_elf, rust)
|
||||||
|
|
||||||
|
if CMAKELISTS != 0:
|
||||||
|
env.Depends(program_elf, cmake_gen)
|
@ -10,6 +10,7 @@ SConscript('SConscript.bootloader_emu', variant_dir='build/bootloader_emu', dupl
|
|||||||
SConscript('SConscript.kernel', variant_dir='build/kernel', duplicate=False)
|
SConscript('SConscript.kernel', variant_dir='build/kernel', duplicate=False)
|
||||||
SConscript('SConscript.firmware', variant_dir='build/firmware', duplicate=False)
|
SConscript('SConscript.firmware', variant_dir='build/firmware', duplicate=False)
|
||||||
SConscript('SConscript.prodtest', variant_dir='build/prodtest', duplicate=False)
|
SConscript('SConscript.prodtest', variant_dir='build/prodtest', duplicate=False)
|
||||||
|
SConscript('SConscript.prodtest_emu', variant_dir='build/prodtest_emu', duplicate=False)
|
||||||
SConscript('SConscript.reflash', variant_dir='build/reflash', duplicate=False)
|
SConscript('SConscript.reflash', variant_dir='build/reflash', duplicate=False)
|
||||||
SConscript('SConscript.unix', variant_dir='build/unix', duplicate=False)
|
SConscript('SConscript.unix', variant_dir='build/unix', duplicate=False)
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include <rtl/cli.h>
|
#include <rtl/cli.h>
|
||||||
|
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
static void prodtest_help(cli_t* cli) {
|
static void prodtest_help(cli_t* cli) {
|
||||||
const char* prefix = cli_arg(cli, "prefix");
|
const char* prefix = cli_arg(cli, "prefix");
|
||||||
size_t prefix_len = strlen(prefix);
|
size_t prefix_len = strlen(prefix);
|
||||||
@ -36,12 +38,8 @@ static void prodtest_help(cli_t* cli) {
|
|||||||
cli_trace(cli, "Available commands (filtered):");
|
cli_trace(cli, "Available commands (filtered):");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern cli_command_t _prodtest_cli_cmd_section_start;
|
const cli_command_t* cmd = commands_get_ptr();
|
||||||
extern cli_command_t _prodtest_cli_cmd_section_end;
|
for (int i = 0; i < commands_count(); i++) {
|
||||||
|
|
||||||
cli_command_t* cmd = &_prodtest_cli_cmd_section_start;
|
|
||||||
|
|
||||||
while (cmd < &_prodtest_cli_cmd_section_end) {
|
|
||||||
if (cmd->name[0] != '$' && strncmp(cmd->name, prefix, prefix_len) == 0) {
|
if (cmd->name[0] != '$' && strncmp(cmd->name, prefix, prefix_len) == 0) {
|
||||||
cli_trace(cli, " %s - %s", cmd->name, cmd->info);
|
cli_trace(cli, " %s - %s", cmd->name, cmd->info);
|
||||||
}
|
}
|
||||||
|
55
core/embed/projects/prodtest/commands.c
Normal file
55
core/embed/projects/prodtest/commands.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* 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 "commands.h"
|
||||||
|
|
||||||
|
#ifdef TREZOR_EMULATOR
|
||||||
|
#include <stdlib.h>
|
||||||
|
const cli_command_t **_cmd_list;
|
||||||
|
size_t _cmd_count;
|
||||||
|
|
||||||
|
void register_cli_command(const cli_command_t *cmd) {
|
||||||
|
_cmd_list = realloc(_cmd_list, sizeof(*_cmd_list) * (_cmd_count + 1));
|
||||||
|
_cmd_list[_cmd_count++] = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const cli_command_t *commands_get_ptr(void) {
|
||||||
|
#ifdef TREZOR_EMULATOR
|
||||||
|
return *_cmd_list;
|
||||||
|
|
||||||
|
#else
|
||||||
|
extern cli_command_t _prodtest_cli_cmd_section_start;
|
||||||
|
|
||||||
|
return &_prodtest_cli_cmd_section_start;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t commands_count(void) {
|
||||||
|
#ifdef TREZOR_EMULATOR
|
||||||
|
return _cmd_count;
|
||||||
|
|
||||||
|
#else
|
||||||
|
extern cli_command_t _prodtest_cli_cmd_section_start;
|
||||||
|
extern cli_command_t _prodtest_cli_cmd_section_end;
|
||||||
|
|
||||||
|
return &_prodtest_cli_cmd_section_end - &_prodtest_cli_cmd_section_start;
|
||||||
|
#endif
|
||||||
|
}
|
28
core/embed/projects/prodtest/commands.h
Normal file
28
core/embed/projects/prodtest/commands.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <trezor_types.h>
|
||||||
|
|
||||||
|
#include <rtl/cli.h>
|
||||||
|
|
||||||
|
const cli_command_t* commands_get_ptr(void);
|
||||||
|
|
||||||
|
size_t commands_count(void);
|
73
core/embed/projects/prodtest/emulator.c
Normal file
73
core/embed/projects/prodtest/emulator.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include <trezor_model.h>
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include <io/display.h>
|
||||||
|
#include <util/flash.h>
|
||||||
|
#include <util/flash_otp.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int prodtest_main(void);
|
||||||
|
|
||||||
|
void usage(void) {
|
||||||
|
printf("Usage: ./build/prodtest/prodtest_emu [options]\n");
|
||||||
|
printf(
|
||||||
|
"To connect via terminal, install socat (i.e. 'sudo apt-get install "
|
||||||
|
"socat' in Ubuntu)\n");
|
||||||
|
printf(
|
||||||
|
"Bind the UDP with 'socat -d -d "
|
||||||
|
"pty,link=/dev/ttyVCP0,mode=666,raw,echo=0 UDP:127.0.0.1:21424'\n");
|
||||||
|
printf("Then you can connect with you terminal to /dev/ttyVCP0\n");
|
||||||
|
printf(" -h show this help\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sdl_event_filter(void *userdata, SDL_Event *event) {
|
||||||
|
switch (event->type) {
|
||||||
|
case SDL_QUIT:
|
||||||
|
exit(3);
|
||||||
|
return 0;
|
||||||
|
case SDL_KEYUP:
|
||||||
|
if (event->key.repeat) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (event->key.keysym.sym) {
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
exit(3);
|
||||||
|
return 0;
|
||||||
|
case SDLK_p:
|
||||||
|
display_save("emu");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
SDL_SetEventFilter(sdl_event_filter, NULL);
|
||||||
|
|
||||||
|
display_init(DISPLAY_RESET_CONTENT);
|
||||||
|
flash_init();
|
||||||
|
flash_otp_init();
|
||||||
|
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt(argc, argv, "h")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int exit_code = prodtest_main();
|
||||||
|
|
||||||
|
char msg[64];
|
||||||
|
snprintf(msg, sizeof(msg), "Exit code: %d", exit_code);
|
||||||
|
|
||||||
|
error_shutdown_ex("PRODTEST ERROR", msg, "UNEXPECTED EXIT");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -31,6 +31,7 @@
|
|||||||
#include <util/rsod.h>
|
#include <util/rsod.h>
|
||||||
#include <util/unit_properties.h>
|
#include <util/unit_properties.h>
|
||||||
|
|
||||||
|
#include "commands.h"
|
||||||
#include "rust_types.h"
|
#include "rust_types.h"
|
||||||
#include "rust_ui_prodtest.h"
|
#include "rust_ui_prodtest.h"
|
||||||
#include "sys/sysevent.h"
|
#include "sys/sysevent.h"
|
||||||
@ -133,6 +134,8 @@ static void vcp_intr(void) { cli_abort(&g_cli); }
|
|||||||
#define VCP_PACKET_LEN 512
|
#define VCP_PACKET_LEN 512
|
||||||
#elif defined(USE_USB_FS)
|
#elif defined(USE_USB_FS)
|
||||||
#define VCP_PACKET_LEN 64
|
#define VCP_PACKET_LEN 64
|
||||||
|
#elif defined(TREZOR_EMULATOR)
|
||||||
|
#define VCP_PACKET_LEN 64
|
||||||
#else
|
#else
|
||||||
#error "USB type not defined"
|
#error "USB type not defined"
|
||||||
#endif
|
#endif
|
||||||
@ -171,9 +174,13 @@ static void usb_init_all(void) {
|
|||||||
.rx_intr_byte = 3, // Ctrl-C
|
.rx_intr_byte = 3, // Ctrl-C
|
||||||
.iface_num = VCP_IFACE,
|
.iface_num = VCP_IFACE,
|
||||||
.data_iface_num = 0x01,
|
.data_iface_num = 0x01,
|
||||||
|
#ifdef TREZOR_EMULATOR
|
||||||
|
.emu_port = 21424,
|
||||||
|
#else
|
||||||
.ep_cmd = 0x02,
|
.ep_cmd = 0x02,
|
||||||
.ep_in = 0x01,
|
.ep_in = 0x01,
|
||||||
.ep_out = 0x01,
|
.ep_out = 0x01,
|
||||||
|
#endif
|
||||||
.polling_interval = 10,
|
.polling_interval = 10,
|
||||||
.max_packet_len = VCP_PACKET_LEN,
|
.max_packet_len = VCP_PACKET_LEN,
|
||||||
};
|
};
|
||||||
@ -254,7 +261,11 @@ void prodtest_show_homescreen(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TREZOR_EMULATOR
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
#else
|
||||||
|
int prodtest_main(void) {
|
||||||
|
#endif
|
||||||
system_init(&rsod_panic_handler);
|
system_init(&rsod_panic_handler);
|
||||||
|
|
||||||
drivers_init();
|
drivers_init();
|
||||||
@ -263,12 +274,7 @@ int main(void) {
|
|||||||
// Initialize command line interface
|
// Initialize command line interface
|
||||||
cli_init(&g_cli, console_read, console_write, NULL);
|
cli_init(&g_cli, console_read, console_write, NULL);
|
||||||
|
|
||||||
extern cli_command_t _prodtest_cli_cmd_section_start;
|
cli_set_commands(&g_cli, commands_get_ptr(), commands_count());
|
||||||
extern cli_command_t _prodtest_cli_cmd_section_end;
|
|
||||||
|
|
||||||
cli_set_commands(
|
|
||||||
&g_cli, &_prodtest_cli_cmd_section_start,
|
|
||||||
&_prodtest_cli_cmd_section_end - &_prodtest_cli_cmd_section_start);
|
|
||||||
|
|
||||||
#ifdef USE_OPTIGA
|
#ifdef USE_OPTIGA
|
||||||
optiga_init();
|
optiga_init();
|
||||||
|
@ -66,12 +66,23 @@ typedef struct {
|
|||||||
#define CONCAT_INDIRECT(x, y) x##y
|
#define CONCAT_INDIRECT(x, y) x##y
|
||||||
#define CONCAT(x, y) CONCAT_INDIRECT(x, y)
|
#define CONCAT(x, y) CONCAT_INDIRECT(x, y)
|
||||||
|
|
||||||
|
#ifdef TREZOR_EMULATOR
|
||||||
|
#define PRODTEST_CLI_CMD(...) PRODTEST_CLI_CMD_IMPL(__COUNTER__, __VA_ARGS__)
|
||||||
|
#define PRODTEST_CLI_CMD_IMPL(cnt, ...) \
|
||||||
|
extern void register_cli_command(const cli_command_t* cmd); \
|
||||||
|
static const cli_command_t CONCAT(_cli_cmd_handler, cnt) = {__VA_ARGS__}; \
|
||||||
|
__attribute__((constructor)) static void CONCAT( \
|
||||||
|
__register, CONCAT(_cli_cmd_handler, cnt))(void) { \
|
||||||
|
register_cli_command(&CONCAT(_cli_cmd_handler, cnt)); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
// Registers a command handler by placing its registration structure
|
// Registers a command handler by placing its registration structure
|
||||||
// into a specially designated linker script section
|
// into a specially designated linker script section
|
||||||
#define PRODTEST_CLI_CMD(...) \
|
#define PRODTEST_CLI_CMD(...) \
|
||||||
__attribute__((used, \
|
__attribute__((used, \
|
||||||
section(".prodtest_cli_cmd"))) static const cli_command_t \
|
section(".prodtest_cli_cmd"))) static const cli_command_t \
|
||||||
CONCAT(_cli_cmd_handler, __COUNTER__) = {__VA_ARGS__};
|
CONCAT(_cli_cmd_handler, __COUNTER__) = {__VA_ARGS__};
|
||||||
|
#endif
|
||||||
|
|
||||||
// Callback for writing characters to console output
|
// Callback for writing characters to console output
|
||||||
typedef size_t (*cli_write_cb_t)(void* ctx, const char* buf, size_t len);
|
typedef size_t (*cli_write_cb_t)(void* ctx, const char* buf, size_t len);
|
||||||
|
Loading…
Reference in New Issue
Block a user