mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-21 02:26:10 +00:00
feat(core): add basic support for STM32U5
This commit is contained in:
parent
937b7d34d0
commit
8150636a81
1
core/.changelog.d/3370.added
Normal file
1
core/.changelog.d/3370.added
Normal file
@ -0,0 +1 @@
|
||||
Added basic support for STM32U5
|
@ -41,21 +41,29 @@ TEST_LANG ?= "en"
|
||||
OPENOCD_INTERFACE ?= stlink
|
||||
# OpenOCD transport default. Alternative: jtag
|
||||
OPENOCD_TRANSPORT ?= hla_swd
|
||||
OPENOCD = openocd -f interface/$(OPENOCD_INTERFACE).cfg -c "transport select $(OPENOCD_TRANSPORT)" -f target/stm32f4x.cfg
|
||||
OPENOCD_T1 = openocd -f interface/$(OPENOCD_INTERFACE).cfg -c "transport select $(OPENOCD_TRANSPORT)" -f target/stm32f2x.cfg
|
||||
|
||||
ifeq ($(TREZOR_MODEL),$(filter $(TREZOR_MODEL),T R DISC1))
|
||||
OPENOCD_TARGET = target/stm32f4x.cfg
|
||||
BOARDLOADER_START = 0x08000000
|
||||
BOARDLOADER_END = 0x0800C000
|
||||
BOOTLOADER_START = 0x08020000
|
||||
FIRMWARE_P1_START = 0x08040000
|
||||
FIRMWARE_START = 0x08040000
|
||||
FIRMWARE_P2_START = 0x08120000
|
||||
PRODTEST_START = 0x08040000
|
||||
FIRMWARE_T1_START = 0x08010000
|
||||
|
||||
BOARDLOADER_MAXSIZE = 49152
|
||||
BOOTLOADER_MAXSIZE = 131072
|
||||
FIRMWARE_P1_MAXSIZE = 786432
|
||||
FIRMWARE_P2_MAXSIZE = 917504
|
||||
FIRMWARE_MAXSIZE = 1703936
|
||||
else ifeq ($(TREZOR_MODEL), 1)
|
||||
OPENOCD_TARGET = target/stm32f2x.cfg
|
||||
FIRMWARE_START = 0x08010000
|
||||
else
|
||||
$(error Unknown TREZOR_MODEL: $(TREZOR_MODEL))
|
||||
endif
|
||||
|
||||
|
||||
OPENOCD = openocd -f interface/$(OPENOCD_INTERFACE).cfg -c "transport select $(OPENOCD_TRANSPORT)" -f $(OPENOCD_TARGET)
|
||||
|
||||
CFLAGS += -DSCM_REVISION='\"$(shell git rev-parse HEAD | sed 's:\(..\):\\x\1:g')\"'
|
||||
|
||||
@ -289,10 +297,12 @@ flash_prodtest: $(PRODTEST_BUILD_DIR)/prodtest.bin ## flash prodtest using OpenO
|
||||
$(OPENOCD) -c "init; reset halt; flash write_image erase $< $(PRODTEST_START); exit"
|
||||
|
||||
flash_firmware: $(FIRMWARE_BUILD_DIR)/firmware.bin ## flash firmware using OpenOCD
|
||||
$(OPENOCD) -c "init; reset halt; flash write_image erase $<.p1 $(FIRMWARE_P1_START); flash write_image erase $<.p2 $(FIRMWARE_P2_START); exit"
|
||||
ifdef FIRMWARE_P2_START
|
||||
$(OPENOCD) -c "init; reset halt; flash write_image erase $<.p1 $(FIRMWARE_START); flash write_image erase $<.p2 $(FIRMWARE_P2_START); exit"
|
||||
|
||||
flash_firmware_t1: $(FIRMWARE_BUILD_DIR)/firmware.bin ## flash T1 core port on T1 using OpenOCD
|
||||
$(OPENOCD_T1) -c "init; reset halt; flash write_image erase $< $(FIRMWARE_T1_START); exit"
|
||||
else
|
||||
$(OPENOCD) -c "init; reset halt; flash write_image erase $< $(FIRMWARE_START); exit"
|
||||
endif
|
||||
|
||||
flash_combine: $(PRODTEST_BUILD_DIR)/combined.bin ## flash combined using OpenOCD
|
||||
$(OPENOCD) -c "init; reset halt; flash write_image erase $< $(BOARDLOADER_START); exit"
|
||||
@ -367,7 +377,11 @@ combine: ## combine boardloader + bootloader + prodtest into one combined image
|
||||
$(BOARDLOADER_BUILD_DIR)/boardloader.bin \
|
||||
$(BOOTLOADER_BUILD_DIR)/bootloader.bin \
|
||||
$(PRODTEST_BUILD_DIR)/prodtest.bin \
|
||||
$(PRODTEST_BUILD_DIR)/combined.bin
|
||||
$(PRODTEST_BUILD_DIR)/combined.bin \
|
||||
$(BOARDLOADER_START) \
|
||||
$(BOARDLOADER_END) \
|
||||
$(BOOTLOADER_START) \
|
||||
$(PRODTEST_START)
|
||||
|
||||
upload: ## upload firmware using trezorctl
|
||||
trezorctl firmware_update -s -f $(FIRMWARE_BUILD_DIR)/firmware.bin
|
||||
|
@ -65,19 +65,21 @@ SOURCE_MOD += [
|
||||
'embed/lib/image.c',
|
||||
'embed/lib/mini_printf.c',
|
||||
'embed/lib/terminal.c',
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
|
||||
]
|
||||
|
||||
SOURCE_BOARDLOADER = [
|
||||
'embed/boardloader/startup.s',
|
||||
'embed/boardloader/main.c',
|
||||
]
|
||||
|
||||
env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0')), CONSTRAINTS=["limited_util_s"])
|
||||
|
||||
FEATURES_AVAILABLE = tools.configure_board(TREZOR_MODEL, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL)
|
||||
|
||||
FILE_SUFFIX= env.get('ENV')['SUFFIX']
|
||||
LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT']
|
||||
|
||||
SOURCE_BOARDLOADER = [
|
||||
f"embed/boardloader/startup_{FILE_SUFFIX}.s",
|
||||
'embed/boardloader/main.c',
|
||||
]
|
||||
|
||||
|
||||
env.Replace(
|
||||
CP='cp',
|
||||
AS='arm-none-eabi-as',
|
||||
@ -104,7 +106,7 @@ env.Replace(
|
||||
'-fstack-protector-all '
|
||||
+ env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD,
|
||||
CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB',
|
||||
LINKFLAGS='-T embed/boardloader/memory.ld -Wl,--gc-sections -Wl,-Map=build/boardloader/boardloader.map -Wl,--warn-common -Wl,--print-memory-usage',
|
||||
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",
|
||||
CPPPATH=[
|
||||
'embed/boardloader',
|
||||
'embed/lib',
|
||||
@ -161,7 +163,7 @@ program_bin = env.Command(
|
||||
target='boardloader.bin',
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary $SOURCE $TARGET',
|
||||
'$OBJCOPY -O binary -j .vector_table -j .text -j .data -j .rodata -j .capabilities -j .sensitive $SOURCE $TARGET',
|
||||
'$CP $TARGET ' + BINARY_NAME,
|
||||
],
|
||||
)
|
||||
|
@ -93,7 +93,6 @@ SOURCE_MOD += [
|
||||
'vendor/micropython/lib/uzlib/adler32.c',
|
||||
'vendor/micropython/lib/uzlib/crc32.c',
|
||||
'vendor/micropython/lib/uzlib/tinflate.c',
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
]
|
||||
|
||||
SOURCE_NANOPB = [
|
||||
@ -102,15 +101,6 @@ SOURCE_NANOPB = [
|
||||
'vendor/nanopb/pb_encode.c',
|
||||
]
|
||||
|
||||
SOURCE_BOOTLOADER = [
|
||||
'embed/bootloader/startup.s',
|
||||
'embed/bootloader/header.S',
|
||||
'embed/bootloader/bootui.c',
|
||||
'embed/bootloader/main.c',
|
||||
'embed/bootloader/messages.c',
|
||||
'embed/bootloader/protob/messages.pb.c',
|
||||
]
|
||||
|
||||
# fonts
|
||||
tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD)
|
||||
tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD)
|
||||
@ -122,6 +112,19 @@ env = Environment(ENV=os.environ, CFLAGS=f"{ARGUMENTS.get('CFLAGS', '')} -DPRODU
|
||||
|
||||
FEATURES_AVAILABLE = tools.configure_board(TREZOR_MODEL, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL)
|
||||
|
||||
FILE_SUFFIX= env.get('ENV')['SUFFIX']
|
||||
LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT']
|
||||
|
||||
SOURCE_BOOTLOADER = [
|
||||
f'embed/bootloader/startup_{FILE_SUFFIX}.s',
|
||||
'embed/bootloader/header.S',
|
||||
'embed/bootloader/bootui.c',
|
||||
'embed/bootloader/main.c',
|
||||
'embed/bootloader/messages.c',
|
||||
'embed/bootloader/protob/messages.pb.c',
|
||||
]
|
||||
|
||||
|
||||
env.Replace(
|
||||
CP='cp',
|
||||
AS='arm-none-eabi-as',
|
||||
@ -148,7 +151,7 @@ env.Replace(
|
||||
'-fstack-protector-all '
|
||||
+ env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD,
|
||||
CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB',
|
||||
LINKFLAGS='-T embed/bootloader/memory.ld -Wl,--gc-sections -Wl,-Map=build/bootloader/bootloader.map -Wl,--warn-common -Wl,--print-memory-usage',
|
||||
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',
|
||||
CPPPATH=[
|
||||
'embed/rust',
|
||||
'embed/bootloader',
|
||||
@ -267,7 +270,7 @@ program_bin = env.Command(
|
||||
target='bootloader.bin',
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary -j .header -j .flash -j .data $SOURCE $TARGET',
|
||||
'$OBJCOPY -O binary -j .header -j .flash -j .data -j .sensitive $SOURCE $TARGET',
|
||||
'$HEADERTOOL $TARGET ' + ('-D' if not PRODUCTION else ''),
|
||||
'$CP $TARGET ' + BINARY_NAME,
|
||||
], )
|
||||
|
@ -66,7 +66,6 @@ SOURCE_MOD += [
|
||||
'vendor/trezor-crypto/memzero.c',
|
||||
'vendor/trezor-crypto/rand.c',
|
||||
'vendor/trezor-crypto/sha2.c',
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
]
|
||||
|
||||
# modtrezorui
|
||||
@ -94,16 +93,6 @@ SOURCE_NANOPB = [
|
||||
'vendor/nanopb/pb_encode.c',
|
||||
]
|
||||
|
||||
SOURCE_BOOTLOADER = [
|
||||
'embed/bootloader_ci/startup.s',
|
||||
'embed/bootloader_ci/header.S',
|
||||
'embed/bootloader_ci/bootui.c',
|
||||
'embed/bootloader_ci/main.c',
|
||||
'embed/bootloader_ci/messages.c',
|
||||
'embed/bootloader_ci/protob/messages.pb.c',
|
||||
]
|
||||
|
||||
|
||||
# fonts
|
||||
tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD)
|
||||
tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD)
|
||||
@ -115,6 +104,18 @@ env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('
|
||||
|
||||
FEATURES_AVAILABLE = tools.configure_board(TREZOR_MODEL, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL)
|
||||
|
||||
FILE_SUFFIX= env.get('ENV')['SUFFIX']
|
||||
LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT']
|
||||
|
||||
SOURCE_BOOTLOADER = [
|
||||
f'embed/bootloader_ci/startup_{FILE_SUFFIX}.s',
|
||||
'embed/bootloader_ci/header.S',
|
||||
'embed/bootloader_ci/bootui.c',
|
||||
'embed/bootloader_ci/main.c',
|
||||
'embed/bootloader_ci/messages.c',
|
||||
'embed/bootloader_ci/protob/messages.pb.c',
|
||||
]
|
||||
|
||||
env.Replace(
|
||||
CP='cp',
|
||||
AS='arm-none-eabi-as',
|
||||
@ -141,7 +142,7 @@ env.Replace(
|
||||
'-fstack-protector-all '
|
||||
+ env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD,
|
||||
CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB',
|
||||
LINKFLAGS='-T embed/bootloader_ci/memory.ld -Wl,--gc-sections -Wl,-Map=build/bootloader_ci/bootloader.map -Wl,--warn-common',
|
||||
LINKFLAGS=f'-T embed/bootloader_ci/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/bootloader_ci/bootloader.map -Wl,--warn-common',
|
||||
CPPPATH=[
|
||||
'embed/bootloader_ci',
|
||||
'embed/bootloader_ci/nanopb',
|
||||
@ -209,7 +210,7 @@ program_bin = env.Command(
|
||||
target='bootloader.bin',
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary -j .header -j .flash -j .data $SOURCE $TARGET',
|
||||
'$OBJCOPY -O binary -j .header -j .flash -j .data -j .sensitive $SOURCE $TARGET',
|
||||
'$HEADERTOOL $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''),
|
||||
'$CP $TARGET ' + BINARY_NAME,
|
||||
], )
|
||||
|
@ -91,9 +91,13 @@ SOURCE_MOD += [
|
||||
'vendor/micropython/lib/uzlib/adler32.c',
|
||||
'vendor/micropython/lib/uzlib/crc32.c',
|
||||
'vendor/micropython/lib/uzlib/tinflate.c',
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
]
|
||||
|
||||
if TREZOR_MODEL in ('1', 'T', 'R', 'DISC1'):
|
||||
SOURCE_MOD += [
|
||||
'vendor/trezor-storage/flash_common_f4.c',
|
||||
]
|
||||
|
||||
if TREZOR_MODEL in ('1', ):
|
||||
SOURCE_MOD += [
|
||||
'embed/models/model_T1B1_layout.c',
|
||||
@ -142,6 +146,8 @@ SOURCE_UNIX = [
|
||||
'embed/unix/profile.c',
|
||||
]
|
||||
|
||||
|
||||
|
||||
# fonts
|
||||
tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD)
|
||||
tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD)
|
||||
|
@ -58,7 +58,6 @@ SOURCE_MOD += [
|
||||
'vendor/trezor-storage/norcow.c',
|
||||
'vendor/trezor-storage/storage.c',
|
||||
'vendor/trezor-storage/storage_utils.c',
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
]
|
||||
|
||||
# modtrezorcrypto
|
||||
@ -345,16 +344,6 @@ SOURCE_MICROPYTHON_SPEED = [
|
||||
'vendor/micropython/py/vm.c',
|
||||
]
|
||||
|
||||
SOURCE_FIRMWARE = [
|
||||
'embed/firmware/bl_check.c',
|
||||
'embed/firmware/delay.c',
|
||||
'embed/firmware/header.S',
|
||||
'embed/firmware/main.c',
|
||||
'embed/firmware/mphalport.c',
|
||||
'embed/firmware/nlrthumb.c',
|
||||
'embed/firmware/startup.S',
|
||||
]
|
||||
|
||||
CPPDEFINES_MOD += ['USE_SVC_SHUTDOWN']
|
||||
|
||||
if FEATURE_FLAGS["RDI"]:
|
||||
@ -389,6 +378,18 @@ env = Environment(ENV=os.environ, CFLAGS=f"{ARGUMENTS.get('CFLAGS', '')} -DPRODU
|
||||
|
||||
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/firmware/bl_check.c',
|
||||
'embed/firmware/delay.c',
|
||||
'embed/firmware/header.S',
|
||||
'embed/firmware/main.c',
|
||||
'embed/firmware/mphalport.c',
|
||||
'embed/firmware/nlrthumb.c',
|
||||
f'embed/firmware/startup_{FILE_SUFFIX}.S',
|
||||
]
|
||||
|
||||
|
||||
if TREZOR_MODEL in ('T', 'DISC1'):
|
||||
UI_LAYOUT = 'UI_LAYOUT_TT'
|
||||
@ -837,23 +838,31 @@ BINARY_NAME += "-dirty" if tools.get_git_modified() else ""
|
||||
BINARY_NAME += ".bin"
|
||||
|
||||
|
||||
if TREZOR_MODEL in ('T', 'R', 'DISC1'):
|
||||
|
||||
if TREZOR_MODEL in ('1',):
|
||||
action_bin=[
|
||||
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data --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 TREZOR_MODEL in ('1',):
|
||||
action_bin=[
|
||||
'$OBJCOPY -O binary -j .header -j .flash -j .data $SOURCE $TARGET',
|
||||
'$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:
|
||||
raise ValueError('Unknown Trezor model')
|
||||
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='firmware.bin',
|
||||
|
@ -91,21 +91,8 @@ SOURCE_MOD += [
|
||||
'vendor/micropython/lib/uzlib/adler32.c',
|
||||
'vendor/micropython/lib/uzlib/crc32.c',
|
||||
'vendor/micropython/lib/uzlib/tinflate.c',
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
]
|
||||
|
||||
SOURCE_PRODTEST = [
|
||||
'embed/prodtest/startup.s',
|
||||
'embed/prodtest/header.S',
|
||||
'embed/prodtest/main.c',
|
||||
'embed/prodtest/prodtest_common.c',
|
||||
]
|
||||
|
||||
if TREZOR_MODEL in ('R',):
|
||||
SOURCE_PRODTEST += [
|
||||
'embed/prodtest/optiga_prodtest.c',
|
||||
]
|
||||
|
||||
# fonts
|
||||
tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD)
|
||||
tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD)
|
||||
@ -117,6 +104,22 @@ env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('
|
||||
|
||||
FEATURES_AVAILABLE = tools.configure_board(TREZOR_MODEL, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL)
|
||||
|
||||
FILE_SUFFIX= env.get('ENV')['SUFFIX']
|
||||
LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT']
|
||||
|
||||
|
||||
SOURCE_PRODTEST = [
|
||||
f'embed/prodtest/startup_{FILE_SUFFIX}.s',
|
||||
'embed/prodtest/header.S',
|
||||
'embed/prodtest/main.c',
|
||||
'embed/prodtest/prodtest_common.c',
|
||||
]
|
||||
|
||||
if 'optiga' in FEATURES_AVAILABLE:
|
||||
SOURCE_PRODTEST += [
|
||||
'embed/prodtest/optiga_prodtest.c',
|
||||
]
|
||||
|
||||
env.Replace(
|
||||
CP='cp',
|
||||
AS='arm-none-eabi-as',
|
||||
@ -143,7 +146,7 @@ env.Replace(
|
||||
'-fstack-protector-all '
|
||||
+ env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD,
|
||||
CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB',
|
||||
LINKFLAGS='-T embed/prodtest/memory.ld -Wl,--gc-sections -Wl,-Map=build/prodtest/prodtest.map -Wl,--warn-common',
|
||||
LINKFLAGS=f'-T embed/prodtest/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/prodtest/prodtest.map -Wl,--warn-common',
|
||||
CPPPATH=[
|
||||
'embed/prodtest',
|
||||
'embed/lib',
|
||||
@ -225,7 +228,7 @@ program_bin = env.Command(
|
||||
target='prodtest.bin',
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data $SOURCE $TARGET',
|
||||
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .sensitive $SOURCE $TARGET',
|
||||
'$HEADERTOOL $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''),
|
||||
'$CP $TARGET ' + BINARY_NAME,
|
||||
], )
|
||||
|
@ -65,13 +65,6 @@ SOURCE_MOD += [
|
||||
'vendor/micropython/lib/uzlib/adler32.c',
|
||||
'vendor/micropython/lib/uzlib/crc32.c',
|
||||
'vendor/micropython/lib/uzlib/tinflate.c',
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
]
|
||||
|
||||
SOURCE_REFLASH = [
|
||||
'embed/reflash/startup.s',
|
||||
'embed/reflash/header.S',
|
||||
'embed/reflash/main.c',
|
||||
]
|
||||
|
||||
# fonts
|
||||
@ -85,6 +78,15 @@ env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('
|
||||
|
||||
FEATURES_AVAILABLE = tools.configure_board(TREZOR_MODEL, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL)
|
||||
|
||||
FILE_SUFFIX= env.get('ENV')['SUFFIX']
|
||||
LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT']
|
||||
|
||||
SOURCE_REFLASH = [
|
||||
f'embed/reflash/startup_{FILE_SUFFIX}.s',
|
||||
'embed/reflash/header.S',
|
||||
'embed/reflash/main.c',
|
||||
]
|
||||
|
||||
env.Replace(
|
||||
CP='cp',
|
||||
AS='arm-none-eabi-as',
|
||||
@ -111,7 +113,7 @@ env.Replace(
|
||||
'-fstack-protector-all '
|
||||
+ env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD,
|
||||
CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB',
|
||||
LINKFLAGS='-T embed/reflash/memory.ld -Wl,--gc-sections -Wl,-Map=build/reflash/reflash.map -Wl,--warn-common',
|
||||
LINKFLAGS=f'-T embed/reflash/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/reflash/reflash.map -Wl,--warn-common',
|
||||
CPPPATH=[
|
||||
'embed/reflash',
|
||||
'embed/lib',
|
||||
@ -182,7 +184,7 @@ program_bin = env.Command(
|
||||
target='reflash.bin',
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data $SOURCE $TARGET',
|
||||
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data -j .sensitive $SOURCE $TARGET',
|
||||
'$HEADERTOOL $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''),
|
||||
'$CP $TARGET ' + BINARY_NAME,
|
||||
], )
|
||||
|
@ -59,9 +59,13 @@ SOURCE_MOD += [
|
||||
'vendor/trezor-storage/norcow.c',
|
||||
'vendor/trezor-storage/storage.c',
|
||||
'vendor/trezor-storage/storage_utils.c',
|
||||
'vendor/trezor-storage/flash_common.c',
|
||||
]
|
||||
|
||||
if TREZOR_MODEL in ('1', 'T', 'R', 'DISC1'):
|
||||
SOURCE_MOD += [
|
||||
'vendor/trezor-storage/flash_common_f4.c',
|
||||
]
|
||||
|
||||
# modtrezorcrypto
|
||||
CCFLAGS_MOD += '-Wno-sequence-point '
|
||||
CPPPATH_MOD += [
|
||||
|
1
core/embed/boardloader/.changelog.d/3370.added
Normal file
1
core/embed/boardloader/.changelog.d/3370.added
Normal file
@ -0,0 +1 @@
|
||||
Added basic support for STM32U5
|
@ -27,8 +27,10 @@
|
||||
#include "flash.h"
|
||||
#include "image.h"
|
||||
#include "model.h"
|
||||
#include "mpu.h"
|
||||
#include "rng.h"
|
||||
#include "terminal.h"
|
||||
|
||||
#ifdef USE_SD_CARD
|
||||
#include "sdcard.h"
|
||||
#endif
|
||||
@ -42,6 +44,12 @@
|
||||
|
||||
#include "memzero.h"
|
||||
|
||||
#ifdef STM32U5
|
||||
#include "secret.h"
|
||||
#include "tamper.h"
|
||||
#include "trustzone.h"
|
||||
#endif
|
||||
|
||||
const uint8_t BOARDLOADER_KEY_M = 2;
|
||||
const uint8_t BOARDLOADER_KEY_N = 3;
|
||||
static const uint8_t * const BOARDLOADER_KEYS[] = {
|
||||
@ -54,6 +62,44 @@ static const uint8_t * const BOARDLOADER_KEYS[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef STM32U5
|
||||
void check_bootloader_version(uint8_t bld_version) {
|
||||
const uint8_t *counter_addr =
|
||||
flash_area_get_address(&SECRET_AREA, SECRET_MONOTONIC_COUNTER_OFFSET,
|
||||
SECRET_MONOTONIC_COUNTER_LEN);
|
||||
|
||||
ensure((counter_addr != NULL) * sectrue, "counter_addr is NULL");
|
||||
|
||||
int counter = 0;
|
||||
|
||||
for (int i = 0; i < SECRET_MONOTONIC_COUNTER_LEN / 16; i++) {
|
||||
secbool not_cleared = sectrue;
|
||||
for (int j = 0; j < 16; j++) {
|
||||
if (counter_addr[i * 16 + j] != 0xFF) {
|
||||
not_cleared = secfalse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (not_cleared != sectrue) {
|
||||
counter++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ensure((bld_version >= counter) * sectrue, "BOOTLOADER DOWNGRADED");
|
||||
|
||||
if (bld_version > counter) {
|
||||
for (int i = 0; i < bld_version; i++) {
|
||||
uint32_t data[4] = {0};
|
||||
secret_write((uint8_t *)data, SECRET_MONOTONIC_COUNTER_OFFSET + i * 16,
|
||||
16);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct BoardCapabilities capablities
|
||||
__attribute__((section(".capabilities_section"))) = {
|
||||
.header = CAPABILITIES_HEADER,
|
||||
@ -194,12 +240,30 @@ int main(void) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
#ifdef STM32U5
|
||||
tamper_init();
|
||||
|
||||
if (sectrue == secret_bhk_locked()) {
|
||||
delete_secrets();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STM32F4
|
||||
clear_otg_hs_memory();
|
||||
#endif
|
||||
|
||||
mpu_config_boardloader();
|
||||
|
||||
#ifdef USE_SDRAM
|
||||
sdram_init();
|
||||
#endif
|
||||
|
||||
#ifdef STM32U5
|
||||
trustzone_init();
|
||||
trustzone_run();
|
||||
#endif
|
||||
|
||||
display_init();
|
||||
display_clear();
|
||||
|
||||
@ -225,8 +289,15 @@ int main(void) {
|
||||
ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE, &BOOTLOADER_AREA),
|
||||
"invalid bootloader hash");
|
||||
|
||||
#ifdef STM32U5
|
||||
check_bootloader_version(hdr->monotonic);
|
||||
#endif
|
||||
|
||||
ensure_compatible_settings();
|
||||
|
||||
mpu_config_off();
|
||||
|
||||
// g_boot_flag is preserved on STM32U5
|
||||
jump_to(BOOTLOADER_START + IMAGE_HEADER_SIZE);
|
||||
|
||||
return 0;
|
||||
|
109
core/embed/boardloader/memory_stm32u5a.ld
Normal file
109
core/embed/boardloader/memory_stm32u5a.ld
Normal file
@ -0,0 +1,109 @@
|
||||
/* Trezor v2 boardloader linker script */
|
||||
|
||||
ENTRY(reset_handler)
|
||||
|
||||
MEMORY {
|
||||
FLASH (rx) : ORIGIN = 0x0C004000, LENGTH = 48K
|
||||
SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4)
|
||||
BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4)
|
||||
SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K
|
||||
SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K
|
||||
SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K
|
||||
SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 0K /* 512K on U5G */
|
||||
SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K
|
||||
}
|
||||
|
||||
main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
|
||||
_sstack = ORIGIN(SRAM2) + 0x100;
|
||||
_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);
|
||||
g_boot_args = (boot_args_start + 4);
|
||||
g_boot_flag = boot_args_start;
|
||||
|
||||
SECTIONS {
|
||||
.vector_table : ALIGN(512) {
|
||||
KEEP(*(.vector_table));
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
.text : ALIGN(4) {
|
||||
*(.text*);
|
||||
. = ALIGN(4); /* make the section size a multiple of the word size */
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
.rodata : ALIGN(4) {
|
||||
*(.rodata*);
|
||||
. = ALIGN(4); /* make the section size a multiple of the word size */
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.data*);
|
||||
. = ALIGN(8);
|
||||
} >SRAM1 AT>FLASH
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.ARM.exidx*);
|
||||
}
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
*(.bss*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.buf : ALIGN(4) {
|
||||
*(.buf*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.stack : ALIGN(8) {
|
||||
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
|
||||
} >SRAM2
|
||||
|
||||
.sensitive : ALIGN(8) {
|
||||
*(.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
|
||||
|
||||
/* Hard-coded address for capabilities structure */
|
||||
.capabilities 0x0C00FF00 : {KEEP(*(.capabilities_section))}
|
||||
}
|
102
core/embed/boardloader/startup_stm32u5.s
Normal file
102
core/embed/boardloader/startup_stm32u5.s
Normal file
@ -0,0 +1,102 @@
|
||||
.syntax unified
|
||||
|
||||
.text
|
||||
|
||||
.global reset_handler
|
||||
.type reset_handler, STT_FUNC
|
||||
reset_handler:
|
||||
bl SystemInit
|
||||
|
||||
// read the first rng data and save it
|
||||
ldr r0, =0 // r0 - previous value
|
||||
ldr r1, =0 // r1 - whether to compare the previous value
|
||||
bl rng_read
|
||||
|
||||
// read the next rng data and make sure it is different than previous
|
||||
// r0 - value returned from previous call
|
||||
ldr r1, =1 // r1 - whether to compare the previous value
|
||||
bl rng_read
|
||||
mov r4, r0 // save TRNG output in r4
|
||||
|
||||
// wipe memory to remove any possible vestiges of sensitive data
|
||||
|
||||
|
||||
fill_ram:
|
||||
ldr r0, =sram1_start // r0 - point to beginning of SRAM
|
||||
ldr r1, =sram1_end // r1 - point to byte after the end of SRAM
|
||||
mov r2, r4 // r2 - the word-sized value to be written
|
||||
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
|
||||
mov r2, r4 // r2 - the word-sized value to be written
|
||||
bl memset_reg
|
||||
|
||||
ldr r0, =sram3_start // r0 - point to beginning of SRAM
|
||||
ldr r1, =sram3_end // r1 - point to byte after the end of SRAM
|
||||
mov r2, r4 // r2 - the word-sized value to be written
|
||||
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
|
||||
mov r2, r4 // r2 - the word-sized value to be written
|
||||
bl memset_reg
|
||||
|
||||
ldr r0, =sram5_start // r0 - point to beginning of SRAM
|
||||
ldr r1, =sram5_end // r1 - point to byte after the end of SRAM
|
||||
mov r2, r4 // r2 - the word-sized value to be written
|
||||
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
|
||||
mov r2, r4 // r2 - the word-sized value to be written
|
||||
bl memset_reg
|
||||
|
||||
|
||||
// setup environment for subsequent stage of code
|
||||
|
||||
|
||||
clear_ram:
|
||||
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, =sram3_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, =sram5_start // r0 - point to beginning of SRAM
|
||||
ldr r1, =sram5_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
|
||||
|
||||
// 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]
|
||||
|
||||
// enter the application code
|
||||
bl main
|
||||
|
||||
b shutdown_privileged
|
||||
|
||||
.end
|
1
core/embed/bootloader/.changelog.d/3370.added
Normal file
1
core/embed/bootloader/.changelog.d/3370.added
Normal file
@ -0,0 +1 @@
|
||||
Added basic support for STM32U5
|
@ -28,7 +28,8 @@ void set_core_clock(int) {}
|
||||
|
||||
int bootloader_main(void);
|
||||
|
||||
bool sector_is_empty(const flash_area_t *area) {
|
||||
// assuming storage is single subarea
|
||||
bool storage_empty(const flash_area_t *area) {
|
||||
const uint8_t *storage = flash_area_get_address(area, 0, 0);
|
||||
size_t storage_size = flash_area_get_size(area);
|
||||
for (size_t i = 0; i < storage_size; i++) {
|
||||
@ -117,7 +118,7 @@ __attribute__((noreturn)) int main(int argc, char **argv) {
|
||||
FIRMWARE_START = (uint8_t *)flash_area_get_address(&FIRMWARE_AREA, 0, 0);
|
||||
|
||||
// simulate non-empty storage so that we know whether it was erased or not
|
||||
if (sector_is_empty(&STORAGE_AREAS[0])) {
|
||||
if (storage_empty(&STORAGE_AREAS[0])) {
|
||||
secbool ret = flash_area_write_word(&STORAGE_AREAS[0], 16, 0x12345678);
|
||||
(void)ret;
|
||||
}
|
||||
@ -197,7 +198,7 @@ void mpu_config_off(void) {}
|
||||
|
||||
__attribute__((noreturn)) void jump_to(void *addr) {
|
||||
bool storage_is_erased =
|
||||
sector_is_empty(&STORAGE_AREAS[0]) && sector_is_empty(&STORAGE_AREAS[1]);
|
||||
storage_empty(&STORAGE_AREAS[0]) && storage_empty(&STORAGE_AREAS[1]);
|
||||
|
||||
if (storage_is_erased) {
|
||||
printf("STORAGE WAS ERASED\n");
|
||||
|
@ -23,8 +23,10 @@
|
||||
#include "boot_internal.h"
|
||||
#include "common.h"
|
||||
#include "display.h"
|
||||
#include "display_utils.h"
|
||||
#include "flash.h"
|
||||
#include "image.h"
|
||||
#include "lowlevel.h"
|
||||
#include "messages.pb.h"
|
||||
#include "random_delays.h"
|
||||
#include "secbool.h"
|
||||
@ -77,9 +79,10 @@ typedef enum {
|
||||
RETURN_TO_MENU = 0x55667788,
|
||||
} usb_result_t;
|
||||
|
||||
volatile secbool dont_optimize_out_true = sectrue;
|
||||
void failed_jump_to_firmware(void);
|
||||
volatile void (*firmware_jump_fn)(void) = failed_jump_to_firmware;
|
||||
|
||||
SENSITIVE volatile secbool dont_optimize_out_true = sectrue;
|
||||
SENSITIVE volatile void (*firmware_jump_fn)(void) = failed_jump_to_firmware;
|
||||
|
||||
static void usb_init_all(secbool usb21_landing) {
|
||||
usb_dev_info_t dev_info = {
|
||||
@ -214,7 +217,7 @@ static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr,
|
||||
case MessageType_MessageType_GetFeatures:
|
||||
process_msg_GetFeatures(USB_IFACE_NUM, msg_size, buf, vhdr, hdr);
|
||||
break;
|
||||
#ifdef USE_OPTIGA
|
||||
#if defined USE_OPTIGA && !defined STM32U5
|
||||
case MessageType_MessageType_UnlockBootloader:
|
||||
response = ui_screen_unlock_bootloader_confirm();
|
||||
if (INPUT_CANCEL == response) {
|
||||
@ -258,7 +261,7 @@ static secbool check_vendor_header_lock(const vendor_header *const vhdr) {
|
||||
|
||||
// protection against bootloader downgrade
|
||||
|
||||
#if PRODUCTION
|
||||
#if PRODUCTION && !defined STM32U5
|
||||
|
||||
static void check_bootloader_version(void) {
|
||||
uint8_t bits[FLASH_OTP_BLOCK_SIZE];
|
||||
@ -317,11 +320,30 @@ void real_jump_to_firmware(void) {
|
||||
&FIRMWARE_AREA),
|
||||
"Firmware is corrupted");
|
||||
|
||||
#ifdef STM32U5
|
||||
secret_bhk_provision();
|
||||
secret_bhk_lock();
|
||||
#ifdef USE_OPTIGA
|
||||
if (sectrue == secret_optiga_present()) {
|
||||
secret_optiga_backup();
|
||||
secret_hide();
|
||||
}
|
||||
#else
|
||||
secret_hide();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
#ifdef STM32U5
|
||||
if ((vhdr.vtrust & VTRUST_SECRET) != 0) {
|
||||
secret_optiga_hide();
|
||||
}
|
||||
#else
|
||||
if (((vhdr.vtrust & VTRUST_SECRET) != 0) && (sectrue != secret_wiped())) {
|
||||
ui_screen_install_restricted();
|
||||
trezor_shutdown();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// if all VTRUST flags are unset = ultimate trust => skip the procedure
|
||||
@ -357,6 +379,18 @@ void real_jump_to_firmware(void) {
|
||||
jump_to(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE);
|
||||
}
|
||||
|
||||
#ifdef STM32U5
|
||||
__attribute__((noreturn)) void jump_to_fw_through_reset(void) {
|
||||
display_fade(display_backlight(-1), 0, 200);
|
||||
|
||||
__disable_irq();
|
||||
delete_secrets();
|
||||
NVIC_SystemReset();
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TREZOR_EMULATOR
|
||||
int main(void) {
|
||||
#else
|
||||
@ -365,7 +399,21 @@ int bootloader_main(void) {
|
||||
secbool stay_in_bootloader = secfalse;
|
||||
|
||||
random_delays_init();
|
||||
// display_init_seq();
|
||||
|
||||
#ifdef STM32U5
|
||||
if (sectrue != flash_configure_sec_area_ob()) {
|
||||
#ifdef STM32U5
|
||||
secret_bhk_regenerate();
|
||||
#endif
|
||||
|
||||
const secbool r =
|
||||
flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL);
|
||||
(void)r;
|
||||
__disable_irq();
|
||||
HAL_NVIC_SystemReset();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_DMA2D
|
||||
dma2d_init();
|
||||
#endif
|
||||
@ -460,7 +508,8 @@ int bootloader_main(void) {
|
||||
|
||||
unit_variant_init();
|
||||
|
||||
#if PRODUCTION
|
||||
#if PRODUCTION && !defined STM32U5
|
||||
// for STM32U5, this check is moved to boardloader
|
||||
check_bootloader_version();
|
||||
#endif
|
||||
|
||||
@ -529,6 +578,9 @@ int bootloader_main(void) {
|
||||
} else {
|
||||
screen = SCREEN_WELCOME;
|
||||
|
||||
#ifdef STM32U5
|
||||
secret_bhk_regenerate();
|
||||
#endif
|
||||
// erase storage
|
||||
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL),
|
||||
NULL);
|
||||
@ -583,7 +635,9 @@ int bootloader_main(void) {
|
||||
screen = SCREEN_INTRO;
|
||||
}
|
||||
if (ui_result == 0x11223344) { // reboot
|
||||
#ifndef STM32U5
|
||||
ui_screen_boot_empty(true);
|
||||
#endif
|
||||
continue_to_firmware = firmware_present;
|
||||
continue_to_firmware_backup = firmware_present_backup;
|
||||
}
|
||||
@ -633,6 +687,10 @@ int bootloader_main(void) {
|
||||
if (continue_to_firmware != continue_to_firmware_backup) {
|
||||
// erase storage if we saw flips randomly flip, most likely due to
|
||||
// glitch
|
||||
|
||||
#ifdef STM32U5
|
||||
secret_bhk_regenerate();
|
||||
#endif
|
||||
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL),
|
||||
NULL);
|
||||
}
|
||||
@ -640,7 +698,11 @@ int bootloader_main(void) {
|
||||
(continue_to_firmware == continue_to_firmware_backup),
|
||||
NULL);
|
||||
if (sectrue == continue_to_firmware) {
|
||||
#ifdef STM32U5
|
||||
firmware_jump_fn = jump_to_fw_through_reset;
|
||||
#else
|
||||
firmware_jump_fn = real_jump_to_firmware;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -648,13 +710,19 @@ int bootloader_main(void) {
|
||||
|
||||
ensure(dont_optimize_out_true * (firmware_present == firmware_present_backup),
|
||||
NULL);
|
||||
|
||||
#ifdef STM32U5
|
||||
if (sectrue == firmware_present &&
|
||||
firmware_jump_fn != jump_to_fw_through_reset) {
|
||||
firmware_jump_fn = real_jump_to_firmware;
|
||||
}
|
||||
#else
|
||||
if (sectrue == firmware_present) {
|
||||
firmware_jump_fn = real_jump_to_firmware;
|
||||
}
|
||||
#endif
|
||||
|
||||
firmware_jump_fn();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
|
||||
|
@ -10,6 +10,8 @@ MEMORY {
|
||||
}
|
||||
|
||||
main_stack_base = ORIGIN(CCMRAM) + SIZEOF(.stack) ; /* 8-byte aligned full descending stack */
|
||||
_sstack = ORIGIN(CCMRAM);
|
||||
_estack = main_stack_base;
|
||||
|
||||
/* used by the startup code to populate variables used by the C code */
|
||||
data_lma = LOADADDR(.data);
|
107
core/embed/bootloader/memory_stm32u5a.ld
Normal file
107
core/embed/bootloader/memory_stm32u5a.ld
Normal file
@ -0,0 +1,107 @@
|
||||
/* Trezor v2 bootloader linker script */
|
||||
|
||||
ENTRY(reset_handler)
|
||||
|
||||
MEMORY {
|
||||
FLASH (rx) : ORIGIN = 0x0C010000, LENGTH = 128K
|
||||
SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4)
|
||||
BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4)
|
||||
SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K
|
||||
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) + 0x100;
|
||||
_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);
|
||||
g_boot_args = (boot_args_start + 4);
|
||||
g_boot_flag = boot_args_start;
|
||||
|
||||
_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive);
|
||||
|
||||
SECTIONS {
|
||||
.header : ALIGN(4) {
|
||||
KEEP(*(.header));
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
.flash : ALIGN(512) {
|
||||
KEEP(*(.vector_table));
|
||||
. = ALIGN(4);
|
||||
*(.text*);
|
||||
. = ALIGN(4);
|
||||
*(.rodata*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.data*);
|
||||
. = ALIGN(512);
|
||||
} >SRAM1 AT>FLASH
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.ARM.exidx*);
|
||||
}
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
*(.bss*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.buf : ALIGN(4) {
|
||||
*(.buf*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.stack : ALIGN(8) {
|
||||
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
|
||||
} >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
|
||||
}
|
@ -637,7 +637,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
||||
is_ilu = sectrue;
|
||||
}
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
#if defined USE_OPTIGA && !defined STM32U5
|
||||
if (sectrue != secret_wiped() && ((vhdr.vtrust & VTRUST_SECRET) != 0)) {
|
||||
MSG_SEND_INIT(Failure);
|
||||
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
|
||||
@ -666,6 +666,9 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
||||
|
||||
// if firmware is not upgrade, erase storage
|
||||
if (sectrue != should_keep_seed) {
|
||||
#ifdef STM32U5
|
||||
secret_bhk_regenerate();
|
||||
#endif
|
||||
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL),
|
||||
NULL);
|
||||
}
|
||||
@ -834,7 +837,7 @@ void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {
|
||||
MSG_SEND(Failure);
|
||||
}
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
#if defined USE_OPTIGA && !defined STM32U5
|
||||
void process_msg_UnlockBootloader(uint8_t iface_num, uint32_t msg_size,
|
||||
uint8_t *buf) {
|
||||
secret_erase();
|
||||
|
78
core/embed/bootloader/startup_stm32u5.s
Normal file
78
core/embed/bootloader/startup_stm32u5.s
Normal file
@ -0,0 +1,78 @@
|
||||
.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
|
||||
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, =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]
|
||||
|
||||
//
|
||||
ldr r0, =g_boot_flag
|
||||
ldr r1, [r0]
|
||||
ldr r0, =g_boot_command
|
||||
str r1, [r0]
|
||||
ldr r0, =g_boot_flag
|
||||
mov r1, #0
|
||||
str r1, [r0]
|
||||
|
||||
// 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
|
||||
|
||||
.bss
|
||||
|
||||
.global g_boot_command
|
||||
g_boot_command:
|
||||
.word 0
|
||||
|
||||
.end
|
1
core/embed/bootloader_ci/.changelog.d/3370.added
Normal file
1
core/embed/bootloader_ci/.changelog.d/3370.added
Normal file
@ -0,0 +1 @@
|
||||
Added basic support for STM32U5
|
@ -9,7 +9,9 @@ MEMORY {
|
||||
SRAM (wal) : ORIGIN = 0x20000000, LENGTH = 192K
|
||||
}
|
||||
|
||||
main_stack_base = ORIGIN(CCMRAM) + LENGTH(CCMRAM); /* 8-byte aligned full descending stack */
|
||||
main_stack_base = ORIGIN(CCMRAM) + SIZEOF(.stack) ; /* 8-byte aligned full descending stack */
|
||||
_sstack = ORIGIN(CCMRAM);
|
||||
_estack = main_stack_base;
|
||||
|
||||
/* used by the startup code to populate variables used by the C code */
|
||||
data_lma = LOADADDR(.data);
|
||||
@ -44,17 +46,27 @@ SECTIONS {
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
.stack : ALIGN(8) {
|
||||
. = 16K; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
|
||||
} >CCMRAM
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.data*);
|
||||
. = ALIGN(512);
|
||||
} >CCMRAM AT>FLASH
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.ARM.exidx*);
|
||||
}
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
*(.bss*);
|
||||
. = ALIGN(4);
|
||||
} >CCMRAM
|
||||
|
||||
.stack : ALIGN(8) {
|
||||
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
|
||||
} >CCMRAM
|
||||
.buf : ALIGN(4) {
|
||||
*(.buf*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM
|
||||
|
||||
}
|
107
core/embed/bootloader_ci/memory_stm32u5a.ld
Normal file
107
core/embed/bootloader_ci/memory_stm32u5a.ld
Normal file
@ -0,0 +1,107 @@
|
||||
/* Trezor v2 bootloader linker script */
|
||||
|
||||
ENTRY(reset_handler)
|
||||
|
||||
MEMORY {
|
||||
FLASH (rx) : ORIGIN = 0x0C010000, LENGTH = 128K
|
||||
SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4)
|
||||
BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4)
|
||||
SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K
|
||||
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) + 0x100;
|
||||
_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);
|
||||
g_boot_args = (boot_args_start + 4);
|
||||
g_boot_flag = boot_args_start;
|
||||
|
||||
_codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive);
|
||||
|
||||
SECTIONS {
|
||||
.header : ALIGN(4) {
|
||||
KEEP(*(.header));
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
.flash : ALIGN(512) {
|
||||
KEEP(*(.vector_table));
|
||||
. = ALIGN(4);
|
||||
*(.text*);
|
||||
. = ALIGN(4);
|
||||
*(.rodata*);
|
||||
. = ALIGN(512);
|
||||
} >FLASH AT>FLASH
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.data*);
|
||||
. = ALIGN(512);
|
||||
} >SRAM1 AT>FLASH
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.ARM.exidx*);
|
||||
}
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
*(.bss*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.buf : ALIGN(4) {
|
||||
*(.buf*);
|
||||
. = ALIGN(4);
|
||||
} >SRAM1
|
||||
|
||||
.stack : ALIGN(8) {
|
||||
. = 16K + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
|
||||
} >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
|
||||
}
|
78
core/embed/bootloader_ci/startup_stm32u5.s
Normal file
78
core/embed/bootloader_ci/startup_stm32u5.s
Normal file
@ -0,0 +1,78 @@
|
||||
.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
|
||||
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, =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]
|
||||
|
||||
//
|
||||
ldr r0, =g_boot_flag
|
||||
ldr r1, [r0]
|
||||
ldr r0, =g_boot_command
|
||||
str r1, [r0]
|
||||
ldr r0, =g_boot_flag
|
||||
mov r1, #0
|
||||
str r1, [r0]
|
||||
|
||||
// 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
|
||||
|
||||
.bss
|
||||
|
||||
.global g_boot_command
|
||||
g_boot_command:
|
||||
.word 0
|
||||
|
||||
.end
|
@ -48,6 +48,7 @@
|
||||
#include "mpu.h"
|
||||
#include "random_delays.h"
|
||||
#include "rust_ui.h"
|
||||
#include "secure_aes.h"
|
||||
|
||||
#include TREZOR_BOARD
|
||||
|
||||
@ -75,8 +76,11 @@
|
||||
#ifdef USE_OPTIGA
|
||||
#include "optiga_commands.h"
|
||||
#include "optiga_transport.h"
|
||||
#endif
|
||||
#if defined USE_OPTIGA | defined STM32U5
|
||||
#include "secret.h"
|
||||
#endif
|
||||
|
||||
#include "unit_variant.h"
|
||||
|
||||
#ifdef SYSTEM_VIEW
|
||||
@ -99,6 +103,10 @@ int main(void) {
|
||||
rdi_start();
|
||||
#endif
|
||||
|
||||
#ifdef STM32U5
|
||||
check_oem_keys();
|
||||
#endif
|
||||
|
||||
// reinitialize HAL for Trezor One
|
||||
#if defined TREZOR_MODEL_1
|
||||
HAL_Init();
|
||||
@ -125,8 +133,7 @@ int main(void) {
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
uint8_t secret[SECRET_OPTIGA_KEY_LEN] = {0};
|
||||
secbool secret_ok =
|
||||
secret_read(secret, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
||||
secbool secret_ok = secret_optiga_extract(secret);
|
||||
#endif
|
||||
|
||||
#if PRODUCTION || BOOTLOADER_QA
|
||||
@ -148,6 +155,10 @@ int main(void) {
|
||||
set_core_clock(CLOCK_180_MHZ);
|
||||
#endif
|
||||
|
||||
#ifdef STM32U5
|
||||
secure_aes_init();
|
||||
#endif
|
||||
|
||||
#ifdef USE_BUTTON
|
||||
button_init();
|
||||
#endif
|
||||
@ -231,25 +242,6 @@ void __attribute__((noreturn)) nlr_jump_fail(void *val) {
|
||||
error_shutdown("INTERNAL ERROR", "(UE)");
|
||||
}
|
||||
|
||||
// interrupt handlers
|
||||
|
||||
void NMI_Handler(void) {
|
||||
// Clock Security System triggered NMI
|
||||
if ((RCC->CIR & RCC_CIR_CSSF) != 0) {
|
||||
error_shutdown("INTERNAL ERROR", "(CS)");
|
||||
}
|
||||
}
|
||||
|
||||
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
|
||||
|
||||
void MemManage_Handler_MM(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
|
||||
|
||||
void MemManage_Handler_SO(void) { error_shutdown("INTERNAL ERROR", "(SO)"); }
|
||||
|
||||
void BusFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(BF)"); }
|
||||
|
||||
void UsageFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(UF)"); }
|
||||
|
||||
// MicroPython builtin stubs
|
||||
|
||||
mp_import_stat_t mp_import_stat(const char *path) {
|
||||
|
@ -26,6 +26,7 @@ ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM);
|
||||
/* reserve 256 bytes for bootloader arguments */
|
||||
boot_args_start = ORIGIN(BOOT_ARGS);
|
||||
boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS);
|
||||
g_boot_args = boot_args_start;
|
||||
|
||||
/* used by the startup code to wipe memory */
|
||||
sram_start = ORIGIN(SRAM);
|
||||
|
@ -66,16 +66,4 @@ reset_handler:
|
||||
|
||||
b shutdown_privileged
|
||||
|
||||
.global MemManage_Handler
|
||||
.type MemManage_Handler, STT_FUNC
|
||||
MemManage_Handler:
|
||||
ldr r2, =_sstack
|
||||
mrs r1, msp
|
||||
ldr r0, =_estack
|
||||
msr msp, r0
|
||||
cmp r1, r2
|
||||
IT lt
|
||||
bllt MemManage_Handler_SO
|
||||
bl MemManage_Handler_MM
|
||||
|
||||
.end
|
67
core/embed/firmware/startup_stm32u5.S
Normal file
67
core/embed/firmware/startup_stm32u5.S
Normal file
@ -0,0 +1,67 @@
|
||||
.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
|
||||
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
|
@ -15,6 +15,7 @@
|
||||
extern const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT];
|
||||
extern const flash_area_t BOARDLOADER_AREA;
|
||||
extern const flash_area_t SECRET_AREA;
|
||||
extern const flash_area_t BHK_AREA;
|
||||
extern const flash_area_t TRANSLATIONS_AREA;
|
||||
extern const flash_area_t BOOTLOADER_AREA;
|
||||
extern const flash_area_t FIRMWARE_AREA;
|
||||
|
@ -19,6 +19,7 @@
|
||||
(const uint8_t *)"\xee\x93\xa4\xf6\x6f\x8d\x16\xb8\x19\xbb\x9b\xeb\x9f\xfc\xcd\xfc\xdc\x14\x12\xe8\x7f\xee\x6a\x32\x4c\x2a\x99\xa1\xe0\xe6\x71\x48",
|
||||
|
||||
#define BOARDLOADER_START 0x08000000
|
||||
#define BOARD_CAPABILITIES_ADDR 0x0800BF00
|
||||
#define BOOTLOADER_START 0x08020000
|
||||
#define FIRMWARE_START 0x08040000
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
(const uint8_t *)"\x07\xc8\x51\x34\x94\x6b\xf8\x9f\xa1\x9b\xdc\x2c\x5e\x5f\xf9\xce\x01\x29\x65\x08\xee\x08\x63\xd0\xff\x6d\x63\x33\x1d\x1a\x25\x16",
|
||||
|
||||
#define BOARDLOADER_START 0x08000000
|
||||
#define BOARD_CAPABILITIES_ADDR 0x0800BF00
|
||||
#define BOOTLOADER_START 0x08020000
|
||||
#define FIRMWARE_START 0x08040000
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
(const uint8_t *)"\xb8\x30\x7a\x71\xf5\x52\xc6\x0a\x4c\xbb\x31\x7f\xf4\x8b\x82\xcd\xbf\x6b\x6b\xb5\xf0\x4c\x92\x0f\xec\x7b\xad\xf0\x17\x88\x37\x51",
|
||||
|
||||
#define BOARDLOADER_START 0x08000000
|
||||
#define BOARD_CAPABILITIES_ADDR 0x0800BF00
|
||||
#define BOOTLOADER_START 0x08020000
|
||||
#define FIRMWARE_START 0x08040000
|
||||
|
||||
|
1
core/embed/prodtest/.changelog.d/3370.added
Normal file
1
core/embed/prodtest/.changelog.d/3370.added
Normal file
@ -0,0 +1 @@
|
||||
Added basic support for STM32U5
|
@ -669,5 +669,3 @@ int main(void) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR!", "(HF)"); }
|
||||
|
@ -10,6 +10,7 @@ MEMORY {
|
||||
}
|
||||
|
||||
main_stack_base = ORIGIN(SRAM) + LENGTH(SRAM); /* 8-byte aligned full descending stack */
|
||||
_sstack = ORIGIN(SRAM);
|
||||
_estack = main_stack_base;
|
||||
|
||||
/* used by the startup code to populate variables used by the C code */
|
123
core/embed/prodtest/memory_stm32u5a.ld
Normal file
123
core/embed/prodtest/memory_stm32u5a.ld
Normal file
@ -0,0 +1,123 @@
|
||||
/* TREZORv2 firmware linker script */
|
||||
|
||||
ENTRY(reset_handler)
|
||||
|
||||
MEMORY {
|
||||
FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K
|
||||
SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4)
|
||||
BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4)
|
||||
SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K
|
||||
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) + 0x100;
|
||||
_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);
|
||||
g_boot_args = (boot_args_start + 4);
|
||||
g_boot_flag= boot_args_start;
|
||||
|
||||
_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 + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
|
||||
} >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
|
||||
}
|
67
core/embed/prodtest/startup_stm32u5.s
Normal file
67
core/embed/prodtest/startup_stm32u5.s
Normal file
@ -0,0 +1,67 @@
|
||||
.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
|
||||
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
|
123
core/embed/reflash/memory_stm32u5a.ld
Normal file
123
core/embed/reflash/memory_stm32u5a.ld
Normal file
@ -0,0 +1,123 @@
|
||||
/* TREZORv2 firmware linker script */
|
||||
|
||||
ENTRY(reset_handler)
|
||||
|
||||
MEMORY {
|
||||
FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K
|
||||
SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4)
|
||||
BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4)
|
||||
SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K
|
||||
SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K
|
||||
SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K
|
||||
SRAM6 (wal) : ORIGIN = 0x30270000, LENGTH = 512K
|
||||
SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K
|
||||
}
|
||||
|
||||
main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */
|
||||
_sstack = ORIGIN(SRAM2) + 0x100;
|
||||
_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);
|
||||
g_boot_args = (boot_args_start + 4);
|
||||
g_boot_flag = boot_args_start;
|
||||
|
||||
_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 + 0x100; /* Exactly 16K allocated for stack. Overflow causes MemManage fault (when using MPU). */
|
||||
} >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
|
||||
}
|
67
core/embed/reflash/startup_stm32u5.s
Normal file
67
core/embed/reflash/startup_stm32u5.s
Normal file
@ -0,0 +1,67 @@
|
||||
.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
|
||||
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
|
@ -447,7 +447,7 @@ fn generate_crypto_bindings() {
|
||||
|
||||
fn is_firmware() -> bool {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
target.starts_with("thumbv7")
|
||||
target.starts_with("thumbv7") || target.starts_with("thumbv8")
|
||||
}
|
||||
|
||||
#[cfg(feature = "test")]
|
||||
|
@ -35,7 +35,6 @@ Last tag must be terminator or all space used.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BOARD_CAPABILITIES_ADDR 0x0800BF00
|
||||
#define BOARD_CAPABILITIES_SIZE 256
|
||||
#define CAPABILITIES_HEADER "TRZC"
|
||||
|
||||
|
@ -27,6 +27,7 @@ void flash_lock_option_bytes(void);
|
||||
void flash_unlock_option_bytes(void);
|
||||
uint32_t flash_set_option_bytes(void);
|
||||
secbool flash_configure_option_bytes(void);
|
||||
secbool flash_configure_sec_area_ob(void);
|
||||
void periph_init(void);
|
||||
secbool reset_flags_check(void);
|
||||
void reset_flags_reset(void);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define __MPU_H__
|
||||
|
||||
void mpu_config_off(void);
|
||||
void mpu_config_boardloader(void);
|
||||
void mpu_config_bootloader(void);
|
||||
void mpu_config_firmware(void);
|
||||
void mpu_config_prodtest(void);
|
||||
|
@ -7,6 +7,12 @@
|
||||
#define SECRET_OPTIGA_KEY_OFFSET 16
|
||||
#define SECRET_OPTIGA_KEY_LEN 32
|
||||
|
||||
#define SECRET_MONOTONIC_COUNTER_OFFSET 48
|
||||
#define SECRET_MONOTONIC_COUNTER_LEN 1024
|
||||
|
||||
#define SECRET_BHK_OFFSET (1024 * 8)
|
||||
#define SECRET_BHK_LEN 32
|
||||
|
||||
secbool secret_bootloader_locked(void);
|
||||
|
||||
void secret_write(uint8_t* data, uint32_t offset, uint32_t len);
|
||||
@ -17,4 +23,22 @@ secbool secret_wiped(void);
|
||||
|
||||
void secret_erase(void);
|
||||
|
||||
void secret_hide(void);
|
||||
|
||||
void secret_write_header(void);
|
||||
|
||||
void secret_optiga_backup(void);
|
||||
|
||||
void secret_optiga_hide(void);
|
||||
|
||||
secbool secret_optiga_extract(uint8_t* dest);
|
||||
|
||||
void secret_bhk_lock(void);
|
||||
|
||||
secbool secret_bhk_locked(void);
|
||||
|
||||
void secret_bhk_regenerate(void);
|
||||
|
||||
void secret_bhk_provision(void);
|
||||
|
||||
secbool secret_optiga_present(void);
|
||||
|
40
core/embed/trezorhal/secure_aes.h
Normal file
40
core/embed/trezorhal/secure_aes.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZOR_HAL_SECURE_AES_H
|
||||
#define TREZOR_HAL_SECURE_AES_H
|
||||
|
||||
#include <secbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Initializes secure AES module
|
||||
secbool secure_aes_init(void);
|
||||
|
||||
// Encrypts a block of data using AES-256 EBB and (DHUK xor BHK) key
|
||||
// Input and output must be aligned to 32 bits, size is in bytes
|
||||
secbool secure_aes_encrypt(uint32_t* input, size_t size, uint32_t* output);
|
||||
|
||||
// Decrypts a block of data using AES-256 ECB and (DHUK xor BHK) key
|
||||
// Input and output must be aligned to 32 bits, size is in bytes
|
||||
secbool secure_aes_decrypt(uint32_t* input, size_t size, uint32_t* output);
|
||||
|
||||
void secure_aes_test();
|
||||
|
||||
#endif // TREZOR_HAL_SECURE_AES_H
|
@ -20,6 +20,7 @@
|
||||
#include "board_capabilities.h"
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#include "model.h"
|
||||
|
||||
#define handle_fault(msg) \
|
||||
(__fatal_error("Fault detected", msg, __FILE__, __LINE__, __func__))
|
||||
|
18
core/embed/trezorhal/stm32f4/fault_handlers.c
Normal file
18
core/embed/trezorhal/stm32f4/fault_handlers.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include "common.h"
|
||||
|
||||
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
|
||||
|
||||
void MemManage_Handler_MM(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
|
||||
|
||||
void MemManage_Handler_SO(void) { error_shutdown("INTERNAL ERROR", "(SO)"); }
|
||||
|
||||
void BusFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(BF)"); }
|
||||
|
||||
void UsageFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(UF)"); }
|
||||
|
||||
void NMI_Handler(void) {
|
||||
// Clock Security System triggered NMI
|
||||
if ((RCC->CIR & RCC_CIR_CSSF) != 0) {
|
||||
error_shutdown("INTERNAL ERROR", "(CS)");
|
||||
}
|
||||
}
|
@ -160,4 +160,7 @@ static inline void restore_irq_pri(uint32_t state) {
|
||||
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
|
||||
#define IRQ_PRI_RTC_WKUP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
|
||||
|
||||
// !@# TAMPER interrupt priority should be probably much higher
|
||||
#define IRQ_PRI_TAMP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
|
||||
|
||||
#endif // MICROPY_INCLUDED_STM32_IRQ_H
|
||||
|
@ -33,6 +33,10 @@ void mpu_config_off(void) {
|
||||
HAL_MPU_Disable();
|
||||
}
|
||||
|
||||
void mpu_config_boardloader(void) {
|
||||
// nothing to be done
|
||||
}
|
||||
|
||||
void mpu_config_bootloader(void) {
|
||||
// Disable MPU
|
||||
HAL_MPU_Disable();
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include STM32_HAL_H
|
||||
#include <stdint.h>
|
||||
|
||||
#define SENSITIVE
|
||||
|
||||
typedef enum {
|
||||
CLOCK_180_MHZ = 0,
|
||||
CLOCK_168_MHZ = 1,
|
||||
|
@ -72,3 +72,7 @@ secbool secret_wiped(void) {
|
||||
void secret_erase(void) {
|
||||
ensure(flash_area_erase(&SECRET_AREA, NULL), "secret erase");
|
||||
}
|
||||
|
||||
secbool secret_optiga_extract(uint8_t* dest) {
|
||||
return secret_read(dest, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
||||
}
|
||||
|
@ -11,13 +11,13 @@
|
||||
// Saves extra parameters for the bootloader
|
||||
static void _copy_boot_args(const void *args, size_t args_size) {
|
||||
// symbols imported from the linker script
|
||||
extern uint8_t boot_args_start;
|
||||
extern uint8_t g_boot_args;
|
||||
extern uint8_t boot_args_end;
|
||||
|
||||
uint8_t *p = &boot_args_start;
|
||||
uint8_t *p = &g_boot_args;
|
||||
|
||||
if (args != NULL && args_size > 0) {
|
||||
size_t max_size = &boot_args_end - &boot_args_start;
|
||||
size_t max_size = &boot_args_end - &g_boot_args;
|
||||
size_t copy_size = MIN(args_size, max_size);
|
||||
memcpy(p, args, copy_size);
|
||||
p += args_size;
|
||||
@ -28,6 +28,16 @@ static void _copy_boot_args(const void *args, size_t args_size) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef STM32U5
|
||||
extern uint32_t g_boot_flag;
|
||||
__attribute__((noreturn)) static void _reboot_to_bootloader(
|
||||
boot_command_t boot_command) {
|
||||
g_boot_flag = boot_command;
|
||||
__disable_irq();
|
||||
delete_secrets();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
#else
|
||||
__attribute__((noreturn)) static void _reboot_to_bootloader(
|
||||
boot_command_t boot_command) {
|
||||
mpu_config_bootloader();
|
||||
@ -35,6 +45,7 @@ __attribute__((noreturn)) static void _reboot_to_bootloader(
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
void svc_reboot_to_bootloader(boot_command_t boot_command, const void *args,
|
||||
size_t args_size) {
|
||||
|
@ -32,6 +32,8 @@
|
||||
#define USB_PHY_ID USB_PHY_FS_ID
|
||||
#elif defined(USE_USB_HS) && defined(USE_USB_HS_IN_FS)
|
||||
#define USB_PHY_ID USB_PHY_HS_ID
|
||||
#elif defined(USE_USB_HS) && !defined(USE_USB_HS_IN_FS)
|
||||
#define USB_PHY_ID USB_PHY_HS_ID
|
||||
#else
|
||||
#error Unable to determine proper USB_PHY_ID to use
|
||||
#endif
|
||||
|
@ -83,6 +83,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
#ifdef USB_OTG_FS
|
||||
if(hpcd->Instance == USB_OTG_FS)
|
||||
{
|
||||
/* Configure USB FS GPIOs */
|
||||
@ -96,7 +97,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* Configure VBUS Pin */
|
||||
/* Configure VBUS Pin */
|
||||
#if defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
|
||||
// USB VBUS detect pin is always A9
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_9;
|
||||
@ -124,9 +125,9 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||
/* Enable USBFS Interrupt */
|
||||
svc_enableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_USB_HS)
|
||||
else if(hpcd->Instance == USB_OTG_HS)
|
||||
{
|
||||
if (hpcd->Instance == USB_OTG_HS) {
|
||||
#if defined(USE_USB_HS_IN_FS)
|
||||
|
||||
/* Configure USB FS GPIOs */
|
||||
@ -168,7 +169,53 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||
/* Enable USB HS Clocks */
|
||||
__USB_OTG_HS_CLK_ENABLE();
|
||||
|
||||
#else // !USE_USB_HS_IN_FS
|
||||
#elif defined USE_USB_HS_INTERNAL_PHY && defined STM32U5
|
||||
|
||||
/* Configure DM and DP PINs */
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
|
||||
GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF10_USB_HS;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
|
||||
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
|
||||
|
||||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USBPHY;
|
||||
PeriphClkInit.UsbPhyClockSelection = RCC_USBPHYCLKSOURCE_HSE;
|
||||
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
|
||||
|
||||
/** Set the OTG PHY reference clock selection
|
||||
*/
|
||||
HAL_SYSCFG_SetOTGPHYReferenceClockSelection(SYSCFG_OTG_HS_PHY_CLK_SELECT_1);
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();
|
||||
__HAL_RCC_USBPHYC_CLK_ENABLE();
|
||||
|
||||
/* Enable VDDUSB */
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
HAL_PWREx_EnableVddUSB();
|
||||
|
||||
/*configure VOSR register of USB*/
|
||||
HAL_PWREx_EnableUSBHSTranceiverSupply();
|
||||
__HAL_RCC_PWR_CLK_DISABLE();
|
||||
|
||||
|
||||
/*Configuring the SYSCFG registers OTG_HS PHY*/
|
||||
/*OTG_HS PHY enable*/
|
||||
HAL_SYSCFG_EnableOTGPHY(SYSCFG_OTG_HS_PHY_ENABLE);
|
||||
|
||||
|
||||
|
||||
#else // !USE_USB_HS_IN_FS && !USE_USB_HS_INTERNAL_PHY
|
||||
|
||||
/* Configure USB HS GPIOs */
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
@ -242,20 +289,22 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||
*/
|
||||
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
#ifdef USB_OTG_FS
|
||||
if(hpcd->Instance == USB_OTG_FS)
|
||||
{
|
||||
/* Disable USB FS Clocks */
|
||||
__HAL_RCC_USB_OTG_FS_CLK_DISABLE();
|
||||
__HAL_RCC_SYSCFG_CLK_DISABLE();
|
||||
}
|
||||
#if defined(USE_USB_HS)
|
||||
else if(hpcd->Instance == USB_OTG_HS)
|
||||
#endif
|
||||
#if defined(USE_USB_HS)
|
||||
if(hpcd->Instance == USB_OTG_HS)
|
||||
{
|
||||
/* Disable USB FS Clocks */
|
||||
__HAL_RCC_USB_OTG_HS_CLK_DISABLE();
|
||||
__HAL_RCC_SYSCFG_CLK_DISABLE();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -440,6 +489,44 @@ USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_USB_HS) && !defined(USE_USB_HS_IN_FS) && defined STM32U5
|
||||
// Trezor T uses the OTG_HS peripheral
|
||||
if (pdev->id == USB_PHY_HS_ID) {
|
||||
/* Set LL Driver parameters */
|
||||
pcd_hs_handle.Instance = USB_OTG_HS;
|
||||
pcd_hs_handle.Init.dev_endpoints = 6;
|
||||
pcd_hs_handle.Init.use_dedicated_ep1 = 0;
|
||||
pcd_hs_handle.Init.ep0_mps = 0x40;
|
||||
pcd_hs_handle.Init.dma_enable = 0;
|
||||
pcd_hs_handle.Init.low_power_enable = 0;
|
||||
pcd_hs_handle.Init.phy_itface = USB_OTG_HS_EMBEDDED_PHY;
|
||||
pcd_hs_handle.Init.Sof_enable = 1;
|
||||
pcd_hs_handle.Init.speed = PCD_SPEED_HIGH;
|
||||
// Trezor T hardware has PB13 connected to HS_VBUS
|
||||
// but we leave vbus sensing disabled because
|
||||
// we don't use it for anything. the device is a bus powered peripheral.
|
||||
pcd_hs_handle.Init.vbus_sensing_enable = 0;
|
||||
/* Link The driver to the stack */
|
||||
pcd_hs_handle.pData = pdev;
|
||||
pdev->pData = &pcd_hs_handle;
|
||||
/* Initialize LL Driver */
|
||||
HAL_PCD_Init(&pcd_hs_handle);
|
||||
// the OTG_HS peripheral has a dedicated 4KiB data RAM from which we
|
||||
// allocate an area for each transmit FIFO and the single shared receive FIFO.
|
||||
// the configuration is in terms of 32-bit words, so we have 1024 32-bit words
|
||||
// in this dedicated 4KiB data RAM to use. see section 35.10.1 and 34.11 in RM0090.
|
||||
// the reference to section 34.11 is for the OTG_FS device, but the FIFO architecture
|
||||
// diagram seems to apply similarly to the FIFO in the OTG_HS that we are using.
|
||||
// USB packets that we deal with are 64 bytes in size which equates to 16 32-bit words.
|
||||
// we size the transmit FIFO's equally and give the rest of the space to the receive FIFO.
|
||||
const uint16_t transmit_fifo_size = 144; // 144 = 16 * 9 meaning that we give 9 packets of space for each transmit fifo
|
||||
const uint16_t receive_fifo_zie = 160; // 160 = 1024 - 6 * 144 section 35.10.1 details what some of this is used for besides storing packets
|
||||
HAL_PCDEx_SetRxFiFo(&pcd_hs_handle, receive_fifo_zie);
|
||||
for (uint16_t i = 0; i < 6; i++) {
|
||||
HAL_PCDEx_SetTxFiFo(&pcd_hs_handle, i, transmit_fifo_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_USB_HS_IN_FS)
|
||||
// Trezor T uses the OTG_HS peripheral
|
||||
if (pdev->id == USB_PHY_HS_ID) {
|
||||
@ -698,6 +785,7 @@ void OTG_HS_IRQHandler(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef STM32U5
|
||||
/**
|
||||
* @brief This function handles USB OTG Common FS/HS Wakeup functions.
|
||||
* @param *pcd_handle for FS or HS
|
||||
@ -763,5 +851,6 @@ void OTG_HS_WKUP_IRQHandler(void) {
|
||||
IRQ_EXIT(OTG_HS_WKUP_IRQn);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
@ -167,4 +167,16 @@ shutdown_privileged:
|
||||
ldr r0, =0
|
||||
b . // loop forever
|
||||
|
||||
.global MemManage_Handler
|
||||
.type MemManage_Handler, STT_FUNC
|
||||
MemManage_Handler:
|
||||
ldr r2, =_sstack
|
||||
mrs r1, msp
|
||||
ldr r0, =_estack
|
||||
msr msp, r0
|
||||
cmp r1, r2
|
||||
IT lt
|
||||
bllt MemManage_Handler_SO
|
||||
bl MemManage_Handler_MM
|
||||
|
||||
.end
|
||||
|
1
core/embed/trezorhal/stm32u5/board_capabilities.c
Symbolic link
1
core/embed/trezorhal/stm32u5/board_capabilities.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/board_capabilities.c
|
205
core/embed/trezorhal/stm32u5/common.c
Normal file
205
core/embed/trezorhal/stm32u5/common.c
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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 STM32_HAL_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "display.h"
|
||||
#include "secret.h"
|
||||
#include "terminal.h"
|
||||
#ifdef FANCY_FATAL_ERROR
|
||||
#include "rust_ui.h"
|
||||
#endif
|
||||
#include "flash.h"
|
||||
#include "model.h"
|
||||
#include "platform.h"
|
||||
#include "rand.h"
|
||||
#include "supervise.h"
|
||||
|
||||
#include "mini_printf.h"
|
||||
#include "stm32u5xx_ll_utils.h"
|
||||
|
||||
#ifdef RGB16
|
||||
#define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00)
|
||||
#else
|
||||
#define COLOR_FATAL_ERROR COLOR_BLACK
|
||||
#endif
|
||||
|
||||
uint32_t systick_val_copy = 0;
|
||||
|
||||
// from util.s
|
||||
extern void shutdown_privileged(void);
|
||||
|
||||
void __attribute__((noreturn)) trezor_shutdown(void) {
|
||||
__HAL_RCC_SAES_CLK_DISABLE();
|
||||
// Erase all secrets
|
||||
TAMP->CR2 |= TAMP_CR2_BKERASE;
|
||||
|
||||
#ifdef USE_SVC_SHUTDOWN
|
||||
svc_shutdown();
|
||||
#else
|
||||
// It won't work properly unless called from the privileged mode
|
||||
shutdown_privileged();
|
||||
#endif
|
||||
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
void __attribute__((noreturn))
|
||||
error_uni(const char *label, const char *msg, const char *footer) {
|
||||
display_orientation(0);
|
||||
|
||||
#ifdef FANCY_FATAL_ERROR
|
||||
|
||||
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
|
||||
display_refresh();
|
||||
#else
|
||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
||||
if (label) {
|
||||
term_printf("%s\n", label);
|
||||
}
|
||||
if (msg) {
|
||||
term_printf("%s\n", msg);
|
||||
}
|
||||
if (footer) {
|
||||
term_printf("\n%s\n", footer);
|
||||
}
|
||||
#endif
|
||||
display_backlight(255);
|
||||
display_refresh();
|
||||
trezor_shutdown();
|
||||
}
|
||||
|
||||
void __attribute__((noreturn))
|
||||
__fatal_error(const char *expr, const char *msg, const char *file, int line,
|
||||
const char *func) {
|
||||
display_orientation(0);
|
||||
display_backlight(255);
|
||||
|
||||
#ifdef FANCY_FATAL_ERROR
|
||||
char buf[256] = {0};
|
||||
mini_snprintf(buf, sizeof(buf), "%s: %d", file, line);
|
||||
screen_fatal_error_rust("INTERNAL ERROR", msg != NULL ? msg : buf,
|
||||
"PLEASE VISIT\nTREZOR.IO/RSOD");
|
||||
display_refresh();
|
||||
#else
|
||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
||||
term_printf("\nINTERNAL ERROR:\n");
|
||||
if (expr) {
|
||||
term_printf("expr: %s\n", expr);
|
||||
}
|
||||
if (msg) {
|
||||
term_printf("msg : %s\n", msg);
|
||||
}
|
||||
if (file) {
|
||||
term_printf("file: %s:%d\n", file, line);
|
||||
}
|
||||
if (func) {
|
||||
term_printf("func: %s\n", func);
|
||||
}
|
||||
#ifdef SCM_REVISION
|
||||
const uint8_t *rev = (const uint8_t *)SCM_REVISION;
|
||||
term_printf("rev : %02x%02x%02x%02x%02x\n", rev[0], rev[1], rev[2], rev[3],
|
||||
rev[4]);
|
||||
#endif
|
||||
term_printf("\nPlease contact Trezor support.\n");
|
||||
#endif
|
||||
trezor_shutdown();
|
||||
}
|
||||
|
||||
void __attribute__((noreturn))
|
||||
error_shutdown(const char *label, const char *msg) {
|
||||
display_orientation(0);
|
||||
|
||||
#ifdef FANCY_FATAL_ERROR
|
||||
|
||||
screen_fatal_error_rust(label, msg, "PLEASE VISIT\nTREZOR.IO/RSOD");
|
||||
display_refresh();
|
||||
#else
|
||||
term_set_color(COLOR_WHITE, COLOR_FATAL_ERROR);
|
||||
if (label) {
|
||||
term_printf("%s\n", label);
|
||||
}
|
||||
if (msg) {
|
||||
term_printf("%s\n", msg);
|
||||
}
|
||||
term_printf("\nPLEASE VISIT TREZOR.IO/RSOD\n");
|
||||
#endif
|
||||
display_backlight(255);
|
||||
trezor_shutdown();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void __assert_func(const char *file, int line, const char *func,
|
||||
const char *expr) {
|
||||
__fatal_error(expr, "assert failed", file, line, func);
|
||||
}
|
||||
#endif
|
||||
|
||||
void hal_delay(uint32_t ms) { HAL_Delay(ms); }
|
||||
uint32_t hal_ticks_ms() { return HAL_GetTick(); }
|
||||
|
||||
uint32_t __stack_chk_guard = 0;
|
||||
|
||||
void __attribute__((noreturn)) __stack_chk_fail(void) {
|
||||
error_shutdown("INTERNAL ERROR", "(SS)");
|
||||
}
|
||||
|
||||
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
|
||||
|
||||
void collect_hw_entropy(void) {
|
||||
// collect entropy from UUID
|
||||
uint32_t w = LL_GetUID_Word0();
|
||||
memcpy(HW_ENTROPY_DATA, &w, 4);
|
||||
w = LL_GetUID_Word1();
|
||||
memcpy(HW_ENTROPY_DATA + 4, &w, 4);
|
||||
w = LL_GetUID_Word2();
|
||||
memcpy(HW_ENTROPY_DATA + 8, &w, 4);
|
||||
|
||||
// set entropy in the OTP randomness block
|
||||
if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) {
|
||||
uint8_t entropy[FLASH_OTP_BLOCK_SIZE];
|
||||
random_buffer(entropy, FLASH_OTP_BLOCK_SIZE);
|
||||
ensure(flash_otp_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy,
|
||||
FLASH_OTP_BLOCK_SIZE),
|
||||
NULL);
|
||||
// ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL);
|
||||
}
|
||||
// collect entropy from OTP randomness block
|
||||
ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, HW_ENTROPY_DATA + 12,
|
||||
FLASH_OTP_BLOCK_SIZE),
|
||||
NULL);
|
||||
}
|
||||
|
||||
// this function resets settings changed in one layer (bootloader/firmware),
|
||||
// which might be incompatible with the other layers older versions,
|
||||
// where this setting might be unknown
|
||||
void ensure_compatible_settings(void) {}
|
||||
|
||||
void show_wipe_code_screen(void) {
|
||||
error_uni("WIPE CODE ENTERED", "All data has been erased from the device",
|
||||
"PLEASE RECONNECT\nTHE DEVICE");
|
||||
}
|
||||
void show_pin_too_many_screen(void) {
|
||||
error_uni("TOO MANY PIN ATTEMPTS", "All data has been erased from the device",
|
||||
"PLEASE RECONNECT\nTHE DEVICE");
|
||||
}
|
1
core/embed/trezorhal/stm32u5/dma2d.c
Symbolic link
1
core/embed/trezorhal/stm32u5/dma2d.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/dma2d.c
|
22
core/embed/trezorhal/stm32u5/fault_handlers.c
Normal file
22
core/embed/trezorhal/stm32u5/fault_handlers.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "common.h"
|
||||
|
||||
void HardFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(HF)"); }
|
||||
|
||||
void MemManage_Handler_MM(void) { error_shutdown("INTERNAL ERROR", "(MM)"); }
|
||||
|
||||
void MemManage_Handler_SO(void) { error_shutdown("INTERNAL ERROR", "(SO)"); }
|
||||
|
||||
void BusFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(BF)"); }
|
||||
|
||||
void UsageFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(UF)"); }
|
||||
|
||||
void SecureFault_Handler(void) { error_shutdown("INTERNAL ERROR", "(SF)"); }
|
||||
|
||||
void GTZC_IRQHandler(void) { error_shutdown("INTERNAL ERROR", "(IA)"); }
|
||||
|
||||
void NMI_Handler(void) {
|
||||
// Clock Security System triggered NMI
|
||||
if ((RCC->CIFR & RCC_CIFR_CSSF) != 0) {
|
||||
error_shutdown("INTERNAL ERROR", "(CS)");
|
||||
}
|
||||
}
|
567
core/embed/trezorhal/stm32u5/flash.c
Normal file
567
core/embed/trezorhal/stm32u5/flash.c
Normal file
@ -0,0 +1,567 @@
|
||||
/*
|
||||
* 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 STM32_HAL_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "flash.h"
|
||||
#include "model.h"
|
||||
|
||||
#define FLASH_SEC_START_ADDRESS 0x0C000000
|
||||
#define FLASH_START_ADDRESS 0x08000000
|
||||
|
||||
#define FLASH_SECTOR_COUNT (256 * 2)
|
||||
|
||||
#define FLASH_STATUS_ALL_FLAGS \
|
||||
(FLASH_NSSR_PGSERR | FLASH_NSSR_PGAERR | FLASH_NSSR_WRPERR | FLASH_NSSR_EOP)
|
||||
|
||||
uint32_t flash_wait_and_clear_status_flags(void) {
|
||||
while (FLASH->NSSR & FLASH_NSSR_BSY)
|
||||
; // wait for all previous flash operations to complete
|
||||
|
||||
uint32_t result =
|
||||
FLASH->NSSR & FLASH_STATUS_ALL_FLAGS; // get the current status flags
|
||||
FLASH->NSSR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
|
||||
|
||||
#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||
while (FLASH->SECSR & FLASH_SECSR_BSY)
|
||||
; // wait for all previous flash operations to complete
|
||||
result |=
|
||||
FLASH->SECSR & FLASH_STATUS_ALL_FLAGS; // get the current status flags
|
||||
FLASH->SECSR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
secbool flash_unlock_write(void) {
|
||||
HAL_FLASH_Unlock();
|
||||
FLASH->NSSR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
|
||||
#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||
FLASH->SECSR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
|
||||
#endif
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_lock_write(void) {
|
||||
HAL_FLASH_Lock();
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size,
|
||||
bool secure_area) {
|
||||
if (sector >= FLASH_SECTOR_COUNT) {
|
||||
return NULL;
|
||||
}
|
||||
uint32_t base_addr = FLASH_START_ADDRESS;
|
||||
|
||||
if (secure_area) {
|
||||
base_addr = FLASH_SEC_START_ADDRESS;
|
||||
}
|
||||
|
||||
const uint32_t addr = base_addr + (FLASH_PAGE_SIZE * sector) + offset;
|
||||
const uint32_t next = base_addr + (FLASH_PAGE_SIZE * (sector + 1));
|
||||
if (addr + size > next) {
|
||||
return NULL;
|
||||
}
|
||||
return (const void *)addr;
|
||||
}
|
||||
|
||||
uint32_t flash_sector_size(uint16_t sector) {
|
||||
if (sector >= FLASH_SECTOR_COUNT) {
|
||||
return 0;
|
||||
}
|
||||
return FLASH_PAGE_SIZE;
|
||||
}
|
||||
|
||||
uint32_t flash_subarea_get_size(const flash_subarea_t *sub) {
|
||||
return FLASH_PAGE_SIZE * sub->num_sectors;
|
||||
}
|
||||
|
||||
uint32_t flash_area_get_size(const flash_area_t *area) {
|
||||
uint32_t size = 0;
|
||||
for (int i = 0; i < area->num_subareas; i++) {
|
||||
size += flash_subarea_get_size(&area->subarea[i]);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
uint16_t flash_total_sectors(const flash_area_t *area) {
|
||||
uint16_t total = 0;
|
||||
for (int i = 0; i < area->num_subareas; i++) {
|
||||
total += area->subarea[i].num_sectors;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
const void *flash_area_get_address(const flash_area_t *area, uint32_t offset,
|
||||
uint32_t size) {
|
||||
uint32_t tmp_offset = offset;
|
||||
|
||||
for (int i = 0; i < area->num_subareas; i++) {
|
||||
uint16_t sector = area->subarea[i].first_sector;
|
||||
|
||||
if (tmp_offset >= flash_subarea_get_size(area->subarea)) {
|
||||
tmp_offset -= flash_subarea_get_size(area->subarea);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t base_addr = FLASH_START_ADDRESS;
|
||||
|
||||
if (area->secure_area) {
|
||||
base_addr = FLASH_SEC_START_ADDRESS;
|
||||
}
|
||||
|
||||
const uint32_t addr = base_addr + (FLASH_PAGE_SIZE * sector) + tmp_offset;
|
||||
const uint32_t area_end =
|
||||
base_addr + (FLASH_PAGE_SIZE * (area->subarea[i].first_sector +
|
||||
area->subarea[i].num_sectors));
|
||||
if (addr + size > area_end) {
|
||||
return NULL;
|
||||
}
|
||||
return (const void *)addr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t flash_get_sector_num(const flash_area_t *area,
|
||||
uint32_t sector_inner_num) {
|
||||
uint16_t sector = 0;
|
||||
uint16_t remaining = sector_inner_num;
|
||||
for (int i = 0; i < area->num_subareas; i++) {
|
||||
if (remaining < area->subarea[i].num_sectors) {
|
||||
sector = area->subarea[i].first_sector + remaining;
|
||||
return sector;
|
||||
} else {
|
||||
remaining -= area->subarea[i].num_sectors;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
secbool flash_area_erase(const flash_area_t *area,
|
||||
void (*progress)(int pos, int len)) {
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
FLASH_EraseInitTypeDef EraseInitStruct;
|
||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
EraseInitStruct.NbPages = 1;
|
||||
|
||||
int total_pages = 0;
|
||||
int done_pages = 0;
|
||||
for (int i = 0; i < area->num_subareas; i++) {
|
||||
total_pages += area->subarea[i].num_sectors;
|
||||
}
|
||||
|
||||
if (progress) {
|
||||
progress(0, total_pages);
|
||||
}
|
||||
|
||||
for (int s = 0; s < area->num_subareas; s++) {
|
||||
for (int i = 0; i < area->subarea[s].num_sectors; i++) {
|
||||
int page = area->subarea[s].first_sector + i;
|
||||
uint32_t sec_start = 0;
|
||||
uint32_t sec_end = 0;
|
||||
uint32_t page_idx = 0;
|
||||
bool secure = area->secure_area;
|
||||
if (page >= 256) {
|
||||
EraseInitStruct.Banks = FLASH_BANK_2;
|
||||
page_idx = page - 256;
|
||||
sec_start = (FLASH->SECWM2R1 & FLASH_SECWM1R1_SECWM1_PSTRT) >>
|
||||
FLASH_SECWM1R1_SECWM1_PSTRT_Pos;
|
||||
sec_end = (FLASH->SECWM2R1 & FLASH_SECWM1R1_SECWM1_PEND) >>
|
||||
FLASH_SECWM1R1_SECWM1_PEND_Pos;
|
||||
} else {
|
||||
EraseInitStruct.Banks = FLASH_BANK_1;
|
||||
page_idx = page;
|
||||
sec_start = (FLASH->SECWM1R1 & FLASH_SECWM1R1_SECWM1_PSTRT) >>
|
||||
FLASH_SECWM1R1_SECWM1_PSTRT_Pos;
|
||||
sec_end = (FLASH->SECWM1R1 & FLASH_SECWM1R1_SECWM1_PEND) >>
|
||||
FLASH_SECWM1R1_SECWM1_PEND_Pos;
|
||||
}
|
||||
|
||||
if (page_idx < sec_start || page_idx > sec_end) {
|
||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES_NS;
|
||||
secure = false;
|
||||
} else {
|
||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
}
|
||||
|
||||
EraseInitStruct.Page = page_idx;
|
||||
uint32_t SectorError;
|
||||
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return secfalse;
|
||||
}
|
||||
// check whether the sector was really deleted (contains only 0xFF)
|
||||
const uint32_t addr_start =
|
||||
(uint32_t)flash_get_address(page, 0, 0, secure);
|
||||
const uint32_t addr_end =
|
||||
(uint32_t)flash_get_address(page + 1, 0, 0, secure);
|
||||
|
||||
for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
|
||||
if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
done_pages++;
|
||||
if (progress && done_pages % 16 == 0) {
|
||||
progress(done_pages, total_pages);
|
||||
}
|
||||
}
|
||||
}
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_area_erase_bulk(const flash_area_t *areas, int count,
|
||||
void (*progress)(int pos, int len)) {
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
FLASH_EraseInitTypeDef EraseInitStruct;
|
||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
EraseInitStruct.NbPages = 1;
|
||||
|
||||
int total_pages = 0;
|
||||
int done_pages = 0;
|
||||
for (int c = 0; c < count; c++) {
|
||||
for (int i = 0; i < areas[c].num_subareas; i++) {
|
||||
total_pages += areas[c].subarea[i].num_sectors;
|
||||
}
|
||||
}
|
||||
|
||||
if (progress) {
|
||||
progress(0, total_pages);
|
||||
}
|
||||
|
||||
for (int c = 0; c < count; c++) {
|
||||
for (int s = 0; s < areas[c].num_subareas; s++) {
|
||||
for (int i = 0; i < areas[c].subarea[s].num_sectors; i++) {
|
||||
int page = areas[c].subarea[s].first_sector + i;
|
||||
if (page >= 256) {
|
||||
EraseInitStruct.Banks = FLASH_BANK_2;
|
||||
} else {
|
||||
EraseInitStruct.Banks = FLASH_BANK_1;
|
||||
}
|
||||
EraseInitStruct.Page = page;
|
||||
uint32_t SectorError;
|
||||
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return secfalse;
|
||||
}
|
||||
// check whether the sector was really deleted (contains only 0xFF)
|
||||
const uint32_t addr_start =
|
||||
(uint32_t)flash_get_address(page, 0, 0, areas[c].secure_area);
|
||||
const uint32_t addr_end =
|
||||
(uint32_t)flash_get_address(page + 1, 0, 0, areas[c].secure_area);
|
||||
|
||||
for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
|
||||
if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
done_pages++;
|
||||
if (progress) {
|
||||
progress(done_pages, total_pages);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_area_erase_partial(const flash_area_t *area, uint32_t offset,
|
||||
uint32_t *bytes_erased) {
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
FLASH_EraseInitTypeDef EraseInitStruct;
|
||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
EraseInitStruct.NbPages = 1;
|
||||
|
||||
*bytes_erased = 0;
|
||||
int32_t page = flash_get_sector_num(area, offset / FLASH_PAGE_SIZE);
|
||||
|
||||
if (page >= 0 && page < FLASH_SECTOR_COUNT) {
|
||||
uint32_t sec_start = 0;
|
||||
uint32_t sec_end = 0;
|
||||
uint32_t page_idx = 0;
|
||||
bool secure = area->secure_area;
|
||||
if (page >= 256) {
|
||||
EraseInitStruct.Banks = FLASH_BANK_2;
|
||||
page_idx = page - 256;
|
||||
sec_start = (FLASH->SECWM2R1 & FLASH_SECWM1R1_SECWM1_PSTRT) >>
|
||||
FLASH_SECWM1R1_SECWM1_PSTRT_Pos;
|
||||
sec_end = (FLASH->SECWM2R1 & FLASH_SECWM1R1_SECWM1_PEND) >>
|
||||
FLASH_SECWM1R1_SECWM1_PEND_Pos;
|
||||
} else {
|
||||
EraseInitStruct.Banks = FLASH_BANK_1;
|
||||
page_idx = page;
|
||||
sec_start = (FLASH->SECWM1R1 & FLASH_SECWM1R1_SECWM1_PSTRT) >>
|
||||
FLASH_SECWM1R1_SECWM1_PSTRT_Pos;
|
||||
sec_end = (FLASH->SECWM1R1 & FLASH_SECWM1R1_SECWM1_PEND) >>
|
||||
FLASH_SECWM1R1_SECWM1_PEND_Pos;
|
||||
}
|
||||
|
||||
if (page_idx < sec_start || page_idx > sec_end) {
|
||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES_NS;
|
||||
secure = false;
|
||||
} else {
|
||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
}
|
||||
|
||||
EraseInitStruct.Page = page_idx;
|
||||
uint32_t SectorError;
|
||||
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return secfalse;
|
||||
}
|
||||
// check whether the sector was really deleted (contains only 0xFF)
|
||||
const uint32_t addr_start = (uint32_t)flash_get_address(page, 0, 0, secure);
|
||||
const uint32_t addr_end =
|
||||
(uint32_t)flash_get_address(page + 1, 0, 0, secure);
|
||||
|
||||
for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
|
||||
if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
ensure(flash_lock_write(), NULL);
|
||||
*bytes_erased = FLASH_PAGE_SIZE;
|
||||
return sectrue;
|
||||
}
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_write_quadword(uint16_t sector, uint32_t offset,
|
||||
const uint32_t *data, bool secure_area) {
|
||||
uint32_t address = (uint32_t)flash_get_address(
|
||||
sector, offset, 4 * sizeof(uint32_t), secure_area);
|
||||
if (address == 0) {
|
||||
return secfalse;
|
||||
}
|
||||
if (offset % (4 * sizeof(uint32_t))) { // we write only at 16-byte boundary
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (data[i] != (data[i] & *((const uint32_t *)address + i))) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
|
||||
secbool all_match = sectrue;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (data[i] != *((const uint32_t *)address + i)) {
|
||||
all_match = secfalse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all_match == sectrue) {
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
if (HAL_OK !=
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, address, (uint32_t)data)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (data[i] != *((const uint32_t *)address + i)) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_write_burst(uint16_t sector, uint32_t offset,
|
||||
const uint32_t *data, bool secure_area) {
|
||||
uint32_t address = (uint32_t)flash_get_address(
|
||||
sector, offset, 8 * 4 * sizeof(uint32_t), secure_area);
|
||||
if (address == 0) {
|
||||
return secfalse;
|
||||
}
|
||||
if (offset %
|
||||
(8 * 4 * sizeof(uint32_t))) { // we write only at 16-byte boundary
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8 * 4; i++) {
|
||||
if (data[i] != (data[i] & *((const uint32_t *)address + i))) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
|
||||
secbool all_match = sectrue;
|
||||
for (int i = 0; i < 8 * 4; i++) {
|
||||
if (data[i] != *((const uint32_t *)address + i)) {
|
||||
all_match = secfalse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all_match == sectrue) {
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
if (HAL_OK !=
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_BURST, address, (uint32_t)data)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8 * 4; i++) {
|
||||
if (data[i] != *((const uint32_t *)address + i)) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_area_write_quadword(const flash_area_t *area, uint32_t offset,
|
||||
const uint32_t *data) {
|
||||
uint32_t tmp_offset = offset;
|
||||
for (int i = 0; i < area->num_subareas; i++) {
|
||||
uint16_t sector = area->subarea[i].first_sector;
|
||||
|
||||
uint32_t sub_size = flash_subarea_get_size(&area->subarea[i]);
|
||||
if (tmp_offset >= sub_size) {
|
||||
tmp_offset -= sub_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
// in correct subarea
|
||||
for (int s = 0; s < area->subarea[i].num_sectors; s++) {
|
||||
const uint32_t sector_size = flash_sector_size(sector);
|
||||
if (tmp_offset >= sector_size) {
|
||||
tmp_offset -= sector_size;
|
||||
sector++;
|
||||
|
||||
if (s == area->subarea[i].num_sectors - 1) {
|
||||
return secfalse;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// in correct sector
|
||||
return flash_write_quadword(sector, tmp_offset, data, area->secure_area);
|
||||
}
|
||||
}
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
secbool flash_area_write_burst(const flash_area_t *area, uint32_t offset,
|
||||
const uint32_t *data) {
|
||||
uint32_t tmp_offset = offset;
|
||||
for (int i = 0; i < area->num_subareas; i++) {
|
||||
uint16_t sector = area->subarea[i].first_sector;
|
||||
|
||||
uint32_t sub_size = flash_subarea_get_size(&area->subarea[i]);
|
||||
if (tmp_offset >= sub_size) {
|
||||
tmp_offset -= sub_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
// in correct subarea
|
||||
for (int s = 0; s < area->subarea[i].num_sectors; s++) {
|
||||
const uint32_t sector_size = flash_sector_size(sector);
|
||||
if (tmp_offset >= sector_size) {
|
||||
tmp_offset -= sector_size;
|
||||
sector++;
|
||||
|
||||
if (s == area->subarea[i].num_sectors - 1) {
|
||||
return secfalse;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// in correct sector
|
||||
return flash_write_burst(sector, tmp_offset, data, area->secure_area);
|
||||
}
|
||||
}
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
|
||||
uint8_t datalen) {
|
||||
if (block >= FLASH_OTP_NUM_BLOCKS ||
|
||||
offset + datalen > FLASH_OTP_BLOCK_SIZE) {
|
||||
return secfalse;
|
||||
}
|
||||
for (uint8_t i = 0; i < datalen; i++) {
|
||||
data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE +
|
||||
offset + i);
|
||||
}
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data,
|
||||
uint8_t datalen) {
|
||||
if (datalen % 16 != 0) {
|
||||
return secfalse;
|
||||
}
|
||||
if (block >= FLASH_OTP_NUM_BLOCKS ||
|
||||
offset + datalen > FLASH_OTP_BLOCK_SIZE) {
|
||||
return secfalse;
|
||||
}
|
||||
ensure(flash_unlock_write(), NULL);
|
||||
for (uint8_t i = 0; i < datalen; i++) {
|
||||
uint32_t address =
|
||||
FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i;
|
||||
ensure(sectrue * (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD,
|
||||
address, (uint32_t)data)),
|
||||
NULL);
|
||||
}
|
||||
ensure(flash_lock_write(), NULL);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_otp_lock(uint8_t block) {
|
||||
// check that all quadwords in the block have been written to
|
||||
volatile uint8_t *addr =
|
||||
(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE);
|
||||
|
||||
secbool qw_locked = secfalse;
|
||||
for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) {
|
||||
if (addr[i] != 0xFF) {
|
||||
qw_locked = sectrue;
|
||||
}
|
||||
if (i % 16 == 15 && qw_locked == secfalse) {
|
||||
return secfalse;
|
||||
}
|
||||
}
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool flash_otp_is_locked(uint8_t block) {
|
||||
// considering block locked if any quadword in the block is non-0xFF
|
||||
volatile uint8_t *addr =
|
||||
(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE);
|
||||
|
||||
for (uint8_t i = 0; i < FLASH_OTP_BLOCK_SIZE; i++) {
|
||||
if (addr[i] != 0xFF) {
|
||||
return sectrue;
|
||||
}
|
||||
}
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
secbool flash_write_block(uint16_t sector, uint32_t offset,
|
||||
const flash_block_t block) {
|
||||
return flash_write_quadword(sector, offset, block);
|
||||
}
|
441
core/embed/trezorhal/stm32u5/i2c.c
Normal file
441
core/embed/trezorhal/stm32u5/i2c.c
Normal file
@ -0,0 +1,441 @@
|
||||
|
||||
|
||||
#include STM32_HAL_H
|
||||
#include TREZOR_BOARD
|
||||
#include "i2c.h"
|
||||
#include "common.h"
|
||||
|
||||
static I2C_HandleTypeDef i2c_handle[I2C_COUNT];
|
||||
|
||||
typedef struct {
|
||||
I2C_TypeDef *Instance;
|
||||
GPIO_TypeDef *SclPort;
|
||||
GPIO_TypeDef *SdaPort;
|
||||
uint16_t SclPin;
|
||||
uint16_t SdaPin;
|
||||
uint8_t PinAF;
|
||||
volatile uint32_t *ResetReg;
|
||||
uint32_t ResetBit;
|
||||
} i2c_instance_t;
|
||||
|
||||
i2c_instance_t i2c_defs[I2C_COUNT] = {
|
||||
{
|
||||
.Instance = I2C_INSTANCE_1,
|
||||
.SclPort = I2C_INSTANCE_1_SCL_PORT,
|
||||
.SdaPort = I2C_INSTANCE_1_SDA_PORT,
|
||||
.SclPin = I2C_INSTANCE_1_SCL_PIN,
|
||||
.SdaPin = I2C_INSTANCE_1_SDA_PIN,
|
||||
.PinAF = I2C_INSTANCE_1_PIN_AF,
|
||||
.ResetReg = I2C_INSTANCE_1_RESET_REG,
|
||||
.ResetBit = I2C_INSTANCE_1_RESET_BIT,
|
||||
},
|
||||
#ifdef I2C_INSTANCE_2
|
||||
{
|
||||
.Instance = I2C_INSTANCE_2,
|
||||
.SclPort = I2C_INSTANCE_2_SCL_PORT,
|
||||
.SdaPort = I2C_INSTANCE_2_SDA_PORT,
|
||||
.SclPin = I2C_INSTANCE_2_SCL_PIN,
|
||||
.SdaPin = I2C_INSTANCE_2_SDA_PIN,
|
||||
.PinAF = I2C_INSTANCE_2_PIN_AF,
|
||||
.ResetReg = I2C_INSTANCE_2_RESET_REG,
|
||||
.ResetBit = I2C_INSTANCE_2_RESET_BIT,
|
||||
},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#ifndef I2C_VALID_TIMING_NBR
|
||||
#define I2C_VALID_TIMING_NBR 128U
|
||||
#endif /* I2C_VALID_TIMING_NBR */
|
||||
|
||||
#define I2C_SPEED_FREQ_STANDARD 0U /* 100 kHz */
|
||||
#define I2C_SPEED_FREQ_FAST 1U /* 400 kHz */
|
||||
#define I2C_SPEED_FREQ_FAST_PLUS 2U /* 1 MHz */
|
||||
#define I2C_ANALOG_FILTER_DELAY_MIN 50U /* ns */
|
||||
#define I2C_ANALOG_FILTER_DELAY_MAX 260U /* ns */
|
||||
#define I2C_USE_ANALOG_FILTER 1U
|
||||
#define I2C_DIGITAL_FILTER_COEF 0U
|
||||
#define I2C_PRESC_MAX 16U
|
||||
#define I2C_SCLDEL_MAX 16U
|
||||
#define I2C_SDADEL_MAX 16U
|
||||
#define I2C_SCLH_MAX 256U
|
||||
#define I2C_SCLL_MAX 256U
|
||||
#define SEC2NSEC 1000000000UL
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup STM32U5x9J_DISCOVERY_BUS_Private_Types BUS Private Types
|
||||
* @{
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t freq; /* Frequency in Hz */
|
||||
uint32_t freq_min; /* Minimum frequency in Hz */
|
||||
uint32_t freq_max; /* Maximum frequency in Hz */
|
||||
uint32_t hddat_min; /* Minimum data hold time in ns */
|
||||
uint32_t vddat_max; /* Maximum data valid time in ns */
|
||||
uint32_t sudat_min; /* Minimum data setup time in ns */
|
||||
uint32_t lscl_min; /* Minimum low period of the SCL clock in ns */
|
||||
uint32_t hscl_min; /* Minimum high period of SCL clock in ns */
|
||||
uint32_t trise; /* Rise time in ns */
|
||||
uint32_t tfall; /* Fall time in ns */
|
||||
uint32_t dnf; /* Digital noise filter coefficient */
|
||||
} I2C_Charac_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t presc; /* Timing prescaler */
|
||||
uint32_t tscldel; /* SCL delay */
|
||||
uint32_t tsdadel; /* SDA delay */
|
||||
uint32_t sclh; /* SCL high period */
|
||||
uint32_t scll; /* SCL low period */
|
||||
} I2C_Timings_t;
|
||||
|
||||
static I2C_Timings_t I2c_valid_timing[I2C_VALID_TIMING_NBR];
|
||||
static uint32_t I2c_valid_timing_nbr = 0;
|
||||
|
||||
static const I2C_Charac_t I2C_Charac[] = {
|
||||
[I2C_SPEED_FREQ_STANDARD] =
|
||||
{
|
||||
.freq = 100000,
|
||||
.freq_min = 80000,
|
||||
.freq_max = 120000,
|
||||
.hddat_min = 0,
|
||||
.vddat_max = 3450,
|
||||
.sudat_min = 250,
|
||||
.lscl_min = 4700,
|
||||
.hscl_min = 4000,
|
||||
.trise = 640,
|
||||
.tfall = 20,
|
||||
.dnf = I2C_DIGITAL_FILTER_COEF,
|
||||
},
|
||||
[I2C_SPEED_FREQ_FAST] =
|
||||
{
|
||||
.freq = 400000,
|
||||
.freq_min = 320000,
|
||||
.freq_max = 480000,
|
||||
.hddat_min = 0,
|
||||
.vddat_max = 900,
|
||||
.sudat_min = 100,
|
||||
.lscl_min = 1300,
|
||||
.hscl_min = 600,
|
||||
.trise = 250,
|
||||
.tfall = 100,
|
||||
.dnf = I2C_DIGITAL_FILTER_COEF,
|
||||
},
|
||||
[I2C_SPEED_FREQ_FAST_PLUS] =
|
||||
{
|
||||
.freq = 1000000,
|
||||
.freq_min = 800000,
|
||||
.freq_max = 1200000,
|
||||
.hddat_min = 0,
|
||||
.vddat_max = 450,
|
||||
.sudat_min = 50,
|
||||
.lscl_min = 500,
|
||||
.hscl_min = 260,
|
||||
.trise = 60,
|
||||
.tfall = 100,
|
||||
.dnf = I2C_DIGITAL_FILTER_COEF,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Compute PRESC, SCLDEL and SDADEL.
|
||||
* @param clock_src_freq I2C source clock in HZ.
|
||||
* @param I2C_speed I2C frequency (index).
|
||||
* @retval None.
|
||||
*/
|
||||
static void I2C_Compute_PRESC_SCLDEL_SDADEL(uint32_t clock_src_freq,
|
||||
uint32_t I2C_speed) {
|
||||
uint32_t prev_presc = I2C_PRESC_MAX;
|
||||
uint32_t ti2cclk;
|
||||
int32_t tsdadel_min;
|
||||
int32_t tsdadel_max;
|
||||
int32_t tscldel_min;
|
||||
uint32_t presc;
|
||||
uint32_t scldel;
|
||||
uint32_t sdadel;
|
||||
uint32_t tafdel_min;
|
||||
uint32_t tafdel_max;
|
||||
ti2cclk = (SEC2NSEC + (clock_src_freq / 2U)) / clock_src_freq;
|
||||
|
||||
tafdel_min = I2C_ANALOG_FILTER_DELAY_MIN;
|
||||
tafdel_max = I2C_ANALOG_FILTER_DELAY_MAX;
|
||||
|
||||
/* tDNF = DNF x tI2CCLK
|
||||
tPRESC = (PRESC+1) x tI2CCLK
|
||||
SDADEL >= {tf +tHD;DAT(min) - tAF(min) - tDNF - [3 x tI2CCLK]} / {tPRESC}
|
||||
SDADEL <= {tVD;DAT(max) - tr - tAF(max) - tDNF- [4 x tI2CCLK]} / {tPRESC}
|
||||
*/
|
||||
|
||||
tsdadel_min =
|
||||
(int32_t)I2C_Charac[I2C_speed].tfall +
|
||||
(int32_t)I2C_Charac[I2C_speed].hddat_min - (int32_t)tafdel_min -
|
||||
(int32_t)(((int32_t)I2C_Charac[I2C_speed].dnf + 3) * (int32_t)ti2cclk);
|
||||
|
||||
tsdadel_max =
|
||||
(int32_t)I2C_Charac[I2C_speed].vddat_max -
|
||||
(int32_t)I2C_Charac[I2C_speed].trise - (int32_t)tafdel_max -
|
||||
(int32_t)(((int32_t)I2C_Charac[I2C_speed].dnf + 4) * (int32_t)ti2cclk);
|
||||
|
||||
/* {[tr+ tSU;DAT(min)] / [tPRESC]} - 1 <= SCLDEL */
|
||||
tscldel_min = (int32_t)I2C_Charac[I2C_speed].trise +
|
||||
(int32_t)I2C_Charac[I2C_speed].sudat_min;
|
||||
|
||||
if (tsdadel_min <= 0) {
|
||||
tsdadel_min = 0;
|
||||
}
|
||||
|
||||
if (tsdadel_max <= 0) {
|
||||
tsdadel_max = 0;
|
||||
}
|
||||
|
||||
for (presc = 0; presc < I2C_PRESC_MAX; presc++) {
|
||||
for (scldel = 0; scldel < I2C_SCLDEL_MAX; scldel++) {
|
||||
/* TSCLDEL = (SCLDEL+1) * (PRESC+1) * TI2CCLK */
|
||||
uint32_t tscldel = (scldel + 1U) * (presc + 1U) * ti2cclk;
|
||||
|
||||
if (tscldel >= (uint32_t)tscldel_min) {
|
||||
for (sdadel = 0; sdadel < I2C_SDADEL_MAX; sdadel++) {
|
||||
/* TSDADEL = SDADEL * (PRESC+1) * TI2CCLK */
|
||||
uint32_t tsdadel = (sdadel * (presc + 1U)) * ti2cclk;
|
||||
|
||||
if ((tsdadel >= (uint32_t)tsdadel_min) &&
|
||||
(tsdadel <= (uint32_t)tsdadel_max)) {
|
||||
if (presc != prev_presc) {
|
||||
I2c_valid_timing[I2c_valid_timing_nbr].presc = presc;
|
||||
I2c_valid_timing[I2c_valid_timing_nbr].tscldel = scldel;
|
||||
I2c_valid_timing[I2c_valid_timing_nbr].tsdadel = sdadel;
|
||||
prev_presc = presc;
|
||||
I2c_valid_timing_nbr++;
|
||||
|
||||
if (I2c_valid_timing_nbr >= I2C_VALID_TIMING_NBR) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate SCLL and SCLH and find best configuration.
|
||||
* @param clock_src_freq I2C source clock in HZ.
|
||||
* @param I2C_speed I2C frequency (index).
|
||||
* @retval config index (0 to I2C_VALID_TIMING_NBR], 0xFFFFFFFF for no valid
|
||||
* config.
|
||||
*/
|
||||
static uint32_t I2C_Compute_SCLL_SCLH(uint32_t clock_src_freq,
|
||||
uint32_t I2C_speed) {
|
||||
uint32_t ret = 0xFFFFFFFFU;
|
||||
uint32_t ti2cclk;
|
||||
uint32_t ti2cspeed;
|
||||
uint32_t prev_error;
|
||||
uint32_t dnf_delay;
|
||||
uint32_t clk_min;
|
||||
uint32_t clk_max;
|
||||
uint32_t scll;
|
||||
uint32_t sclh;
|
||||
uint32_t tafdel_min;
|
||||
|
||||
ti2cclk = (SEC2NSEC + (clock_src_freq / 2U)) / clock_src_freq;
|
||||
ti2cspeed = (SEC2NSEC + (I2C_Charac[I2C_speed].freq / 2U)) /
|
||||
I2C_Charac[I2C_speed].freq;
|
||||
|
||||
tafdel_min = I2C_ANALOG_FILTER_DELAY_MIN;
|
||||
|
||||
/* tDNF = DNF x tI2CCLK */
|
||||
dnf_delay = I2C_Charac[I2C_speed].dnf * ti2cclk;
|
||||
|
||||
clk_max = SEC2NSEC / I2C_Charac[I2C_speed].freq_min;
|
||||
clk_min = SEC2NSEC / I2C_Charac[I2C_speed].freq_max;
|
||||
|
||||
prev_error = ti2cspeed;
|
||||
|
||||
for (uint32_t count = 0; count < I2c_valid_timing_nbr; count++) {
|
||||
/* tPRESC = (PRESC+1) x tI2CCLK*/
|
||||
uint32_t tpresc = (I2c_valid_timing[count].presc + 1U) * ti2cclk;
|
||||
|
||||
for (scll = 0; scll < I2C_SCLL_MAX; scll++) {
|
||||
/* tLOW(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLL+1) x tPRESC ] */
|
||||
uint32_t tscl_l =
|
||||
tafdel_min + dnf_delay + (2U * ti2cclk) + ((scll + 1U) * tpresc);
|
||||
|
||||
/* The I2CCLK period tI2CCLK must respect the following conditions:
|
||||
tI2CCLK < (tLOW - tfilters) / 4 and tI2CCLK < tHIGH */
|
||||
if ((tscl_l > I2C_Charac[I2C_speed].lscl_min) &&
|
||||
(ti2cclk < ((tscl_l - tafdel_min - dnf_delay) / 4U))) {
|
||||
for (sclh = 0; sclh < I2C_SCLH_MAX; sclh++) {
|
||||
/* tHIGH(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLH+1) x tPRESC]
|
||||
*/
|
||||
uint32_t tscl_h =
|
||||
tafdel_min + dnf_delay + (2U * ti2cclk) + ((sclh + 1U) * tpresc);
|
||||
|
||||
/* tSCL = tf + tLOW + tr + tHIGH */
|
||||
uint32_t tscl = tscl_l + tscl_h + I2C_Charac[I2C_speed].trise +
|
||||
I2C_Charac[I2C_speed].tfall;
|
||||
|
||||
if ((tscl >= clk_min) && (tscl <= clk_max) &&
|
||||
(tscl_h >= I2C_Charac[I2C_speed].hscl_min) &&
|
||||
(ti2cclk < tscl_h)) {
|
||||
int32_t error = (int32_t)tscl - (int32_t)ti2cspeed;
|
||||
|
||||
if (error < 0) {
|
||||
error = -error;
|
||||
}
|
||||
|
||||
/* look for the timings with the lowest clock error */
|
||||
if ((uint32_t)error < prev_error) {
|
||||
prev_error = (uint32_t)error;
|
||||
I2c_valid_timing[count].scll = scll;
|
||||
I2c_valid_timing[count].sclh = sclh;
|
||||
ret = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Compute I2C timing according current I2C clock source and required
|
||||
* I2C clock.
|
||||
* @param clock_src_freq I2C clock source in Hz.
|
||||
* @param i2c_freq Required I2C clock in Hz.
|
||||
* @retval I2C timing or 0 in case of error.
|
||||
*/
|
||||
static uint32_t I2C_GetTiming(uint32_t clock_src_freq, uint32_t i2c_freq) {
|
||||
uint32_t ret = 0;
|
||||
uint32_t speed;
|
||||
uint32_t idx;
|
||||
|
||||
if ((clock_src_freq != 0U) && (i2c_freq != 0U)) {
|
||||
for (speed = 0; speed <= (uint32_t)I2C_SPEED_FREQ_FAST_PLUS; speed++) {
|
||||
if ((i2c_freq >= I2C_Charac[speed].freq_min) &&
|
||||
(i2c_freq <= I2C_Charac[speed].freq_max)) {
|
||||
I2C_Compute_PRESC_SCLDEL_SDADEL(clock_src_freq, speed);
|
||||
idx = I2C_Compute_SCLL_SCLH(clock_src_freq, speed);
|
||||
|
||||
if (idx < I2C_VALID_TIMING_NBR) {
|
||||
ret = ((I2c_valid_timing[idx].presc & 0x0FU) << 28) |
|
||||
((I2c_valid_timing[idx].tscldel & 0x0FU) << 20) |
|
||||
((I2c_valid_timing[idx].tsdadel & 0x0FU) << 16) |
|
||||
((I2c_valid_timing[idx].sclh & 0xFFU) << 8) |
|
||||
((I2c_valid_timing[idx].scll & 0xFFU) << 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void i2c_init_instance(uint16_t idx, i2c_instance_t *instance) {
|
||||
if (i2c_handle[idx].Instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
// configure CTP I2C SCL and SDA GPIO lines
|
||||
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStructure.Speed =
|
||||
GPIO_SPEED_FREQ_LOW; // I2C is a KHz bus and low speed is still good into
|
||||
// the low MHz
|
||||
|
||||
GPIO_InitStructure.Alternate = instance->PinAF;
|
||||
GPIO_InitStructure.Pin = instance->SclPin;
|
||||
HAL_GPIO_Init(instance->SclPort, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.Alternate = instance->PinAF;
|
||||
GPIO_InitStructure.Pin = instance->SdaPin;
|
||||
HAL_GPIO_Init(instance->SdaPort, &GPIO_InitStructure);
|
||||
|
||||
i2c_handle[idx].Instance = instance->Instance;
|
||||
i2c_handle[idx].Init.Timing = I2C_GetTiming(HAL_RCC_GetPCLK1Freq(), 400000);
|
||||
i2c_handle[idx].Init.OwnAddress1 = 0xFE; // master
|
||||
i2c_handle[idx].Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
i2c_handle[idx].Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
|
||||
i2c_handle[idx].Init.OwnAddress2 = 0;
|
||||
i2c_handle[idx].Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||
i2c_handle[idx].Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||
|
||||
if (HAL_OK != HAL_I2C_Init(&i2c_handle[idx])) {
|
||||
ensure(secfalse, "I2C was not loaded properly.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_init(void) {
|
||||
// enable I2C clock
|
||||
I2C_INSTANCE_1_CLK_EN();
|
||||
I2C_INSTANCE_1_SCL_CLK_EN();
|
||||
I2C_INSTANCE_1_SDA_CLK_EN();
|
||||
i2c_init_instance(0, &i2c_defs[0]);
|
||||
|
||||
#ifdef I2C_INSTANCE_2
|
||||
I2C_INSTANCE_2_CLK_EN();
|
||||
I2C_INSTANCE_2_SCL_CLK_EN();
|
||||
I2C_INSTANCE_2_SDA_CLK_EN();
|
||||
i2c_init_instance(1, &i2c_defs[1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void i2c_deinit(uint16_t idx) {
|
||||
__HAL_RCC_I2C5_FORCE_RESET();
|
||||
if (i2c_handle[idx].Instance) {
|
||||
HAL_I2C_DeInit(&i2c_handle[idx]);
|
||||
i2c_handle[idx].Instance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_ensure_pin(GPIO_TypeDef *port, uint16_t GPIO_Pin,
|
||||
GPIO_PinState PinState) {
|
||||
HAL_GPIO_WritePin(port, GPIO_Pin, PinState);
|
||||
while (HAL_GPIO_ReadPin(port, GPIO_Pin) != PinState)
|
||||
;
|
||||
}
|
||||
|
||||
void i2c_cycle(uint16_t idx) {
|
||||
SET_BIT(*i2c_defs[idx].ResetReg, i2c_defs[idx].ResetBit);
|
||||
CLEAR_BIT(*i2c_defs[idx].ResetReg, i2c_defs[idx].ResetBit);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef i2c_transmit(uint16_t idx, uint8_t addr, uint8_t *data,
|
||||
uint16_t len, uint32_t timeout) {
|
||||
return HAL_I2C_Master_Transmit(&i2c_handle[idx], addr, data, len, timeout);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef i2c_receive(uint16_t idx, uint8_t addr, uint8_t *data,
|
||||
uint16_t len, uint32_t timeout) {
|
||||
HAL_StatusTypeDef ret =
|
||||
HAL_I2C_Master_Receive(&i2c_handle[idx], addr, data, len, timeout);
|
||||
#ifdef USE_OPTIGA
|
||||
if (idx == OPTIGA_I2C_INSTANCE) {
|
||||
// apply GUARD_TIME as specified by the OPTIGA datasheet
|
||||
// (only applies to the I2C bus to which the OPTIGA is connected)
|
||||
hal_delay_us(50);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef i2c_mem_write(uint16_t idx, uint8_t addr, uint16_t mem_addr,
|
||||
uint16_t mem_addr_size, uint8_t *data,
|
||||
uint16_t len, uint32_t timeout) {
|
||||
return HAL_I2C_Mem_Write(&i2c_handle[idx], addr, mem_addr, mem_addr_size,
|
||||
data, len, timeout);
|
||||
}
|
||||
HAL_StatusTypeDef i2c_mem_read(uint16_t idx, uint8_t addr, uint16_t mem_addr,
|
||||
uint16_t mem_addr_size, uint8_t *data,
|
||||
uint16_t len, uint32_t timeout) {
|
||||
return HAL_I2C_Mem_Read(&i2c_handle[idx], addr, mem_addr, mem_addr_size, data,
|
||||
len, timeout);
|
||||
}
|
1
core/embed/trezorhal/stm32u5/i2c.h
Symbolic link
1
core/embed/trezorhal/stm32u5/i2c.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/i2c.h
|
1
core/embed/trezorhal/stm32u5/irq.h
Symbolic link
1
core/embed/trezorhal/stm32u5/irq.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/irq.h
|
145
core/embed/trezorhal/stm32u5/limited_util.s
Normal file
145
core/embed/trezorhal/stm32u5/limited_util.s
Normal file
@ -0,0 +1,145 @@
|
||||
.syntax unified
|
||||
|
||||
.text
|
||||
|
||||
.global memset_reg
|
||||
.type memset_reg, STT_FUNC
|
||||
memset_reg:
|
||||
// call with the following (note that the arguments are not validated prior to use):
|
||||
// r0 - address of first word to write (inclusive)
|
||||
// r1 - address of first word following the address in r0 to NOT write (exclusive)
|
||||
// r2 - word value to be written
|
||||
// both addresses in r0 and r1 needs to be divisible by 4!
|
||||
cmp r0, r1
|
||||
beq .L_loop_end
|
||||
.L_loop_begin:
|
||||
str r2, [r0], 4 // store the word in r2 to the address in r0, post-indexed
|
||||
cmp r0, r1
|
||||
bne .L_loop_begin
|
||||
.L_loop_end:
|
||||
bx lr
|
||||
|
||||
// Jump to address given in first argument R0 that points to next's stage's VTOR
|
||||
// Clear memory and all registers before jump
|
||||
.global jump_to
|
||||
.type jump_to, STT_FUNC
|
||||
jump_to:
|
||||
mov r4, r0 // save input argument r0 (the address of the next stage's vector table) (r4 is callee save)
|
||||
// this subroutine re-points the exception handlers before the C code
|
||||
// that comprises them has been given a good environment to run.
|
||||
// therefore, this code needs to disable interrupts before the VTOR
|
||||
// update. then, the reset_handler of the next stage needs to re-enable interrupts.
|
||||
// the following prevents activation of all exceptions except Non-Maskable Interrupt (NMI).
|
||||
// according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.8:
|
||||
// "there is no requirement to insert memory barrier instructions after CPSID".
|
||||
cpsid f
|
||||
// wipe memory at the end of the current stage of code
|
||||
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, =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
|
||||
mov lr, r4
|
||||
// clear out the general purpose registers before the next stage's code can run (even the NMI exception handler)
|
||||
ldr r0, =0
|
||||
mov r1, r0
|
||||
mov r2, r0
|
||||
mov r3, r0
|
||||
mov r4, r0
|
||||
mov r5, r0
|
||||
mov r6, r0
|
||||
mov r7, r0
|
||||
mov r8, r0
|
||||
mov r9, r0
|
||||
mov r10, r0
|
||||
mov r11, r0
|
||||
mov r12, r0
|
||||
// give the next stage a fresh main stack pointer
|
||||
ldr r0, [lr] // set r0 to the main stack pointer in the next stage's vector table
|
||||
msr msp, r0 // give the next stage its main stack pointer
|
||||
// point to the next stage's exception handlers
|
||||
// AN321, section 4.11: "a memory barrier is not required after a VTOR update"
|
||||
.set SCB_VTOR, 0xE000ED08 // reference "Cortex-M4 Devices Generic User Guide" section 4.3
|
||||
ldr r0, =SCB_VTOR
|
||||
str lr, [r0]
|
||||
mov r0, r1 // zero out r0
|
||||
// go on to the next stage
|
||||
ldr lr, [lr, 4] // set lr to the next stage's reset_handler
|
||||
bx lr
|
||||
|
||||
|
||||
.global shutdown_privileged
|
||||
.type shutdown_privileged, STT_FUNC
|
||||
// The function must be called from the privileged mode
|
||||
shutdown_privileged:
|
||||
cpsid f // disable all exceptions (except for NMI), the instruction is ignored in unprivileged mode
|
||||
// if the exceptions weren't disabled, an exception handler (for example systick handler)
|
||||
// could be called after the memory is erased, which would lead to another exception
|
||||
ldr r0, =0
|
||||
mov r1, r0
|
||||
mov r2, r0
|
||||
mov r3, r0
|
||||
mov r4, r0
|
||||
mov r5, r0
|
||||
mov r6, r0
|
||||
mov r7, r0
|
||||
mov r8, r0
|
||||
mov r9, r0
|
||||
mov r10, r0
|
||||
mov r11, r0
|
||||
mov r12, r0
|
||||
ldr lr, =0xffffffff
|
||||
|
||||
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
|
||||
|
||||
ldr r0, =1
|
||||
msr control, r0 // jump to unprivileged mode
|
||||
ldr r0, =0
|
||||
b . // loop forever
|
||||
|
||||
.global MemManage_Handler
|
||||
.type MemManage_Handler, STT_FUNC
|
||||
MemManage_Handler:
|
||||
ldr r2, =_sstack
|
||||
mrs r1, msp
|
||||
ldr r0, =_estack
|
||||
msr msp, r0
|
||||
cmp r1, r2
|
||||
IT lt
|
||||
bllt MemManage_Handler_SO
|
||||
bl MemManage_Handler_MM
|
||||
|
||||
.end
|
311
core/embed/trezorhal/stm32u5/lowlevel.c
Normal file
311
core/embed/trezorhal/stm32u5/lowlevel.c
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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 STM32_HAL_H
|
||||
|
||||
#include "lowlevel.h"
|
||||
#include "common.h"
|
||||
#include "flash.h"
|
||||
#include "model.h"
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#pragma GCC optimize( \
|
||||
"no-stack-protector") // applies to all functions in this file
|
||||
|
||||
#if PRODUCTION
|
||||
#define WANT_RDP_LEVEL (OB_RDP_LEVEL_2)
|
||||
#define WANT_WRP_PAGE_START 2
|
||||
#define WANT_WRP_PAGE_END 7
|
||||
#else
|
||||
#define WANT_RDP_LEVEL (OB_RDP_LEVEL_0)
|
||||
#endif
|
||||
|
||||
#ifdef VDD_3V3
|
||||
// BOR LEVEL 0: Reset level threshold is around 2.8 V
|
||||
#define WANT_BOR_LEVEL (OB_BOR_LEVEL_4)
|
||||
#define USE_PVD 1
|
||||
#elif VDD_1V8
|
||||
// BOR LEVEL 0: Reset level threshold is around 1.7 V
|
||||
#define WANT_BOR_LEVEL (OB_BOR_LEVEL_0)
|
||||
#else
|
||||
#error "VDD_3V3 or VDD_1V8 must be defined"
|
||||
#endif
|
||||
|
||||
#if defined STM32U5A9xx | defined STM32U5G9xx
|
||||
#define SEC_AREA_1_PAGE_START 0
|
||||
#define HDP_AREA_1_PAGE_END 1
|
||||
#define SEC_AREA_1_PAGE_END 0xFF
|
||||
#define SEC_AREA_2_PAGE_START 0
|
||||
#define SEC_AREA_2_PAGE_END 0xFF
|
||||
#elif define STM32U585xx
|
||||
#define SEC_AREA_1_PAGE_START 0
|
||||
#define HDP_AREA_1_PAGE_END 1
|
||||
#define SEC_AREA_1_PAGE_END 0x7F
|
||||
#define SEC_AREA_2_PAGE_START 0
|
||||
#define SEC_AREA_2_PAGE_END 0x7F
|
||||
#else
|
||||
#error Unknown MCU
|
||||
#endif
|
||||
|
||||
#define FLASH_OPTR_VALUE \
|
||||
(FLASH_OPTR_TZEN | FLASH_OPTR_PA15_PUPEN | FLASH_OPTR_nBOOT0 | \
|
||||
FLASH_OPTR_SRAM3_ECC | FLASH_OPTR_BKPRAM_ECC | FLASH_OPTR_DUALBANK | \
|
||||
FLASH_OPTR_WWDG_SW | FLASH_OPTR_IWDG_STOP | FLASH_OPTR_IWDG_STDBY | \
|
||||
FLASH_OPTR_IWDG_SW | FLASH_OPTR_SRAM_RST | FLASH_OPTR_nRST_SHDW | \
|
||||
FLASH_OPTR_nRST_STDBY | FLASH_OPTR_nRST_STOP | WANT_BOR_LEVEL | \
|
||||
(WANT_RDP_LEVEL << FLASH_OPTR_RDP_Pos))
|
||||
|
||||
#define FALSH_SECBOOTADD0R_VALUE \
|
||||
((BOARDLOADER_START & 0xFFFFFF80) | FLASH_SECBOOTADD0R_BOOT_LOCK | 0x7C)
|
||||
#define FLASH_SECWM1R1_VALUE \
|
||||
(SEC_AREA_1_PAGE_START << FLASH_SECWM1R1_SECWM1_PSTRT_Pos | \
|
||||
SEC_AREA_1_PAGE_END << FLASH_SECWM1R1_SECWM1_PEND_Pos | 0xFF00FF00)
|
||||
#define FLASH_SECWM1R2_VALUE \
|
||||
(HDP_AREA_1_PAGE_END << FLASH_SECWM1R2_HDP1_PEND_Pos | \
|
||||
FLASH_SECWM1R2_HDP1EN | 0x7F007F00)
|
||||
#define FLASH_SECWM2R1_VALUE \
|
||||
(SEC_AREA_2_PAGE_START << FLASH_SECWM1R1_SECWM1_PSTRT_Pos | \
|
||||
SEC_AREA_2_PAGE_END << FLASH_SECWM1R1_SECWM1_PEND_Pos | 0xFF00FF00)
|
||||
#define FLASH_SECWM2R2_VALUE (0x7F007F00)
|
||||
|
||||
secbool flash_check_option_bytes(void) {
|
||||
flash_wait_and_clear_status_flags();
|
||||
// check values stored in flash interface registers
|
||||
if (FLASH->OPTR !=
|
||||
FLASH_OPTR_VALUE) { // ignore bits 0 and 1 because they are control bits
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
if (FLASH->SECBOOTADD0R != FALSH_SECBOOTADD0R_VALUE) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
#if PRODUCTION
|
||||
if (FLASH->WRP1AR != (WANT_WRP_PAGE_START | (WANT_WRP_PAGE_END << 16))) {
|
||||
return secfalse;
|
||||
}
|
||||
#else
|
||||
if (FLASH->WRP1AR != 0xFF00FFFF) {
|
||||
return secfalse;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (FLASH->WRP1BR != 0xFF00FFFF) {
|
||||
return secfalse;
|
||||
}
|
||||
if (FLASH->WRP2AR != 0xFF00FFFF) {
|
||||
return secfalse;
|
||||
}
|
||||
if (FLASH->WRP2BR != 0xFF00FFFF) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
void flash_lock_option_bytes(void) {
|
||||
FLASH->NSCR |= FLASH_NSCR_OPTLOCK; // lock the option bytes
|
||||
}
|
||||
|
||||
void flash_unlock_option_bytes(void) {
|
||||
if ((FLASH->NSCR & FLASH_NSCR_OPTLOCK) == 0) {
|
||||
return; // already unlocked
|
||||
}
|
||||
// reference RM0090 section 3.7.2
|
||||
// write the special sequence to unlock
|
||||
FLASH->OPTKEYR = FLASH_OPTKEY1;
|
||||
FLASH->OPTKEYR = FLASH_OPTKEY2;
|
||||
while (FLASH->NSCR & FLASH_NSCR_OPTLOCK)
|
||||
; // wait until the flash option control register is unlocked
|
||||
}
|
||||
|
||||
uint32_t flash_set_option_bytes(void) {
|
||||
if (flash_unlock_write() != sectrue) {
|
||||
return 0;
|
||||
}
|
||||
flash_wait_and_clear_status_flags();
|
||||
flash_unlock_option_bytes();
|
||||
flash_wait_and_clear_status_flags();
|
||||
|
||||
FLASH->OPTR =
|
||||
FLASH_OPTR_VALUE; // WARNING: dev board safe unless you compile for
|
||||
// PRODUCTION or change this value!!!
|
||||
|
||||
FLASH->SECBOOTADD0R = FALSH_SECBOOTADD0R_VALUE;
|
||||
|
||||
#if PRODUCTION
|
||||
FLASH->WRP1AR = WANT_WRP_PAGE_START | (WANT_WRP_PAGE_END << 16);
|
||||
FLASH->WRP1BR = 0xFF00FFFF;
|
||||
FLASH->WRP2AR = 0xFF00FFFF;
|
||||
FLASH->WRP2BR = 0xFF00FFFF;
|
||||
#endif
|
||||
|
||||
FLASH_WaitForLastOperation(HAL_MAX_DELAY);
|
||||
|
||||
FLASH->NSCR |= FLASH_NSCR_OPTSTRT;
|
||||
uint32_t result =
|
||||
flash_wait_and_clear_status_flags(); // wait until changes are committed
|
||||
|
||||
FLASH_WaitForLastOperation(HAL_MAX_DELAY);
|
||||
|
||||
FLASH->NSCR |= FLASH_NSCR_OBL_LAUNCH; // begin committing changes to flash
|
||||
result =
|
||||
flash_wait_and_clear_status_flags(); // wait until changes are committed
|
||||
flash_lock_option_bytes();
|
||||
|
||||
if (flash_lock_write() != sectrue) {
|
||||
return 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void check_oem_keys(void) {
|
||||
ensure(((FLASH_S->NSSR & FLASH_NSSR_OEM1LOCK) == 0) * sectrue,
|
||||
"OEM1 KEY SET");
|
||||
ensure(((FLASH_S->NSSR & FLASH_NSSR_OEM2LOCK) == 0) * sectrue,
|
||||
"OEM2 KEY SET");
|
||||
}
|
||||
|
||||
secbool flash_configure_option_bytes(void) {
|
||||
if (sectrue == flash_check_option_bytes()) {
|
||||
return sectrue; // we DID NOT have to change the option bytes
|
||||
}
|
||||
|
||||
do {
|
||||
flash_set_option_bytes();
|
||||
} while (sectrue != flash_check_option_bytes());
|
||||
|
||||
check_oem_keys();
|
||||
|
||||
return secfalse; // notify that we DID have to change the option bytes
|
||||
}
|
||||
|
||||
secbool flash_check_sec_area_ob(void) {
|
||||
flash_wait_and_clear_status_flags();
|
||||
// check values stored in flash interface registers
|
||||
|
||||
if (FLASH->SECWM1R1 != FLASH_SECWM1R1_VALUE) {
|
||||
return secfalse;
|
||||
}
|
||||
if (FLASH->SECWM1R2 != FLASH_SECWM1R2_VALUE) {
|
||||
return secfalse;
|
||||
}
|
||||
if (FLASH->SECWM2R1 != FLASH_SECWM2R1_VALUE) {
|
||||
return secfalse;
|
||||
}
|
||||
if (FLASH->SECWM2R2 != FLASH_SECWM2R2_VALUE) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
uint32_t flash_set_sec_area_ob(void) {
|
||||
if (flash_unlock_write() != sectrue) {
|
||||
return 0;
|
||||
}
|
||||
flash_wait_and_clear_status_flags();
|
||||
flash_unlock_option_bytes();
|
||||
flash_wait_and_clear_status_flags();
|
||||
|
||||
FLASH->SECWM1R1 = FLASH_SECWM1R1_VALUE;
|
||||
FLASH->SECWM1R2 = FLASH_SECWM1R2_VALUE;
|
||||
|
||||
FLASH->SECWM2R1 = FLASH_SECWM2R1_VALUE;
|
||||
FLASH->SECWM2R2 = FLASH_SECWM2R2_VALUE;
|
||||
|
||||
FLASH_WaitForLastOperation(HAL_MAX_DELAY);
|
||||
|
||||
FLASH->NSCR |= FLASH_NSCR_OPTSTRT;
|
||||
uint32_t result =
|
||||
flash_wait_and_clear_status_flags(); // wait until changes are committed
|
||||
|
||||
FLASH_WaitForLastOperation(HAL_MAX_DELAY);
|
||||
|
||||
FLASH->NSCR |= FLASH_NSCR_OBL_LAUNCH; // begin committing changes to flash
|
||||
result =
|
||||
flash_wait_and_clear_status_flags(); // wait until changes are committed
|
||||
flash_lock_option_bytes();
|
||||
|
||||
if (flash_lock_write() != sectrue) {
|
||||
return 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
secbool flash_configure_sec_area_ob(void) {
|
||||
if (sectrue == flash_check_sec_area_ob()) {
|
||||
return sectrue; // we DID NOT have to change the option bytes
|
||||
}
|
||||
|
||||
do {
|
||||
flash_set_sec_area_ob();
|
||||
} while (sectrue != flash_check_sec_area_ob());
|
||||
|
||||
check_oem_keys();
|
||||
|
||||
return secfalse; // notify that we DID have to change the option bytes
|
||||
}
|
||||
|
||||
void periph_init(void) {
|
||||
// STM32U5xx HAL library initialization:
|
||||
// - configure the Flash prefetch, instruction and data caches
|
||||
// - configure the Systick to generate an interrupt each 1 msec
|
||||
// - set NVIC Group Priority to 4
|
||||
// - global MSP (MCU Support Package) initialization
|
||||
HAL_Init();
|
||||
|
||||
// Enable GPIO clocks
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
|
||||
#ifdef USE_PVD
|
||||
// enable the PVD (programmable voltage detector).
|
||||
// select the "2.8V" threshold (level 5).
|
||||
// this detector will be active regardless of the
|
||||
// flash option byte BOR setting.
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
PWR_PVDTypeDef pvd_config;
|
||||
pvd_config.PVDLevel = PWR_PVDLEVEL_5;
|
||||
pvd_config.Mode = PWR_PVD_MODE_IT_RISING_FALLING;
|
||||
HAL_PWR_ConfigPVD(&pvd_config);
|
||||
HAL_PWR_EnablePVD();
|
||||
NVIC_EnableIRQ(PVD_PVM_IRQn);
|
||||
#endif
|
||||
}
|
||||
|
||||
secbool reset_flags_check(void) {
|
||||
#if PRODUCTION
|
||||
// this is effective enough that it makes development painful, so only use it
|
||||
// for production. check the reset flags to assure that we arrive here due to
|
||||
// a regular full power-on event, and not as a result of a lesser reset.
|
||||
if ((RCC->CSR & (RCC_CSR_LPWRRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_IWDGRSTF |
|
||||
RCC_CSR_SFTRSTF | RCC_CSR_PINRSTF | RCC_CSR_BORRSTF |
|
||||
RCC_CSR_OBLRSTF)) != (RCC_CSR_PINRSTF | RCC_CSR_BORRSTF)) {
|
||||
return secfalse;
|
||||
}
|
||||
#endif
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
void reset_flags_reset(void) {
|
||||
RCC->CSR |= RCC_CSR_RMVF; // clear the reset flags
|
||||
}
|
258
core/embed/trezorhal/stm32u5/mpu.c
Normal file
258
core/embed/trezorhal/stm32u5/mpu.c
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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 STM32_HAL_H
|
||||
#include "common.h"
|
||||
#include "flash.h"
|
||||
#include "model.h"
|
||||
#include "stm32u5xx_ll_cortex.h"
|
||||
|
||||
#define ATTR_IDX_FLASH (0 << 1)
|
||||
#define ATTR_IDX_FLASH_NON_CACHABLE (3 << 1)
|
||||
#define ATTR_IDX_SRAM (1 << 1)
|
||||
#define ATTR_IDX_PERIPH (2 << 1)
|
||||
#define REGION_END(x) (((x) & ~0x1F) | 0x01)
|
||||
|
||||
#define SHAREABILITY_FLASH (LL_MPU_ACCESS_NOT_SHAREABLE)
|
||||
#define SHAREABILITY_SRAM \
|
||||
(LL_MPU_ACCESS_INNER_SHAREABLE | LL_MPU_ACCESS_OUTER_SHAREABLE)
|
||||
|
||||
void mpu_config_off(void) {
|
||||
// Disable MPU
|
||||
HAL_MPU_Disable();
|
||||
}
|
||||
|
||||
static uint32_t area_start(const flash_area_t* area) {
|
||||
return (uint32_t)flash_area_get_address(area, 0, 0);
|
||||
}
|
||||
|
||||
static uint32_t area_end(const flash_area_t* area) {
|
||||
uint32_t start = area_start(area);
|
||||
uint32_t size = flash_area_get_size(area);
|
||||
return start + size;
|
||||
}
|
||||
|
||||
void mpu_config_boardloader(void) {
|
||||
// Disable MPU
|
||||
HAL_MPU_Disable();
|
||||
|
||||
// flash memory
|
||||
MPU->MAIR0 = 0xAA;
|
||||
// internal ram
|
||||
MPU->MAIR0 |= 0xAA << 8;
|
||||
// peripherals
|
||||
MPU->MAIR0 |= 0x00 << 16;
|
||||
// non-cachable flash
|
||||
MPU->MAIR0 |= 0x44 << 24;
|
||||
|
||||
// Secret
|
||||
MPU->RNR = MPU_REGION_NUMBER0;
|
||||
MPU->RBAR = FLASH_BASE_S | LL_MPU_REGION_ALL_RW | SHAREABILITY_FLASH |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE;
|
||||
MPU->RLAR = REGION_END(BOARDLOADER_START - 1) | ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// Flash boardloader (read-write)
|
||||
MPU->RNR = MPU_REGION_NUMBER1;
|
||||
MPU->RBAR = BOARDLOADER_START | LL_MPU_REGION_ALL_RW | SHAREABILITY_FLASH;
|
||||
MPU->RLAR = REGION_END(BOOTLOADER_START - 1) | ATTR_IDX_FLASH;
|
||||
|
||||
// Flash rest
|
||||
MPU->RNR = MPU_REGION_NUMBER2;
|
||||
MPU->RBAR = BOOTLOADER_START | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_FLASH;
|
||||
MPU->RLAR =
|
||||
REGION_END(FLASH_BASE_S + 0x400000 - 1) | ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// RAM (read-write, execute never) (SRAM1)
|
||||
MPU->RNR = MPU_REGION_NUMBER3;
|
||||
MPU->RBAR = SRAM1_BASE_S | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR = REGION_END(SRAM1_BASE_S + 0xC0000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// RAM (read-write, execute never) (SRAM2, 3, 5, 6)
|
||||
// reserve 256 bytes for stack overflow detection
|
||||
MPU->RNR = MPU_REGION_NUMBER4;
|
||||
MPU->RBAR = (SRAM2_BASE_S + 0x100) | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR = REGION_END(SRAM1_BASE_S + 0x2F0000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// GFXMMU_VIRTUAL_BUFFERS (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER5;
|
||||
MPU->RBAR = GFXMMU_VIRTUAL_BUFFERS_BASE_S | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR =
|
||||
REGION_END(GFXMMU_VIRTUAL_BUFFERS_BASE_S + 0x1000000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// Peripherals (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER6;
|
||||
MPU->RBAR =
|
||||
PERIPH_BASE_NS | LL_MPU_REGION_ALL_RW | LL_MPU_INSTRUCTION_ACCESS_DISABLE;
|
||||
MPU->RLAR = REGION_END(PERIPH_BASE_NS + 0x20000000 - 1) | ATTR_IDX_PERIPH;
|
||||
|
||||
// OTP (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER7;
|
||||
MPU->RBAR = FLASH_OTP_BASE | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_FLASH;
|
||||
MPU->RLAR = REGION_END(FLASH_OTP_BASE + FLASH_OTP_SIZE - 1) |
|
||||
ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// Non-secure Flash
|
||||
MPU->RNR = MPU_REGION_NUMBER7;
|
||||
MPU->RBAR = FLASH_BASE_NS | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_FLASH;
|
||||
MPU->RLAR =
|
||||
REGION_END(FLASH_BASE_NS + 0x400000 - 1) | ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// Enable MPU
|
||||
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
|
||||
}
|
||||
|
||||
void mpu_config_bootloader(void) {
|
||||
// Disable MPU
|
||||
HAL_MPU_Disable();
|
||||
|
||||
// flash memory
|
||||
MPU->MAIR0 = 0xAA;
|
||||
// internal ram
|
||||
MPU->MAIR0 |= 0xAA << 8;
|
||||
// peripherals
|
||||
MPU->MAIR0 |= 0x00 << 16;
|
||||
// non-cachable flash
|
||||
MPU->MAIR0 |= 0x44 << 24;
|
||||
|
||||
// Secret + boardloader
|
||||
MPU->RNR = MPU_REGION_NUMBER0;
|
||||
MPU->RBAR = FLASH_BASE_S | LL_MPU_REGION_ALL_RW | SHAREABILITY_FLASH;
|
||||
MPU->RLAR = REGION_END(BOOTLOADER_START - 1) | ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// Bootloader (read-write)
|
||||
MPU->RNR = MPU_REGION_NUMBER1;
|
||||
MPU->RBAR = BOOTLOADER_START | LL_MPU_REGION_ALL_RW | SHAREABILITY_FLASH;
|
||||
MPU->RLAR = REGION_END(area_start(&STORAGE_AREAS[0]) - 1) | ATTR_IDX_FLASH;
|
||||
|
||||
// Flash firmware + storage (read-write, execute never), till flash end
|
||||
MPU->RNR = MPU_REGION_NUMBER2;
|
||||
MPU->RBAR = area_start(&STORAGE_AREAS[0]) | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_FLASH;
|
||||
MPU->RLAR =
|
||||
REGION_END(FLASH_BASE_S + 0x400000 - 1) | ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// RAM (read-write, execute never) (SRAM1)
|
||||
MPU->RNR = MPU_REGION_NUMBER3;
|
||||
MPU->RBAR = SRAM1_BASE_S | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR = REGION_END(SRAM1_BASE_S + 0xC0000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// RAM (read-write, execute never) (SRAM2, 3, 5, 6)
|
||||
// reserve 256 bytes for stack overflow detection
|
||||
MPU->RNR = MPU_REGION_NUMBER4;
|
||||
MPU->RBAR = (SRAM2_BASE_S + 0x100) | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR = REGION_END(SRAM1_BASE_S + 0x2F0000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// GFXMMU_VIRTUAL_BUFFERS (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER5;
|
||||
MPU->RBAR = GFXMMU_VIRTUAL_BUFFERS_BASE_S | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR =
|
||||
REGION_END(GFXMMU_VIRTUAL_BUFFERS_BASE_S + 0x1000000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// Peripherals (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER6;
|
||||
MPU->RBAR =
|
||||
PERIPH_BASE_S | LL_MPU_REGION_ALL_RW | LL_MPU_INSTRUCTION_ACCESS_DISABLE;
|
||||
MPU->RLAR = REGION_END(PERIPH_BASE_S + 0x10000000 - 1) | ATTR_IDX_PERIPH;
|
||||
|
||||
// OTP (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER7;
|
||||
MPU->RBAR = FLASH_OTP_BASE | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_FLASH;
|
||||
MPU->RLAR = REGION_END(FLASH_OTP_BASE + FLASH_OTP_SIZE - 1) |
|
||||
ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// Enable MPU
|
||||
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
|
||||
}
|
||||
|
||||
void mpu_config_firmware(void) {
|
||||
// Disable MPU
|
||||
HAL_MPU_Disable();
|
||||
|
||||
// flash memory
|
||||
MPU->MAIR0 = 0xAA;
|
||||
// internal ram
|
||||
MPU->MAIR0 |= 0xAA << 8;
|
||||
// peripherals
|
||||
MPU->MAIR0 |= 0x00 << 16;
|
||||
// non-cachable flash
|
||||
MPU->MAIR0 |= 0x44 << 24;
|
||||
|
||||
// bootloader + boardloader: no access, execute never: need to do everything
|
||||
// before turning on MPU
|
||||
|
||||
// Storage (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER0;
|
||||
MPU->RBAR = area_start(&STORAGE_AREAS[0]) | LL_MPU_REGION_ALL_RW |
|
||||
SHAREABILITY_FLASH | LL_MPU_INSTRUCTION_ACCESS_DISABLE;
|
||||
MPU->RLAR = REGION_END(FIRMWARE_START - 1) | ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// Flash firmware (read-write)
|
||||
MPU->RNR = MPU_REGION_NUMBER1;
|
||||
MPU->RBAR = (FIRMWARE_START) | LL_MPU_REGION_ALL_RO | SHAREABILITY_FLASH;
|
||||
MPU->RLAR = REGION_END(area_end(&FIRMWARE_AREA) - 1) | ATTR_IDX_FLASH;
|
||||
|
||||
// RAM (read-write, execute never) (SRAM1)
|
||||
MPU->RNR = MPU_REGION_NUMBER2;
|
||||
MPU->RBAR = SRAM1_BASE_S | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR = REGION_END(SRAM1_BASE_S + 0xC0000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// RAM (read-write, execute never) (SRAM2, 3, 5, 6)
|
||||
// reserve 256 bytes for stack overflow detection
|
||||
MPU->RNR = MPU_REGION_NUMBER3;
|
||||
MPU->RBAR = (SRAM2_BASE_S + 0x100) | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR = REGION_END(SRAM1_BASE_S + 0x2F0000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// GFXMMU_VIRTUAL_BUFFERS (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER4;
|
||||
MPU->RBAR = GFXMMU_VIRTUAL_BUFFERS_BASE_S | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_SRAM;
|
||||
MPU->RLAR =
|
||||
REGION_END(GFXMMU_VIRTUAL_BUFFERS_BASE_S + 0x1000000 - 1) | ATTR_IDX_SRAM;
|
||||
|
||||
// Peripherals (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER5;
|
||||
MPU->RBAR =
|
||||
PERIPH_BASE_S | LL_MPU_REGION_ALL_RW | LL_MPU_INSTRUCTION_ACCESS_DISABLE;
|
||||
MPU->RLAR = REGION_END(PERIPH_BASE_S + 0x10000000 - 1) | ATTR_IDX_PERIPH;
|
||||
|
||||
// OTP (read-write, execute never)
|
||||
MPU->RNR = MPU_REGION_NUMBER6;
|
||||
MPU->RBAR = FLASH_OTP_BASE | LL_MPU_REGION_ALL_RW |
|
||||
LL_MPU_INSTRUCTION_ACCESS_DISABLE | SHAREABILITY_FLASH;
|
||||
MPU->RLAR = REGION_END(FLASH_OTP_BASE + FLASH_OTP_SIZE - 1) |
|
||||
ATTR_IDX_FLASH_NON_CACHABLE;
|
||||
|
||||
// Enable MPU
|
||||
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
|
||||
|
||||
__asm__ volatile("dsb");
|
||||
__asm__ volatile("isb");
|
||||
}
|
212
core/embed/trezorhal/stm32u5/platform.c
Normal file
212
core/embed/trezorhal/stm32u5/platform.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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 STM32_HAL_H
|
||||
|
||||
#include "platform.h"
|
||||
#include "rng.h"
|
||||
#include TREZOR_BOARD
|
||||
|
||||
const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U};
|
||||
const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U};
|
||||
const uint32_t MSIRangeTable[16] = {48000000U, 24000000U, 16000000U, 12000000U,
|
||||
4000000U, 2000000U, 1330000U, 1000000U,
|
||||
3072000U, 1536000U, 1024000U, 768000U,
|
||||
400000U, 200000U, 133000U, 100000U};
|
||||
typedef struct {
|
||||
uint32_t freq;
|
||||
uint32_t pllq;
|
||||
uint32_t pllp;
|
||||
uint32_t pllm;
|
||||
uint32_t plln;
|
||||
} clock_conf_t;
|
||||
|
||||
#if defined STM32U5
|
||||
#define DEFAULT_FREQ 160U
|
||||
#define DEFAULT_PLLM 1
|
||||
#define DEFAULT_PLLN (10 * PLLN_COEF) // mult by 10
|
||||
#define DEFAULT_PLLR 1U // division by 1
|
||||
#define DEFAULT_PLLQ 1U // division by 1
|
||||
#define DEFAULT_PLLP 5U // division by 5
|
||||
#else
|
||||
#error Unsupported MCU
|
||||
#endif
|
||||
|
||||
uint32_t SystemCoreClock = DEFAULT_FREQ * 1000000U;
|
||||
|
||||
// PLLCLK = ((HSE / PLLM) * PLLN) / PLLR
|
||||
#ifdef HSE_16MHZ
|
||||
#define PLLN_COEF 1U
|
||||
#elif defined HSE_8MHZ
|
||||
#define PLLN_COEF 2U
|
||||
#else
|
||||
#error Unsupported HSE frequency
|
||||
#endif
|
||||
|
||||
// assuming HSE 16 MHz
|
||||
clock_conf_t clock_conf[1] = {
|
||||
{
|
||||
// clk = ((16MHz / 1) * 10) / 1 = 160 MHz
|
||||
.freq = 160,
|
||||
.pllp = 1,
|
||||
.pllq = 1,
|
||||
.pllm = 1,
|
||||
.plln = 10 * PLLN_COEF,
|
||||
},
|
||||
};
|
||||
|
||||
#pragma GCC optimize( \
|
||||
"no-stack-protector") // applies to all functions in this file
|
||||
|
||||
void SystemInit(void) {
|
||||
// set flash wait states for an increasing HCLK frequency
|
||||
|
||||
FLASH->ACR = FLASH_ACR_LATENCY_5WS;
|
||||
// wait until the new wait state config takes effect -- per section 3.5.1
|
||||
// guidance
|
||||
while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_5WS)
|
||||
;
|
||||
|
||||
/* Reset the RCC clock configuration to the default reset state ------------*/
|
||||
/* Set MSION bit */
|
||||
RCC->CR = RCC_CR_MSISON;
|
||||
|
||||
/* Reset CFGR register */
|
||||
RCC->CFGR1 = 0U;
|
||||
RCC->CFGR2 = 0U;
|
||||
RCC->CFGR3 = 0U;
|
||||
|
||||
/* Reset HSEON, CSSON , HSION, PLLxON bits */
|
||||
RCC->CR &= ~(RCC_CR_HSEON | RCC_CR_CSSON | RCC_CR_PLL1ON | RCC_CR_PLL2ON |
|
||||
RCC_CR_PLL3ON | RCC_CR_HSI48ON);
|
||||
|
||||
/* Reset PLLCFGR register */
|
||||
RCC->PLL1CFGR = 0U;
|
||||
|
||||
/* Reset HSEBYP bit */
|
||||
RCC->CR &= ~(RCC_CR_HSEBYP);
|
||||
|
||||
/* Disable all interrupts */
|
||||
RCC->CIER = 0U;
|
||||
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
|
||||
MODIFY_REG(PWR->VOSR, (PWR_VOSR_VOS | PWR_VOSR_BOOSTEN),
|
||||
PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
while (HAL_IS_BIT_CLR(PWR->VOSR, PWR_VOSR_VOSRDY))
|
||||
;
|
||||
while (HAL_IS_BIT_CLR(PWR->SVMSR, PWR_SVMSR_ACTVOSRDY))
|
||||
;
|
||||
|
||||
__HAL_RCC_HSE_CONFIG(RCC_HSE_ON);
|
||||
while (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)
|
||||
;
|
||||
|
||||
__HAL_RCC_PLL_CONFIG(RCC_PLLSOURCE_HSE, RCC_PLLMBOOST_DIV1, DEFAULT_PLLM,
|
||||
DEFAULT_PLLN, DEFAULT_PLLP, DEFAULT_PLLQ, DEFAULT_PLLR);
|
||||
|
||||
__HAL_RCC_PLL_FRACN_DISABLE();
|
||||
|
||||
__HAL_RCC_PLL_VCIRANGE(RCC_PLLVCIRANGE_1);
|
||||
|
||||
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVR);
|
||||
|
||||
__HAL_RCC_PLL_ENABLE();
|
||||
while (READ_BIT(RCC->CR, RCC_CR_PLL1RDY) == 0U)
|
||||
;
|
||||
|
||||
__HAL_RCC_HSI48_ENABLE();
|
||||
while (READ_BIT(RCC->CR, RCC_CR_HSI48RDY) == 0U)
|
||||
;
|
||||
|
||||
/** Initializes the CPU, AHB and APB buses clocks
|
||||
*/
|
||||
FLASH->ACR = FLASH_ACR_LATENCY_4WS;
|
||||
// wait until the new wait state config takes effect -- per section 3.5.1
|
||||
// guidance
|
||||
while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_4WS)
|
||||
;
|
||||
MODIFY_REG(RCC->CFGR3, RCC_CFGR3_PPRE3, RCC_HCLK_DIV1);
|
||||
MODIFY_REG(RCC->CFGR2, RCC_CFGR2_PPRE2, ((RCC_HCLK_DIV1) << 4));
|
||||
MODIFY_REG(RCC->CFGR2, RCC_CFGR2_PPRE1, RCC_HCLK_DIV1);
|
||||
MODIFY_REG(RCC->CFGR2, RCC_CFGR2_HPRE, RCC_SYSCLK_DIV1);
|
||||
|
||||
MODIFY_REG(RCC->CFGR1, RCC_CFGR1_SW, RCC_SYSCLKSOURCE_PLLCLK);
|
||||
|
||||
/*
|
||||
* Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral
|
||||
*/
|
||||
HAL_PWREx_DisableUCPDDeadBattery();
|
||||
|
||||
/*
|
||||
* Switch to SMPS regulator instead of LDO
|
||||
*/
|
||||
SET_BIT(PWR->CR3, PWR_CR3_REGSEL);
|
||||
/* Wait until system switch on new regulator */
|
||||
while (HAL_IS_BIT_CLR(PWR->SVMSR, PWR_SVMSR_REGS))
|
||||
;
|
||||
|
||||
__HAL_RCC_PWR_CLK_DISABLE();
|
||||
|
||||
// this will be overriden by static initialization
|
||||
SystemCoreClock = DEFAULT_FREQ * 1000000U;
|
||||
|
||||
// enable clock security system, HSE clock, and main PLL
|
||||
RCC->CR |= RCC_CR_CSSON;
|
||||
|
||||
// turn off the HSI as it is now unused (it will be turned on again
|
||||
// automatically if a clock security failure occurs)
|
||||
RCC->CR &= ~RCC_CR_HSION;
|
||||
// wait until ths HSI is off
|
||||
while ((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION)
|
||||
;
|
||||
|
||||
// TODO turn off MSI?
|
||||
|
||||
// init the TRNG peripheral
|
||||
rng_init();
|
||||
|
||||
// set CP10 and CP11 to enable full access to the fpu coprocessor;
|
||||
SCB->CPACR |=
|
||||
((3UL << 20U) | (3UL << 22U)); /* set CP10 and CP11 Full Access */
|
||||
|
||||
#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||
SCB_NS->CPACR |=
|
||||
((3UL << 20U) | (3UL << 22U)); /* set CP10 and CP11 Full Access */
|
||||
#endif
|
||||
|
||||
// enable instruction cache in default 2-way mode
|
||||
ICACHE->CR = ICACHE_CR_EN;
|
||||
}
|
||||
|
||||
void drop_privileges(void) {
|
||||
// jump to unprivileged mode
|
||||
// http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/CHDBIBGJ.html
|
||||
__asm__ volatile("msr control, %0" ::"r"(0x1));
|
||||
__asm__ volatile("isb");
|
||||
}
|
||||
|
||||
// from util.s
|
||||
extern void shutdown_privileged(void);
|
||||
|
||||
void PVD_PVM_IRQHandler(void) {
|
||||
TIM1->CCR1 = 0; // turn off display backlight
|
||||
shutdown_privileged();
|
||||
}
|
56
core/embed/trezorhal/stm32u5/platform.h
Normal file
56
core/embed/trezorhal/stm32u5/platform.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_STM32_H
|
||||
#define TREZORHAL_STM32_H
|
||||
|
||||
#include STM32_HAL_H
|
||||
#include <stdint.h>
|
||||
|
||||
#define SENSITIVE __attribute__((section(".sensitive")))
|
||||
|
||||
typedef enum {
|
||||
CLOCK_160_MHZ = 0,
|
||||
} clock_settings_t;
|
||||
|
||||
void set_core_clock(clock_settings_t settings);
|
||||
void ensure_compatible_settings(void);
|
||||
void drop_privileges(void);
|
||||
|
||||
// the following functions are defined in util.s
|
||||
void memset_reg(volatile void *start, volatile void *stop, uint32_t val);
|
||||
void jump_to(uint32_t address);
|
||||
void jump_to_unprivileged(uint32_t address);
|
||||
void jump_to_with_flag(uint32_t address, uint32_t register_flag);
|
||||
|
||||
extern uint32_t __stack_chk_guard;
|
||||
|
||||
// this deletes all secrets and SRAM2 where stack is located
|
||||
// to prevent stack smashing error, do not return from function calling this
|
||||
static inline void __attribute__((always_inline)) delete_secrets(void) {
|
||||
// Disable SAES peripheral clock, so that we don't get tamper events
|
||||
__HAL_RCC_SAES_CLK_DISABLE();
|
||||
|
||||
// Erase all
|
||||
TAMP->CR2 |= TAMP_CR2_BKERASE;
|
||||
}
|
||||
|
||||
void check_oem_keys(void);
|
||||
|
||||
#endif // TREZORHAL_STM32_H
|
1
core/embed/trezorhal/stm32u5/random_delays.c
Symbolic link
1
core/embed/trezorhal/stm32u5/random_delays.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/random_delays.c
|
1
core/embed/trezorhal/stm32u5/rng.c
Symbolic link
1
core/embed/trezorhal/stm32u5/rng.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/rng.c
|
1
core/embed/trezorhal/stm32u5/sbu.c
Symbolic link
1
core/embed/trezorhal/stm32u5/sbu.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/sbu.c
|
162
core/embed/trezorhal/stm32u5/secret.c
Normal file
162
core/embed/trezorhal/stm32u5/secret.c
Normal file
@ -0,0 +1,162 @@
|
||||
#include "secret.h"
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#include "flash.h"
|
||||
#include "model.h"
|
||||
#include "rng.h"
|
||||
|
||||
static secbool bootloader_locked_set = secfalse;
|
||||
static secbool bootloader_locked = secfalse;
|
||||
|
||||
static secbool verify_header(void) {
|
||||
uint8_t header[SECRET_HEADER_LEN] = {0};
|
||||
|
||||
memcpy(header, flash_area_get_address(&SECRET_AREA, 0, SECRET_HEADER_LEN),
|
||||
SECRET_HEADER_LEN);
|
||||
|
||||
bootloader_locked =
|
||||
memcmp(header, SECRET_HEADER_MAGIC, 4) == 0 ? sectrue : secfalse;
|
||||
bootloader_locked_set = sectrue;
|
||||
return bootloader_locked;
|
||||
}
|
||||
|
||||
secbool secret_bootloader_locked(void) {
|
||||
if (bootloader_locked_set != sectrue) {
|
||||
// Set bootloader_locked.
|
||||
verify_header();
|
||||
}
|
||||
|
||||
return bootloader_locked;
|
||||
}
|
||||
|
||||
void secret_write_header(void) {
|
||||
uint8_t header[SECRET_HEADER_LEN] = {0};
|
||||
memcpy(header, SECRET_HEADER_MAGIC, 4);
|
||||
secret_write(header, 0, SECRET_HEADER_LEN);
|
||||
}
|
||||
|
||||
void secret_write(uint8_t *data, uint32_t offset, uint32_t len) {
|
||||
ensure(flash_unlock_write(), "secret write");
|
||||
for (int i = 0; i < len / 16; i++) {
|
||||
ensure(flash_area_write_quadword(&SECRET_AREA, offset + (i * 16),
|
||||
(uint32_t *)&data[(i * 16)]),
|
||||
"secret write");
|
||||
}
|
||||
ensure(flash_lock_write(), "secret write");
|
||||
}
|
||||
|
||||
secbool secret_read(uint8_t *data, uint32_t offset, uint32_t len) {
|
||||
if (sectrue != verify_header()) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
memcpy(data, flash_area_get_address(&SECRET_AREA, offset, len), len);
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
void secret_hide(void) {
|
||||
FLASH->SECHDPCR |= FLASH_SECHDPCR_HDP1_ACCDIS_Msk;
|
||||
FLASH->SECHDPCR |= FLASH_SECHDPCR_HDP2_ACCDIS_Msk;
|
||||
}
|
||||
|
||||
void secret_bhk_lock(void) {
|
||||
TAMP_S->SECCFGR = 8 << TAMP_SECCFGR_BKPRWSEC_Pos | TAMP_SECCFGR_BHKLOCK;
|
||||
}
|
||||
|
||||
secbool secret_bhk_locked(void) {
|
||||
return ((TAMP_S->SECCFGR & TAMP_SECCFGR_BHKLOCK) == TAMP_SECCFGR_BHKLOCK) *
|
||||
sectrue;
|
||||
}
|
||||
|
||||
void secret_bhk_provision(void) {
|
||||
uint32_t secret[SECRET_BHK_LEN / sizeof(uint32_t)] = {0};
|
||||
secbool ok =
|
||||
secret_read((uint8_t *)secret, SECRET_BHK_OFFSET, SECRET_BHK_LEN);
|
||||
|
||||
volatile uint32_t *reg1 = &TAMP->BKP0R;
|
||||
if (sectrue == ok) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*reg1 = ((uint32_t *)secret)[i];
|
||||
reg1++;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*reg1 = 0;
|
||||
reg1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void secret_bhk_regenerate(void) {
|
||||
ensure(flash_area_erase(&BHK_AREA, NULL), "Failed regenerating BHK");
|
||||
ensure(flash_unlock_write(), "Failed regenerating BHK");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
uint32_t val[4] = {0};
|
||||
for (int j = 0; j < 4; j++) {
|
||||
val[j] = rng_get();
|
||||
}
|
||||
ensure(flash_area_write_quadword(&BHK_AREA, i * 4 * sizeof(uint32_t), val),
|
||||
"Failed regenerating BHK");
|
||||
}
|
||||
ensure(flash_lock_write(), "Failed regenerating BHK");
|
||||
}
|
||||
|
||||
secbool secret_optiga_present(void) {
|
||||
uint8_t *optiga_secret = (uint8_t *)flash_area_get_address(
|
||||
&SECRET_AREA, SECRET_OPTIGA_KEY_OFFSET, SECRET_OPTIGA_KEY_LEN);
|
||||
|
||||
int optiga_secret_empty_bytes = 0;
|
||||
|
||||
for (int i = 0; i < SECRET_OPTIGA_KEY_LEN; i++) {
|
||||
if (optiga_secret[i] == 0xFF) {
|
||||
optiga_secret_empty_bytes++;
|
||||
}
|
||||
}
|
||||
return sectrue * (optiga_secret_empty_bytes != SECRET_OPTIGA_KEY_LEN);
|
||||
}
|
||||
|
||||
void secret_optiga_backup(void) {
|
||||
uint32_t secret[SECRET_OPTIGA_KEY_LEN / sizeof(uint32_t)] = {0};
|
||||
secbool ok = secret_read((uint8_t *)secret, SECRET_OPTIGA_KEY_OFFSET,
|
||||
SECRET_OPTIGA_KEY_LEN);
|
||||
|
||||
volatile uint32_t *reg1 = &TAMP->BKP8R;
|
||||
if (sectrue == ok) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*reg1 = ((uint32_t *)secret)[i];
|
||||
reg1++;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*reg1 = 0;
|
||||
reg1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
secbool secret_optiga_extract(uint8_t *dest) {
|
||||
bool all_zero = true;
|
||||
volatile uint32_t *reg1 = &TAMP->BKP8R;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint32_t val = *reg1++;
|
||||
|
||||
if (val != 0) {
|
||||
all_zero = false;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
dest[i * 4 + j] = (val >> (j * 8)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return all_zero ? secfalse : sectrue;
|
||||
}
|
||||
|
||||
void secret_optiga_hide(void) {
|
||||
volatile uint32_t *reg1 = &TAMP->BKP8R;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*reg1 = 0;
|
||||
reg1++;
|
||||
}
|
||||
}
|
117
core/embed/trezorhal/stm32u5/secure_aes.c
Normal file
117
core/embed/trezorhal/stm32u5/secure_aes.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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 <secure_aes.h>
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stm32u5xx_hal_cryp.h>
|
||||
|
||||
secbool secure_aes_init(void) {
|
||||
RCC_OscInitTypeDef osc_init_def = {0};
|
||||
osc_init_def.OscillatorType = RCC_OSCILLATORTYPE_SHSI;
|
||||
osc_init_def.SHSIState = RCC_SHSI_ON;
|
||||
|
||||
// Enable SHSI clock
|
||||
if (HAL_RCC_OscConfig(&osc_init_def) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
// Enable SAES peripheral clock
|
||||
__HAL_RCC_SAES_CLK_ENABLE();
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
static void secure_aes_load_bhk(void) {
|
||||
TAMP->BKP7R;
|
||||
TAMP->BKP6R;
|
||||
TAMP->BKP5R;
|
||||
TAMP->BKP4R;
|
||||
TAMP->BKP3R;
|
||||
TAMP->BKP2R;
|
||||
TAMP->BKP1R;
|
||||
TAMP->BKP0R;
|
||||
}
|
||||
|
||||
secbool secure_aes_encrypt(uint32_t* input, size_t size, uint32_t* output) {
|
||||
CRYP_HandleTypeDef hcryp = {0};
|
||||
uint32_t iv[] = {0, 0, 0, 0};
|
||||
|
||||
hcryp.Instance = SAES;
|
||||
hcryp.Init.DataType = CRYP_NO_SWAP;
|
||||
hcryp.Init.KeySelect = CRYP_KEYSEL_HSW;
|
||||
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
|
||||
hcryp.Init.pKey = NULL;
|
||||
hcryp.Init.pInitVect = iv;
|
||||
hcryp.Init.Algorithm = CRYP_AES_ECB;
|
||||
hcryp.Init.Header = NULL;
|
||||
hcryp.Init.HeaderSize = 0;
|
||||
hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
|
||||
hcryp.Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE;
|
||||
hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
|
||||
hcryp.Init.KeyMode = CRYP_KEYMODE_NORMAL;
|
||||
|
||||
if (HAL_CRYP_Init(&hcryp) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
secure_aes_load_bhk();
|
||||
|
||||
if (HAL_CRYP_Encrypt(&hcryp, input, size, output, HAL_MAX_DELAY) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
HAL_CRYP_DeInit(&hcryp);
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool secure_aes_decrypt(uint32_t* input, size_t size, uint32_t* output) {
|
||||
CRYP_HandleTypeDef hcryp = {0};
|
||||
uint32_t iv[] = {0, 0, 0, 0};
|
||||
|
||||
hcryp.Instance = SAES;
|
||||
hcryp.Init.DataType = CRYP_NO_SWAP;
|
||||
hcryp.Init.KeySelect = CRYP_KEYSEL_HSW;
|
||||
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
|
||||
hcryp.Init.pKey = NULL;
|
||||
hcryp.Init.pInitVect = iv;
|
||||
hcryp.Init.Algorithm = CRYP_AES_ECB;
|
||||
hcryp.Init.Header = NULL;
|
||||
hcryp.Init.HeaderSize = 0;
|
||||
hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
|
||||
hcryp.Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE;
|
||||
hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
|
||||
hcryp.Init.KeyMode = CRYP_KEYMODE_NORMAL;
|
||||
|
||||
if (HAL_CRYP_Init(&hcryp) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
secure_aes_load_bhk();
|
||||
|
||||
if (HAL_CRYP_Decrypt(&hcryp, input, size, output, HAL_MAX_DELAY) != HAL_OK) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
HAL_CRYP_DeInit(&hcryp);
|
||||
|
||||
return sectrue;
|
||||
}
|
563
core/embed/trezorhal/stm32u5/stm32u5xx_hal_conf.h
Normal file
563
core/embed/trezorhal/stm32u5/stm32u5xx_hal_conf.h
Normal file
@ -0,0 +1,563 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32u5xx_hal_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief HAL configuration file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2021 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef STM32U5xx_HAL_CONF_H
|
||||
#define STM32U5xx_HAL_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
#define USE_USB_HS
|
||||
#define USE_USB_HS_INTERNAL_PHY
|
||||
|
||||
/* ########################## Module Selection ############################## */
|
||||
/**
|
||||
* @brief This is the list of modules to be used in the HAL driver
|
||||
*/
|
||||
|
||||
#define HAL_MODULE_ENABLED
|
||||
|
||||
/*#define HAL_ADC_MODULE_ENABLED */
|
||||
/*#define HAL_MDF_MODULE_ENABLED */
|
||||
/*#define HAL_COMP_MODULE_ENABLED */
|
||||
/*#define HAL_CORDIC_MODULE_ENABLED */
|
||||
/*#define HAL_CRC_MODULE_ENABLED */
|
||||
/*#define HAL_CRYP_MODULE_ENABLED */
|
||||
/*#define HAL_DAC_MODULE_ENABLED */
|
||||
#define HAL_DMA2D_MODULE_ENABLED
|
||||
#define HAL_DSI_MODULE_ENABLED
|
||||
/*#define HAL_FDCAN_MODULE_ENABLED */
|
||||
/*#define HAL_FMAC_MODULE_ENABLED */
|
||||
#define HAL_GFXMMU_MODULE_ENABLED
|
||||
/*#define HAL_GPU2D_MODULE_ENABLED */
|
||||
#define HAL_GTZC_MODULE_ENABLED
|
||||
/*#define HAL_HASH_MODULE_ENABLED */
|
||||
/*#define HAL_HRTIM_MODULE_ENABLED */
|
||||
/*#define HAL_IRDA_MODULE_ENABLED */
|
||||
/*#define HAL_IWDG_MODULE_ENABLED */
|
||||
#define HAL_I2C_MODULE_ENABLED
|
||||
/*#define HAL_I2S_MODULE_ENABLED */
|
||||
/*#define HAL_LPTIM_MODULE_ENABLED */
|
||||
#define HAL_LTDC_MODULE_ENABLED
|
||||
/*#define HAL_NAND_MODULE_ENABLED */
|
||||
/*#define HAL_NOR_MODULE_ENABLED */
|
||||
/*#define HAL_OPAMP_MODULE_ENABLED */
|
||||
/*#define HAL_OSPI_MODULE_ENABLED */
|
||||
/*#define HAL_OTFDEC_MODULE_ENABLED */
|
||||
/*#define HAL_PKA_MODULE_ENABLED */
|
||||
/*#define HAL_QSPI_MODULE_ENABLED */
|
||||
/*#define HAL_RNG_MODULE_ENABLED */
|
||||
#define HAL_RTC_MODULE_ENABLED
|
||||
/*#define HAL_SAI_MODULE_ENABLED */
|
||||
#define HAL_CRYP_MODULE_ENABLED
|
||||
/*#define HAL_SD_MODULE_ENABLED */
|
||||
/*#define HAL_MMC_MODULE_ENABLED */
|
||||
/*#define HAL_SMARTCARD_MODULE_ENABLED */
|
||||
/*#define HAL_SMBUS_MODULE_ENABLED */
|
||||
/*#define HAL_SPI_MODULE_ENABLED */
|
||||
/*#define HAL_SRAM_MODULE_ENABLED */
|
||||
/*#define HAL_TIM_MODULE_ENABLED */
|
||||
/*#define HAL_TSC_MODULE_ENABLED */
|
||||
/*#define HAL_RAMCFG_MODULE_ENABLED */
|
||||
#define HAL_UART_MODULE_ENABLED
|
||||
/*#define HAL_USART_MODULE_ENABLED */
|
||||
/*#define HAL_WWDG_MODULE_ENABLED */
|
||||
/*#define HAL_DCMI_MODULE_ENABLED */
|
||||
/*#define HAL_PSSI_MODULE_ENABLED */
|
||||
#define HAL_ICACHE_MODULE_ENABLED
|
||||
/*#define HAL_DCACHE_MODULE_ENABLED */
|
||||
#define HAL_PCD_MODULE_ENABLED
|
||||
/*#define HAL_HCD_MODULE_ENABLED */
|
||||
/*#define HAL_XSPI_MODULE_ENABLED */
|
||||
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
#define HAL_EXTI_MODULE_ENABLED
|
||||
#define HAL_DMA_MODULE_ENABLED
|
||||
#define HAL_RCC_MODULE_ENABLED
|
||||
#define HAL_FLASH_MODULE_ENABLED
|
||||
#define HAL_PWR_MODULE_ENABLED
|
||||
#define HAL_CORTEX_MODULE_ENABLED
|
||||
|
||||
/* ########################## Oscillator Values adaptation
|
||||
* ####################*/
|
||||
/**
|
||||
* @brief Adjust the value of External High Speed oscillator (HSE) used in your
|
||||
* application. This value is used by the RCC HAL module to compute the system
|
||||
* frequency (when HSE is used as system clock source, directly or through the
|
||||
* PLL).
|
||||
*/
|
||||
#if !defined(HSE_VALUE)
|
||||
#define HSE_VALUE 16000000UL /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined(HSE_STARTUP_TIMEOUT)
|
||||
#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up, in ms */
|
||||
#endif /* HSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Internal Multiple Speed oscillator (MSI) default value.
|
||||
* This value is the default MSI range value after Reset.
|
||||
*/
|
||||
#if !defined(MSI_VALUE)
|
||||
#define MSI_VALUE 4000000UL /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* MSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Internal High Speed oscillator (HSI) value.
|
||||
* This value is used by the RCC HAL module to compute the system
|
||||
* frequency (when HSI is used as system clock source, directly or through the
|
||||
* PLL).
|
||||
*/
|
||||
#if !defined(HSI_VALUE)
|
||||
#define HSI_VALUE 16000000UL /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and
|
||||
* RNG. This internal oscillator is mainly dedicated to provide a high precision
|
||||
* clock to the USB peripheral by means of a special Clock Recovery System (CRS)
|
||||
* circuitry. When the CRS is not used, the HSI48 RC oscillator runs on it
|
||||
* default frequency which is subject to manufacturing process variations.
|
||||
*/
|
||||
#if !defined(HSI48_VALUE)
|
||||
#define HSI48_VALUE \
|
||||
48000000UL /*!< Value of the Internal High Speed oscillator for USB \
|
||||
FS/SDMMC/RNG in Hz. The real value my vary depending on \
|
||||
manufacturing process variations.*/
|
||||
#endif /* HSI48_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Internal Low Speed oscillator (LSI) value.
|
||||
*/
|
||||
#if !defined(LSI_VALUE)
|
||||
#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz*/
|
||||
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz \
|
||||
The real value may vary depending on the \
|
||||
variations in voltage and temperature.*/
|
||||
/**
|
||||
* @brief External Low Speed oscillator (LSE) value.
|
||||
* This value is used by the UART, RTC HAL module to compute the system
|
||||
* frequency
|
||||
*/
|
||||
#if !defined(LSE_VALUE)
|
||||
#define LSE_VALUE \
|
||||
32768UL /*!< Value of the External Low Speed oscillator in Hz */
|
||||
#endif /* LSE_VALUE */
|
||||
|
||||
#if !defined(LSE_STARTUP_TIMEOUT)
|
||||
#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up, in ms */
|
||||
#endif /* LSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief External clock source for SAI1 peripheral
|
||||
* This value is used by the RCC HAL module to compute the SAI1 & SAI2
|
||||
* clock source frequency.
|
||||
*/
|
||||
#if !defined(EXTERNAL_SAI1_CLOCK_VALUE)
|
||||
#define EXTERNAL_SAI1_CLOCK_VALUE \
|
||||
48000UL /*!< Value of the SAI1 External clock source in Hz*/
|
||||
#endif /* EXTERNAL_SAI1_CLOCK_VALUE */
|
||||
|
||||
/* Tip: To avoid modifying this file each time you need to use different HSE,
|
||||
=== you can define the HSE value in your toolchain compiler preprocessor. */
|
||||
|
||||
/* ########################### System Configuration ######################### */
|
||||
/**
|
||||
* @brief This is the HAL system configuration section
|
||||
*/
|
||||
|
||||
#define VDD_VALUE 3300UL /*!< Value of VDD in mv */
|
||||
#define TICK_INT_PRIORITY \
|
||||
(15UL) /*!< tick interrupt priority (lowest by default) */
|
||||
#define USE_RTOS 0U
|
||||
#define PREFETCH_ENABLE 1U /*!< Enable prefetch */
|
||||
|
||||
/* ########################## Assert Selection ############################## */
|
||||
/**
|
||||
* @brief Uncomment the line below to expanse the "assert_param" macro in the
|
||||
* HAL drivers code
|
||||
*/
|
||||
|
||||
/* #define USE_FULL_ASSERT 1U */
|
||||
|
||||
/* ################## Register callback feature configuration ############### */
|
||||
/**
|
||||
* @brief Set below the peripheral configuration to "1U" to add the support
|
||||
* of HAL callback registration/unregistration feature for the HAL
|
||||
* driver(s). This allows user application to provide specific callback
|
||||
* functions thanks to HAL_PPP_RegisterCallback() rather than overwriting
|
||||
* the default weak callback functions (see each stm32u5xx_hal_ppp.h file
|
||||
* for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef
|
||||
* for each PPP peripheral).
|
||||
*/
|
||||
#define USE_HAL_ADC_REGISTER_CALLBACKS \
|
||||
0U /* ADC register callback disabled */
|
||||
#define USE_HAL_COMP_REGISTER_CALLBACKS \
|
||||
0U /* COMP register callback disabled */
|
||||
#define USE_HAL_CORDIC_REGISTER_CALLBACKS \
|
||||
0U /* CORDIC register callback disabled */
|
||||
#define USE_HAL_CRYP_REGISTER_CALLBACKS \
|
||||
0U /* CRYP register callback disabled */
|
||||
#define USE_HAL_DAC_REGISTER_CALLBACKS \
|
||||
0U /* DAC register callback disabled */
|
||||
#define USE_HAL_DCMI_REGISTER_CALLBACKS \
|
||||
0U /* DCMI register callback disabled */
|
||||
#define USE_HAL_DMA2D_REGISTER_CALLBACKS \
|
||||
0U /* DMA2D register callback disabled */
|
||||
#define USE_HAL_DSI_REGISTER_CALLBACKS \
|
||||
0U /* DSI register callback disabled */
|
||||
#define USE_HAL_ETH_REGISTER_CALLBACKS \
|
||||
0U /* ETH register callback disabled */
|
||||
#define USE_HAL_FDCAN_REGISTER_CALLBACKS \
|
||||
0U /* FDCAN register callback disabled */
|
||||
#define USE_HAL_FMAC_REGISTER_CALLBACKS \
|
||||
0U /* FMAC register callback disabled */
|
||||
#define USE_HAL_HASH_REGISTER_CALLBACKS \
|
||||
0U /* HASH register callback disabled */
|
||||
#define USE_HAL_HCD_REGISTER_CALLBACKS \
|
||||
0U /* HCD register callback disabled */
|
||||
#define USE_HAL_GFXMMU_REGISTER_CALLBACKS \
|
||||
0U /* GFXMMU register callback disabled */
|
||||
#define USE_HAL_GPU2D_REGISTER_CALLBACKS \
|
||||
0U /* GPU2D register callback disabled */
|
||||
#define USE_HAL_I2C_REGISTER_CALLBACKS \
|
||||
0U /* I2C register callback disabled */
|
||||
#define USE_HAL_IWDG_REGISTER_CALLBACKS \
|
||||
0U /* IWDG register callback disabled */
|
||||
#define USE_HAL_IRDA_REGISTER_CALLBACKS \
|
||||
0U /* IRDA register callback disabled */
|
||||
#define USE_HAL_LPTIM_REGISTER_CALLBACKS \
|
||||
0U /* LPTIM register callback disabled */
|
||||
#define USE_HAL_LTDC_REGISTER_CALLBACKS \
|
||||
0U /* LTDC register callback disabled */
|
||||
#define USE_HAL_MDF_REGISTER_CALLBACKS \
|
||||
0U /* MDF register callback disabled */
|
||||
#define USE_HAL_MMC_REGISTER_CALLBACKS \
|
||||
0U /* MMC register callback disabled */
|
||||
#define USE_HAL_NAND_REGISTER_CALLBACKS \
|
||||
0U /* NAND register callback disabled */
|
||||
#define USE_HAL_NOR_REGISTER_CALLBACKS \
|
||||
0U /* NOR register callback disabled */
|
||||
#define USE_HAL_OPAMP_REGISTER_CALLBACKS \
|
||||
0U /* MDIO register callback disabled */
|
||||
#define USE_HAL_OTFDEC_REGISTER_CALLBACKS \
|
||||
0U /* OTFDEC register callback disabled */
|
||||
#define USE_HAL_PCD_REGISTER_CALLBACKS \
|
||||
0U /* PCD register callback disabled */
|
||||
#define USE_HAL_PKA_REGISTER_CALLBACKS \
|
||||
0U /* PKA register callback disabled */
|
||||
#define USE_HAL_RAMCFG_REGISTER_CALLBACKS \
|
||||
0U /* RAMCFG register callback disabled */
|
||||
#define USE_HAL_RNG_REGISTER_CALLBACKS \
|
||||
0U /* RNG register callback disabled */
|
||||
#define USE_HAL_RTC_REGISTER_CALLBACKS \
|
||||
0U /* RTC register callback disabled */
|
||||
#define USE_HAL_SAI_REGISTER_CALLBACKS \
|
||||
0U /* SAI register callback disabled */
|
||||
#define USE_HAL_SD_REGISTER_CALLBACKS \
|
||||
0U /* SD register callback disabled */
|
||||
#define USE_HAL_SDRAM_REGISTER_CALLBACKS \
|
||||
0U /* SDRAM register callback disabled */
|
||||
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS \
|
||||
0U /* SMARTCARD register callback disabled */
|
||||
#define USE_HAL_SMBUS_REGISTER_CALLBACKS \
|
||||
0U /* SMBUS register callback disabled */
|
||||
#define USE_HAL_SPI_REGISTER_CALLBACKS \
|
||||
0U /* SPI register callback disabled */
|
||||
#define USE_HAL_SRAM_REGISTER_CALLBACKS \
|
||||
0U /* SRAM register callback disabled */
|
||||
#define USE_HAL_TIM_REGISTER_CALLBACKS \
|
||||
0U /* TIM register callback disabled */
|
||||
#define USE_HAL_TSC_REGISTER_CALLBACKS \
|
||||
0U /* TSC register callback disabled */
|
||||
#define USE_HAL_UART_REGISTER_CALLBACKS \
|
||||
0U /* UART register callback disabled */
|
||||
#define USE_HAL_USART_REGISTER_CALLBACKS \
|
||||
0U /* USART register callback disabled */
|
||||
#define USE_HAL_WWDG_REGISTER_CALLBACKS \
|
||||
0U /* WWDG register callback disabled */
|
||||
#define USE_HAL_OSPI_REGISTER_CALLBACKS \
|
||||
0U /* OSPI register callback disabled */
|
||||
/* ################## SPI peripheral configuration ########################## */
|
||||
|
||||
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
|
||||
* Activated: CRC code is present inside driver
|
||||
* Deactivated: CRC code cleaned from driver
|
||||
*/
|
||||
#define USE_SPI_CRC 0U
|
||||
|
||||
/* ################## SDMMC peripheral configuration #########################
|
||||
*/
|
||||
|
||||
#define USE_SD_TRANSCEIVER 0U /*!< use uSD Transceiver */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Include module's header file
|
||||
*/
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_rcc.h"
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_gpio.h"
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ICACHE_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_icache.h"
|
||||
#endif /* HAL_ICACHE_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DCACHE_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_dcache.h"
|
||||
#endif /* HAL_DCACHE_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GTZC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_gtzc.h"
|
||||
#endif /* HAL_GTZC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DMA_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_dma.h"
|
||||
#endif /* HAL_DMA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DMA2D_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_dma2d.h"
|
||||
#endif /* HAL_DMA2D_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DSI_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_dsi.h"
|
||||
#endif /* HAL_DSI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_cortex.h"
|
||||
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PKA_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_pka.h"
|
||||
#endif /* HAL_PKA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ADC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_adc.h"
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_COMP_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_comp.h"
|
||||
#endif /* HAL_COMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_crc.h"
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRYP_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_cryp.h"
|
||||
#endif /* HAL_CRYP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DAC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_dac.h"
|
||||
#endif /* HAL_DAC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_flash.h"
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HASH_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_hash.h"
|
||||
#endif /* HAL_HASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SRAM_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_sram.h"
|
||||
#endif /* HAL_SRAM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_MMC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_mmc.h"
|
||||
#endif /* HAL_MMC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_NOR_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_nor.h"
|
||||
#endif /* HAL_NOR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_NAND_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_nand.h"
|
||||
#endif /* HAL_NAND_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_i2c.h"
|
||||
#endif /* HAL_I2C_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_iwdg.h"
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LPTIM_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_lptim.h"
|
||||
#endif /* HAL_LPTIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LTDC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_ltdc.h"
|
||||
#endif /* HAL_LTDC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_OPAMP_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_opamp.h"
|
||||
#endif /* HAL_OPAMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_pwr.h"
|
||||
#endif /* HAL_PWR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_OSPI_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_ospi.h"
|
||||
#endif /* HAL_OSPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RNG_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_rng.h"
|
||||
#endif /* HAL_RNG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_rtc.h"
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SAI_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_sai.h"
|
||||
#endif /* HAL_SAI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SD_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_sd.h"
|
||||
#endif /* HAL_SD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMBUS_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_smbus.h"
|
||||
#endif /* HAL_SMBUS_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_spi.h"
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_tim.h"
|
||||
#endif /* HAL_TIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TSC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_tsc.h"
|
||||
#endif /* HAL_TSC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_uart.h"
|
||||
#endif /* HAL_UART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_usart.h"
|
||||
#endif /* HAL_USART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IRDA_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_irda.h"
|
||||
#endif /* HAL_IRDA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMARTCARD_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_smartcard.h"
|
||||
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_WWDG_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_wwdg.h"
|
||||
#endif /* HAL_WWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_pcd.h"
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HCD_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_hcd.h"
|
||||
#endif /* HAL_HCD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORDIC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_cordic.h"
|
||||
#endif /* HAL_CORDIC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DCMI_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_dcmi.h"
|
||||
#endif /* HAL_DCMI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_exti.h"
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FDCAN_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_fdcan.h"
|
||||
#endif /* HAL_FDCAN_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FMAC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_fmac.h"
|
||||
#endif /* HAL_FMAC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GFXMMU_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_gfxmmu.h"
|
||||
#endif /* HAL_GFXMMU_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPU2D_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_gpu2d.h"
|
||||
#endif /* HAL_GPU2D_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_OTFDEC_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_otfdec.h"
|
||||
#endif /* HAL_OTFDEC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PSSI_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_pssi.h"
|
||||
#endif /* HAL_PSSI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RAMCFG_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_ramcfg.h"
|
||||
#endif /* HAL_RAMCFG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_MDF_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_mdf.h"
|
||||
#endif /* HAL_MDF_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_XSPI_MODULE_ENABLED
|
||||
#include "stm32u5xx_hal_xspi.h"
|
||||
#endif /* HAL_XSPI_MODULE_ENABLED */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief The assert_param macro is used for function's parameters check.
|
||||
* @param expr: If expr is false, it calls assert_failed function
|
||||
* which reports the name of the source file and the source
|
||||
* line number of the call that failed.
|
||||
* If expr is true, it returns no value.
|
||||
* @retval None
|
||||
*/
|
||||
#define assert_param(expr) \
|
||||
((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void assert_failed(uint8_t *file, uint32_t line);
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* STM32U5xx_HAL_CONF_H */
|
1
core/embed/trezorhal/stm32u5/supervise.c
Symbolic link
1
core/embed/trezorhal/stm32u5/supervise.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/supervise.c
|
1
core/embed/trezorhal/stm32u5/supervise.h
Symbolic link
1
core/embed/trezorhal/stm32u5/supervise.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/supervise.h
|
1
core/embed/trezorhal/stm32u5/systemview.h
Symbolic link
1
core/embed/trezorhal/stm32u5/systemview.h
Symbolic link
@ -0,0 +1 @@
|
||||
../../firmware/systemview.h
|
1
core/embed/trezorhal/stm32u5/systick.c
Symbolic link
1
core/embed/trezorhal/stm32u5/systick.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/systick.c
|
1
core/embed/trezorhal/stm32u5/systick.h
Symbolic link
1
core/embed/trezorhal/stm32u5/systick.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/systick.h
|
217
core/embed/trezorhal/stm32u5/tamper.c
Normal file
217
core/embed/trezorhal/stm32u5/tamper.c
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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 <irq.h>
|
||||
#include <supervise.h>
|
||||
#include <tamper.h>
|
||||
#include STM32_HAL_H
|
||||
|
||||
// Fixes a typo in CMSIS Device library for STM32U5
|
||||
#undef TAMP_CR3_ITAMP7NOER_Msk
|
||||
#undef TAMP_CR3_ITAMP7NOER
|
||||
#define TAMP_CR3_ITAMP7NOER_Msk (0x1UL << TAMP_CR3_ITAMP7NOER_Pos)
|
||||
#define TAMP_CR3_ITAMP7NOER TAMP_CR3_ITAMP7NOER_Msk
|
||||
|
||||
// more flash efficient function than standard HAL
|
||||
HAL_StatusTypeDef lsi_init(void) {
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
FlagStatus pwrclkchanged = RESET;
|
||||
|
||||
/* Update LSI configuration in Backup Domain control register */
|
||||
/* Requires to enable write access to Backup Domain of necessary */
|
||||
if (__HAL_RCC_PWR_IS_CLK_DISABLED()) {
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
pwrclkchanged = SET;
|
||||
}
|
||||
|
||||
if (HAL_IS_BIT_CLR(PWR->DBPR, PWR_DBPR_DBP)) {
|
||||
/* Enable write access to Backup domain */
|
||||
SET_BIT(PWR->DBPR, PWR_DBPR_DBP);
|
||||
|
||||
/* Wait for Backup domain Write protection disable */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
while (HAL_IS_BIT_CLR(PWR->DBPR, PWR_DBPR_DBP)) {
|
||||
if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) {
|
||||
/* Restore clock configuration if changed */
|
||||
if (pwrclkchanged == SET) {
|
||||
__HAL_RCC_PWR_CLK_DISABLE();
|
||||
}
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bdcr_temp = RCC->BDCR;
|
||||
|
||||
if (RCC_LSI_DIV1 != (bdcr_temp & RCC_BDCR_LSIPREDIV)) {
|
||||
if (((bdcr_temp & RCC_BDCR_LSIRDY) == RCC_BDCR_LSIRDY) &&
|
||||
((bdcr_temp & RCC_BDCR_LSION) != RCC_BDCR_LSION)) {
|
||||
/* If LSIRDY is set while LSION is not enabled, LSIPREDIV can't be updated
|
||||
*/
|
||||
/* The LSIPREDIV cannot be changed if the LSI is used by the IWDG or by
|
||||
* the RTC */
|
||||
/* Restore clock configuration if changed */
|
||||
if (pwrclkchanged == SET) {
|
||||
__HAL_RCC_PWR_CLK_DISABLE();
|
||||
}
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Turn off LSI before changing RCC_BDCR_LSIPREDIV */
|
||||
if ((bdcr_temp & RCC_BDCR_LSION) == RCC_BDCR_LSION) {
|
||||
__HAL_RCC_LSI_DISABLE();
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till LSI is disabled */
|
||||
while (READ_BIT(RCC->BDCR, RCC_BDCR_LSIRDY) != 0U)
|
||||
;
|
||||
}
|
||||
|
||||
/* Set LSI division factor */
|
||||
MODIFY_REG(RCC->BDCR, RCC_BDCR_LSIPREDIV, 0);
|
||||
}
|
||||
|
||||
/* Enable the Internal Low Speed oscillator (LSI) */
|
||||
__HAL_RCC_LSI_ENABLE();
|
||||
|
||||
/* Wait till LSI is ready */
|
||||
while (READ_BIT(RCC->BDCR, RCC_BDCR_LSIRDY) == 0U)
|
||||
;
|
||||
|
||||
/* Restore clock configuration if changed */
|
||||
if (pwrclkchanged == SET) {
|
||||
__HAL_RCC_PWR_CLK_DISABLE();
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
void tamper_init(void) {
|
||||
RCC_PeriphCLKInitTypeDef clk_init_def = {0};
|
||||
|
||||
// Enable LSI clock
|
||||
lsi_init();
|
||||
|
||||
// Select RTC peripheral clock source
|
||||
clk_init_def.PeriphClockSelection = RCC_PERIPHCLK_RTC;
|
||||
clk_init_def.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
|
||||
HAL_RCCEx_PeriphCLKConfig(&clk_init_def);
|
||||
|
||||
// Enable RTC peripheral (tampers are part of it)
|
||||
__HAL_RCC_RTC_ENABLE();
|
||||
__HAL_RCC_RTCAPB_CLK_ENABLE();
|
||||
|
||||
// Clear all pending interrupts
|
||||
// They may be some as RTC/TAMP peripherals resides inside the
|
||||
// backup voltage domain
|
||||
TAMP->SCR = TAMP_SCR_CTAMP2F | TAMP_SCR_CITAMP1F | TAMP_SCR_CITAMP2F |
|
||||
TAMP_SCR_CITAMP3F | TAMP_SCR_CITAMP5F | TAMP_SCR_CITAMP6F |
|
||||
TAMP_SCR_CITAMP7F | TAMP_SCR_CITAMP8F | TAMP_SCR_CITAMP9F |
|
||||
TAMP_SCR_CITAMP11F | TAMP_SCR_CITAMP12F | TAMP_SCR_CITAMP13F;
|
||||
|
||||
NVIC_ClearPendingIRQ(TAMP_IRQn);
|
||||
|
||||
// Enable battery and power monitoring (!@# rework it)
|
||||
RCC->AHB3ENR |= RCC_AHB3ENR_PWREN;
|
||||
// HAL_PWR_EnableBkUpAccess();
|
||||
PWR->BDCR1 |= PWR_BDCR1_MONEN;
|
||||
// HAL_PWR_DisableBkUpAccess();
|
||||
|
||||
// Enable all internal tampers (4th and 10th are intentionally skipped)
|
||||
// We select all of them despite some of them are never triggered
|
||||
TAMP->CR1 =
|
||||
TAMP_CR1_ITAMP1E | // backup domain voltage monitoring
|
||||
TAMP_CR1_ITAMP2E | // temperature monitoring
|
||||
TAMP_CR1_ITAMP3E | // LSE monitoring (LSECSS)
|
||||
TAMP_CR1_ITAMP5E | // RTC calendar overflow
|
||||
TAMP_CR1_ITAMP6E | // JTAG/SWD access when RDP > 0
|
||||
TAMP_CR1_ITAMP7E | // ADC4 analog watchdog monitoring 1
|
||||
TAMP_CR1_ITAMP8E | // Monotonic counter 1 overflow
|
||||
TAMP_CR1_ITAMP9E | // Crypto periherals fault (SAES, AES, PKA, TRNG)
|
||||
TAMP_CR1_ITAMP11E | // IWDG reset when tamper flag is set
|
||||
TAMP_CR1_ITAMP12E | // ADC4 analog watchdog monitoring 2
|
||||
TAMP_CR1_ITAMP13E; // ADC4 analog watchdog monitoring 3
|
||||
|
||||
// Switch all internal tampers to the "confirmed" mode
|
||||
// => all secrets all deleted when any tamper event is triggered
|
||||
TAMP->CR3 = 0;
|
||||
|
||||
// Setup external tampers
|
||||
// TAMP_IN2 active low, "confirmed" mode
|
||||
TAMP->CR2 = 0;
|
||||
// TAMP_CR2_TAMP2TRG;
|
||||
|
||||
// Set external tamper input filter
|
||||
TAMP->FLTCR =
|
||||
// TAMP_FLTCR_TAMPPUDIS | // disable pre-charge of TAMP_INx pins
|
||||
(3 << TAMP_FLTCR_TAMPPRCH_Pos) | // pre-charge 8 RTCCLK cycles
|
||||
(2 << TAMP_FLTCR_TAMPFLT_Pos) | // activated after 4 same samples
|
||||
(7 << TAMP_FLTCR_TAMPFREQ_Pos); // sampling period RTCCLK / 256 (128Hz)
|
||||
|
||||
// Enable all interrupts for all internal tampers
|
||||
TAMP->IER = TAMP_IER_TAMP2IE | TAMP_IER_ITAMP1IE | TAMP_IER_ITAMP2IE |
|
||||
TAMP_IER_ITAMP3IE | TAMP_IER_ITAMP5IE | TAMP_IER_ITAMP6IE |
|
||||
TAMP_IER_ITAMP7IE | TAMP_IER_ITAMP8IE | TAMP_IER_ITAMP9IE |
|
||||
TAMP_IER_ITAMP11IE | TAMP_IER_ITAMP12IE | TAMP_IER_ITAMP13IE;
|
||||
|
||||
// Enable TAMP interrupt at NVIC controller
|
||||
NVIC_SetPriority(TAMP_IRQn, IRQ_PRI_TAMP);
|
||||
NVIC_EnableIRQ(TAMP_IRQn);
|
||||
}
|
||||
|
||||
// Interrupt handle for all tamper events
|
||||
// It displays an error message
|
||||
void TAMP_IRQHandler(void) {
|
||||
const char* reason = "UNKNOWN";
|
||||
|
||||
uint32_t sr = TAMP->SR;
|
||||
TAMP->SCR = sr;
|
||||
|
||||
if (sr & TAMP_SR_TAMP1F) {
|
||||
reason = "INPUT1";
|
||||
} else if (sr & TAMP_SR_TAMP2F) {
|
||||
reason = "INPUT2";
|
||||
} else if (sr & TAMP_SR_ITAMP1F) {
|
||||
reason = "VOLTAGE";
|
||||
} else if (sr & TAMP_SR_ITAMP2F) {
|
||||
reason = "TEMPERATURE";
|
||||
} else if (sr & TAMP_SR_ITAMP3F) {
|
||||
reason = "LSE CLOCK";
|
||||
} else if (sr & TAMP_SR_ITAMP5F) {
|
||||
reason = "RTC OVERFLOW";
|
||||
} else if (sr & TAMP_SR_ITAMP6F) {
|
||||
reason = "SWD ACCESS";
|
||||
} else if (sr & TAMP_SR_ITAMP7F) {
|
||||
reason = "ANALOG WDG1";
|
||||
} else if (sr & TAMP_SR_ITAMP8F) {
|
||||
reason = "MONO COUNTER";
|
||||
} else if (sr & TAMP_SR_ITAMP9F) {
|
||||
reason = "CRYPTO ERROR";
|
||||
} else if (sr & TAMP_SR_ITAMP11F) {
|
||||
reason = "IWDG";
|
||||
} else if (sr & TAMP_SR_ITAMP12F) {
|
||||
reason = "ANALOG WDG2";
|
||||
} else if (sr & TAMP_SR_ITAMP13F) {
|
||||
reason = "ANALOG WDG3";
|
||||
}
|
||||
|
||||
error_shutdown("INTERNAL TAMPER", reason);
|
||||
}
|
200
core/embed/trezorhal/stm32u5/trustzone.c
Normal file
200
core/embed/trezorhal/stm32u5/trustzone.c
Normal file
@ -0,0 +1,200 @@
|
||||
#include "trustzone.h"
|
||||
|
||||
#ifdef BOARDLOADER
|
||||
|
||||
#include STM32_HAL_H
|
||||
|
||||
void trustzone_init(void) {
|
||||
#if defined(__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
|
||||
|
||||
#if defined(SAU_INIT_REGION0) && (SAU_INIT_REGION0 == 1U)
|
||||
SAU_INIT_REGION(0);
|
||||
#endif
|
||||
|
||||
#if defined(SAU_INIT_REGION1) && (SAU_INIT_REGION1 == 1U)
|
||||
SAU_INIT_REGION(1);
|
||||
#endif
|
||||
|
||||
#if defined(SAU_INIT_REGION2) && (SAU_INIT_REGION2 == 1U)
|
||||
SAU_INIT_REGION(2);
|
||||
#endif
|
||||
|
||||
#if defined(SAU_INIT_REGION3) && (SAU_INIT_REGION3 == 1U)
|
||||
SAU_INIT_REGION(3);
|
||||
#endif
|
||||
|
||||
#if defined(SAU_INIT_REGION4) && (SAU_INIT_REGION4 == 1U)
|
||||
SAU_INIT_REGION(4);
|
||||
#endif
|
||||
|
||||
#if defined(SAU_INIT_REGION5) && (SAU_INIT_REGION5 == 1U)
|
||||
SAU_INIT_REGION(5);
|
||||
#endif
|
||||
|
||||
#if defined(SAU_INIT_REGION6) && (SAU_INIT_REGION6 == 1U)
|
||||
SAU_INIT_REGION(6);
|
||||
#endif
|
||||
|
||||
#if defined(SAU_INIT_REGION7) && (SAU_INIT_REGION7 == 1U)
|
||||
SAU_INIT_REGION(7);
|
||||
#endif
|
||||
|
||||
/* repeat this for all possible SAU regions */
|
||||
|
||||
#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
|
||||
|
||||
#if defined(SAU_INIT_CTRL) && (SAU_INIT_CTRL == 1U)
|
||||
SAU->CTRL =
|
||||
((SAU_INIT_CTRL_ENABLE << SAU_CTRL_ENABLE_Pos) & SAU_CTRL_ENABLE_Msk) |
|
||||
((SAU_INIT_CTRL_ALLNS << SAU_CTRL_ALLNS_Pos) & SAU_CTRL_ALLNS_Msk);
|
||||
#endif
|
||||
|
||||
#if defined(SCB_CSR_AIRCR_INIT) && (SCB_CSR_AIRCR_INIT == 1U)
|
||||
SCB->SCR = (SCB->SCR & ~(SCB_SCR_SLEEPDEEPS_Msk)) |
|
||||
((SCB_CSR_DEEPSLEEPS_VAL << SCB_SCR_SLEEPDEEPS_Pos) &
|
||||
SCB_SCR_SLEEPDEEPS_Msk);
|
||||
|
||||
SCB->AIRCR =
|
||||
(SCB->AIRCR & ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_SYSRESETREQS_Msk |
|
||||
SCB_AIRCR_BFHFNMINS_Msk | SCB_AIRCR_PRIS_Msk)) |
|
||||
((0x05FAU << SCB_AIRCR_VECTKEY_Pos) & SCB_AIRCR_VECTKEY_Msk) |
|
||||
((SCB_AIRCR_SYSRESETREQS_VAL << SCB_AIRCR_SYSRESETREQS_Pos) &
|
||||
SCB_AIRCR_SYSRESETREQS_Msk) |
|
||||
((SCB_AIRCR_PRIS_VAL << SCB_AIRCR_PRIS_Pos) & SCB_AIRCR_PRIS_Msk) |
|
||||
((SCB_AIRCR_BFHFNMINS_VAL << SCB_AIRCR_BFHFNMINS_Pos) &
|
||||
SCB_AIRCR_BFHFNMINS_Msk);
|
||||
#endif /* defined (SCB_CSR_AIRCR_INIT) && (SCB_CSR_AIRCR_INIT == 1U) */
|
||||
|
||||
#if defined(__FPU_USED) && (__FPU_USED == 1U) && defined(TZ_FPU_NS_USAGE) && \
|
||||
(TZ_FPU_NS_USAGE == 1U)
|
||||
|
||||
SCB->NSACR = (SCB->NSACR & ~(SCB_NSACR_CP10_Msk | SCB_NSACR_CP11_Msk)) |
|
||||
((SCB_NSACR_CP10_11_VAL << SCB_NSACR_CP10_Pos) &
|
||||
(SCB_NSACR_CP10_Msk | SCB_NSACR_CP11_Msk));
|
||||
|
||||
FPU->FPCCR = (FPU->FPCCR & ~(FPU_FPCCR_TS_Msk | FPU_FPCCR_CLRONRETS_Msk |
|
||||
FPU_FPCCR_CLRONRET_Msk)) |
|
||||
((FPU_FPCCR_TS_VAL << FPU_FPCCR_TS_Pos) & FPU_FPCCR_TS_Msk) |
|
||||
((FPU_FPCCR_CLRONRETS_VAL << FPU_FPCCR_CLRONRETS_Pos) &
|
||||
FPU_FPCCR_CLRONRETS_Msk) |
|
||||
((FPU_FPCCR_CLRONRET_VAL << FPU_FPCCR_CLRONRET_Pos) &
|
||||
FPU_FPCCR_CLRONRET_Msk);
|
||||
#endif
|
||||
|
||||
#if defined(NVIC_INIT_ITNS0) && (NVIC_INIT_ITNS0 == 1U)
|
||||
NVIC->ITNS[0] = NVIC_INIT_ITNS0_VAL;
|
||||
#endif
|
||||
|
||||
#if defined(NVIC_INIT_ITNS1) && (NVIC_INIT_ITNS1 == 1U)
|
||||
NVIC->ITNS[1] = NVIC_INIT_ITNS1_VAL;
|
||||
#endif
|
||||
|
||||
#if defined(NVIC_INIT_ITNS2) && (NVIC_INIT_ITNS2 == 1U)
|
||||
NVIC->ITNS[2] = NVIC_INIT_ITNS2_VAL;
|
||||
#endif
|
||||
|
||||
#if defined(NVIC_INIT_ITNS3) && (NVIC_INIT_ITNS3 == 1U)
|
||||
NVIC->ITNS[3] = NVIC_INIT_ITNS3_VAL;
|
||||
#endif
|
||||
|
||||
#if defined(NVIC_INIT_ITNS4) && (NVIC_INIT_ITNS4 == 1U)
|
||||
NVIC->ITNS[4] = NVIC_INIT_ITNS4_VAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void trustzone_run(void) {
|
||||
uint32_t index;
|
||||
MPCBB_ConfigTypeDef MPCBB_desc;
|
||||
|
||||
/* Enable GTZC peripheral clock */
|
||||
__HAL_RCC_GTZC1_CLK_ENABLE();
|
||||
__HAL_RCC_GTZC2_CLK_ENABLE();
|
||||
|
||||
/* -------------------------------------------------------------------------*/
|
||||
/* Memory isolation configuration */
|
||||
/* Initializes the memory that secure application books for non secure */
|
||||
/* -------------------------------------------------------------------------*/
|
||||
|
||||
/* -------------------------------------------------------------------------*/
|
||||
/* Internal RAM : */
|
||||
/* The booking is done through GTZC MPCBB. */
|
||||
/* Internal SRAMs are secured by default and configured by block */
|
||||
/* of 512 bytes. */
|
||||
|
||||
MPCBB_desc.SecureRWIllegalMode = GTZC_MPCBB_SRWILADIS_DISABLE;
|
||||
MPCBB_desc.InvertSecureState = GTZC_MPCBB_INVSECSTATE_NOT_INVERTED;
|
||||
MPCBB_desc.AttributeConfig.MPCBB_LockConfig_array[0] =
|
||||
0x00000000U; /* Unlocked configuration */
|
||||
|
||||
for (index = 0; index < 52; index++) {
|
||||
MPCBB_desc.AttributeConfig.MPCBB_SecConfig_array[index] = 0xFFFFFFFFU;
|
||||
MPCBB_desc.AttributeConfig.MPCBB_PrivConfig_array[index] = 0x00000000U;
|
||||
}
|
||||
|
||||
HAL_GTZC_MPCBB_ConfigMem(SRAM1_BASE, &MPCBB_desc);
|
||||
HAL_GTZC_MPCBB_ConfigMem(SRAM2_BASE, &MPCBB_desc);
|
||||
HAL_GTZC_MPCBB_ConfigMem(SRAM3_BASE, &MPCBB_desc);
|
||||
HAL_GTZC_MPCBB_ConfigMem(SRAM4_BASE, &MPCBB_desc);
|
||||
#if defined STM32U5A9xx | defined STM32U5G9xx
|
||||
HAL_GTZC_MPCBB_ConfigMem(SRAM5_BASE, &MPCBB_desc);
|
||||
#endif
|
||||
#if defined STM32U5G9xx
|
||||
HAL_GTZC_MPCBB_ConfigMem(SRAM6_BASE, &MPCBB_desc);
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------*/
|
||||
/* Internal Flash */
|
||||
/* The booking is done in both IDAU/SAU and FLASH interface */
|
||||
|
||||
/* Flash memory is secured by default and modified with Option Byte Loading */
|
||||
/* Insure SECWM2_PSTRT > SECWM2_PEND in order to have all Bank2 non-secure */
|
||||
|
||||
/* -------------------------------------------------------------------------*/
|
||||
/* External OctoSPI memory */
|
||||
/* The booking is done in both IDAU/SAU and GTZC MPCWM interface */
|
||||
|
||||
/* Default secure configuration */
|
||||
/* Else need to use HAL_GTZC_TZSC_MPCWM_ConfigMemAttributes() */
|
||||
|
||||
/* -------------------------------------------------------------------------*/
|
||||
/* External NOR/FMC memory */
|
||||
/* The booking is done in both IDAU/SAU and GTZC MPCWM interface */
|
||||
|
||||
/* Default secure configuration */
|
||||
/* Else need to use HAL_GTZC_TZSC_MPCWM_ConfigMemAttributes() */
|
||||
|
||||
/* -------------------------------------------------------------------------*/
|
||||
/* External NAND/FMC memory */
|
||||
/* The booking is done in both IDAU/SAU and GTZC MPCWM interface */
|
||||
|
||||
/* Default secure configuration */
|
||||
/* Else need to use HAL_GTZC_TZSC_MPCWM_ConfigMemAttributes() */
|
||||
|
||||
/* -------------------------------------------------------------------------*/
|
||||
/* Peripheral isolation configuration */
|
||||
/* Initializes the peripherals and features that secure application books */
|
||||
/* for secure (RCC, PWR, RTC, EXTI, DMA, OTFDEC, etc..) or leave them to */
|
||||
/* non-secure (GPIO (secured by default)) */
|
||||
/* -------------------------------------------------------------------------*/
|
||||
|
||||
#if defined STM32U5A9xx | defined STM32U5G9xx
|
||||
HAL_GTZC_TZSC_ConfigPeriphAttributes(GTZC_PERIPH_LTDC, GTZC_TZSC_PERIPH_SEC);
|
||||
HAL_GTZC_TZSC_ConfigPeriphAttributes(GTZC_PERIPH_DSI, GTZC_TZSC_PERIPH_SEC);
|
||||
HAL_GTZC_TZSC_ConfigPeriphAttributes(GTZC_PERIPH_GFXMMU,
|
||||
GTZC_TZSC_PERIPH_SEC);
|
||||
HAL_GTZC_TZSC_ConfigPeriphAttributes(GTZC_PERIPH_GFXMMU_REG,
|
||||
GTZC_TZSC_PERIPH_SEC);
|
||||
#endif
|
||||
HAL_GTZC_TZSC_ConfigPeriphAttributes(GTZC_PERIPH_DMA2D, GTZC_TZSC_PERIPH_SEC);
|
||||
|
||||
/* Clear all illegal access flags in GTZC TZIC */
|
||||
HAL_GTZC_TZIC_ClearFlag(GTZC_PERIPH_ALL);
|
||||
|
||||
/* Enable all illegal access interrupts in GTZC TZIC */
|
||||
HAL_GTZC_TZIC_EnableIT(GTZC_PERIPH_ALL);
|
||||
|
||||
/* Enable GTZC secure interrupt */
|
||||
HAL_NVIC_SetPriority(GTZC_IRQn, 0, 0); /* Highest priority level */
|
||||
HAL_NVIC_EnableIRQ(GTZC_IRQn);
|
||||
}
|
||||
#endif
|
1
core/embed/trezorhal/stm32u5/usb.c
Symbolic link
1
core/embed/trezorhal/stm32u5/usb.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usb.c
|
1
core/embed/trezorhal/stm32u5/usb_hid-impl.h
Symbolic link
1
core/embed/trezorhal/stm32u5/usb_hid-impl.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usb_hid-impl.h
|
1
core/embed/trezorhal/stm32u5/usb_vcp-impl.h
Symbolic link
1
core/embed/trezorhal/stm32u5/usb_vcp-impl.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usb_vcp-impl.h
|
1
core/embed/trezorhal/stm32u5/usb_webusb-impl.h
Symbolic link
1
core/embed/trezorhal/stm32u5/usb_webusb-impl.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usb_webusb-impl.h
|
1
core/embed/trezorhal/stm32u5/usbd_conf.c
Symbolic link
1
core/embed/trezorhal/stm32u5/usbd_conf.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usbd_conf.c
|
1
core/embed/trezorhal/stm32u5/usbd_conf.h
Symbolic link
1
core/embed/trezorhal/stm32u5/usbd_conf.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usbd_conf.h
|
1
core/embed/trezorhal/stm32u5/usbd_core.c
Symbolic link
1
core/embed/trezorhal/stm32u5/usbd_core.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usbd_core.c
|
1
core/embed/trezorhal/stm32u5/usbd_core.h
Symbolic link
1
core/embed/trezorhal/stm32u5/usbd_core.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usbd_core.h
|
1
core/embed/trezorhal/stm32u5/usbd_ctlreq.c
Symbolic link
1
core/embed/trezorhal/stm32u5/usbd_ctlreq.c
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usbd_ctlreq.c
|
1
core/embed/trezorhal/stm32u5/usbd_ctlreq.h
Symbolic link
1
core/embed/trezorhal/stm32u5/usbd_ctlreq.h
Symbolic link
@ -0,0 +1 @@
|
||||
../stm32f4/usbd_ctlreq.h
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user