// // Created by jedi on 25.06.21. // #include "system.h" #include "crc32.h" #include "log.h" #include #include #include #include #include #include #include #define min(a, b) \ ({ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \ _a < _b ? _a : _b; }) void system_clear_config() { vPortEnterCritical(); uint32_t num_sectors = 0x2000 / sdk_flashchip.sector_size; uint32_t start = 0x00100000; for (uint32_t i = 0; i < num_sectors; i++) { spiflash_erase_sector(start + i * sdk_flashchip.sector_size); } if(sysparam_create_area(start, num_sectors, true) == SYSPARAM_OK) { sysparam_init(start, 0); } sysparam_init(start, start + 0x2000); sdk_system_restart(); } void system_init_config() { uint32_t base_addr = 0x00100000; uint32_t num_sectors; sysparam_init(base_addr, 0); if(sysparam_get_info(&base_addr, &num_sectors) != SYSPARAM_OK) { syslog("Warning: WiFi config, sysparam not initialized\n"); num_sectors = 0x2000 / sdk_flashchip.sector_size; if(sysparam_create_area(base_addr, num_sectors, true) == SYSPARAM_OK) { sysparam_init(base_addr, 0); } sdk_system_restart(); } } #define MAX_IMAGE_SIZE 0x100000 struct { rboot_write_status status; uint32_t head; uint32_t base; uint16_t seq; uint8_t slot; } otaflash_context; void system_otaflash_init() { rboot_config conf; conf = rboot_get_config(); otaflash_context.slot = (conf.current_rom + 1) % conf.count; otaflash_context.base = rboot_get_slot_offset(otaflash_context.slot); otaflash_context.status = rboot_write_init(otaflash_context.base); otaflash_context.head = otaflash_context.base; otaflash_context.seq = 0; } enum return_code system_otaflash_chunk(uint8_t *data, uint16_t len, uint16_t seq, uint32_t hash, uint16_t *ack) { uint32_t local_hash = crc32(data, len); if(hash == local_hash && otaflash_context.seq == seq) { if(otaflash_context.head % SECTOR_SIZE == 0) { sdk_spi_flash_erase_sector(otaflash_context.head / SECTOR_SIZE); } if(((uint32_t) data) % 4) { uint32 buf[len / 4]; memcpy(buf, data, len); sdk_spi_flash_write(otaflash_context.head, buf, len); } else { sdk_spi_flash_write(otaflash_context.head, (uint32_t *) data, len); } otaflash_context.head += len; otaflash_context.seq++; return OK; } else if(hash != local_hash) { return CHECKSUM_MISMATCH; } else { if(ack) *ack = otaflash_context.seq; return SEQUENCE_OUT_OF_ORDER; } } void system_otaflash_verify_chunk(void *ctx, void *data, size_t len) { uint32_t digest = *(uint32_t *) ctx; digest = crc32_partial(digest, data, len); *(uint32_t *) ctx = digest; } enum return_code system_otaflash_verify_and_switch(uint32_t len, uint32_t hash) { uint32_t digest = 0; rboot_digest_image(otaflash_context.base, min(len, MAX_IMAGE_SIZE), system_otaflash_verify_chunk, &digest); if(hash != digest) { syslog("OTA failed to verify firmware\r\n"); return CHECKSUM_MISMATCH; } vPortEnterCritical(); if(!rboot_set_current_rom(otaflash_context.slot)) { syslog("OTA Update failed to set new rboot slot\r\n"); vPortExitCritical(); return RBOOT_SWITCH_FAILED; } vPortExitCritical(); return OK; }