Fix FS record publication ordering (#35).

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2026-08-14 00:05:59 +02:00
parent 9b23d4b42d
commit f0d58025e1
+20 -9
View File
@@ -82,15 +82,16 @@ static size_t flash_record_size(uintptr_t base) {
return 2 * sizeof(uintptr_t) + sizeof(uint16_t) + flash_record_length_size(base) + flash_record_payload_size(base);
}
static uintptr_t allocate_free_addr(uint32_t size, bool persistent) {
static uintptr_t allocate_free_addr(uint32_t size, bool persistent, uintptr_t *publish_at) {
size_t length_size = size >= FLASH_FILE_EXTENDED_LENGTH ? FLASH_FILE_EXTENDED_LENGTH_SIZE : FLASH_FILE_LEGACY_LENGTH_SIZE;
size_t overhead = 2 * sizeof(uintptr_t) + sizeof(uint16_t) + length_size;
size_t real_size = 0;
uintptr_t next_base = 0x0, endp = end_data_pool, startp = start_data_pool;
if (size > SIZE_MAX - overhead) {
if (!publish_at || size > SIZE_MAX - overhead) {
return 0x0;
}
*publish_at = 0x0;
real_size = overhead + size;
if (persistent) {
endp = end_rom_pool;
@@ -121,12 +122,17 @@ static uintptr_t allocate_free_addr(uint32_t size, bool persistent) {
}
if (gap_reusable && potential_addr >= gap_start && potential_addr >= startp) {
flash_program_uintptr(potential_addr, next_base);
flash_program_uintptr(potential_addr + sizeof(uintptr_t), base);
if (next_base != 0x0) {
flash_program_uintptr(next_base + sizeof(uintptr_t), potential_addr);
int r = flash_program_uintptr(potential_addr, next_base);
if (r == PICOKEYS_OK) {
r = flash_program_uintptr(potential_addr + sizeof(uintptr_t), base);
}
flash_program_uintptr(base, potential_addr);
if (r == PICOKEYS_OK && next_base != 0x0) {
r = flash_program_uintptr(next_base + sizeof(uintptr_t), potential_addr);
}
if (r != PICOKEYS_OK) {
return 0x0;
}
*publish_at = base;
return potential_addr;
}
if (next_base == 0x0) {
@@ -205,7 +211,8 @@ static int flash_write_data_to_file_internal(file_t *file, const_byte_array_t da
file_t old_file = *file;
bool replacing = old_file.data != NULL;
uintptr_t new_addr = allocate_free_addr(new_size, (file_get_type(file) & FILE_PERSISTENT) == FILE_PERSISTENT);
uintptr_t publish_at = 0x0;
uintptr_t new_addr = allocate_free_addr(new_size, (file_get_type(file) & FILE_PERSISTENT) == FILE_PERSISTENT, &publish_at);
if (new_addr == 0x0) {
return PICOKEYS_ERR_NO_MEMORY;
}
@@ -235,9 +242,13 @@ static int flash_write_data_to_file_internal(file_t *file, const_byte_array_t da
if (r == PICOKEYS_OK && partial && replacing && write_end < old_size) {
r = copy_file_range(&old_file, write_end, payload + write_end, old_size - write_end);
}
if (r == PICOKEYS_OK && 2 * sizeof(uintptr_t) + sizeof(uint16_t) + length_size + new_size > FLASH_SECTOR_SIZE && !flash_commit_sync(5000u)) {
/* Publish only after the record is complete; across sectors the record must be durable first. */
if (r == PICOKEYS_OK && (publish_at & ~(uintptr_t)(FLASH_SECTOR_SIZE - 1)) != (new_addr & ~(uintptr_t)(FLASH_SECTOR_SIZE - 1)) && !flash_commit_sync(5000u)) {
r = PICOKEYS_ERR_MEMORY_FATAL;
}
if (r == PICOKEYS_OK) {
r = flash_program_uintptr(publish_at, new_addr);
}
if (r != PICOKEYS_OK) {
flash_clear_file(&new_file);
return r;