diff --git a/stm-firmware/include/reflow-controller/safety/safety-memory.h b/stm-firmware/include/reflow-controller/safety/safety-memory.h index 300ebfd..6e99d91 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-memory.h +++ b/stm-firmware/include/reflow-controller/safety/safety-memory.h @@ -47,6 +47,8 @@ #define SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT 32UL +#define SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE 256U + /** * @brief Safety memory header */ @@ -55,6 +57,7 @@ struct safety_memory_header { uint32_t boot_status_offset; /**< @brief Offset of the safety_memory_boot_status struct (in 32 bit words)*/ uint32_t config_overrides_offset; /**< @brief Offset address of override entries */ uint32_t config_overrides_len; /**< @brief Length of override entries in words */ + uint32_t firmware_update_filename; /**< @brief Filename of the firmware update. This string is at maximum 256 bytes long including the 0 terminator */ uint32_t err_memory_offset; /**< @brief Offset of the error memory */ uint32_t err_memory_end; /**< @brief End of the error memory. This points to the word after the error memory, containing the CRC of the whole backup RAM. */ uint32_t crc; /**< @brief CRC of the header */ @@ -247,6 +250,26 @@ int safety_memory_get_config_override_count(uint32_t *count); */ int safety_memory_get_config_override(uint32_t idx, struct config_override *config_override); +/** + * @brief Read the set update filename from the safety backup memory + * + * \p filename has to be large enough to hold the filename (255 chars) plus the '\0'-terminator. + * + * @param[out] filename Array to fill in file name. May be NULL to only read the length. + * @param[out] outlen String length of the filename. May be NULL to only read the file name. + * @note \p filename may be NULL. In this case this function can be used to read the currently set filename's length. + * @warning Function will fail if both parameters are NULL + * @return 0 if successful + */ +int safety_memory_get_update_filename(char *filename, size_t *outlen); + +/** + * @brief Set the filename of the update file + * @param[in] filename Filename to set. Must be 255 chars at max (256 including null terminator) + * @return 0 if successful + */ +int safety_memory_set_update_filename(const char *filename); + #ifndef SAFETY_MEMORY_STRIPOUT_DUMP /** diff --git a/stm-firmware/safety/safety-memory.c b/stm-firmware/safety/safety-memory.c index 34cff71..2aaf37c 100644 --- a/stm-firmware/safety/safety-memory.c +++ b/stm-firmware/safety/safety-memory.c @@ -22,6 +22,7 @@ #include #include #include +#include #ifndef SAFETY_MEMORY_STRIPOUT_DUMP #include @@ -102,7 +103,9 @@ static enum safety_memory_state safety_memory_get_header(struct safety_memory_he res++; if (header->config_overrides_len > SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT) res++; - if (header->err_memory_offset < header->config_overrides_offset + header->config_overrides_len) + if (header->firmware_update_filename < header->config_overrides_offset + header->config_overrides_len) + res++; + if (header->err_memory_offset < header->firmware_update_filename + (SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE / 4)) res++; if (header->err_memory_end >= backup_ram_get_size_in_words() || header->err_memory_end < header->err_memory_offset) res++; @@ -136,7 +139,8 @@ static void safety_memory_write_new_header(void) header.boot_status_offset = wordsize_of(struct safety_memory_header); header.config_overrides_len = SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT; header.config_overrides_offset = header.boot_status_offset + wordsize_of(struct safety_memory_boot_status); - header.err_memory_offset = header.config_overrides_offset + SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT; + header.firmware_update_filename = header.config_overrides_offset + SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT; + header.err_memory_offset = header.firmware_update_filename + (SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE / 4); header.err_memory_end = header.err_memory_offset; header.magic = SAFETY_MEMORY_MAGIC; @@ -640,3 +644,64 @@ int safety_memory_dump_base64(char *buffer, size_t buffsize, size_t *used_size) } #endif /* SAFETY_MEMORY_STRIPOUT_DUMP */ + +int safety_memory_get_update_filename(char *filename, size_t *outlen) +{ + struct safety_memory_header header; + unsigned int i; + volatile char *ptr; + size_t len = 0u; + + /* If filename and outlen are both NULL, we don't do anything */ + if (!filename && !outlen) + return -1; + + if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) + return -2000; + + /* Get the filename */ + ptr = (volatile char *)backup_ram_get_base_ptr(); + ptr += (unsigned int)(header.firmware_update_filename * 4); + for (i = 0; i < SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE; i++) { + if (filename) + filename[i] = *ptr; + if (*ptr) + len++; + else + break; + ptr++; + } + + if (outlen) + *outlen = len; + + return 0; +} + +int safety_memory_set_update_filename(const char *filename) +{ + int ret = 0; + size_t len; + unsigned int i; + struct safety_memory_header header; + volatile char *ram_ptr; + + if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) + return -2000; + + if (!filename) + return -1001; + + len = strnlen(filename, SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE - 1); + ram_ptr = backup_ram_get_base_ptr(); + ram_ptr += header.firmware_update_filename * 4; + + for (i = 0u; i < len; i++) { + ram_ptr[i] = filename[i]; + } + ram_ptr[i] = 0; + + ret = safety_memory_gen_crc(); + + return ret; +}