# source directories SRCDIR_MP = vendor/micropython SRCDIR_FW = micropython # directory containing scripts to be frozen as bytecode FROZEN_MPY_DIR ?= src # target directory TARGET ?= firmware BUILD ?= micropython/$(TARGET)/build # include py core make definitions include $(SRCDIR_MP)/py/mkenv.mk MAKE_FROZEN = $(SRCDIR_MP)/tools/make-frozen.py MPY_CROSS = $(SRCDIR_MP)/mpy-cross/mpy-cross MPY_TOOL = $(SRCDIR_MP)/tools/mpy-tool.py # sources # ===================================== BUILD_MP = $(BUILD)/$(SRCDIR_MP) BUILD_FW = $(BUILD)/$(SRCDIR_FW) BUILD_HDR = $(BUILD)/genhdr MICROPY_PY_TREZORCONFIG = 1 MICROPY_PY_TREZORCRYPTO = 1 MICROPY_PY_TREZORDEBUG = 1 MICROPY_PY_TREZORMSG = 1 MICROPY_PY_TREZORUI = 1 MICROPY_PY_TREZORUTILS = 1 MICROPY_PY_UTIME = 1 # OBJ micropython/extmod/modtrezorconfig ifeq ($(MICROPY_PY_TREZORCONFIG),1) OBJ_MOD += $(addprefix $(BUILD_FW)/,\ extmod/modtrezorconfig/modtrezorconfig.o \ extmod/modtrezorconfig/norcow.o \ ) endif # OBJ micropython/extmod/modtrezorcrypto ifeq ($(MICROPY_PY_TREZORCRYPTO),1) CFLAGS_MOD += \ -I$(SRCDIR_FW)/extmod/modtrezorcrypto/trezor-crypto \ -I$(SRCDIR_FW)/extmod/modtrezorcrypto/trezor-crypto/ed25519-donna \ -DAES_128 \ -DAES_192 \ -DUSE_KECCAK=1 \ -Wno-sequence-point OBJ_MOD += $(addprefix $(BUILD_FW)/,\ extmod/modtrezorcrypto/modtrezorcrypto.o \ extmod/modtrezorcrypto/rand.o \ extmod/modtrezorcrypto/ssss.o \ extmod/modtrezorcrypto/trezor-crypto/address.o \ extmod/modtrezorcrypto/trezor-crypto/aescrypt.o \ extmod/modtrezorcrypto/trezor-crypto/aeskey.o \ extmod/modtrezorcrypto/trezor-crypto/aes_modes.o \ extmod/modtrezorcrypto/trezor-crypto/aestab.o \ extmod/modtrezorcrypto/trezor-crypto/base58.o \ extmod/modtrezorcrypto/trezor-crypto/bignum.o \ extmod/modtrezorcrypto/trezor-crypto/bip32.o \ extmod/modtrezorcrypto/trezor-crypto/bip39.o \ extmod/modtrezorcrypto/trezor-crypto/blake2b.o \ extmod/modtrezorcrypto/trezor-crypto/blake2s.o \ extmod/modtrezorcrypto/trezor-crypto/curves.o \ extmod/modtrezorcrypto/trezor-crypto/ecdsa.o \ extmod/modtrezorcrypto/trezor-crypto/ed25519-donna/ed25519.o \ extmod/modtrezorcrypto/trezor-crypto/hmac.o \ extmod/modtrezorcrypto/trezor-crypto/nist256p1.o \ extmod/modtrezorcrypto/trezor-crypto/pbkdf2.o \ extmod/modtrezorcrypto/trezor-crypto/ripemd160.o \ extmod/modtrezorcrypto/trezor-crypto/secp256k1.o \ extmod/modtrezorcrypto/trezor-crypto/sha2.o \ extmod/modtrezorcrypto/trezor-crypto/sha3.o \ ) endif # OBJ micropython/extmod/modtrezordebug ifeq ($(MICROPY_PY_TREZORDEBUG),1) OBJ_MOD += $(addprefix $(BUILD_FW)/,\ extmod/modtrezordebug/modtrezordebug.o \ ) endif # OBJ micropython/extmod/modtrezormsg ifeq ($(MICROPY_PY_TREZORMSG),1) OBJ_MOD += $(addprefix $(BUILD_FW)/,\ extmod/modtrezormsg/modtrezormsg.o \ ) endif # OBJ micropython/extmod/modtrezorui ifeq ($(MICROPY_PY_TREZORUI),1) CFLAGS_MOD += -DQR_MAX_VERSION=0 OBJ_MOD += $(addprefix $(BUILD_FW)/,\ extmod/modtrezorui/display.o \ extmod/modtrezorui/inflate.o \ extmod/modtrezorui/font_bitmap.o \ extmod/modtrezorui/font_roboto_bold_20.o \ extmod/modtrezorui/font_roboto_regular_20.o \ extmod/modtrezorui/font_robotomono_regular_20.o \ extmod/modtrezorui/modtrezorui.o \ extmod/modtrezorui/trezor-qrenc/qr_encode.o \ ) endif # OBJ micropython/extmod/modtrezorutils ifeq ($(MICROPY_PY_TREZORUTILS),1) OBJ_MOD += $(addprefix $(BUILD_FW)/,\ extmod/modtrezorutils/modtrezorutils.o \ ) endif # OBJ micropython/extmod/modutime ifeq ($(MICROPY_PY_UTIME),1) OBJ_MOD += $(addprefix $(BUILD_FW)/,\ firmware/modutime.o \ ) endif # OBJ vendor/micropython OBJ_MICROPYTHON += $(addprefix $(BUILD_MP)/,\ \ extmod/modubinascii.o \ extmod/moductypes.o \ extmod/moduheapq.o \ extmod/modutimeq.o \ extmod/moduzlib.o \ extmod/utime_mphal.o \ \ lib/embed/abort_.o \ lib/libc/string0.o \ lib/libm/acoshf.o \ lib/libm/asinfacosf.o \ lib/libm/asinhf.o \ lib/libm/atan2f.o \ lib/libm/atanf.o \ lib/libm/atanhf.o \ lib/libm/ef_rem_pio2.o \ lib/libm/erf_lgamma.o \ lib/libm/fmodf.o \ lib/libm/kf_cos.o \ lib/libm/kf_rem_pio2.o \ lib/libm/kf_sin.o \ lib/libm/kf_tan.o \ lib/libm/log1pf.o \ lib/libm/math.o \ lib/libm/nearbyintf.o \ lib/libm/roundf.o \ lib/libm/sf_cos.o \ lib/libm/sf_erf.o \ lib/libm/sf_frexp.o \ lib/libm/sf_ldexp.o \ lib/libm/sf_modf.o \ lib/libm/sf_sin.o \ lib/libm/sf_tan.o \ lib/libm/thumb_vfp_sqrtf.o \ lib/libm/wf_lgamma.o \ lib/libm/wf_tgamma.o \ lib/utils/interrupt_char.o \ lib/utils/printf.o \ lib/utils/pyexec.o \ lib/utils/stdout_helpers.o \ \ py/argcheck.o \ py/asmarm.o \ py/asmbase.o \ py/asmthumb.o \ py/asmx64.o \ py/asmx86.o \ py/asmxtensa.o \ py/bc.o \ py/binary.o \ py/builtinevex.o \ py/builtinhelp.o \ py/builtinimport.o \ py/compile.o \ py/emitbc.o \ py/emitcommon.o \ py/emitglue.o \ py/emitinlinethumb.o \ py/emitinlinextensa.o \ py/formatfloat.o \ py/frozenmod.o \ py/gc.o \ py/lexer.o \ py/malloc.o \ py/map.o \ py/modarray.o \ py/modbuiltins.o \ py/modcmath.o \ py/modcollections.o \ py/modgc.o \ py/modio.o \ py/modmath.o \ py/modmicropython.o \ py/modstruct.o \ py/modsys.o \ py/modthread.o \ py/moduerrno.o \ py/mpprint.o \ py/mpstate.o \ py/mpz.o \ py/nativeglue.o \ py/nlrsetjmp.o \ py/nlrthumb.o \ py/nlrx64.o \ py/nlrx86.o \ py/nlrxtensa.o \ py/obj.o \ py/objarray.o \ py/objattrtuple.o \ py/objbool.o \ py/objboundmeth.o \ py/objcell.o \ py/objclosure.o \ py/objcomplex.o \ py/objdict.o \ py/objenumerate.o \ py/objexcept.o \ py/objfilter.o \ py/objfloat.o \ py/objfun.o \ py/objgenerator.o \ py/objgetitemiter.o \ py/objint_longlong.o \ py/objint_mpz.o \ py/objint.o \ py/objlist.o \ py/objmap.o \ py/objmodule.o \ py/objnamedtuple.o \ py/objnone.o \ py/objobject.o \ py/objpolyiter.o \ py/objproperty.o \ py/objrange.o \ py/objreversed.o \ py/objset.o \ py/objsingleton.o \ py/objslice.o \ py/objstr.o \ py/objstringio.o \ py/objstrunicode.o \ py/objtuple.o \ py/objtype.o \ py/objzip.o \ py/opmethods.o \ py/parse.o \ py/parsenum.o \ py/parsenumbase.o \ py/persistentcode.o \ py/qstr.o \ py/reader.o \ py/repl.o \ py/runtime_utils.o \ py/runtime.o \ py/scope.o \ py/sequence.o \ py/showbc.o \ py/smallint.o \ py/stackctrl.o \ py/stream.o \ py/unicode.o \ py/vm.o \ py/vstr.o \ py/warning.o \ \ stmhal/gccollect.o \ stmhal/gchelper.o \ stmhal/pendsv.o \ stmhal/startup_stm32.o \ stmhal/systick.o \ ) # OBJ vendor/micropython OBJ_STMHAL += $(addprefix $(BUILD_MP)/,\ stmhal/hal/f4/src/stm32f4xx_hal_adc_ex.o \ stmhal/hal/f4/src/stm32f4xx_hal_adc.o \ stmhal/hal/f4/src/stm32f4xx_hal_can.o \ stmhal/hal/f4/src/stm32f4xx_hal_cortex.o \ stmhal/hal/f4/src/stm32f4xx_hal_dac_ex.o \ stmhal/hal/f4/src/stm32f4xx_hal_dac.o \ stmhal/hal/f4/src/stm32f4xx_hal_dma.o \ stmhal/hal/f4/src/stm32f4xx_hal_flash_ex.o \ stmhal/hal/f4/src/stm32f4xx_hal_flash.o \ stmhal/hal/f4/src/stm32f4xx_hal_gpio.o \ stmhal/hal/f4/src/stm32f4xx_hal_i2c.o \ stmhal/hal/f4/src/stm32f4xx_hal_pcd_ex.o \ stmhal/hal/f4/src/stm32f4xx_hal_pcd.o \ stmhal/hal/f4/src/stm32f4xx_hal_pwr_ex.o \ stmhal/hal/f4/src/stm32f4xx_hal_pwr.o \ stmhal/hal/f4/src/stm32f4xx_hal_rcc_ex.o \ stmhal/hal/f4/src/stm32f4xx_hal_rcc.o \ stmhal/hal/f4/src/stm32f4xx_hal_rng.o \ stmhal/hal/f4/src/stm32f4xx_hal_rtc_ex.o \ stmhal/hal/f4/src/stm32f4xx_hal_rtc.o \ stmhal/hal/f4/src/stm32f4xx_hal_sd.o \ stmhal/hal/f4/src/stm32f4xx_hal_spi.o \ stmhal/hal/f4/src/stm32f4xx_hal_tim_ex.o \ stmhal/hal/f4/src/stm32f4xx_hal_tim.o \ stmhal/hal/f4/src/stm32f4xx_hal_uart.o \ stmhal/hal/f4/src/stm32f4xx_hal.o \ stmhal/hal/f4/src/stm32f4xx_ll_sdmmc.o \ stmhal/hal/f4/src/stm32f4xx_ll_usb.o \ ) # OBJ micropython/ OBJ_FIRMWARE += $(addprefix $(BUILD_FW)/, \ firmware/vendorheader.o \ firmware/header.o \ firmware/main.o \ firmware/mphalport.o \ ) OBJ_TREZORHAL += $(addprefix $(BUILD_FW)/, \ trezorhal/common.o \ trezorhal/flash.o \ trezorhal/rng.o \ trezorhal/sdcard.o \ trezorhal/stm32_it.o \ trezorhal/stm32_system.o \ trezorhal/touch.o \ trezorhal/usb.o \ trezorhal/usbd_conf.o \ trezorhal/usbd_core.o \ trezorhal/usbd_ctlreq.o \ trezorhal/usbd_ioreq.o \ trezorhal/hal/stm32f4xx_hal_sram.o \ trezorhal/hal/stm32f4xx_ll_fsmc.o \ ) # make a list of all the .py files that need compiling and freezing FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)/==') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) OBJ = $(OBJ_MICROPYTHON) $(OBJ_STMHAL) $(OBJ_TREZORHAL) OBJ += $(OBJ_MOD) OBJ += $(OBJ_FIRMWARE) OBJ += $(BUILD)/frozen_mpy.o SRC_MP = $(patsubst $(BUILD_MP)%.o, $(SRCDIR_MP)%.c, $(OBJ_MICROPYTHON)) SRC_MOD = $(patsubst $(BUILD_FW)%.o, $(SRCDIR_FW)%.c, $(OBJ_MOD)) # comp flags # ===================================== CROSS_COMPILE = arm-none-eabi- INC += -I. INC += -I$(SRCDIR_FW)/$(TARGET) INC += -I$(SRCDIR_FW)/extmod/modtrezorui INC += -I$(SRCDIR_FW)/trezorhal INC += -I$(SRCDIR_FW)/trezorhal/hal INC += -I$(SRCDIR_MP) INC += -I$(SRCDIR_MP)/stmhal INC += -I$(SRCDIR_MP)/stmhal/cmsis INC += -I$(SRCDIR_MP)/stmhal/hal/f4/inc INC += -I$(SRCDIR_MP)/lib/cmsis/inc INC += -I$(BUILD) ifeq ($(DEBUG), 1) CFLAGS += -Os -ggdb else CFLAGS += -Os -DNDEBUG endif CFLAGS += $(INC) $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -std=gnu99 -nostdlib -Wall -Werror -Wdouble-promotion -Wpointer-arith CFLAGS += -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant CFLAGS += -DSTM32F405xx -DMCU_SERIES_F4 CFLAGS += -DSTM32_HAL_H='' CFLAGS += -DTREZOR_STM32 CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LDFLAGS = -nostdlib -T $(SRCDIR_FW)/$(TARGET)/memory.ld -Map=$@.map --cref # remove uncalled code from the final image CFLAGS += -fdata-sections -ffunction-sections LDFLAGS += --gc-sections # QSTR file locations QSTR_DEFS = $(SRCDIR_MP)/py/qstrdefs.h QSTR_DEFS_COLLECTED = $(BUILD_HDR)/qstrdefs.collected.h # SRC files for QSTR extraction SRC_QSTR_IGNORE = $(addprefix $(SRCDIR_MP)/py/, \ nlr% emitnx86% emitnx64% emitnthumb% emitnarm% emitnxtensa%) SRC_QSTR += $(SRC_MOD) SRC_QSTR += $(filter $(SRCDIR_MP)/lib/%,$(SRC_MP)) SRC_QSTR += $(filter $(SRCDIR_MP)/extmod/%,$(SRC_MP)) # SRC_QSTR += $(filter $(SRCDIR_MP)/stmhal/%,$(filter-out %/gchelper.o,$(SRC_MP))) SRC_QSTR += $(filter-out $(SRC_QSTR_IGNORE),$(filter $(SRCDIR_MP)/py/%,$(SRC_MP))) # extra cpp CFLAGS for QSTR extraction QSTR_GEN_EXTRA_CFLAGS += -DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB -DN_ARM -DN_XTENSA # comp rules # ===================================== all: $(BUILD)/$(TARGET).bin $(BUILD_FW)/firmware/vendorheader.o: $(SRCDIR_FW)/firmware/vendorheader.bin $(Q)$(OBJCOPY) -I binary -O elf32-littlearm -B arm \ --rename-section .data=.vendorheader,alloc,load,readonly,contents \ $< $@ $(BUILD)/$(TARGET).elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ $(BUILD)/$(TARGET).bin: $(BUILD)/$(TARGET).elf $(Q)$(OBJCOPY) -O binary -j .header -j .flash -j .data $^ $(BUILD)/$(TARGET).bin $(BUILD)/%.o: %.S $(ECHO) "CC $<" $(Q)$(CC) $(CFLAGS) -c -o $@ $< $(BUILD)/%.o: %.s $(ECHO) "AS $<" $(Q)$(AS) -o $@ $< $(BUILD)/%.o: %.c $(ECHO) "CC $<" $(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< OBJ_DIRS = $(sort $(dir $(OBJ))) $(OBJ): | $(OBJ_DIRS) $(OBJ_DIRS) $(BUILD_HDR): $(MKDIR) -p $@ $(OBJ): | $(BUILD_HDR)/qstrdefs.generated.h $(BUILD_HDR)/mpversion.h $(BUILD_HDR)/qstr.i.last: $(SRC_QSTR) | $(BUILD_HDR)/mpversion.h $(ECHO) "GEN $@" $(Q)$(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $^ >$(BUILD_HDR)/qstr.i.last; \ $(BUILD_HDR)/qstr.split: $(BUILD_HDR)/qstr.i.last $(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split $(BUILD_HDR)/qstr.i.last $(BUILD_HDR)/qstr $(QSTR_DEFS_COLLECTED) $(Q)touch $@ $(QSTR_DEFS_COLLECTED): $(BUILD_HDR)/qstr.split $(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py cat $(BUILD_HDR)/qstr.i.last $(BUILD_HDR)/qstr $(QSTR_DEFS_COLLECTED) $(BUILD_HDR)/qstrdefs.generated.h: $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) $(SRCDIR_FW)/firmware/mpconfigport.h | $(BUILD_HDR) $(ECHO) "GEN $@" $(Q)cat $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) \ | $(SED) 's/^Q(.*)/"&"/' \ | $(CPP) $(CFLAGS) - \ | $(SED) 's/^"\(Q(.*)\)"/\1/' \ > $(BUILD_HDR)/qstrdefs.preprocessed.h $(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(BUILD_HDR)/qstrdefs.preprocessed.h > $@ $(BUILD_HDR)/mpversion.h: | $(BUILD_HDR) $(Q)$(PYTHON) $(PY_SRC)/makeversionhdr.py $@ $(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py @$(ECHO) "MPY $<" $(Q)$(MKDIR) -p $(dir $@) $(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^ $(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h @$(ECHO) "Creating $@" $(Q)PYTHONPATH=$(SRCDIR_MP)/py $(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@ clean: $(RM) -rf $(BUILD) .PHONY: all clean