From 42075b1e390d19a3d104c6ecf6282f18033dd99c Mon Sep 17 00:00:00 2001 From: Lume <141330891+Kniffler@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:09:09 +0100 Subject: [PATCH] Changed fseek guard clauses to properly handle error codes fseek returns non-zero value upon failure, not -1. Added proper implementation of load skip in load_program to allow skipping a program when it already exists --- Code/pico_multi_booter/sd_boot/main.c | 96 +++++++++++++++------------ 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/Code/pico_multi_booter/sd_boot/main.c b/Code/pico_multi_booter/sd_boot/main.c index c6a3884..69edf02 100644 --- a/Code/pico_multi_booter/sd_boot/main.c +++ b/Code/pico_multi_booter/sd_boot/main.c @@ -63,22 +63,26 @@ bool fs_init(void) true); filesystem_t *fat = filesystem_fat_create(); int err = fs_mount("/", fat, sd); - if (err == -1) - { - DEBUG_PRINT("format /\n"); - err = fs_format(fat, sd); - if (err == -1) - { - DEBUG_PRINT("format err: %s\n", strerror(errno)); - return false; - } - err = fs_mount("/", fat, sd); - if (err == -1) - { - DEBUG_PRINT("mount err: %s\n", strerror(errno)); - return false; - } - } + if (err != -1) + { + DEBUG_PRINT("Mounted SD card at /\n"); + return true; + } + + err = fs_format(fat, sd); + if (err == -1) + { + DEBUG_PRINT("Failed to format SD card\n"); + return false; + } + + err = fs_mount("/", fat, sd); + if (err == -1) + { + DEBUG_PRINT("Failed to mount SD card at /\n"); + return false; + } + DEBUG_PRINT("Mounted SD card at /\n"); return true; } @@ -97,6 +101,28 @@ static bool __not_in_flash_func(is_same_existing_program)(FILE *fp) return true; } +// Check if a valid application exists in flash by examining the vector table +static bool is_valid_application(uint32_t *app_location) +{ + // Check that the initial stack pointer is within a plausible RAM region. + // Assumed range for Pico: 0x20000000 to 0x20040000 + SCRATCH_X + SCRATCH_Y + // Which is the same as the range 0x20000000 to 0x20042000 + uint32_t stack_pointer = app_location[0]; + + if (stack_pointer < 0x20000000 || stack_pointer > MAX_RAM + 2*4*1024) // MAX_RAM + 8KB (4KB per scratch region) + { + return false; + } + + // Check that the reset vector is within the valid flash application area + uint32_t reset_vector = app_location[1]; + if (reset_vector < (0x10000000 + SD_BOOT_FLASH_OFFSET) || reset_vector > (0x10000000 + PICO_FLASH_SIZE_BYTES)) + { + return false; + } + return true; +} + // This function must run from RAM since it erases and programs flash memory static bool __not_in_flash_func(load_program)(const char *filename) { @@ -106,13 +132,9 @@ static bool __not_in_flash_func(load_program)(const char *filename) DEBUG_PRINT("open %s fail: %s\n", filename, strerror(errno)); return false; } - if (is_same_existing_program(fp)) - { - // Program is up to date - } // Check file size to ensure it doesn't exceed the available flash space - if (fseek(fp, 0, SEEK_END) == -1) + if (fseek(fp, 0, SEEK_END) != 0) { DEBUG_PRINT("seek err: %s\n", strerror(errno)); fclose(fp); @@ -120,7 +142,7 @@ static bool __not_in_flash_func(load_program)(const char *filename) } long file_size = ftell(fp); - if (file_size <= 0) + if (file_size <= 0) // Negative, to include error code -1 { DEBUG_PRINT("invalid size: %ld\n", file_size); fclose(fp); @@ -135,13 +157,21 @@ static bool __not_in_flash_func(load_program)(const char *filename) } DEBUG_PRINT("updating: %ld bytes\n", file_size); - if (fseek(fp, 0, SEEK_SET) == -1) + if (fseek(fp, 0, SEEK_SET) != 0) { DEBUG_PRINT("seek err: %s\n", strerror(errno)); fclose(fp); return false; } + // Only check for validity after the guard clauses to make sure the file pointer (fp) is valid + if ( is_same_existing_program(fp) && is_valid_application((uint32_t*)(XIP_BASE + SD_BOOT_FLASH_OFFSET)) ) + { + DEBUG_PRINT("Same program already valid in flash, skipping\n"); + fclose(fp); + return true; + } + size_t program_size = 0; uint8_t buffer[FLASH_SECTOR_SIZE] = {0}; size_t len = 0; @@ -185,26 +215,6 @@ void __not_in_flash_func(launch_application_from)(uint32_t *app_location) :); } -// Check if a valid application exists in flash by examining the vector table -static bool is_valid_application(uint32_t *app_location) -{ - // Check that the initial stack pointer is within a plausible RAM region (assumed range for Pico: 0x20000000 to 0x20040000) - uint32_t stack_pointer = app_location[0]; - - if (stack_pointer < 0x20000000 || stack_pointer > MAX_RAM + 2*4*1024) // MAX_RAM + 8KB - { - return false; - } - - // Check that the reset vector is within the valid flash application area - uint32_t reset_vector = app_location[1]; - if (reset_vector < (0x10000000 + SD_BOOT_FLASH_OFFSET) || reset_vector > (0x10000000 + PICO_FLASH_SIZE_BYTES)) - { - return false; - } - return true; -} - void boot_default() { DEBUG_PRINT("entering boot_default\n");