diff --git a/core/Makefile b/core/Makefile index a56518d51..c55bda722 100644 --- a/core/Makefile +++ b/core/Makefile @@ -12,6 +12,9 @@ BOOTLOADER_EMU_BUILD_DIR = $(BUILD_DIR)/bootloader_emu PRODTEST_BUILD_DIR = $(BUILD_DIR)/prodtest REFLASH_BUILD_DIR = $(BUILD_DIR)/reflash FIRMWARE_BUILD_DIR = $(BUILD_DIR)/firmware +FW_SS_BUILD_DIR = $(BUILD_DIR)/fw_ss +FW_CS_BUILD_DIR = $(BUILD_DIR)/fw_cs +FW_AP_BUILD_DIR = $(BUILD_DIR)/fw_ap UNIX_BUILD_DIR = $(BUILD_DIR)/unix RUST_BUILD_DIR = $(BUILD_DIR)/rust @@ -223,6 +226,32 @@ build_firmware: templates build_cross ## build firmware with frozen modules DISABLE_OPTIGA="$(DISABLE_OPTIGA)" \ $(FIRMWARE_BUILD_DIR)/firmware.bin +build_fw_ss: templates build_cross ## build secure services firmware (experiment) + $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ + TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ + PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" \ + BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \ + DISABLE_OPTIGA="$(DISABLE_OPTIGA)" \ + $(FW_SS_BUILD_DIR)/fw_ss.bin + +build_fw_cs: templates build_cross ## build secure services firmware (experiment) + $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ + TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ + PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" \ + BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \ + DISABLE_OPTIGA="$(DISABLE_OPTIGA)" \ + $(FW_CS_BUILD_DIR)/fw_cs.bin + +build_fw_ap: templates build_cross ## build secure services firmware (experiment) + $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" \ + TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ + PYOPT="$(PYOPT)" BITCOIN_ONLY="$(BITCOIN_ONLY)" \ + BOOTLOADER_QA="$(BOOTLOADER_QA)" BOOTLOADER_DEVEL="$(BOOTLOADER_DEVEL)" \ + DISABLE_OPTIGA="$(DISABLE_OPTIGA)" \ + $(FW_AP_BUILD_DIR)/fw_ap.bin + +build_fw: build_fw_ss build_fw_cs build_fw_ap + build_unix: templates ## build unix port $(SCONS) CFLAGS="$(CFLAGS)" $(UNIX_BUILD_DIR)/trezor-emu-core $(UNIX_PORT_OPTS) \ TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" \ @@ -268,6 +297,9 @@ clean_reflash: ## clean reflash build clean_firmware: ## clean firmware build rm -rf $(FIRMWARE_BUILD_DIR) $(RUST_BUILD_DIR) +clean_fw_ss: ## clean secure services firmware build (experimental) + rm -rf $(FW_SS_BUILD_DIR) + clean_unix: ## clean unix build rm -rf $(UNIX_BUILD_DIR) $(RUST_BUILD_DIR) @@ -298,6 +330,17 @@ else $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(FIRMWARE_START); exit" endif +flash_fw_ss: $(FW_SS_BUILD_DIR)/fw_ss.bin ## flash secure service firmware using OpenOCD (experiment) + $(OPENOCD) -c "init; reset halt; flash write_image erase $< 0x0C050000; exit" + +flash_fw_cs: $(FW_CS_BUILD_DIR)/fw_cs.bin ## flash core service firmware using OpenOCD (experiment) + $(OPENOCD) -c "init; reset halt; flash write_image erase $< 0x08090000; exit" + +flash_fw_ap: $(FW_AP_BUILD_DIR)/fw_ap.bin ## flash application firmware using OpenOCD (experiment) + $(OPENOCD) -c "init; reset halt; flash write_image erase $< 0x080D0000; exit" + +flash_fw: flash_fw_ss flash_fw_cs flash_fw_ap ## flash ss/cs/ap + flash_combine: $(PRODTEST_BUILD_DIR)/combined.bin ## flash combined using OpenOCD $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(BOARDLOADER_START); exit" diff --git a/core/SConscript.boardloader b/core/SConscript.boardloader index 696ba8529..59b9cd063 100644 --- a/core/SConscript.boardloader +++ b/core/SConscript.boardloader @@ -103,6 +103,7 @@ env.Replace( '-fsingle-precision-constant -fdata-sections -ffunction-sections ' '-ffreestanding ' '-fstack-protector-all ' + '-mcmse ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', LINKFLAGS=f"-T embed/boardloader/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/boardloader/boardloader.map -Wl,--warn-common -Wl,--print-memory-usage", diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index a63d80714..fb3956bd8 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -148,6 +148,7 @@ env.Replace( '-fsingle-precision-constant -fdata-sections -ffunction-sections ' '-ffreestanding ' '-fstack-protector-all ' + '-mcmse ' + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', LINKFLAGS=f'-T embed/bootloader/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/bootloader/bootloader.map -Wl,--warn-common -Wl,--print-memory-usage', diff --git a/core/SConscript.fw_ap b/core/SConscript.fw_ap new file mode 100644 index 000000000..4b5a2ee7f --- /dev/null +++ b/core/SConscript.fw_ap @@ -0,0 +1,107 @@ +# pylint: disable=E0602 +# fmt: off + +import os +import tools +from site_scons.boards import get_hw_model_as_number + +PRODUCTION = ARGUMENTS.get('PRODUCTION', '0') == '1' +BOOTLOADER_QA = ARGUMENTS.get('BOOTLOADER_QA', '0') == '1' +BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' +TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') + +env = Environment(ENV=os.environ, CFLAGS=f"{ARGUMENTS.get('CFLAGS', '')} -DPRODUCTION={int(PRODUCTION)} -DBOOTLOADER_QA={int(BOOTLOADER_QA)}") + +FILE_SUFFIX= env.get('ENV')['SUFFIX'] + +SOURCE_FIRMWARE = [ + 'embed/fw_ap/main.c', + 'embed/fw_ap/core_api.S', + 'embed/fw_ap/libc_syscalls.c', + 'embed/fw_ap/startup.S', +] + +env.Replace( + CAT='cat', + DD='dd', + CP='cp', + SED='sed', + AS='arm-none-eabi-as', + AR='arm-none-eabi-ar', + CC='arm-none-eabi-gcc', + LINK='arm-none-eabi-gcc', + SIZE='arm-none-eabi-size', + STRIP='arm-none-eabi-strip', + OBJCOPY='arm-none-eabi-objcopy', ) + +env.Replace( + TREZOR_MODEL=TREZOR_MODEL,) + +if TREZOR_MODEL in ('1',): + LD_VARIANT = '' if EVERYTHING else '_min' +else: + LD_VARIANT = '' + +env.Replace( + COPT=env.get('ENV').get('OPTIMIZE', '-O0'), + CCFLAGS='$COPT ' + '-g3 ' + '-nostdlib ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -fno-common ' + '-fsingle-precision-constant -fdata-sections -ffunction-sections ' + '-ffreestanding ' + '-fstack-protector-all ' + + env.get('ENV')["CPU_CCFLAGS"], + LINKFLAGS='-T embed/fw_ap/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/fw_ap/fw_ap.map -Wl,--warn-common build/fw_ss/fw_ss_cmse.o' % LD_VARIANT, + CPPPATH=[ + '.', + 'embed/fw_ap', + ], + CPPDEFINES=[ + 'TREZOR_MODEL_'+TREZOR_MODEL, + f'HW_MODEL={get_hw_model_as_number("D002")}', + 'HW_REVISION=0', + ], + ASFLAGS=env.get('ENV')['CPU_ASFLAGS'], + ASPPFLAGS='$CFLAGS $CCFLAGS', + ) + +env.Replace( + PYTHON='python', +) + + +# +# Program objects +# + +source_files = SOURCE_FIRMWARE +obj_program = [] +obj_program.extend(env.Object(source=SOURCE_FIRMWARE)) + + +MODEL_IDENTIFIER = tools.get_model_identifier(TREZOR_MODEL) + +program_elf = env.Command( + target='fw_ap.elf', + source=obj_program, + action= + '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', +) + +BINARY_NAME = f"build/fw_ap/fw_ap-{tools.get_model_identifier(TREZOR_MODEL)}" +BINARY_NAME += "-" + tools.get_version('embed/fw_ap/version.h') +BINARY_NAME += "-" + tools.get_git_revision_short_hash() +BINARY_NAME += "-dirty" if tools.get_git_modified() else "" +BINARY_NAME += ".bin" + +action_bin=[ + '$OBJCOPY -O binary -j .flash -j .data $SOURCE ${TARGET}', + '$CP $TARGET ' + BINARY_NAME, + ] + +program_bin = env.Command( + target='fw_ap.bin', + source=program_elf, + action=action_bin, +) diff --git a/core/SConscript.fw_cs b/core/SConscript.fw_cs new file mode 100644 index 000000000..98183cf09 --- /dev/null +++ b/core/SConscript.fw_cs @@ -0,0 +1,365 @@ +# pylint: disable=E0602 +# fmt: off + +import os +import tools + +BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0') +PRODUCTION = ARGUMENTS.get('PRODUCTION', '0') == '1' +BOOTLOADER_QA = ARGUMENTS.get('BOOTLOADER_QA', '0') == '1' +BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' +EVERYTHING = BITCOIN_ONLY != '1' +TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') +CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) +PYOPT = ARGUMENTS.get('PYOPT', '1') +DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1' + + +FEATURE_FLAGS = { + "RDI": False, + "SECP256K1_ZKP": False, # required for trezor.crypto.curve.bip340 (BIP340/Taproot) + "SYSTEM_VIEW": False, +} + +FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga"] +if DISABLE_OPTIGA and PYOPT == '0': + FEATURES_WANTED.remove("optiga") + +CCFLAGS_MOD = '' +CPPPATH_MOD = [] +CPPDEFINES_MOD = [] +SOURCE_MOD = [] +CPPDEFINES_HAL = [] +SOURCE_HAL = [] +PATH_HAL = [] + +FROZEN = False + +if TREZOR_MODEL in ('1', 'R'): + FONT_NORMAL='Font_PixelOperator_Regular_8' + FONT_DEMIBOLD='Font_Unifont_Bold_16' + FONT_BOLD='Font_PixelOperator_Bold_8' + FONT_MONO='Font_PixelOperatorMono_Regular_8' + FONT_BIG='Font_Unifont_Regular_16' +elif TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): + FONT_NORMAL='Font_TTHoves_Regular_21' + FONT_DEMIBOLD='Font_TTHoves_DemiBold_21' + FONT_BOLD='Font_TTHoves_Bold_17' + FONT_MONO='Font_RobotoMono_Medium_20' + FONT_BIG=None + +# modtrezorconfig +CPPPATH_MOD += [ + 'embed/extmod/modtrezorconfig', + 'vendor/trezor-storage', +] +SOURCE_MOD += [ + 'vendor/trezor-storage/norcow.c', + 'vendor/trezor-storage/storage.c', + 'vendor/trezor-storage/flash_area.c', + 'vendor/trezor-crypto/memzero.c', +] + +# modtrezorcrypto +CCFLAGS_MOD += '-Wno-sequence-point ' +CPPPATH_MOD += [ + 'vendor/trezor-crypto', +] +CPPDEFINES_MOD += [ + 'AES_128', + 'AES_192', + ('USE_BIP32_CACHE', '0'), + ('USE_KECCAK', '1'), + ('USE_ETHEREUM', '1' if EVERYTHING else '0'), + ('USE_MONERO', '1' if EVERYTHING else '0'), + ('USE_CARDANO', '1' if EVERYTHING else '0'), + ('USE_NEM', '1' if (EVERYTHING and TREZOR_MODEL != "R") else '0'), + ('USE_EOS', '1' if (EVERYTHING and TREZOR_MODEL != "R") else '0'), +] +SOURCE_MOD += [ + 'embed/lib/buffers.c', + 'embed/lib/display.c', + 'embed/lib/colors.c', + 'embed/lib/fonts/fonts.c', + 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', + 'embed/lib/mini_printf.c', + ] + +if EVERYTHING: + SOURCE_MOD += [ + 'vendor/trezor-crypto/cardano.c', + 'vendor/trezor-crypto/monero/base58.c', + 'vendor/trezor-crypto/monero/serialize.c', + 'vendor/trezor-crypto/monero/xmr.c', + ] + +# libsecp256k1-zkp +if FEATURE_FLAGS["SECP256K1_ZKP"]: + CPPPATH_MOD += [ + 'vendor/secp256k1-zkp', + 'vendor/secp256k1-zkp/src', + 'vendor/secp256k1-zkp/include', + ] + CPPDEFINES_MOD += [ + 'USE_SECP256K1_ZKP', + 'USE_SECP256K1_ZKP_ECDSA', + ('SECP256K1_CONTEXT_SIZE', '180'), + 'USE_ASM_ARM', + 'USE_EXTERNAL_ASM', + 'USE_EXTERNAL_DEFAULT_CALLBACKS', + ('ECMULT_GEN_PREC_BITS', '2'), + ('ECMULT_WINDOW_SIZE', '8'), + 'ENABLE_MODULE_GENERATOR', + 'ENABLE_MODULE_RECOVERY', + 'ENABLE_MODULE_SCHNORRSIG', + 'ENABLE_MODULE_EXTRAKEYS', + ] + SOURCE_MOD_SECP256K1_ZKP = [ + 'vendor/secp256k1-zkp/src/secp256k1.c', + 'vendor/secp256k1-zkp/src/precomputed_ecmult.c', + 'vendor/secp256k1-zkp/src/precomputed_ecmult_gen.c', + 'vendor/secp256k1-zkp/src/asm/field_10x26_arm.s' + ] + SOURCE_MOD += [ + 'vendor/trezor-crypto/zkp_context.c', + 'vendor/trezor-crypto/zkp_ecdsa.c', + 'vendor/trezor-crypto/zkp_bip340.c', + ] + + +CPPDEFINES_MOD += [ + 'TREZOR_UI2', +] + +if FEATURE_FLAGS["RDI"]: + CPPDEFINES_MOD += ['RDI'] + +if FEATURE_FLAGS["SYSTEM_VIEW"]: + SOURCE_FIRMWARE += [ + 'embed/segger/SEGGER/SEGGER_SYSVIEW_Config_NoOS.c', + 'embed/segger/SEGGER/SEGGER_SYSVIEW.c', + 'embed/segger/SEGGER/SEGGER_RTT.c', + 'embed/segger/SEGGER/SEGGER_RTT_ASM_ARMv7M.S', + 'embed/segger/SEGGER/Syscalls/SEGGER_RTT_Syscalls_GCC.c', + 'embed/fw_cs/systemview.c', + ] + CPPPATH_MOD += [ + 'embed/segger/SEGGER/', + 'embed/segger/Config/', + ] + CPPDEFINES_MOD += ['SYSTEM_VIEW'] + CCFLAGS_MOD += '-DSYSTEM_VIEW ' + +# fonts +tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('DEMIBOLD', FONT_DEMIBOLD, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('MONO', FONT_MONO, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BIG', FONT_BIG, CPPDEFINES_MOD, SOURCE_MOD) + + +env = Environment(ENV=os.environ, CFLAGS=f"{ARGUMENTS.get('CFLAGS', '')} -DPRODUCTION={int(PRODUCTION)} -DPYOPT={PYOPT} -DBOOTLOADER_QA={int(BOOTLOADER_QA)} -DBITCOIN_ONLY={BITCOIN_ONLY}") + +FEATURES_AVAILABLE = tools.configure_board(TREZOR_MODEL, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) + +FILE_SUFFIX= env.get('ENV')['SUFFIX'] + +SOURCE_FIRMWARE = [ + 'embed/fw_cs/jump_unprivileged.s', + 'embed/fw_cs/svc_handler_low.s', + 'embed/fw_cs/svc_handler.c', + 'embed/fw_cs/core_api_impl.c', + 'embed/fw_cs/header.S', + 'embed/fw_cs/main.c', + f'embed/fw_cs/startup_{FILE_SUFFIX}.S', +] + + +if TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): + UI_LAYOUT = 'UI_LAYOUT_TT' + ui_layout_feature = 'model_tt' +elif TREZOR_MODEL in ('1', 'R'): + UI_LAYOUT = 'UI_LAYOUT_TR' + ui_layout_feature = 'model_tr' +else: + raise ValueError('Unknown Trezor model') + +if 'sd_card' in FEATURES_AVAILABLE: + SDCARD = True +else: + SDCARD = False + + +env.Replace( + CAT='cat', + DD='dd', + CP='cp', + SED='sed', + AS='arm-none-eabi-as', + AR='arm-none-eabi-ar', + CC='arm-none-eabi-gcc', + LINK='arm-none-eabi-gcc', + SIZE='arm-none-eabi-size', + STRIP='arm-none-eabi-strip', + OBJCOPY='arm-none-eabi-objcopy', ) + +env.Replace( + TREZOR_MODEL=TREZOR_MODEL,) + +if TREZOR_MODEL in ('1',): + LD_VARIANT = '' if EVERYTHING else '_min' +else: + LD_VARIANT = '' + +env.Replace( + COPT=env.get('ENV').get('OPTIMIZE', '-O0'), + CCFLAGS='$COPT ' + '-g3 ' + '-nostdlib ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -fno-common ' + '-fsingle-precision-constant -fdata-sections -ffunction-sections ' + '-ffreestanding ' + '-fstack-protector-all ' + + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, + LINKFLAGS='-T embed/fw_cs/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/fw_cs/fw_cs.map -Wl,--warn-common build/fw_ss/fw_ss_cmse.o' % LD_VARIANT, + CPPPATH=[ + '.', + 'embed/rust', + 'embed/fw_cs', + 'embed/lib', + 'embed/models', + 'embed/trezorhal', + 'embed/extmod/modtrezorui', + ] + CPPPATH_MOD + PATH_HAL, + CPPDEFINES=[ + 'FIRMWARE', + 'TREZOR_MODEL_'+TREZOR_MODEL, + 'USE_HAL_DRIVER', + 'ARM_USER_MODE', + UI_LAYOUT, + ] + CPPDEFINES_MOD + CPPDEFINES_HAL, + ASFLAGS=env.get('ENV')['CPU_ASFLAGS'], + ASPPFLAGS='$CFLAGS $CCFLAGS', + ) + +env.Replace( + HEADERTOOL='tools/headertool.py', + PYTHON='python', + MAKEVERSIONHDR='$PYTHON vendor/micropython/py/makeversionhdr.py', + MAKEMODULEDEFS='$PYTHON vendor/micropython/py/makemoduledefs.py', + MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', +) + + +# +# Program objects +# + +source_files = SOURCE_MOD + SOURCE_FIRMWARE + SOURCE_HAL +obj_program = [] +obj_program.extend(env.Object(source=SOURCE_MOD)) +obj_program.extend(env.Object(source=SOURCE_FIRMWARE)) +obj_program.extend(env.Object(source=SOURCE_HAL)) + +env.Replace( + ALLSOURCES=source_files, + ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES'] + [f"PRODUCTION={int(PRODUCTION)}", f"BOOTLOADER_QA={int(BOOTLOADER_QA)}", f"PYOPT={PYOPT}", f"BITCOIN_ONLY={BITCOIN_ONLY}"])) + + +cmake_gen = env.Command( + target='CMakeLists.txt', + source='', + action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', +) + + +MODEL_IDENTIFIER = tools.get_model_identifier(TREZOR_MODEL) +BOOTLOADER_SUFFIX = MODEL_IDENTIFIER +if BOOTLOADER_QA: + BOOTLOADER_SUFFIX += '_qa' + +# select vendor header +if BOOTLOADER_QA or BOOTLOADER_DEVEL: + vendor = "dev_DO_NOT_SIGN_signed_dev" +elif not PRODUCTION: + vendor = "unsafe_signed_prod" +else: + if TREZOR_MODEL in ('T',): + vendor = "satoshilabs_signed_prod" + elif BITCOIN_ONLY == '1': + vendor = "trezor_btconly_signed_prod" + else: + vendor = "trezor_signed_prod" + +VENDORHEADER = f'embed/vendorheader/{MODEL_IDENTIFIER}/vendorheader_{vendor}.bin' + + +if TREZOR_MODEL not in ('1',): + obj_program.extend( + env.Command( + target='embed/fw_cs/vendorheader.o', + source=VENDORHEADER, + action='$OBJCOPY -I binary -O elf32-littlearm -B arm' + ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' + ' $SOURCE $TARGET', )) + +if TREZOR_MODEL not in ('DISC1', 'DISC2'): + tools.embed_binary( + obj_program, + env, + 'bootloader', + 'embed/fw_cs/bootloaders/bootloader.o', + f'embed/fw_cs/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin', + ) + +program_elf = env.Command( + target='fw_cs.elf', + source=obj_program, + action= + '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', +) + +if CMAKELISTS != 0: + env.Depends(program_elf, cmake_gen) + +BINARY_NAME = f"build/fw_cs/fw_cs-{tools.get_model_identifier(TREZOR_MODEL)}" +if not EVERYTHING: + BINARY_NAME += "-btconly" +BINARY_NAME += "-" + tools.get_version('embed/fw_cs/version.h') +BINARY_NAME += "-" + tools.get_git_revision_short_hash() +BINARY_NAME += "-dirty" if tools.get_git_modified() else "" +BINARY_NAME += ".bin" + + + +if TREZOR_MODEL in ('1',): + action_bin=[ + '$OBJCOPY -O binary -j .header -j .flash -j .data -j .sensitive $SOURCE $TARGET', + '../legacy/bootloader/firmware_sign.py -f $TARGET', + '$CP $TARGET ' + BINARY_NAME, + ] +else: + if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .sensitive --pad-to 0x08100000 $SOURCE ${TARGET}.p1', + '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', + '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', + '$CP $TARGET ' + BINARY_NAME, + ] + elif 'STM32U5A9xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .sensitive $SOURCE ${TARGET}', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$CP $TARGET ' + BINARY_NAME, + ] + else: + raise Exception("Unknown MCU") + +program_bin = env.Command( + target='fw_cs.bin', + source=program_elf, + action=action_bin, +) diff --git a/core/SConscript.fw_ss b/core/SConscript.fw_ss new file mode 100644 index 000000000..495d7a2c2 --- /dev/null +++ b/core/SConscript.fw_ss @@ -0,0 +1,364 @@ +# pylint: disable=E0602 +# fmt: off + +import os +import tools + +BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0') +PRODUCTION = ARGUMENTS.get('PRODUCTION', '0') == '1' +BOOTLOADER_QA = ARGUMENTS.get('BOOTLOADER_QA', '0') == '1' +BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' +EVERYTHING = BITCOIN_ONLY != '1' +TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') +CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) +PYOPT = ARGUMENTS.get('PYOPT', '1') +DISABLE_OPTIGA = ARGUMENTS.get('DISABLE_OPTIGA', '0') == '1' + + +FEATURE_FLAGS = { + "RDI": False, + "SECP256K1_ZKP": False, # required for trezor.crypto.curve.bip340 (BIP340/Taproot) + "SYSTEM_VIEW": False, +} + +FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "dma2d", "consumption_mask", "usb" ,"optiga"] +if DISABLE_OPTIGA and PYOPT == '0': + FEATURES_WANTED.remove("optiga") + +CCFLAGS_MOD = '' +CPPPATH_MOD = [] +CPPDEFINES_MOD = [] +SOURCE_MOD = [] +CPPDEFINES_HAL = [] +SOURCE_HAL = [] +PATH_HAL = [] + +FROZEN = False + +if TREZOR_MODEL in ('1', 'R'): + FONT_NORMAL='Font_PixelOperator_Regular_8' + FONT_DEMIBOLD='Font_Unifont_Bold_16' + FONT_BOLD='Font_PixelOperator_Bold_8' + FONT_MONO='Font_PixelOperatorMono_Regular_8' + FONT_BIG='Font_Unifont_Regular_16' +elif TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): + FONT_NORMAL='Font_TTHoves_Regular_21' + FONT_DEMIBOLD='Font_TTHoves_DemiBold_21' + FONT_BOLD='Font_TTHoves_Bold_17' + FONT_MONO='Font_RobotoMono_Medium_20' + FONT_BIG=None + +# modtrezorconfig +CPPPATH_MOD += [ + 'embed/extmod/modtrezorconfig', + 'vendor/trezor-storage', +] +SOURCE_MOD += [ + 'vendor/trezor-storage/norcow.c', + 'vendor/trezor-storage/storage.c', + 'vendor/trezor-storage/flash_area.c', + 'vendor/trezor-crypto/memzero.c', +] + +# modtrezorcrypto +CCFLAGS_MOD += '-Wno-sequence-point ' +CPPPATH_MOD += [ + 'vendor/trezor-crypto', +] +CPPDEFINES_MOD += [ + 'AES_128', + 'AES_192', + ('USE_BIP32_CACHE', '0'), + ('USE_KECCAK', '1'), + ('USE_ETHEREUM', '1' if EVERYTHING else '0'), + ('USE_MONERO', '1' if EVERYTHING else '0'), + ('USE_CARDANO', '1' if EVERYTHING else '0'), + ('USE_NEM', '1' if (EVERYTHING and TREZOR_MODEL != "R") else '0'), + ('USE_EOS', '1' if (EVERYTHING and TREZOR_MODEL != "R") else '0'), +] +SOURCE_MOD += [ + 'embed/lib/buffers.c', + 'embed/lib/display.c', + 'embed/lib/colors.c', + 'embed/lib/fonts/fonts.c', + 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/image.c', + 'embed/lib/mini_printf.c', + ] + +if EVERYTHING: + SOURCE_MOD += [ + 'vendor/trezor-crypto/cardano.c', + 'vendor/trezor-crypto/monero/base58.c', + 'vendor/trezor-crypto/monero/serialize.c', + 'vendor/trezor-crypto/monero/xmr.c', + ] + +# libsecp256k1-zkp +if FEATURE_FLAGS["SECP256K1_ZKP"]: + CPPPATH_MOD += [ + 'vendor/secp256k1-zkp', + 'vendor/secp256k1-zkp/src', + 'vendor/secp256k1-zkp/include', + ] + CPPDEFINES_MOD += [ + 'USE_SECP256K1_ZKP', + 'USE_SECP256K1_ZKP_ECDSA', + ('SECP256K1_CONTEXT_SIZE', '180'), + 'USE_ASM_ARM', + 'USE_EXTERNAL_ASM', + 'USE_EXTERNAL_DEFAULT_CALLBACKS', + ('ECMULT_GEN_PREC_BITS', '2'), + ('ECMULT_WINDOW_SIZE', '8'), + 'ENABLE_MODULE_GENERATOR', + 'ENABLE_MODULE_RECOVERY', + 'ENABLE_MODULE_SCHNORRSIG', + 'ENABLE_MODULE_EXTRAKEYS', + ] + SOURCE_MOD_SECP256K1_ZKP = [ + 'vendor/secp256k1-zkp/src/secp256k1.c', + 'vendor/secp256k1-zkp/src/precomputed_ecmult.c', + 'vendor/secp256k1-zkp/src/precomputed_ecmult_gen.c', + 'vendor/secp256k1-zkp/src/asm/field_10x26_arm.s' + ] + SOURCE_MOD += [ + 'vendor/trezor-crypto/zkp_context.c', + 'vendor/trezor-crypto/zkp_ecdsa.c', + 'vendor/trezor-crypto/zkp_bip340.c', + ] + + +CPPDEFINES_MOD += [ + 'TREZOR_UI2', +] + +if FEATURE_FLAGS["RDI"]: + CPPDEFINES_MOD += ['RDI'] + +if FEATURE_FLAGS["SYSTEM_VIEW"]: + SOURCE_FIRMWARE += [ + 'embed/segger/SEGGER/SEGGER_SYSVIEW_Config_NoOS.c', + 'embed/segger/SEGGER/SEGGER_SYSVIEW.c', + 'embed/segger/SEGGER/SEGGER_RTT.c', + 'embed/segger/SEGGER/SEGGER_RTT_ASM_ARMv7M.S', + 'embed/segger/SEGGER/Syscalls/SEGGER_RTT_Syscalls_GCC.c', + 'embed/fw_ss/systemview.c', + ] + CPPPATH_MOD += [ + 'embed/segger/SEGGER/', + 'embed/segger/Config/', + ] + CPPDEFINES_MOD += ['SYSTEM_VIEW'] + CCFLAGS_MOD += '-DSYSTEM_VIEW ' + +# fonts +tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('DEMIBOLD', FONT_DEMIBOLD, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('MONO', FONT_MONO, CPPDEFINES_MOD, SOURCE_MOD) +tools.add_font('BIG', FONT_BIG, CPPDEFINES_MOD, SOURCE_MOD) + + +env = Environment(ENV=os.environ, CFLAGS=f"{ARGUMENTS.get('CFLAGS', '')} -DPRODUCTION={int(PRODUCTION)} -DPYOPT={PYOPT} -DBOOTLOADER_QA={int(BOOTLOADER_QA)} -DBITCOIN_ONLY={BITCOIN_ONLY}") + +FEATURES_AVAILABLE = tools.configure_board(TREZOR_MODEL, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) + +FILE_SUFFIX= env.get('ENV')['SUFFIX'] + +SOURCE_FIRMWARE = [ + 'embed/fw_ss/header.S', + 'embed/fw_ss/asm_helpers.S', + 'embed/fw_ss/secure_api.c', + 'embed/fw_ss/main.c', + f'embed/fw_ss/startup_{FILE_SUFFIX}.S', +] + + +if TREZOR_MODEL in ('T', 'DISC1', 'DISC2'): + UI_LAYOUT = 'UI_LAYOUT_TT' + ui_layout_feature = 'model_tt' +elif TREZOR_MODEL in ('1', 'R'): + UI_LAYOUT = 'UI_LAYOUT_TR' + ui_layout_feature = 'model_tr' +else: + raise ValueError('Unknown Trezor model') + +if 'sd_card' in FEATURES_AVAILABLE: + SDCARD = True +else: + SDCARD = False + + +env.Replace( + CAT='cat', + DD='dd', + CP='cp', + SED='sed', + AS='arm-none-eabi-as', + AR='arm-none-eabi-ar', + CC='arm-none-eabi-gcc', + LINK='arm-none-eabi-gcc', + SIZE='arm-none-eabi-size', + STRIP='arm-none-eabi-strip', + OBJCOPY='arm-none-eabi-objcopy', ) + +env.Replace( + TREZOR_MODEL=TREZOR_MODEL,) + +if TREZOR_MODEL in ('1',): + LD_VARIANT = '' if EVERYTHING else '_min' +else: + LD_VARIANT = '' + +env.Replace( + COPT=env.get('ENV').get('OPTIMIZE', '-O0'), + CCFLAGS='$COPT ' + '-g3 ' + '-nostdlib ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -fno-common ' + '-fsingle-precision-constant -fdata-sections -ffunction-sections ' + '-ffreestanding ' + '-fstack-protector-all ' + '-mcmse ' + + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, + LINKFLAGS='-T embed/fw_ss/memory_${TREZOR_MODEL}%s.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=build/fw_ss/fw_ss.map -Wl,--warn-common -Wl,--cmse-implib -Wl,--out-implib=build/fw_ss/fw_ss_cmse.o' % LD_VARIANT, + CPPPATH=[ + '.', + 'embed/rust', + 'embed/fw_ss', + 'embed/lib', + 'embed/models', + 'embed/trezorhal', + 'embed/extmod/modtrezorui', + ] + CPPPATH_MOD + PATH_HAL, + CPPDEFINES=[ + 'FIRMWARE', + 'TREZOR_MODEL_'+TREZOR_MODEL, + 'USE_HAL_DRIVER', + 'ARM_USER_MODE', + UI_LAYOUT, + ] + CPPDEFINES_MOD + CPPDEFINES_HAL, + ASFLAGS=env.get('ENV')['CPU_ASFLAGS'], + ASPPFLAGS='$CFLAGS $CCFLAGS', + ) + +env.Replace( + HEADERTOOL='tools/headertool.py', + PYTHON='python', + MAKEVERSIONHDR='$PYTHON vendor/micropython/py/makeversionhdr.py', + MAKEMODULEDEFS='$PYTHON vendor/micropython/py/makemoduledefs.py', + MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', +) + + +# +# Program objects +# + +source_files = SOURCE_MOD + SOURCE_FIRMWARE + SOURCE_HAL +obj_program = [] +obj_program.extend(env.Object(source=SOURCE_MOD)) +obj_program.extend(env.Object(source=SOURCE_FIRMWARE)) +obj_program.extend(env.Object(source=SOURCE_HAL)) + +env.Replace( + ALLSOURCES=source_files, + ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES'] + [f"PRODUCTION={int(PRODUCTION)}", f"BOOTLOADER_QA={int(BOOTLOADER_QA)}", f"PYOPT={PYOPT}", f"BITCOIN_ONLY={BITCOIN_ONLY}"])) + + +cmake_gen = env.Command( + target='CMakeLists.txt', + source='', + action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', +) + + +MODEL_IDENTIFIER = tools.get_model_identifier(TREZOR_MODEL) +BOOTLOADER_SUFFIX = MODEL_IDENTIFIER +if BOOTLOADER_QA: + BOOTLOADER_SUFFIX += '_qa' + +# select vendor header +if BOOTLOADER_QA or BOOTLOADER_DEVEL: + vendor = "dev_DO_NOT_SIGN_signed_dev" +elif not PRODUCTION: + vendor = "unsafe_signed_prod" +else: + if TREZOR_MODEL in ('T',): + vendor = "satoshilabs_signed_prod" + elif BITCOIN_ONLY == '1': + vendor = "trezor_btconly_signed_prod" + else: + vendor = "trezor_signed_prod" + +VENDORHEADER = f'embed/vendorheader/{MODEL_IDENTIFIER}/vendorheader_{vendor}.bin' + + +if TREZOR_MODEL not in ('1',): + obj_program.extend( + env.Command( + target='embed/fw_ss/vendorheader.o', + source=VENDORHEADER, + action='$OBJCOPY -I binary -O elf32-littlearm -B arm' + ' --rename-section .data=.vendorheader,alloc,load,readonly,contents' + ' $SOURCE $TARGET', )) + +if TREZOR_MODEL not in ('DISC1', 'DISC2'): + tools.embed_binary( + obj_program, + env, + 'bootloader', + 'embed/fw_ss/bootloaders/bootloader.o', + f'embed/fw_ss/bootloaders/bootloader_{BOOTLOADER_SUFFIX}.bin', + ) + +program_elf = env.Command( + target='fw_ss.elf', + source=obj_program, + action= + '$LINK -o $TARGET $CCFLAGS $CFLAGS $SOURCES $LINKFLAGS -lc_nano -lm -lgcc', +) + +if CMAKELISTS != 0: + env.Depends(program_elf, cmake_gen) + +BINARY_NAME = f"build/fw_ss/fw_ss-{tools.get_model_identifier(TREZOR_MODEL)}" +if not EVERYTHING: + BINARY_NAME += "-btconly" +BINARY_NAME += "-" + tools.get_version('embed/fw_ss/version.h') +BINARY_NAME += "-" + tools.get_git_revision_short_hash() +BINARY_NAME += "-dirty" if tools.get_git_modified() else "" +BINARY_NAME += ".bin" + + + +if TREZOR_MODEL in ('1',): + action_bin=[ + '$OBJCOPY -O binary -j .header -j .flash -j .data -j .sensitive $SOURCE $TARGET', + '../legacy/bootloader/firmware_sign.py -f $TARGET', + '$CP $TARGET ' + BINARY_NAME, + ] +else: + if 'STM32F427xx' in CPPDEFINES_HAL or 'STM32F429xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .sensitive --pad-to 0x08100000 $SOURCE ${TARGET}.p1', + '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', + '$CAT ${TARGET}.p1 ${TARGET}.p2 > $TARGET', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', + '$CP $TARGET ' + BINARY_NAME, + ] + elif 'STM32U5A9xx' in CPPDEFINES_HAL: + action_bin=[ + '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash_vectors -j .gnu.sgstubs -j .flash -j .data -j .sensitive -j .flash_fill $SOURCE ${TARGET}', + '$HEADERTOOL -h $TARGET ' + ('-D' if not PRODUCTION else ''), + '$CP $TARGET ' + BINARY_NAME, + ] + else: + raise Exception("Unknown MCU") + +program_bin = env.Command( + target='fw_ss.bin', + source=program_elf, + action=action_bin, +) diff --git a/core/SConstruct b/core/SConstruct index a04364313..6f6a063a4 100644 --- a/core/SConstruct +++ b/core/SConstruct @@ -8,3 +8,6 @@ SConscript('SConscript.firmware', variant_dir='build/firmware', duplicate=False) SConscript('SConscript.prodtest', variant_dir='build/prodtest', duplicate=False) SConscript('SConscript.reflash', variant_dir='build/reflash', duplicate=False) SConscript('SConscript.unix', variant_dir='build/unix', duplicate=False) +SConscript('SConscript.fw_ss', variant_dir='build/fw_ss', duplicate=False) +SConscript('SConscript.fw_cs', variant_dir='build/fw_cs', duplicate=False) +SConscript('SConscript.fw_ap', variant_dir='build/fw_ap', duplicate=False) diff --git a/core/embed/fw_ap/core_api.S b/core/embed/fw_ap/core_api.S new file mode 100644 index 000000000..b9ebdd1b1 --- /dev/null +++ b/core/embed/fw_ap/core_api.S @@ -0,0 +1,19 @@ + #include + + .syntax unified + + .text + + .global core_print + .global core_get_secret + +core_print: + svc #CORE_SVC_PRINT + bx lr + +core_get_secret: + svc #CORE_SVC_GET_SECRET + bx lr + + + .end diff --git a/core/embed/fw_ap/libc_syscalls.c b/core/embed/fw_ap/libc_syscalls.c new file mode 100644 index 000000000..be1fabd88 --- /dev/null +++ b/core/embed/fw_ap/libc_syscalls.c @@ -0,0 +1,168 @@ +/* +****************************************************************************** +File: syscalls.c +Info: Generated by Atollic TrueSTUDIO(R) 9.2.0 2019-04-13 + +The MIT License (MIT) +Copyright (c) 2018 STMicroelectronics + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +****************************************************************************** +*/ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Variables */ +#undef errno +extern int32_t errno; + +uint8_t *__env[1] = {0}; +uint8_t **environ = __env; + +/* Functions */ +void initialise_monitor_handles(void) {} + +int _getpid(void) { + errno = ENOSYS; + return -1; +} + +int _gettimeofday(struct timeval *ptimeval, void *ptimezone) { + errno = ENOSYS; + return -1; +} + +int _kill(int32_t pid, int32_t sig) { + errno = ENOSYS; + return -1; +} + +void _exit(int32_t status) { + while (1) { + } /* Make sure we hang here */ +} + +int _write(int32_t file, uint8_t *ptr, int32_t len) { + /* Implement your write code here, this is used by puts and printf for example + */ + /* return len; */ + + errno = ENOSYS; + return -1; +} + +void *_sbrk(int32_t incr) { + extern char _heap_end; // Set by linker + static char *heap_end; + char *prev_heap_end; + + if (heap_end == 0) { + heap_end = &_heap_end; + } + + prev_heap_end = heap_end; + heap_end += incr; + + return prev_heap_end; +} + +int _close(int32_t file) { + errno = ENOSYS; + return -1; +} + +int _fstat(int32_t file, struct stat *st) { + errno = ENOSYS; + return -1; +} + +int _isatty(int32_t file) { + errno = ENOSYS; + return 0; +} + +int _lseek(int32_t file, int32_t ptr, int32_t dir) { + errno = ENOSYS; + return -1; +} + +int _read(int32_t file, uint8_t *ptr, int32_t len) { + errno = ENOSYS; + return -1; +} + +int _readlink(const char *path, char *buf, size_t bufsize) { + errno = ENOSYS; + return -1; +} + +int _open(const uint8_t *path, int32_t flags, int32_t mode) { + errno = ENOSYS; + return -1; +} + +int _wait(int32_t *status) { + errno = ENOSYS; + return -1; +} + +int _unlink(const uint8_t *name) { + errno = ENOSYS; + return -1; +} + +int _times(struct tms *buf) { + errno = ENOSYS; + return -1; +} + +int _stat(const uint8_t *file, struct stat *st) { + errno = ENOSYS; + return -1; +} + +int _symlink(const char *path1, const char *path2) { + errno = ENOSYS; + return -1; +} + +int _link(const uint8_t *old, const uint8_t *new) { + errno = ENOSYS; + return -1; +} + +int _fork(void) { + errno = ENOSYS; + return -1; +} + +int _execve(const uint8_t *name, uint8_t *const *argv, uint8_t *const *env) { + errno = ENOSYS; + return -1; +} diff --git a/core/embed/fw_ap/main.c b/core/embed/fw_ap/main.c new file mode 100644 index 000000000..bb0906449 --- /dev/null +++ b/core/embed/fw_ap/main.c @@ -0,0 +1,46 @@ +/* + * 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 . + */ + +#include +#include +#include + +#include "embed/fw_cs/core_api.h" +#include + +int main(void) { // UNPRIVILEGED APPLICATION + + char text[64]; + + core_print("Unprivileged application is running...\n"); + + // get secret from privileged-world + snprintf(text, sizeof(text), "secret = %d\n", core_get_secret()); + core_print(text); + + // get secret from secure-world directly + snprintf(text, sizeof(text), "secret = %d\n", secure_get_secret()); + core_print(text); + + + while (1) + ; + + return 0; +} diff --git a/core/embed/fw_ap/memory_DISC2.ld b/core/embed/fw_ap/memory_DISC2.ld new file mode 100644 index 000000000..a49d858ff --- /dev/null +++ b/core/embed/fw_ap/memory_DISC2.ld @@ -0,0 +1,65 @@ +/* TREZORv2 firmware linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x080D0000, LENGTH = 256K + SRAM1 (wal) : ORIGIN = 0x20040000, LENGTH = 128K + SRAM2 (wal) : ORIGIN = 0x200C8000, LENGTH = 16K +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_estack = main_stack_base; + +/* used by the startup code to populate variables used by the C code */ +data_lma = LOADADDR(.data); +data_vma = ADDR(.data); +data_size = SIZEOF(.data); + +/* used by the startup code to wipe memory */ +sram1_start = ORIGIN(SRAM1); +sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); +sram2_start = ORIGIN(SRAM2); +sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); + +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +SECTIONS { + .flash : ALIGN(512) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .heap : ALIGN(4) { + . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ + . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ + } >SRAM1 + + .stack : ALIGN(8) { + . = 16K; /* Overflow causes UsageFault */ + } >SRAM2 + +} diff --git a/core/embed/fw_ap/startup.S b/core/embed/fw_ap/startup.S new file mode 100644 index 000000000..7a4162750 --- /dev/null +++ b/core/embed/fw_ap/startup.S @@ -0,0 +1,59 @@ + .syntax unified + + .text + + .global reset_handler + + .type reset_handler, STT_FUNC +reset_handler: + // setup environment for subsequent stage of code + ldr r2, =0 // r2 - the word-sized value to be written + + ldr r0, =sram1_start // r0 - point to beginning of SRAM + ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + +sram1_loop: + str r2, [r0], #4 + cmp r0, r1 + bne sram1_loop + + ldr r0, =sram2_start // r0 - point to beginning of SRAM + ldr r1, =sram2_end // r1 - point to byte after the end of SRAM +sram2_loop: + str r2, [r0], #4 + cmp r0, r1 + bne sram2_loop + + // copy data in from flash + ldr r0, =data_vma // dst addr + ldr r1, =data_lma // src addr + ldr r2, =data_size // size in bytes + bl memcpy + + // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value + ldr r0, =0xF1CD3A4D + ldr r1, = __stack_chk_guard + str r0, [r1] + + // call static constructors + //bl __libc_init_array + +reset: // just for the nice backtrace + // enter the application code + bl main + + +loop_forever: + b loop_forever + +// ================================================================ +// The minimal vector table for unprivileged application + + .section .vector_table,"a",%progbits + +vector_table: + .word _estack + .word reset_handler + + + .end diff --git a/core/embed/fw_ap/version.h b/core/embed/fw_ap/version.h new file mode 100644 index 000000000..7f757eff1 --- /dev/null +++ b/core/embed/fw_ap/version.h @@ -0,0 +1,11 @@ +#define VERSION_MAJOR 2 +#define VERSION_MINOR 6 +#define VERSION_PATCH 4 +#define VERSION_BUILD 0 + +#define FIX_VERSION_MAJOR 2 +#define FIX_VERSION_MINOR 4 +#define FIX_VERSION_PATCH 0 +#define FIX_VERSION_BUILD 0 + +#define VERSION_MONOTONIC 1 diff --git a/core/embed/fw_cs/core_api.h b/core/embed/fw_cs/core_api.h new file mode 100644 index 000000000..071d1f21d --- /dev/null +++ b/core/embed/fw_cs/core_api.h @@ -0,0 +1,8 @@ +#ifndef CORE_CALLS_H +#define CORE_CALLS_H + +extern void core_print(char* text); + +extern int core_get_secret(void); + +#endif // CORE_CALLS_H \ No newline at end of file diff --git a/core/embed/fw_cs/core_api_impl.c b/core/embed/fw_cs/core_api_impl.c new file mode 100644 index 000000000..d77c53257 --- /dev/null +++ b/core/embed/fw_cs/core_api_impl.c @@ -0,0 +1,9 @@ +#include + +#include + +#include + +void core_print(char* text) { display_printf("%s", text); } + +int core_get_secret(void) { return secure_get_secret(); } \ No newline at end of file diff --git a/core/embed/fw_cs/header.S b/core/embed/fw_cs/header.S new file mode 100644 index 000000000..3531e2395 --- /dev/null +++ b/core/embed/fw_cs/header.S @@ -0,0 +1,54 @@ + .syntax unified + +#include "version.h" + + .section .header, "a" + + .type g_header, %object + .size g_header, .-g_header + +// Firmware header for both Trezor One and Trezor T. +// Trezor One must have bootloader version >= 1.8.0 (before that version the hdrlen used to be reset vector) + +g_header: + .byte 'T','R','Z','F' // magic + .word g_header_end - g_header // hdrlen +#ifdef TREZOR_MODEL_T + .word 0 // expiry +#else + .word 1 // expiry +#endif + .word _codelen // codelen + .byte VERSION_MAJOR // vmajor + .byte VERSION_MINOR // vminor + .byte VERSION_PATCH // vpatch + .byte VERSION_BUILD // vbuild + .byte FIX_VERSION_MAJOR // fix_vmajor + .byte FIX_VERSION_MINOR // fix_vminor + .byte FIX_VERSION_PATCH // fix_vpatch + .byte FIX_VERSION_BUILD // fix_vbuild + .word HW_MODEL // type of the designated hardware + .byte HW_REVISION // revision of the designated hardware + .byte VERSION_MONOTONIC // monotonic version of the binary + . = . + 2 // reserved + . = . + 512 // hash1 ... hash16 + +#if !defined TREZOR_MODEL_1 +// trezor-core header style + . = . + 415 // reserved + .byte 0 // sigmask + . = . + 64 // sig +#else +// model 1 compatibility header + . = . + 64 // sig1 + . = . + 64 // sig2 + . = . + 64 // sig3 + .byte 0 // sigindex1 + .byte 0 // sigindex2 + .byte 0 // sigindex3 + . = . + 220 // reserved + . = . + 65 // reserved +#endif + +g_header_end: + diff --git a/core/embed/fw_cs/jump_unprivileged.s b/core/embed/fw_cs/jump_unprivileged.s new file mode 100644 index 000000000..ba32a24a9 --- /dev/null +++ b/core/embed/fw_cs/jump_unprivileged.s @@ -0,0 +1,47 @@ + .syntax unified + + .text + + .global jump_unprivileged + + +// jump_unprivileged() can be called only from an exception handler +// (handler mode) + +jump_unprivileged: + + ldr r12, [r0, #0] // stack pointer + sub r12, r12, #32 + msr PSP, r12 + + ldr r1, [r0, #0] + sub r1, r1, #16384 // stack limit + msr PSPLIM, r1 + + mov r1, #0 + str r1, [r12, #0] // r0 + str r1, [r12, #4] // r1 + str r1, [r12, #8] // r2 + str r1, [r12, #12] // r3 + str r1, [r12, #16] // r12 + str r1, [r12, #20] // lr + + ldr r1, [r0, #4] // reset vector + bic r1, r1, #1 + str r1, [r12, #24] // return address + + ldr r1, = 0x01000000 + str r1, [r12, #28] // xPSR + + // set thread mode to unprivileged level + mrs r1, CONTROL + orr r1, r1, #1 + msr CONTROL, r1 + + // return to Non-Secure Thread mode + // use Non-Secure PSP + ldr lr, = 0xFFFFFFBC + bx lr + + .end + diff --git a/core/embed/fw_cs/main.c b/core/embed/fw_cs/main.c new file mode 100644 index 000000000..939c302ab --- /dev/null +++ b/core/embed/fw_cs/main.c @@ -0,0 +1,83 @@ +/* + * 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 . + */ + +#include STM32_HAL_H + +#include +#include +#include + +#include +#include +#include + +#include "svc_numbers.h" +#include + +void jump_to_user_app(void) { + asm volatile( "svc %0" : : "i"(CORE_SVC_START_APP)); +} + +void enum_callback(void* context, int secret) { + display_printf("secret = %d\n", secret); +} + +void core_init() { + HAL_Init(); + mpu_config_cs(); + touch_init(); + display_reinit(); +} + +int main(void) { // CORE SERVICES + + // Initialize hardware drivers + core_init(); + + display_printf("Core Services are running...\n"); + + // Call a function in the secure world + secure_enumerate_secrets(enum_callback, NULL); + + { + uint8_t in_buff[64]; + uint8_t out_buff[64]; + + // Test cmse_check_address_range() function + // OK + display_printf("%d\n", secure_process_buff(in_buff, sizeof(in_buff), out_buff, sizeof(out_buff))); + // in_buff in secure memory + display_printf("%d\n", secure_process_buff((void *)0x30000000, sizeof(in_buff), out_buff, sizeof(out_buff))); + // out buff in secure memory + display_printf("%d\n", secure_process_buff(in_buff, sizeof(in_buff), (void *)0x30000000, sizeof(out_buff))); + // out buff in read only memory + display_printf("%d\n", secure_process_buff(in_buff, sizeof(in_buff), (void *)0x08090000, sizeof(out_buff))); + } + + + HAL_Delay(500); // uses Non-Secure SysTick + + // Configure MPU for the unprivileged application + // isolate_unprivileged_world(); + + // Jump to unprivileged user application + jump_to_user_app(); + + return 0; +} diff --git a/core/embed/fw_cs/memory_DISC2.ld b/core/embed/fw_cs/memory_DISC2.ld new file mode 100644 index 000000000..03364243b --- /dev/null +++ b/core/embed/fw_cs/memory_DISC2.ld @@ -0,0 +1,128 @@ +/* TREZORv2 firmware linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x08090000, LENGTH = 256K + SRAM1 (wal) : ORIGIN = 0x20020000, LENGTH = 128K + BOOT_ARGS (wal) : ORIGIN = 0x200BFF00, LENGTH = 0x100 + SRAM2 (wal) : ORIGIN = 0x200C4000, LENGTH = 16K + SRAM3 (wal) : ORIGIN = 0x200D0000, LENGTH = 832K + SRAM5 (wal) : ORIGIN = 0x201A0000, LENGTH = 832K + SRAM6 (wal) : ORIGIN = 0x20270000, LENGTH = 0 + SRAM4 (wal) : ORIGIN = 0x28000000, LENGTH = 16K +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_estack = main_stack_base; + +/* used by the startup code to populate variables used by the C code */ +data_lma = LOADADDR(.data); +data_vma = ADDR(.data); +data_size = SIZEOF(.data); + +/* used by the startup code to populate variables used by the C code */ +sensitive_lma = LOADADDR(.sensitive); +sensitive_vma = ADDR(.sensitive); +sensitive_size = SIZEOF(.sensitive); + +/* used by the startup code to wipe memory */ +sram1_start = ORIGIN(SRAM1); +sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); +sram2_start = ORIGIN(SRAM2); +sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); +sram3_start = ORIGIN(SRAM3); +sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); +sram4_start = ORIGIN(SRAM4); +sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); +sram5_start = ORIGIN(SRAM5); +sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); +sram6_start = ORIGIN(SRAM6); +sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash : ALIGN(512) { + KEEP(*(.vector_table)); + . = ALIGN(4); + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(512); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .data_ccm : ALIGN(4) { + *(.no_dma_buffers*); + . = ALIGN(4); + } >SRAM1 + + .heap : ALIGN(4) { + . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ + . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ + } >SRAM1 + + .stack : ALIGN(8) { + . = 16K; /* Overflow causes UsageFault */ + } >SRAM2 + + .sensitive : ALIGN(512) { + *(.sensitive*); + . = ALIGN(512); + } >SRAM2 AT>FLASH + + .fb1 : ALIGN(4) { + __fb_start = .; + *(.fb1*); + *(.gfxmmu_table*); + *(.framebuffer_select*); + . = ALIGN(4); + } >SRAM3 + + .fb2 : ALIGN(4) { + *(.fb2*); + __fb_end = .; + . = ALIGN(4); + } >SRAM5 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS +} diff --git a/core/embed/fw_cs/startup_stm32u5.S b/core/embed/fw_cs/startup_stm32u5.S new file mode 100644 index 000000000..48be736e7 --- /dev/null +++ b/core/embed/fw_cs/startup_stm32u5.S @@ -0,0 +1,60 @@ + .syntax unified + + .text + + .global reset_handler + .type reset_handler, STT_FUNC +reset_handler: + // set the stack protection + ldr r0, =_sstack + add r0, r0, #32 // reserved for UsageFault exception + msr MSPLIM, r0 + + // setup environment for subsequent stage of code + ldr r2, =0 // r2 - the word-sized value to be written + + ldr r0, =sram1_start // r0 - point to beginning of SRAM + ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =sram2_start // r0 - point to beginning of SRAM + ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =sram3_start // r0 - point to beginning of SRAM + ldr r1, =__fb_start // r1 - point to beginning of framebuffer + bl memset_reg + + ldr r0, =__fb_end // r0 - point to end of framebuffer + ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + bl memset_reg + + // copy data in from flash + ldr r0, =data_vma // dst addr + ldr r1, =data_lma // src addr + ldr r2, =data_size // size in bytes + bl memcpy + + // copy sensitive data in from flash + ldr r0, =sensitive_vma // dst addr + ldr r1, =sensitive_lma // src addr + ldr r2, =sensitive_size // size in bytes + bl memcpy + + // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value + bl rng_get + ldr r1, = __stack_chk_guard + str r0, [r1] + + // re-enable exceptions + // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.7: + // "If it is not necessary to ensure that a pended interrupt is recognized immediately before + // subsequent operations, it is not necessary to insert a memory barrier instruction." + cpsie f + + // enter the application code + bl main + + b shutdown_privileged + + .end diff --git a/core/embed/fw_cs/svc_handler.c b/core/embed/fw_cs/svc_handler.c new file mode 100644 index 000000000..b2200948c --- /dev/null +++ b/core/embed/fw_cs/svc_handler.c @@ -0,0 +1,40 @@ + +#include "core_api.h" +#include "svc_numbers.h" + +#include +#include + +#define APP_FIRMWARE_VTBL 0x080D0000 + +extern void jump_unprivileged(uint32_t location); + + +// !!! SVC_Handler should have the second lowest priority in the system (just after PendSV_Handler) +// => SVC_Handler can be prememted by any interrupt +// !!! PendSV_Handler should be used for task switching (entering into app modules) + + +void SVC_C_Handler(uint32_t *svc_args) { + // Stack contains: + // r0, r1, r2, r3, r12, r14, the return address and xPSR + // First argument (r0) is svc_args[0] + + // __LDRT(), __STRT() instrinsic function should be used to access unprivileged memory + + uint8_t svc_number = ((uint8_t *)svc_args[6])[-2]; + + switch (svc_number) { + case CORE_SVC_PRINT: + core_print((char *)svc_args[0]); + break; + + case CORE_SVC_GET_SECRET: + svc_args[0] = core_get_secret(); + break; + + case CORE_SVC_START_APP: + jump_unprivileged(APP_FIRMWARE_VTBL); + break; + } +} diff --git a/core/embed/fw_cs/svc_handler_low.s b/core/embed/fw_cs/svc_handler_low.s new file mode 100644 index 000000000..edf355d1b --- /dev/null +++ b/core/embed/fw_cs/svc_handler_low.s @@ -0,0 +1,15 @@ + .syntax unified + + .text + + .global SVC_Handler + + .thumb_func +SVC_Handler: + tst lr, #4 + ite eq + mrseq r0, msp + mrsne r0, psp + b SVC_C_Handler + + .end diff --git a/core/embed/fw_cs/svc_numbers.h b/core/embed/fw_cs/svc_numbers.h new file mode 100644 index 000000000..dc0aafdbf --- /dev/null +++ b/core/embed/fw_cs/svc_numbers.h @@ -0,0 +1,11 @@ +#ifndef CORE_SVC_NUMBERS_H +#define CORE_SVC_NUMBERS_H + +// service calls +#define CORE_SVC_PRINT 1 +#define CORE_SVC_GET_SECRET 2 + +// special service calls +#define CORE_SVC_START_APP 255 + +#endif // CORE_SVC_NUMBERS_H diff --git a/core/embed/fw_cs/version.h b/core/embed/fw_cs/version.h new file mode 100644 index 000000000..7f757eff1 --- /dev/null +++ b/core/embed/fw_cs/version.h @@ -0,0 +1,11 @@ +#define VERSION_MAJOR 2 +#define VERSION_MINOR 6 +#define VERSION_PATCH 4 +#define VERSION_BUILD 0 + +#define FIX_VERSION_MAJOR 2 +#define FIX_VERSION_MINOR 4 +#define FIX_VERSION_PATCH 0 +#define FIX_VERSION_BUILD 0 + +#define VERSION_MONOTONIC 1 diff --git a/core/embed/fw_ss/asm_helpers.S b/core/embed/fw_ss/asm_helpers.S new file mode 100644 index 000000000..c7912d157 --- /dev/null +++ b/core/embed/fw_ss/asm_helpers.S @@ -0,0 +1,22 @@ + .syntax unified + + .text + + .global jump_unsecure + +.set SCB_VTOR_NS, 0xE002ED08 + +jump_unsecure: + + ldr r1, =SCB_VTOR_NS + str r0, [r1] + + ldr r1, [r0, #0] + msr MSP_NS, r1 + + ldr r1, [r0, #4] + movs r0, #1 + bics r1, r0 // bit0 == 0 => transition to Non-secure + + bxns r1 + diff --git a/core/embed/fw_ss/header.S b/core/embed/fw_ss/header.S new file mode 100644 index 000000000..3531e2395 --- /dev/null +++ b/core/embed/fw_ss/header.S @@ -0,0 +1,54 @@ + .syntax unified + +#include "version.h" + + .section .header, "a" + + .type g_header, %object + .size g_header, .-g_header + +// Firmware header for both Trezor One and Trezor T. +// Trezor One must have bootloader version >= 1.8.0 (before that version the hdrlen used to be reset vector) + +g_header: + .byte 'T','R','Z','F' // magic + .word g_header_end - g_header // hdrlen +#ifdef TREZOR_MODEL_T + .word 0 // expiry +#else + .word 1 // expiry +#endif + .word _codelen // codelen + .byte VERSION_MAJOR // vmajor + .byte VERSION_MINOR // vminor + .byte VERSION_PATCH // vpatch + .byte VERSION_BUILD // vbuild + .byte FIX_VERSION_MAJOR // fix_vmajor + .byte FIX_VERSION_MINOR // fix_vminor + .byte FIX_VERSION_PATCH // fix_vpatch + .byte FIX_VERSION_BUILD // fix_vbuild + .word HW_MODEL // type of the designated hardware + .byte HW_REVISION // revision of the designated hardware + .byte VERSION_MONOTONIC // monotonic version of the binary + . = . + 2 // reserved + . = . + 512 // hash1 ... hash16 + +#if !defined TREZOR_MODEL_1 +// trezor-core header style + . = . + 415 // reserved + .byte 0 // sigmask + . = . + 64 // sig +#else +// model 1 compatibility header + . = . + 64 // sig1 + . = . + 64 // sig2 + . = . + 64 // sig3 + .byte 0 // sigindex1 + .byte 0 // sigindex2 + .byte 0 // sigindex3 + . = . + 220 // reserved + . = . + 65 // reserved +#endif + +g_header_end: + diff --git a/core/embed/fw_ss/main.c b/core/embed/fw_ss/main.c new file mode 100644 index 000000000..893cc2817 --- /dev/null +++ b/core/embed/fw_ss/main.c @@ -0,0 +1,207 @@ +/* + * 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 . + */ + +#include STM32_HAL_H + +#include +#include +#include + +#include +#include + +#define CORE_SERVICE_VTBL 0x08091600 + +extern void jump_unsecure(uint32_t location); + +void jump_to_core_services(void) { jump_unsecure(CORE_SERVICE_VTBL); } + + +// from linker +extern uint8_t _sgstubs_start; +extern uint8_t _sgstubs_end; + + +static void trustzone_configure_sau() { + // configure unsecure regions for core services & application + + // Flash (Non-Secure) + SAU->RNR = 0; + SAU->RBAR = 0x08090000 & SAU_RBAR_BADDR_Msk; + SAU->RLAR = ((0x08110000 - 1) & SAU_RLAR_LADDR_Msk) | 0x01; + // Flash (Non-Secure callable) + SAU->RNR = 1; + SAU->RBAR = (uint32_t) &_sgstubs_start & SAU_RBAR_BADDR_Msk; + SAU->RLAR = (((uint32_t) &_sgstubs_end - 1) & SAU_RLAR_LADDR_Msk) | 0x01 | 0x02; + // SRAM1 (Non-Secure) + SAU->RNR = 2; + SAU->RBAR = 0x20020000 & SAU_RBAR_BADDR_Msk; + SAU->RLAR = ((0x20060000 - 1) & SAU_RLAR_LADDR_Msk) | 0x01; + // SRAM2 ((Non-Secure, stack) + SAU->RNR = 3; + SAU->RBAR = 0x200C4000 & SAU_RBAR_BADDR_Msk; + SAU->RLAR = ((0x200CC000 - 1) & SAU_RLAR_LADDR_Msk) | 0x01; + // SRAM3+5 (Non-Secure, fb1+fb2) + SAU->RNR = 4; + SAU->RBAR = 0x200D0000 & SAU_RBAR_BADDR_Msk; + SAU->RLAR = ((0x20270000 - 1) & SAU_RLAR_LADDR_Msk) | 0x01; + // PERIPHERAL (Non-Secure) + SAU->RNR = 5; + SAU->RBAR = PERIPH_BASE_NS & SAU_RBAR_BADDR_Msk; + SAU->RLAR = + ((PERIPH_BASE_NS + 256 * 1024 * 1024 - 1) & SAU_RLAR_LADDR_Msk) | 0x01; + // GFXMMU (Non-Secure) + SAU->RNR = 6; + SAU->RBAR = GFXMMU_VIRTUAL_BUFFERS_BASE_NS & SAU_RBAR_BADDR_Msk; + SAU->RLAR = ((GFXMMU_VIRTUAL_BUFFERS_BASE_NS + 16 * 1024 * 1024 - 1) & + SAU_RLAR_LADDR_Msk) | + 0x01; + + // Enable SAU + SAU->CTRL = SAU_CTRL_ENABLE_Msk; +} + +// Configure SRAM security +static void trustzone_configure_sram(void) { + MPCBB_ConfigTypeDef mpcbb = {0}; + + // No exceptions on illegal access + mpcbb.SecureRWIllegalMode = GTZC_MPCBB_SRWILADIS_DISABLE; + // Settings of SRAM clock in RCC is secure + mpcbb.InvertSecureState = GTZC_MPCBB_INVSECSTATE_NOT_INVERTED; + // Set configuration as unlocked + mpcbb.AttributeConfig.MPCBB_LockConfig_array[0] = 0x00000000U; + + // Set all blocks unsecured & unprivileged + for (int index = 0; index < 52; index++) { + mpcbb.AttributeConfig.MPCBB_SecConfig_array[index] = 0x00000000U; + mpcbb.AttributeConfig.MPCBB_PrivConfig_array[index] = 0x00000000U; + } + + HAL_GTZC_MPCBB_ConfigMem(SRAM3_BASE, &mpcbb); + HAL_GTZC_MPCBB_ConfigMem(SRAM4_BASE, &mpcbb); +#if defined STM32U5A9xx | defined STM32U5G9xx + HAL_GTZC_MPCBB_ConfigMem(SRAM5_BASE, &mpcbb); +#endif + + // Set all blocks secured & unprivileged + for (int index = 0; index < 52; index++) { + mpcbb.AttributeConfig.MPCBB_SecConfig_array[index] = 0xFFFFFFFFU; + mpcbb.AttributeConfig.MPCBB_PrivConfig_array[index] = 0x00000000U; + } + + // unsecure 256KB of SRAM1 for core services & app + for (int index = 8; index < 24; index++) { + mpcbb.AttributeConfig.MPCBB_SecConfig_array[index] = 0x00000000U; + } + + HAL_GTZC_MPCBB_ConfigMem(SRAM1_BASE, &mpcbb); + + // Set all blocks secured & unprivileged + for (int index = 0; index < 52; index++) { + mpcbb.AttributeConfig.MPCBB_SecConfig_array[index] = 0xFFFFFFFFU; + mpcbb.AttributeConfig.MPCBB_PrivConfig_array[index] = 0x00000000U; + } + + // unsecure 32KB of SRAM2 (stack) for core services & app + mpcbb.AttributeConfig.MPCBB_SecConfig_array[1] = 0x00000000U; + mpcbb.AttributeConfig.MPCBB_SecConfig_array[2] = 0x00000000U; + + HAL_GTZC_MPCBB_ConfigMem(SRAM2_BASE, &mpcbb); +} + +// Configure FLASH security +static void trustzone_configure_flash(void) { + FLASH_BBAttributesTypeDef flash_bb = {0}; + + flash_bb.Bank = FLASH_BANK_1; + flash_bb.BBAttributesType = FLASH_BB_SEC; + + HAL_FLASHEx_GetConfigBBAttributes(&flash_bb); + + // Set 512KB (64 pages) after secure services unsecure + flash_bb.BBAttributes_array[2] = 0x000000FF; + flash_bb.BBAttributes_array[3] = 0x00000000; + flash_bb.BBAttributes_array[4] = 0xFFFFFF00; + + HAL_FLASHEx_ConfigBBAttributes(&flash_bb); +} + +static void trustzone_configure_peripherals(void) { + // Make all peripherals unsecure + HAL_GTZC_TZSC_ConfigPeriphAttributes(GTZC_PERIPH_ALL, GTZC_TZSC_PERIPH_NSEC); +} + +void isolate_unsecured_world(void) { + trustzone_configure_sau(); + trustzone_configure_flash(); + trustzone_configure_sram(); + trustzone_configure_peripherals(); + + // SCB->AIRCR + // SYSRESETREQS <- ?, + // BFHFMINS <- BusFault, HarudFault, NMI Secure/Non-Secure + // SCB->SCR + // SLEEPDEEPS <- ? + + // Select secure/unsecure flag for exception handlers + // + + // Select secure/unsecure flag for interrupts + // NVIC_SetTargetState() + + + // PWR_SECCFGR -- Secure everything needed for secure services + // PWR_PRIVCFGR -- NSPRIV, SPRIV <- 1 + // TODO + + // RCC_SECCFGR -- Secure everything needed for secure services + // RCC_PRIVCFGR -- NSPRIV, SPRIV <- 1 + // TODO + + // SYSCFG_SECCFGR + // TODO + + // GPIO -- Set selected PINs unsecure (all are secure by default) + // TODO +} + +void platform_init() { + touch_init(); + display_reinit(); +} + +int main(void) { // SECURE SERVICES + + // Initialize hardware driver + platform_init(); + + display_printf("Secure services are running...\n"); + + HAL_Delay(500); // uses Secure SysTick + + // Configure trust-zone + isolate_unsecured_world(); + + // Pass execution to unsecured core services + jump_to_core_services(); + + return 0; +} + diff --git a/core/embed/fw_ss/memory_DISC2.ld b/core/embed/fw_ss/memory_DISC2.ld new file mode 100644 index 000000000..9ca2bcb66 --- /dev/null +++ b/core/embed/fw_ss/memory_DISC2.ld @@ -0,0 +1,147 @@ +/* TREZORv2 firmware linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 256K + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 128K + BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 + SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 16K + SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K + SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K + SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0 + SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_estack = main_stack_base; + +/* used by the startup code to populate variables used by the C code */ +data_lma = LOADADDR(.data); +data_vma = ADDR(.data); +data_size = SIZEOF(.data); + +/* used by the startup code to populate variables used by the C code */ +sensitive_lma = LOADADDR(.sensitive); +sensitive_vma = ADDR(.sensitive); +sensitive_size = SIZEOF(.sensitive); + +/* used by the startup code to wipe memory */ +sram1_start = ORIGIN(SRAM1); +sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); +sram2_start = ORIGIN(SRAM2); +sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); +sram3_start = ORIGIN(SRAM3); +sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); +sram4_start = ORIGIN(SRAM4); +sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); +sram5_start = ORIGIN(SRAM5); +sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); +sram6_start = ORIGIN(SRAM6); +sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +_codelen = ADDR(.flash_fill) + SIZEOF(.flash_fill) - ADDR(.flash_vectors); +_flash_start = ORIGIN(FLASH); +_flash_end = ORIGIN(FLASH) + LENGTH(FLASH); +_heap_start = ADDR(.heap); +_heap_end = ADDR(.heap) + SIZEOF(.heap); + +_sgstubs_start = ADDR(.gnu.sgstubs); +_sgstubs_end = ADDR(.gnu.sgstubs) + SIZEOF(.gnu.sgstubs); + + + +SECTIONS { + .vendorheader : ALIGN(4) { + KEEP(*(.vendorheader)) + } >FLASH AT>FLASH + + .header : ALIGN(4) { + KEEP(*(.header)); + } >FLASH AT>FLASH + + .flash_vectors : ALIGN(512) { + KEEP(*(.vector_table)); + } + + .gnu.sgstubs : ALIGN (32) + { + . = ALIGN(32); + KEEP(*(.gnu.sgstubs*)); + . = ALIGN(32); + } > FLASH + + .flash : ALIGN(4) { + *(.text*); + . = ALIGN(4); + *(.rodata*); + . = ALIGN(4); + KEEP(*(.bootloader)); + *(.bootloader*); + . = ALIGN(512); + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(32); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .data_ccm : ALIGN(4) { + *(.no_dma_buffers*); + . = ALIGN(4); + } >SRAM1 + + .heap : ALIGN(4) { + . = 37K; /* this acts as a build time assertion that at least this much memory is available for heap use */ + . = ABSOLUTE(sram1_end); /* this explicitly sets the end of the heap */ + } >SRAM1 + + .stack : ALIGN(8) { + . = 16K; /* Overflow causes UsageFault */ + } >SRAM2 + + .sensitive : ALIGN(4) { + *(.sensitive*); + . = ALIGN(4); + } >SRAM2 AT>FLASH + + .fb1 : ALIGN(4) { + __fb_start = .; + *(.fb1*); + *(.gfxmmu_table*); + *(.framebuffer_select*); + . = ALIGN(4); + } >SRAM3 + + .fb2 : ALIGN(4) { + *(.fb2*); + __fb_end = .; + . = ALIGN(4); + } >SRAM5 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS + + .flash_fill : { + BYTE(0); + . = ALIGN(512); + } > FLASH = 0x00 +} diff --git a/core/embed/fw_ss/notes.md b/core/embed/fw_ss/notes.md new file mode 100644 index 000000000..e6d1acdef --- /dev/null +++ b/core/embed/fw_ss/notes.md @@ -0,0 +1,15 @@ + +- automatizace nastaveni sau a mpu (pouziti symbolu z linker skriptu) +- navrhnout hlavicku neprivilegovane aplikace +- navrh secure API, core API +// - dalsi zkoumani trustzone na STM32U5 (rozdeleni zodpovednosti mezi secure a privileged) + + +//- prozkoumat primy prechod z unsecure+unprivileged do secure+privileged +//- core_api, kopirovani a kontrola parametru, ochrana proti TOCTOU utoku +//- secure_api, kopirovani a kontrola parametru, cmse_check_address_range() (TT instrukce) +//- dalsich zkoumani Cortex-M33 (registry cpu) +//- nastudovovat zranitelnosti https://cactilab.github.io/assets/pdf/ret2ns2023.pdf +//- prechod secure -> unsecure, vynulovat registry + + diff --git a/core/embed/fw_ss/secure_api.c b/core/embed/fw_ss/secure_api.c new file mode 100644 index 000000000..16af43c43 --- /dev/null +++ b/core/embed/fw_ss/secure_api.c @@ -0,0 +1,57 @@ +#include "secure_api.h" + +#include STM32_HAL_H + +// When returning from or calling a callback from Secure to Non-Secure, +// all registers (r0-15, s0-31) are overwritten by constants, except +// for those that contain important information. + +__attribute__((cmse_nonsecure_entry)) int secure_get_secret() { + return 987654321; +} + +__attribute__((cmse_nonsecure_entry)) void secure_enumerate_secrets( + secure_enum_callback_t callback, void* callback_context) { + for (int i = 0; i < 5; i++) { + callback(callback_context, i); + } +} + +typedef __attribute__((cmse_nonsecure_call)) secure_callback_t ns_secure_callback_t; + +__attribute__((cmse_nonsecure_entry)) void secure_another_func( + secure_callback_t callback, void* callback_context) { + + // make non-secure callback from normal function ptr + ns_secure_callback_t ns_callback = (ns_secure_callback_t) cmse_nsfptr_create(callback); + + ns_callback(callback_context); +} + + +static inline const void * cmse_check_inbuff(const void * ptr, size_t size) { + return cmse_check_address_range((void *)ptr, size, CMSE_MPU_READ | CMSE_MPU_NONSECURE | CMSE_AU_NONSECURE); +} + +static inline void * cmse_check_outbuff( void * ptr, size_t size) { + return cmse_check_address_range(ptr, size, CMSE_MPU_READWRITE | CMSE_MPU_NONSECURE | CMSE_AU_NONSECURE); +} + + +__attribute__((cmse_nonsecure_entry)) +int secure_process_buff(const uint8_t * in_ptr, size_t in_size, + uint8_t * out_ptr, size_t out_size) { + + if (! cmse_check_inbuff(in_ptr, in_size)) { + return -1; + } + + if (! cmse_check_outbuff(out_ptr, out_size)) { + return -2; + } + + return 0; +} + + + diff --git a/core/embed/fw_ss/secure_api.h b/core/embed/fw_ss/secure_api.h new file mode 100644 index 000000000..969cd4941 --- /dev/null +++ b/core/embed/fw_ss/secure_api.h @@ -0,0 +1,32 @@ +#ifndef SECURE_API_H +#define SECURE_API_H + +#include +#include + + +#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define CMSE_NONSECURE_CALL __attribute__((cmse_nonsecure_call)) +#else +#define CMSE_NONSECURE_CALL +#endif + +int secure_get_secret(void); + +typedef void (*secure_enum_callback_t)(void* context, + int secret) CMSE_NONSECURE_CALL; + +void secure_enumerate_secrets(secure_enum_callback_t callback, + void* callback_context); + + +typedef void (*secure_callback_t)(void * context); + +void secure_another_function(secure_callback_t * callback, void * context); + + +int secure_process_buff(const uint8_t * in_ptr, size_t in_size, + uint8_t * out_ptr, size_t out_size); + + +#endif // SECURE_API_H diff --git a/core/embed/fw_ss/startup_stm32u5.S b/core/embed/fw_ss/startup_stm32u5.S new file mode 100644 index 000000000..6f05b2302 --- /dev/null +++ b/core/embed/fw_ss/startup_stm32u5.S @@ -0,0 +1,72 @@ + .syntax unified + + .text + + .global reset_handler + .type reset_handler, STT_FUNC +reset_handler: + // set the stack protection + ldr r0, =_sstack + add r0, r0, #32 // reserved for UsageFault exception + msr MSPLIM, r0 + + // setup environment for subsequent stage of code + ldr r2, =0 // r2 - the word-sized value to be written + + ldr r0, =sram1_start // r0 - point to beginning of SRAM + ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =sram2_start // r0 - point to beginning of SRAM + ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =sram4_start // r0 - point to beginning of SRAM + ldr r1, =sram4_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =sram6_start // r0 - point to beginning of SRAM + ldr r1, =sram6_end // r1 - point to byte after the end of SRAM + bl memset_reg + + ldr r0, =boot_args_start // r0 - point to beginning of boot args + ldr r1, =boot_args_end // r1 - point to byte after the end of boot args + bl memset_reg + + ldr r0, =sram3_start // r0 - point to beginning of SRAM + ldr r1, =__fb_start // r1 - point to beginning of framebuffer + bl memset_reg + + ldr r0, =__fb_end // r0 - point to end of framebuffer + ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + bl memset_reg + + // copy data in from flash + ldr r0, =data_vma // dst addr + ldr r1, =data_lma // src addr + ldr r2, =data_size // size in bytes + bl memcpy + + // copy sensitive data in from flash + ldr r0, =sensitive_vma // dst addr + ldr r1, =sensitive_lma // src addr + ldr r2, =sensitive_size // size in bytes + bl memcpy + + // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value + bl rng_get + ldr r1, = __stack_chk_guard + str r0, [r1] + + // re-enable exceptions + // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.7: + // "If it is not necessary to ensure that a pended interrupt is recognized immediately before + // subsequent operations, it is not necessary to insert a memory barrier instruction." + cpsie f + + // enter the application code + bl main + + b shutdown_privileged + + .end diff --git a/core/embed/fw_ss/version.h b/core/embed/fw_ss/version.h new file mode 100644 index 000000000..7f757eff1 --- /dev/null +++ b/core/embed/fw_ss/version.h @@ -0,0 +1,11 @@ +#define VERSION_MAJOR 2 +#define VERSION_MINOR 6 +#define VERSION_PATCH 4 +#define VERSION_BUILD 0 + +#define FIX_VERSION_MAJOR 2 +#define FIX_VERSION_MINOR 4 +#define FIX_VERSION_PATCH 0 +#define FIX_VERSION_BUILD 0 + +#define VERSION_MONOTONIC 1 diff --git a/core/embed/lib/image.c b/core/embed/lib/image.c index 3a2909fd7..7e1473396 100644 --- a/core/embed/lib/image.c +++ b/core/embed/lib/image.c @@ -264,7 +264,7 @@ secbool check_image_contents(const image_header *const hdr, uint32_t firstskip, offset += bytes_to_check; } - + /* // Check the padding to the end of the area end_offset = flash_area_get_size(area); @@ -297,7 +297,7 @@ secbool check_image_contents(const image_header *const hdr, uint32_t firstskip, offset += bytes_to_check; } - } + }*/ return sectrue; } diff --git a/core/embed/trezorhal/mpu.h b/core/embed/trezorhal/mpu.h index d9c22de61..265ffd2fd 100644 --- a/core/embed/trezorhal/mpu.h +++ b/core/embed/trezorhal/mpu.h @@ -25,5 +25,6 @@ void mpu_config_boardloader(void); void mpu_config_bootloader(void); void mpu_config_firmware(void); void mpu_config_prodtest(void); +void mpu_config_cs(void); #endif diff --git a/core/embed/trezorhal/stm32f4/supervise.c b/core/embed/trezorhal/stm32f4/supervise.c index c1ea8f75a..dab4eeb08 100644 --- a/core/embed/trezorhal/stm32f4/supervise.c +++ b/core/embed/trezorhal/stm32f4/supervise.c @@ -39,7 +39,7 @@ void svc_reboot_to_bootloader(void) { } } -void SVC_C_Handler(uint32_t *stack) { +/*void SVC_C_Handler(uint32_t *stack) { uint8_t svc_number = ((uint8_t *)stack[6])[-2]; switch (svc_number) { case SVC_ENABLE_IRQ: @@ -95,6 +95,6 @@ __attribute__((naked)) void SVC_Handler(void) { " mrsne r0, psp \n" // Make R0 point to process stack pointer " b SVC_C_Handler \n" // Off to C land ); -} +}*/ #endif // ARM_USER_MODE diff --git a/core/embed/trezorhal/stm32u5/displays/dsi.c b/core/embed/trezorhal/stm32u5/displays/dsi.c index cf31cf640..2a0a2fc5a 100644 --- a/core/embed/trezorhal/stm32u5/displays/dsi.c +++ b/core/embed/trezorhal/stm32u5/displays/dsi.c @@ -1103,7 +1103,7 @@ static int32_t LCD_Init(void) { status = BSP_ERROR_PERIPH_FAILURE; } else { if (MX_LTDC_ConfigLayer(&hlcd_ltdc, LTDC_LAYER_1, - GFXMMU_VIRTUAL_BUFFER0_BASE_S) != HAL_OK) { + GFXMMU_VIRTUAL_BUFFER0_BASE) != HAL_OK) { status = BSP_ERROR_PERIPH_FAILURE; } } @@ -1557,9 +1557,9 @@ void display_pixeldata(uint16_t c) { uint32_t address = 0; if (act_frame_buffer == 0) { - address = GFXMMU_VIRTUAL_BUFFER1_BASE_S; + address = GFXMMU_VIRTUAL_BUFFER1_BASE; } else { - address = GFXMMU_VIRTUAL_BUFFER0_BASE_S; + address = GFXMMU_VIRTUAL_BUFFER0_BASE; } /* Get the rectangle start address */ @@ -1596,9 +1596,9 @@ uint8_t *display_get_wr_addr(void) { uint32_t address = 0; if (act_frame_buffer == 0) { - address = GFXMMU_VIRTUAL_BUFFER1_BASE_S; + address = GFXMMU_VIRTUAL_BUFFER1_BASE; } else { - address = GFXMMU_VIRTUAL_BUFFER0_BASE_S; + address = GFXMMU_VIRTUAL_BUFFER0_BASE; } /* Get the rectangle start address */ @@ -1612,9 +1612,9 @@ uint32_t *display_get_fb_addr(void) { uint32_t address = 0; if (act_frame_buffer == 0) { - address = GFXMMU_VIRTUAL_BUFFER1_BASE_S; + address = GFXMMU_VIRTUAL_BUFFER1_BASE; } else { - address = GFXMMU_VIRTUAL_BUFFER0_BASE_S; + address = GFXMMU_VIRTUAL_BUFFER0_BASE; } return (uint32_t *)address; @@ -1704,9 +1704,9 @@ void display_reinit(void) { MX_LTDC_Reinit(&hlcd_ltdc); if (act_frame_buffer == 0) { - MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); + MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER0_BASE); } else { - MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); + MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER1_BASE); } } void display_sync(void) {} @@ -1714,11 +1714,11 @@ void display_sync(void) {} void display_refresh(void) { if (act_frame_buffer == 0) { act_frame_buffer = 1; - MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); + MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER1_BASE); memcpy(PhysFrameBuffer0, PhysFrameBuffer1, sizeof(PhysFrameBuffer1)); } else { act_frame_buffer = 0; - MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); + MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, GFXMMU_VIRTUAL_BUFFER0_BASE); memcpy(PhysFrameBuffer1, PhysFrameBuffer0, sizeof(PhysFrameBuffer1)); } } diff --git a/core/embed/trezorhal/stm32u5/flash.c b/core/embed/trezorhal/stm32u5/flash.c index a20cc579a..07b9ee323 100644 --- a/core/embed/trezorhal/stm32u5/flash.c +++ b/core/embed/trezorhal/stm32u5/flash.c @@ -87,7 +87,7 @@ secbool flash_sector_erase(uint16_t sector) { } FLASH_EraseInitTypeDef EraseInitStruct = { - .TypeErase = FLASH_TYPEERASE_PAGES_NS, + .TypeErase = FLASH_TYPEERASE_PAGES, .Banks = FLASH_BANK_1, .Page = sector, .NbPages = 1, @@ -98,9 +98,11 @@ secbool flash_sector_erase(uint16_t sector) { EraseInitStruct.Page = sector - 256; } - if (flash_sector_is_secure(sector)) { - EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; +#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + if (!flash_sector_is_secure(sector)) { + EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES_NS; } +#endif uint32_t sector_error = 0; diff --git a/core/embed/trezorhal/stm32u5/mpu.c b/core/embed/trezorhal/stm32u5/mpu.c index 51f3b0d42..25b4a64bc 100644 --- a/core/embed/trezorhal/stm32u5/mpu.c +++ b/core/embed/trezorhal/stm32u5/mpu.c @@ -107,13 +107,18 @@ static void mpu_set_attributes() { } #define GFXMMU_BUFFERS_S GFXMMU_VIRTUAL_BUFFERS_BASE_S +#define GFXMMU_BUFFERS GFXMMU_VIRTUAL_BUFFERS_BASE #define SIZE_16K (16 * 1024) #define SIZE_48K (48 * 1024) +#define SIZE_32K (32 * 1024) #define SIZE_64K (64 * 1024) #define SIZE_128K (128 * 1024) #define SIZE_192K (192 * 1024) +#define SIZE_256K (256 * 1024) #define SIZE_320K (320 * 1024) +#define SIZE_512K (512 * 1024) +#define SIZE_768K (768 * 1024) #define SIZE_2496K (2496 * 1024) #define SIZE_3776K ((4096 - 320) * 1024) #define SIZE_3904K ((4096 - 192) * 1024) @@ -173,4 +178,22 @@ void mpu_config_firmware() { HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); } +void mpu_config_cs() { + HAL_MPU_Disable(); + mpu_set_attributes(); + // clang-format off + // REGION ADDRESS SIZE TYPE WRITE UNPRIV + SET_REGION( 0, FLASH_BASE + SIZE_320K, SIZE_512K, FLASH_CODE, NO, NO ); // Firmware + SET_REGION( 1, SRAM1_BASE, SIZE_2496K, SRAM, YES, YES ); // SRAM1/2/3/5 + DIS_REGION( 2 ); + SET_REGION( 3, GFXMMU_BUFFERS, SIZE_16M, SRAM, YES, NO ); // Frame buffer + SET_REGION( 4, PERIPH_BASE, SIZE_256M, PERIPHERAL, YES, NO ); // Peripherals + DIS_REGION( 5 ); + SET_REGION( 6, FLASH_BASE + SIZE_320K + SIZE_512K, SIZE_256K,FLASH_CODE, NO, YES ); // Firmware + DIS_REGION( 7 ); + + // clang-format on + HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); +} + void mpu_config_off(void) { HAL_MPU_Disable(); } diff --git a/core/site_scons/boards/discovery2.py b/core/site_scons/boards/discovery2.py index 2780a8e06..96039e82f 100644 --- a/core/site_scons/boards/discovery2.py +++ b/core/site_scons/boards/discovery2.py @@ -27,7 +27,7 @@ def configure( ] = "-mthumb -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 " env.get("ENV")[ "CPU_CCFLAGS" - ] = "-mthumb -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -mtune=cortex-m33 -mcmse " + ] = "-mthumb -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -mtune=cortex-m33 " env.get("ENV")["RUST_TARGET"] = "thumbv8m.main-none-eabihf" defines += [mcu]