21#include <ota/flasher.h>
22#include <utils/etl_base64.h>
23#include <utils/logging.h>
24#include <utils/reboot.h>
31#define FLASH_ID "fw_teensy41"
32#define FLASH_ID_LEN (11)
33#define FLASH_SIZE (0x800000)
34#define FLASH_SECTOR_SIZE (0x1000)
35#define FLASH_WRITE_SIZE (4)
38#define FLASH_RESERVE (80 * FLASH_SECTOR_SIZE)
39#define FLASH_BASE_ADDR (0x60000000)
41#define IN_FLASH(a) ((a) >= FLASH_BASE_ADDR && (a) < FLASH_BASE_ADDR + FLASH_SIZE)
44#define CPU_RESTART_ADDR ((uint32_t *)0xE000ED0C)
45#define CPU_RESTART_VAL (0x5FA0004)
46#define REBOOT (*CPU_RESTART_ADDR = CPU_RESTART_VAL)
50#define RAMFUNC __attribute__((section(".fastrun"), noinline, noclone, optimize("Os")))
77 LOGMEV(
"Search starting at 0x%0X", *buffer_addr);
78 while (*buffer_addr > 0 && *((
uint32_t *)*buffer_addr) == 0xFFFFFFFF)
81 LOGMEV(
"Found first non-erased flash byte at 0x%0X", *buffer_addr);
100loader::FirmwareBuffer::FirmwareBuffer() {
117 if (*sector++ != 0xFFFFFFFF)
128 uint32_t offset = 0, error = 0, addr;
135 while (offset <
size && error == 0) {
143 if (flash_sector_not_erased(addr)) {
144#if defined(__IMXRT1062__)
146#elif (FLASH_WRITE_SIZE == 4)
147 error |= flash_erase_sector(addr, 1);
149 error |= flash_word(0x40C, 0xfffff9de, 1, 1);
150#elif (FLASH_WRITE_SIZE == 8)
151 error |= flash_erase_sector(addr, 1);
153 error |= flash_phrase(0x408, 0xfffff9deffffffff, 1, 1);
160#if defined(__IMXRT1062__)
164#elif (FLASH_WRITE_SIZE == 4)
165 error |= flash_word(addr, *(
uint32_t *)(
src + offset), 1, 0);
166#elif (FLASH_WRITE_SIZE == 8)
167 error |= flash_phrase(addr, *(uint64_t *)(
src + offset), 1, 0);
181 if (flash_sector_not_erased(addr)) {
182#if defined(__IMXRT1062__)
185 error |= flash_erase_sector(addr, 0);
207 while (address < (start +
size) && error == 0) {
209 if (flash_sector_not_erased(address)) {
210#if defined(__IMXRT1062__)
212#elif defined(KINETISK) || defined(KINETISL)
213 error = flash_erase_sector(address, 0);
229#if (FLASH_WRITE_SIZE == 4)
231#elif (FLASH_WRITE_SIZE == 8)
240 if ((addr % 4) != 0 || (count % 4) != 0) {
244 if (buf_count > 0 && addr != next_addr) {
247 next_addr = addr + count;
250 while (data_i < count) {
251 ((uint8_t *)&buf)[buf_count++] = data[data_i++];
255#if defined(__IMXRT1062__)
257#elif (FLASH_WRITE_SIZE == 4)
258 ret = flash_word(addr, buf, 0, 0);
259#elif (FLASH_WRITE_SIZE == 8)
260 ret = flash_phrase(addr, buf, 0, 0);
276#define return_err(code, msg) \
278 msg_out["error"] = msg; \
281#define return_errf(code, msg, ...) \
284 snprintf(msgbuf, sizeof(msgbuf), msg, __VA_ARGS__); \
285 msg_out["error"] = msgbuf; \
301#ifdef ANABRID_ENABLE_OTA_FLASHING
302#define RETURN_IF_FLASHING_NOT_ENABLED
304#define RETURN_IF_FLASHING_NOT_ENABLED return_err(0, "OTA Flashing is disabled in this firmware build")
307FLASHMEM
int loader::FirmwareFlasher::init(JsonObjectConst msg_in, JsonObject &msg_out) {
310 return_err(1,
"Firmware upgrade already running. Cancel it before doing another one");
312 upgrade =
new loader::FirmwareBuffer();
313 upgrade->name = msg_in[
"name"].as<std::string>();
314 upgrade->imagelen = msg_in[
"imagelen"];
315 upgrade->upstream_hash = utils::parse_sha256(msg_in[
"upstream_hash"]);
316 upgrade->bytes_transmitted = 0;
318 if (upgrade->imagelen > upgrade->buffer_size) {
322 "New firmware image too large for OTA upgrade process. Image size: %zu bytes > Buffer size: %ld bytes",
323 upgrade->imagelen, upgrade->buffer_size);
329 msg_out[
"encoding"] =
"binary-base64";
333FLASHMEM
int loader::FirmwareFlasher::stream(JsonObjectConst msg_in, JsonObject &msg_out) {
336 return_err(1,
"No firmware upgrade running.");
337 if (upgrade->transfer_completed())
341 auto base64_payload = msg_in[
"payload"].as<std::string>();
342 auto payload_base64_size = base64_payload.size();
343 if (!payload_base64_size)
345 if ((payload_base64_size % 4) != 0)
346 return_err(4,
"Payload has not correct length to be base64-encoded.");
348 auto payload_bin_size =
349 etl::base64::decode(base64_payload.c_str(), base64_payload.length(), decoded_buffer,
bin_chunk_size);
350 if (!payload_bin_size)
351 return_err(2,
"Could not decode base64-encoded payload.");
353 LOGV(
"payload_base64_size=%d, payload_bin_size=%d", payload_base64_size, payload_bin_size);
356 return_errf(6,
"Chunk size too large. Given %zu bytes > buffer size %zu bytes", payload_bin_size,
358 if (upgrade->bytes_transmitted + payload_bin_size > upgrade->imagelen)
359 return_errf(7,
"Chunk size too large, yields to image size %zu bytes but only %zu announced.",
360 upgrade->bytes_transmitted + payload_bin_size, upgrade->imagelen);
361 if ((payload_bin_size % 4) != 0)
362 return_err(8,
"Chunk not 32-bit aligned. Expecting buffer size multiples of 4 bytes.");
364 LOGV(
"Loaded %zu bytes to RAM, ready for flash writing", payload_bin_size);
368 flash_write_block(upgrade->buffer_addr + upgrade->bytes_transmitted, decoded_buffer, payload_bin_size);
370 return_errf(50 + write_error,
"flash_write_block() error %02X", write_error);
372 upgrade->bytes_transmitted += payload_bin_size;
376FLASHMEM
void loader::FirmwareFlasher::status(JsonObject &msg_out) {
377#ifndef ANABRID_ENABLE_OTA_FLASHING
378 msg_out[
"disabled"] =
379 "OTA flashing is disabled due to absence of firmware build flag ANABRID_ENABLE_OTA_FLASHING";
382 msg_out[
"is_upgrade_running"] = bool(upgrade);
384 msg_out[
"name"] = upgrade->name;
385 msg_out[
"size"] = upgrade->imagelen;
386 msg_out[
"upstream_hash"] = utils::sha256_to_string(upgrade->upstream_hash);
387 msg_out[
"bytes_transmitted"] = upgrade->bytes_transmitted;
388 msg_out[
"transfer_completed"] = upgrade->transfer_completed();
390 if (upgrade->transfer_completed()) {
391 auto actual_hash =
utils::hash_sha256((uint8_t *)upgrade->buffer_addr, upgrade->imagelen);
392 msg_out[
"hash_correct"] = actual_hash == upgrade->upstream_hash;
394 msg_out[
"actual_hash"] = utils::sha256_to_string(actual_hash);
398 msg_out[
"buffer_addr"] = upgrade->buffer_addr;
399 msg_out[
"buffer_size"] = upgrade->buffer_size;
402 uint32_t potential_buffer_addr, potential_buffer_size;
404 &potential_buffer_size);
405 msg_out[
"buffer_addr"] = potential_buffer_addr;
406 msg_out[
"buffer_size"] = potential_buffer_size;
410FLASHMEM
int loader::FirmwareFlasher::abort(JsonObjectConst msg_in, JsonObject &msg_out) {
413 return_err(1,
"No upgrade running which I could abort");
418FLASHMEM
int loader::FirmwareFlasher::complete(JsonObjectConst msg_in, JsonObject &msg_out) {
420 if (!upgrade->transfer_completed())
421 return_err(1,
"Require transfer to be completed");
423 LOG_ALWAYS(
"Checking new firmware image hash...");
424 auto actual_hash =
utils::hash_sha256((uint8_t *)upgrade->buffer_addr, upgrade->imagelen);
425 if (actual_hash != upgrade->upstream_hash)
426 return_err(2,
"Corrupted upload data, hash mismatch. Please try again (start new init)");
428 LOG_ALWAYS(
"Moving new firmware image into place and rebooting...");
void eepromemu_flash_erase_64K_block(void *addr)
#define return_err(code, msg)
void eepromemu_flash_erase_sector(void *addr)
constexpr static size_t bin_chunk_size
void firmware_buffer_init(uint32_t *buffer_addr, uint32_t *buffer_size)
#define return_errf(code, msg,...)
constexpr static size_t json_overhead
void firmware_buffer_free(uint32_t buffer_addr, uint32_t buffer_size)
#define RETURN_IF_FLASHING_NOT_ENABLED
int flash_erase_block(uint32_t address, uint32_t size)
void eepromemu_flash_erase_32K_block(void *addr)
static constexpr int success
static int leave_interrupts_disabled
int flash_write_block(uint32_t addr, char *data, uint32_t count)
__attribute__((section(".fastrun"), noinline, noclone, optimize("Os"))) int flash_sector_not_erased(uint32_t address)
constexpr static size_t base64_chunk_size
#define FLASH_SECTOR_SIZE
void eepromemu_flash_write(void *addr, const void *data, uint32_t len)
void reboot()
Just a little generic Teensy reboot routine.
FLASHMEM void hash_sha256(const uint8_t *msg, size_t msg_len, uint8_t *out_hash)
Computes the SHA256 sum of an arbitrary message (large memory segment).