From 1d0bc5efdf7e175608cc1c038b592b511143ed26 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 18 Dec 2019 09:17:38 -0800 Subject: [PATCH] Allow GZIP compressed flash updates (#6820) * Allow GZIP compressed flash updates Modified the bootloader to be able to take stored updates in compressed GZIP format (i.e. the output of "gzip -9 xxx.bin") and decompress them on-the-fly to their final destination. This can work for apps and for filesystems (when used with the 2-step update option). Allow eboot to be built using -Os/2 optimizations by fixing some portions which failed when any optimizations were used. Add -Wall and use data and function sections to reduce size. Use -Os to minimize size. Remove obsolete esptool-ck calls to build a .ROM image, we don't use it. Move all uninitted variables to RAM from IRAM, allowing 8-bit access. Hook in @d-a-v and @pfalcon's uzlib port to actually do the decompression. Do not use any CRC checking which saves space. Since we have overwritten all of flash by the time we know id the CRC matches, there's nothing we could have done anyway. Adjust the Updater class to support GZIP files and not attempt to patch them. Bootloader builds to 0xd90 out of 0xfff bytes. * Add @d-a-v's patch for httpupdate https://github.com/esp8266/Arduino/pull/6820#pullrequestreview-326541014 * Update uzlib to point to pfalcon++ For now, because there are some self-test failures with @d-a-v's esp8266 branch (whose cool new features we don't actually use in eboot now) start with pfalcon's 2.9 release and add the 2 patches (clcidx to code from IRAM/RODATA, and the Windows test file renaming) needed to build and run successfully. * Add (c) notice for uzlib to README --- .gitmodules | 3 + README.md | 2 + bootloaders/eboot/Makefile | 31 +++--- bootloaders/eboot/eboot.c | 102 +++++++++++++++--- bootloaders/eboot/eboot.elf | Bin 14532 -> 34856 bytes bootloaders/eboot/eboot.ld | 3 +- bootloaders/eboot/eboot_command.c | 2 +- cores/esp8266/Updater.cpp | 12 ++- .../src/ESP8266httpUpdate.cpp | 18 ++-- tools/sdk/uzlib | 1 + 10 files changed, 132 insertions(+), 42 deletions(-) create mode 160000 tools/sdk/uzlib diff --git a/.gitmodules b/.gitmodules index ca26e7d93b..403d4ce64e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "tools/esptool"] path = tools/esptool url = https://github.com/espressif/esptool.git +[submodule "tools/sdk/uzlib"] + path = tools/sdk/uzlib + url = https://github.com/earlephilhower/uzlib.git diff --git a/README.md b/README.md index b135c682f5..da691966d2 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,8 @@ ESP8266 core files are licensed under LGPL. [LittleFS](https://github.com/ARMmbed/littlefs) library written by ARM Limited and released under the [BSD 3-clause license](https://github.com/ARMmbed/littlefs/blob/master/LICENSE.md). +[uzlib](https://github.com/pfalcon/uzlib) library written and (c) 2014-2018 Paul Sokolovsky, licensed under the ZLib license (https://www.zlib.net/zlib_license.html). + ### Other useful links ### [Toolchain repo](https://github.com/earlephilhower/esp-quick-toolchain) diff --git a/bootloaders/eboot/Makefile b/bootloaders/eboot/Makefile index 3e25eb139e..dc28219b61 100644 --- a/bootloaders/eboot/Makefile +++ b/bootloaders/eboot/Makefile @@ -6,25 +6,30 @@ TARGET_DIR := ./ TARGET_OBJ_FILES := \ eboot.o \ - eboot_command.o \ - + eboot_command.o TARGET_OBJ_PATHS := $(addprefix $(TARGET_DIR)/,$(TARGET_OBJ_FILES)) +UZLIB_PATH := ../../tools/sdk/uzlib/src +UZLIB_FLAGS := -DRUNTIME_BITS_TABLES + CC := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-gcc CXX := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-g++ AR := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-ar LD := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-gcc OBJDUMP := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-objdump -INC += -I../../tools/sdk/include +INC += -I../../tools/sdk/include -I../../tools/sdk/uzlib/src + 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 -Wall -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mno-text-section-literals -ffunction-sections -fdata-sections CFLAGS += $(INC) -LDFLAGS += -nostdlib -Wl,--no-check-sections -umain +CFLAGS += $(UZLIB_FLAGS) + +LDFLAGS += -nostdlib -Wl,--no-check-sections -Wl,--gc-sections -umain LD_SCRIPT := -Teboot.ld @@ -32,18 +37,20 @@ APP_OUT:= eboot.elf APP_AR := eboot.a APP_FW := eboot.bin -all: $(APP_FW) -$(APP_AR): $(TARGET_OBJ_PATHS) - $(AR) cru $@ $^ +all: $(APP_OUT) +tinflate.o: $(UZLIB_PATH)/tinflate.c $(UZLIB_PATH)/uzlib.h $(UZLIB_PATH)/uzlib_conf.h + $(CC) $(CFLAGS) -c -o tinflate.o $(UZLIB_PATH)/tinflate.c -$(APP_OUT): $(APP_AR) - $(LD) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group -Wl,--whole-archive $(APP_AR) -Wl,--end-group -o $@ +tinfgzip.o: $(UZLIB_PATH)/tinfgzip.c $(UZLIB_PATH)/uzlib.h $(UZLIB_PATH)/uzlib_conf.h + $(CC) $(CFLAGS) -c -o tinfgzip.o $(UZLIB_PATH)/tinfgzip.c -$(APP_FW): $(APP_OUT) - $(ESPTOOL) -vvv -eo $(APP_OUT) -bo $@ -bs .text -bs .data -bs .rodata -bc -ec || true +$(APP_AR): $(TARGET_OBJ_PATHS) tinflate.o tinfgzip.o + $(AR) cru $@ $^ +$(APP_OUT): $(APP_AR) + $(LD) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group -Wl,--whole-archive $(APP_AR) -Wl,--end-group -o $@ clean: rm -f *.o diff --git a/bootloaders/eboot/eboot.c b/bootloaders/eboot/eboot.c index a640f9130e..b9d655778b 100644 --- a/bootloaders/eboot/eboot.c +++ b/bootloaders/eboot/eboot.c @@ -12,6 +12,9 @@ #include #include "flash.h" #include "eboot_command.h" +#include + +extern unsigned char _gzip_dict; #define SWRST do { (*((volatile uint32_t*) 0x60000700)) |= 0x80000000; } while(0); @@ -24,10 +27,14 @@ int print_version(const uint32_t flash_addr) if (SPIRead(flash_addr + APP_START_OFFSET + sizeof(image_header_t) + sizeof(section_header_t), &ver, sizeof(ver))) { return 1; } - const char* __attribute__ ((aligned (4))) fmtt = "v%08x\n\0\0"; - uint32_t fmt[2]; - fmt[0] = ((uint32_t*) fmtt)[0]; - fmt[1] = ((uint32_t*) fmtt)[1]; + char fmt[16]; + fmt[0] = 'v'; + fmt[1] = '%'; + fmt[2] = '0'; + fmt[3] = '8'; + fmt[4] = 'x'; + fmt[5] = '\n'; + fmt[6] = '0'; ets_printf((const char*) fmt, ver); return 0; } @@ -80,37 +87,96 @@ int load_app_from_flash_raw(const uint32_t flash_addr) pos += section_header.size; } - register uint32_t sp asm("a1") = 0x3ffffff0; - register uint32_t pc asm("a3") = image_header.entry; - __asm__ __volatile__ ("jx a3"); + asm volatile("" ::: "memory"); + asm volatile ("mov.n a1, %0\n" + "mov.n a3, %1\n" + "jx a3\n" : : "r" (0x3ffffff0), "r" (image_header.entry) ); + __builtin_unreachable(); // Save a few bytes by letting GCC know no need to pop regs/return return 0; } +uint8_t read_flash_byte(const uint32_t addr) +{ + uint8_t __attribute__((aligned(4))) buff[4]; + SPIRead(addr & ~3, buff, 4); + return buff[addr & 3]; +} +unsigned char __attribute__((aligned(4))) uzlib_flash_read_cb_buff[4096]; +uint32_t uzlib_flash_read_cb_addr; +int uzlib_flash_read_cb(struct uzlib_uncomp *m) +{ + m->source = uzlib_flash_read_cb_buff; + m->source_limit = uzlib_flash_read_cb_buff + sizeof(uzlib_flash_read_cb_buff); + SPIRead(uzlib_flash_read_cb_addr, uzlib_flash_read_cb_buff, sizeof(uzlib_flash_read_cb_buff)); + uzlib_flash_read_cb_addr += sizeof(uzlib_flash_read_cb_buff); + return *(m->source++); +} +unsigned char gzip_dict[32768]; 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) { + if ((src_addr & 0xfff) != 0 || + (dst_addr & 0xfff) != 0) { return 1; } const uint32_t buffer_size = FLASH_SECTOR_SIZE; uint8_t buffer[buffer_size]; - uint32_t left = ((size+buffer_size-1) & ~(buffer_size-1)); + int32_t left = ((size+buffer_size-1) & ~(buffer_size-1)); uint32_t saddr = src_addr; uint32_t daddr = dst_addr; - - while (left) { + struct uzlib_uncomp m_uncomp; + bool gzip = false; + + // Check if we are uncompressing a GZIP upload or not + if ((read_flash_byte(saddr) == 0x1f) && (read_flash_byte(saddr + 1) == 0x8b)) { + // GZIP signature matched. Find real size as encoded at the end + left = read_flash_byte(saddr + size - 4); + left += read_flash_byte(saddr + size - 3)<<8; + left += read_flash_byte(saddr + size - 2)<<16; + left += read_flash_byte(saddr + size - 1)<<24; + + uzlib_init(); + + /* all 3 fields below must be initialized by user */ + m_uncomp.source = NULL; + m_uncomp.source_limit = NULL; + uzlib_flash_read_cb_addr = src_addr; + m_uncomp.source_read_cb = uzlib_flash_read_cb; + uzlib_uncompress_init(&m_uncomp, gzip_dict, sizeof(gzip_dict)); + + int res = uzlib_gzip_parse_header(&m_uncomp); + if (res != TINF_OK) { + return 5; // Error uncompress header read + } + gzip = true; + } + while (left > 0) { if (SPIEraseSector(daddr/buffer_size)) { return 2; } - if (SPIRead(saddr, buffer, buffer_size)) { - return 3; + if (!gzip) { + if (SPIRead(saddr, buffer, buffer_size)) { + return 3; + } + } else { + m_uncomp.dest_start = buffer; + m_uncomp.dest = buffer; + int to_read = (left > buffer_size) ? buffer_size : left; + m_uncomp.dest_limit = buffer + to_read; + int res = uzlib_uncompress(&m_uncomp); + if ((res != TINF_DONE) && (res != TINF_OK)) { + return 6; + } + // Fill any remaining with 0xff + for (int i = to_read; i < buffer_size; i++) { + buffer[i] = 0xff; + } } if (SPIWrite(daddr, buffer, buffer_size)) { return 4; @@ -124,13 +190,12 @@ int copy_raw(const uint32_t src_addr, } - -void main() +int main() { int res = 9; bool clear_cmd = false; struct eboot_command cmd; - + print_version(0); if (eboot_command_read(&cmd) == 0) { @@ -172,4 +237,7 @@ void main() } while(true){} + + __builtin_unreachable(); + return 0; } diff --git a/bootloaders/eboot/eboot.elf b/bootloaders/eboot/eboot.elf index 147a1c9c7ddc0f30770711e4313b28bc8912b158..442ad15f542c9fd9fc810b683e6bed08a260e975 100755 GIT binary patch literal 34856 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 :dram0_0_bss_phdr @@ -150,7 +152,6 @@ SECTIONS *(.bss) *(.bss.*) *(.gnu.linkonce.b.*) - *(COMMON) . = ALIGN (8); _bss_end = ABSOLUTE(.); } >iram1_0_seg :iram1_0_phdr diff --git a/bootloaders/eboot/eboot_command.c b/bootloaders/eboot/eboot_command.c index 648039e48a..54d4895c94 100644 --- a/bootloaders/eboot/eboot_command.c +++ b/bootloaders/eboot/eboot_command.c @@ -37,7 +37,7 @@ int eboot_command_read(struct eboot_command* cmd) } uint32_t crc32 = eboot_command_calculate_crc32(cmd); - if (cmd->magic & EBOOT_MAGIC_MASK != EBOOT_MAGIC || + if ((cmd->magic & EBOOT_MAGIC_MASK) != EBOOT_MAGIC || cmd->crc32 != crc32) { return 1; } diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp index a8c443f62f..ebb893aabd 100644 --- a/cores/esp8266/Updater.cpp +++ b/cores/esp8266/Updater.cpp @@ -329,7 +329,8 @@ bool UpdaterClass::_writeBuffer(){ bool modifyFlashMode = false; FlashMode_t flashMode = FM_QIO; FlashMode_t bufferFlashMode = FM_QIO; - if ((_currentAddress == _startAddress + FLASH_MODE_PAGE) && (_command == U_FLASH)) { + //TODO - GZIP can't do this + if ((_currentAddress == _startAddress + FLASH_MODE_PAGE) && (_buffer[0] != 0x1f) && (_command == U_FLASH)) { flashMode = ESP.getFlashChipMode(); #ifdef DEBUG_UPDATER DEBUG_UPDATER.printf_P(PSTR("Header: 0x%1X %1X %1X %1X\n"), _buffer[0], _buffer[1], _buffer[2], _buffer[3]); @@ -411,7 +412,7 @@ size_t UpdaterClass::write(uint8_t *data, size_t len) { bool UpdaterClass::_verifyHeader(uint8_t data) { if(_command == U_FLASH) { // check for valid first magic byte (is always 0xE9) - if(data != 0xE9) { + if ((data != 0xE9) && (data != 0x1f)) { _currentAddress = (_startAddress + _size); _setError(UPDATE_ERROR_MAGIC_BYTE); return false; @@ -435,7 +436,12 @@ bool UpdaterClass::_verifyEnd() { } // check for valid first magic byte - if(buf[0] != 0xE9) { + // + // TODO: GZIP compresses the chipsize flags, so can't do check here + if ((buf[0] == 0x1f) && (buf[1] == 0x8b)) { + // GZIP, just assume OK + return true; + } else if (buf[0] != 0xE9) { _currentAddress = (_startAddress); _setError(UPDATE_ERROR_MAGIC_BYTE); return false; diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index f736120650..2198a28eb4 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -370,7 +370,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& } // check for valid first magic byte - if(buf[0] != 0xE9) { + if(buf[0] != 0xE9 && buf[0] != 0x1f) { DEBUG_HTTP_UPDATE("[httpUpdate] Magic header does not start with 0xE9\n"); _setLastError(HTTP_UE_BIN_VERIFY_HEADER_FAILED); http.end(); @@ -378,14 +378,16 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& } - uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4); + if (buf[0] == 0xe9) { + uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4); - // check if new bin fits to SPI flash - if(bin_flash_size > ESP.getFlashChipRealSize()) { - DEBUG_HTTP_UPDATE("[httpUpdate] New binary does not fit SPI Flash size\n"); - _setLastError(HTTP_UE_BIN_FOR_WRONG_FLASH); - http.end(); - return HTTP_UPDATE_FAILED; + // check if new bin fits to SPI flash + if(bin_flash_size > ESP.getFlashChipRealSize()) { + DEBUG_HTTP_UPDATE("[httpUpdate] New binary does not fit SPI Flash size\n"); + _setLastError(HTTP_UE_BIN_FOR_WRONG_FLASH); + http.end(); + return HTTP_UPDATE_FAILED; + } } } if(runUpdate(*tcp, len, http.header("x-MD5"), command)) { diff --git a/tools/sdk/uzlib b/tools/sdk/uzlib new file mode 160000 index 0000000000..80765a42d6 --- /dev/null +++ b/tools/sdk/uzlib @@ -0,0 +1 @@ +Subproject commit 80765a42d657fcd3a24e036ac9822f9dbf862449