diff --git a/bootloaders/eboot/Makefile b/bootloaders/eboot/Makefile index 32e325f34..8aaac9cab 100644 --- a/bootloaders/eboot/Makefile +++ b/bootloaders/eboot/Makefile @@ -5,6 +5,7 @@ TARGET_DIR := ./ TARGET_OBJ_FILES := \ eboot.o \ + eboot_command.o \ TARGET_OBJ_PATHS := $(addprefix $(TARGET_DIR)/,$(TARGET_OBJ_FILES)) @@ -17,7 +18,7 @@ OBJDUMP := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-objdump CFLAGS += -std=gnu99 -CFLAGS += -O0 -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mno-text-section-literals +CFLAGS += -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mno-text-section-literals LDFLAGS += -nostdlib -Wl,--no-check-sections -umain diff --git a/bootloaders/eboot/eboot.c b/bootloaders/eboot/eboot.c index e39375d2d..86a27eff0 100644 --- a/bootloaders/eboot/eboot.c +++ b/bootloaders/eboot/eboot.c @@ -10,6 +10,7 @@ #include #include #include "eboot.h" +#include "eboot_command.h" extern void* flashchip; #define SWRST do { (*((volatile uint32_t*) 0x60000700)) |= 0x80000000; } while(0); @@ -71,9 +72,100 @@ int load_app_from_flash_raw(const uint32_t flash_addr) } + +int erase(const uint32_t start, const uint32_t size) +{ + if (start & (FLASH_SECTOR_SIZE - 1) != 0) { + return 1; + } + + const uint32_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE; + uint32_t current_sector = start / FLASH_SECTOR_SIZE; + uint32_t sector_count = (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE; + const uint32_t end = current_sector + sector_count; + + for (; current_sector < end && (current_sector & (sectors_per_block-1)); + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 2; + } + } + + for (;current_sector + sectors_per_block <= end; + current_sector += sectors_per_block, + sector_count -= sectors_per_block) { + if (SPIEraseBlock(current_sector / sectors_per_block)) { + return 3; + } + } + + for (; current_sector < end; + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 4; + } + } + + return 0; +} + +int copy_raw(const uint32_t src_addr, + const uint32_t dst_addr, + const uint32_t size) +{ + // require regions to be aligned + if (src_addr & 0xfff != 0 || + dst_addr & 0xfff != 0) { + return 1; + } + + if (erase(dst_addr, size)) { + return 2; + } + + const uint32_t buffer_size = 4096; + uint8_t buffer[buffer_size]; + + const uint32_t end = src_addr + size; + uint32_t saddr = src_addr; + uint32_t daddr = dst_addr; + uint32_t left = size; + while (saddr < end) { + uint32_t will_copy = (left < buffer_size) ? left : buffer_size; + if (SPIRead(saddr, buffer, will_copy)) { + return 3; + } + if (SPIWrite(daddr, buffer, will_copy)) { + return 4; + } + saddr += will_copy; + daddr += will_copy; + left -= will_copy; + } + + return 0; +} + + + void main() { - int res = load_app_from_flash_raw(0); + int res; + struct eboot_command cmd; + + eboot_command_read(&cmd); + + if (cmd.action == ACTION_COPY_RAW) { + res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2]); + if (res == 0) { + cmd.action = ACTION_LOAD_APP; + } + } + + if (cmd.action == ACTION_LOAD_APP) { + res = load_app_from_flash_raw(0); + } + if (res) { ets_putc('\n'); ets_putc('#'); diff --git a/bootloaders/eboot/eboot.elf b/bootloaders/eboot/eboot.elf index b2381a409..b7908dfd6 100755 Binary files a/bootloaders/eboot/eboot.elf and b/bootloaders/eboot/eboot.elf differ diff --git a/bootloaders/eboot/eboot.h b/bootloaders/eboot/eboot.h index b77f8f45a..973c616a8 100644 --- a/bootloaders/eboot/eboot.h +++ b/bootloaders/eboot/eboot.h @@ -14,6 +14,9 @@ int SPIEraseSector(uint32_t sector); int SPIRead(uint32_t addr, void *dest, size_t size); int SPIWrite(uint32_t addr, void *src, size_t size); + +#define FLASH_SECTOR_SIZE 0x1000 +#define FLASH_BLOCK_SIZE 0x10000 #define APP_START_OFFSET 0x1000 typedef struct { diff --git a/bootloaders/eboot/eboot_command.c b/bootloaders/eboot/eboot_command.c new file mode 100644 index 000000000..1e9cbed2c --- /dev/null +++ b/bootloaders/eboot/eboot_command.c @@ -0,0 +1,47 @@ +#include "eboot_command.h" + +uint32_t crc_update(uint32_t crc, const uint8_t *data, size_t length) +{ + uint32_t i; + bool bit; + uint8_t c; + + while (length--) { + c = *data++; + for (i = 0x80; i > 0; i >>= 1) { + bit = crc & 0x80000000; + if (c & i) { + bit = !bit; + } + crc <<= 1; + if (bit) { + crc ^= 0x04c11db7; + } + } + } + return crc; +} + +uint32_t eboot_command_calculate_crc32(const struct eboot_command* cmd) +{ + return crc_update(0xffffffff, (const uint8_t*) cmd, + offsetof(struct eboot_command, crc32)); +} + +void eboot_command_read(struct eboot_command* cmd) +{ + const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); + uint32_t* dst = (uint32_t *) cmd; + for (uint32_t i = 0; i < dw_count; ++i) { + dst[i] = RTC_MEM[i]; + } + + uint32_t crc32 = eboot_command_calculate_crc32(cmd); + if (cmd->magic & EBOOT_MAGIC_MASK != EBOOT_MAGIC || + cmd->crc32 != crc32) { + + cmd->action = ACTION_LOAD_APP; + cmd->args[0] = 0; + } +} + diff --git a/bootloaders/eboot/eboot_command.h b/bootloaders/eboot/eboot_command.h new file mode 100644 index 000000000..aa0fc11bb --- /dev/null +++ b/bootloaders/eboot/eboot_command.h @@ -0,0 +1,29 @@ +#ifndef EBOOT_COMMAND_H +#define EBOOT_COMMAND_H + +#include +#include +#include + +#define RTC_MEM ((volatile uint32_t*)0x60001200) + +enum action_t { + ACTION_COPY_RAW = 0x00000001, + ACTION_LOAD_APP = 0xffffffff +}; + +#define EBOOT_MAGIC 0xeb001000 +#define EBOOT_MAGIC_MASK 0xfffff000 + +struct eboot_command { + uint32_t magic; + enum action_t action; + uint32_t args[29]; + uint32_t crc32; +}; + + +void eboot_command_read(struct eboot_command* cmd); + + +#endif //EBOOT_COMMAND_H