diff --git a/Makefile b/Makefile index b15f38dc..9951e54a 100644 --- a/Makefile +++ b/Makefile @@ -8,16 +8,23 @@ fw-$(1)-$(2)-clean: endef $(eval $(call RULES,simtrace,dfu)) +$(eval $(call RULES,simtrace,blupdate)) $(eval $(call RULES,simtrace,trace)) $(eval $(call RULES,simtrace,cardem)) $(eval $(call RULES,qmod,dfu)) +$(eval $(call RULES,qmod,blupdate)) $(eval $(call RULES,qmod,cardem)) $(eval $(call RULES,ngff_cardem,dfu)) +$(eval $(call RULES,ngff_cardem,blupdate)) $(eval $(call RULES,ngff_cardem,trace)) $(eval $(call RULES,ngff_cardem,cardem)) -fw-clean: fw-simtrace-dfu-clean fw-simtrace-trace-clean fw-simtrace-cardem-clean fw-qmod-dfu-clean fw-qmod-cardem-clean -fw: fw-simtrace-dfu fw-simtrace-trace fw-simtrace-cardem fw-qmod-dfu fw-qmod-cardem fw-ngff_cardem-dfu fw-ngff_cardem-trace fw-ngff_cardem-cardem +fw-clean: fw-simtrace-dfu-clean fw-simtrace-blupdate-clean fw-simtrace-trace-clean fw-simtrace-cardem-clean \ + fw-qmod-dfu-clean fw-qmod-blupdate-clean fw-qmod-cardem-clean \ + fw-ngff_cardem-dfu-clean fw-ngff_cardem-blupdate-clean fw-ngff_cardem-trace-clean fw-ngff_cardem-cardem-clean +fw: fw-simtrace-dfu fw-simtrace-blupdate fw-simtrace-trace fw-simtrace-cardem \ + fw-qmod-dfu fw-qmod-blupdate fw-qmod-cardem \ + fw-ngff_cardem-dfu fw-ngff_cardem-blupdate fw-ngff_cardem-trace fw-ngff_cardem-cardem utils: (cd host && \ diff --git a/firmware/Makefile b/firmware/Makefile index bfe2c9d6..810c7f3e 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -245,12 +245,13 @@ apps/$(APP)/usb_strings_generated.h: apps/$(APP)/usb_strings.txt.patched usbstri define RULES C_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(C_OBJECTS)) ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS)) +EXTRA_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(EXTRA_OBJECTS)) -$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1)) - $(SILENT)$(CC) $(CFLAGS) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS) - $(SILENT)$(NM) $(OUTPUT)-$$@.elf >$(OUTPUT)-$$@.elf.txt - $(SILENT)$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin - $(SILENT)$(SIZE) $$^ $(OUTPUT)-$$@.elf +build_$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1)) $$(EXTRA_OBJECTS_$(1)) + $(SILENT)$(CC) $(CFLAGS) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$(1).ld" -Wl,-Map,$(OUTPUT)-$(1).map -o $(OUTPUT)-$(1).elf $$^ $(LIBS) + $(SILENT)$(NM) $(OUTPUT)-$(1).elf >$(OUTPUT)-$(1).elf.txt + $(SILENT)$(OBJCOPY) -O binary $(OUTPUT)-$(1).elf $(OUTPUT)-$(1).bin + $(SILENT)$(SIZE) $$^ $(OUTPUT)-$(1).elf $$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN) @echo [COMPILING $$<] @@ -258,13 +259,34 @@ $$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN) $$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN) @echo [ASSEMBLING $$@] - $(SILENT)@$(CC) $(ASFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$< + $(SILENT)$(CC) $(ASFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$< debug_$(1): $(1) $(GDB) -x "$(BOARD_LIB)/resources/gcc/$(BOARD)_$(1).gdb" -ex "reset" -readnow -se $(OUTPUT)-$(1).elf endef -$(foreach MEMORY, $(MEMORIES), $(eval $(call RULES,$(MEMORY)))) +ALL_MEMORIES = dfu flash ram +$(foreach MEMORY, $(ALL_MEMORIES), $(eval $(call RULES,$(MEMORY)))) + +# files with those names do exist.. +.PHONY: ram +.PHONY: dfu +.PHONY: flash +ram: build_ram +dfu: build_dfu +ifeq ($(APP), blupdate) + $(info updating updater section with padded bootloader file..) + $(SILENT)dd if=/dev/zero bs=16384 count=1 of=$(BIN)/$(BOARD)-dfu-flash-padded.bin + $(SILENT)dd if=$(BIN)/$(BOARD)-dfu-flash.bin conv=notrunc of=$(BIN)/$(BOARD)-dfu-flash-padded.bin + $(SILENT)$(OBJCOPY) --update-section .blupdate=bin/$(BOARD)-dfu-flash-padded.bin bin/$(BOARD)-blupdate-dfu.elf + $(SILENT)$(OBJCOPY) -O binary bin/$(BOARD)-blupdate-dfu.elf bin/$(BOARD)-blupdate-dfu.bin +endif +flash: build_flash +#alternate way of embedding: obj file +#ifeq ($(APP), dfu) +# $(info bootloader bin file to obj..) +# $(SILENT)$(OBJCOPY) --rename-section .data=.fwupdate -I binary -O elf32-littlearm bin/$(BOARD)-dfu-flash.bin $(OBJ)/flash_fwupdate.o +#endif program: openocd -f openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/project-flash.bin 0" -c "reset" -c "shutdown" diff --git a/firmware/apps/blupdate/Makefile b/firmware/apps/blupdate/Makefile new file mode 100644 index 00000000..4f1d3779 --- /dev/null +++ b/firmware/apps/blupdate/Makefile @@ -0,0 +1,12 @@ + +C_FILES += $(C_LIBUSB_DFU) + +# Trace level used for compilation +# (can be overridden by adding TRACE_LEVEL=#number to the command-line) +# TRACE_LEVEL_DEBUG 5 +# TRACE_LEVEL_INFO 4 +# TRACE_LEVEL_WARNING 3 +# TRACE_LEVEL_ERROR 2 +# TRACE_LEVEL_FATAL 1 +# TRACE_LEVEL_NO_TRACE 0 +TRACE_LEVEL ?= 3 diff --git a/firmware/apps/blupdate/main.c b/firmware/apps/blupdate/main.c new file mode 100644 index 00000000..330d0408 --- /dev/null +++ b/firmware/apps/blupdate/main.c @@ -0,0 +1,134 @@ +/* SIMtrace 2 firmware USB DFU bootloader + * + * (C) 2015-2017 by Harald Welte + * (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "board.h" +#include "core_cm3.h" +#include "flashd.h" +#include "utils.h" +#include "usb/device/dfu/dfu.h" +#include "usb/common/dfu/usb_dfu.h" +#include "manifest.h" +#include "USBD_HAL.h" + +#include + +/* actual section content must be replaced with the padded bootloader by running objcopy! */ +const uint32_t bl_update_data[BOARD_DFU_BOOT_SIZE / sizeof(uint32_t)] __attribute__((section(".fwupdate"))) = { 0xFF }; + +unsigned int g_unique_id[4]; +/* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */ +static bool watchdog_configured = false; + +extern uint32_t _end; +extern uint32_t _srelocate; +extern uint32_t _etext; + +void DFURT_SwitchToDFU(void) +{ +} +void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request) +{ +} +int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, uint8_t *data, unsigned int len) +{ + return 0; +} +int USBDFU_handle_upload(uint8_t altif, unsigned int offset, uint8_t *data, unsigned int req_len) +{ + return 0; +} +int USBDFU_OverrideEnterDFU(void) +{ + return 0; +} + +__attribute__((section(".ramfunc"), noinline)) static uint32_t flash_wait_ready() +{ + Efc *efc = EFC; + uint32_t dwStatus; + + do { + dwStatus = efc->EEFC_FSR; + } while ((dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY); + return (dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)); +} + +__attribute__((section(".ramfunc"), noinline)) static void flash_cmd(uint32_t dwCommand, uint32_t dwArgument) +{ + Efc *efc = EFC; + uint32_t dwStatus; + efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand); +} + +__attribute__((section(".ramfunc"), noinline, noreturn)) static void erase_first_app_sector() +{ + /* page 64 */ + uint32_t first_app_page = (BOARD_DFU_BOOT_SIZE / IFLASH_PAGE_SIZE); + uint32_t *first_app_address = (uint32_t *)(IFLASH_ADDR + first_app_page * IFLASH_PAGE_SIZE + 0); + +#if 1 + /* overwrite first app sector so we don't keep booting this */ + for (int i = 0; i < IFLASH_PAGE_SIZE / 4; i++) + first_app_address[i] = 0xffffffff; + + flash_cmd(EFC_FCMD_EWP, first_app_page); +#else + /* why does erasing the whole flash with a protected bootloader not work at all? */ + flash_cmd(EFC_FCMD_EA, 0); +#endif + flash_wait_ready(); + for (;;) + NVIC_SystemReset(); +} + +#define MAX_USB_ITER BOARD_MCK / 72 // This should be around a second +extern int main(void) +{ + uint8_t isUsbConnected = 0; + unsigned int i = 0; + uint32_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos; + + /* Enable watchdog for 2000ms, with no window */ + WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | (WDT_GetPeriod(2000) << 16) | + WDT_GetPeriod(2000)); + watchdog_configured = true; + + EEFC_ReadUniqueID(g_unique_id); + + printf("\n\r\n\r"); + printf("bootloader updater %s for board %s\n\r" + "(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r", + manifest_revision, manifest_board); + + /* clear g_dfu on power-up reset */ + memset(g_dfu, 0, sizeof(*g_dfu)); + + TRACE_INFO("USB init...\n\r"); + /* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */ + USBD_Disconnect(); + + /* Initialize the flash to be able to write it, using the IAP ROM code */ + FLASHD_Initialize(BOARD_MCK, 1); + + __disable_irq(); + FLASHD_Unlock(IFLASH_ADDR, IFLASH_ADDR + IFLASH_SIZE - 1, 0, 0); + FLASHD_Write(IFLASH_ADDR, bl_update_data, BOARD_DFU_BOOT_SIZE); + + erase_first_app_sector(); +} diff --git a/firmware/libboard/common/resources/sam3s4/dfu.ld b/firmware/libboard/common/resources/sam3s4/dfu.ld index db747fad..7d896c62 100644 --- a/firmware/libboard/common/resources/sam3s4/dfu.ld +++ b/firmware/libboard/common/resources/sam3s4/dfu.ld @@ -101,6 +101,14 @@ SECTIONS *(.ARM.exidx) } + .blupdate : + { + . = ALIGN(4); + _blupdate_start = .; + KEEP(*(.fwupdate .fwupdate.*)); + _blupdate_end = .; + } > rom + . = ALIGN(4); _etext = .;