You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by mi...@apache.org on 2026/03/18 12:06:13 UTC

(nuttx-apps) 01/03: boot/nxboot: add flush barriers and CRC-validate primary before boot

This is an automated email from the ASF dual-hosted git repository.

michallenc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 4decc1699a18cc81f4b72837626fa32a1059b9fd
Author: Neil Berkman <ne...@xuku.com>
AuthorDate: Tue Mar 17 15:39:02 2026 -0700

    boot/nxboot: add flush barriers and CRC-validate primary before boot
    
    Two hardening fixes for nxboot power-loss resilience:
    
    1. Add flash_partition_flush() calls between critical partition
       operations in perform_update(). Without explicit flush barriers,
       writes may remain buffered in RAM (e.g. via FTL rwbuffer) when
       nxboot proceeds to the next phase. A power loss between phases
       can leave the recovery image uncommitted while the staging
       partition has already been consumed.
    
       Flush points added:
       - After copy_partition(primary, recovery) completes
       - After copy_partition(update, primary) completes, before
         erasing the staging first sector
    
    2. Replace validate_image_header() with validate_image() in the
       final primary validation path of nxboot_perform_update(). The
       header-only check validates magic and platform identifier but
       does not CRC-check the image body. After an interrupted update,
       a corrupt primary with an intact header would pass this check
       and be booted, resulting in a persistent boot failure.
    
    Signed-off-by: Neil Berkman <ne...@xuku.com>
---
 boot/nxboot/loader/boot.c  |  6 ++++--
 boot/nxboot/loader/flash.c | 20 ++++++++++++++++++++
 boot/nxboot/loader/flash.h | 16 ++++++++++++++++
 3 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/boot/nxboot/loader/boot.c b/boot/nxboot/loader/boot.c
index 6de9659ac..8bcd24cef 100644
--- a/boot/nxboot/loader/boot.c
+++ b/boot/nxboot/loader/boot.c
@@ -417,6 +417,7 @@ static int perform_update(struct nxboot_state *state, bool check_only)
           syslog(LOG_INFO, "Creating recovery image.\n");
           nxboot_progress(nxboot_progress_start, recovery_create);
           copy_partition(primary, recovery, state, false);
+          flash_partition_flush(recovery);
           nxboot_progress(nxboot_progress_end);
           nxboot_progress(nxboot_progress_start, validate_recovery);
           successful = validate_image(recovery);
@@ -444,6 +445,8 @@ static int perform_update(struct nxboot_state *state, bool check_only)
           nxboot_progress(nxboot_progress_start, update_from_update);
           if (copy_partition(update, primary, state, true) >= 0)
             {
+              flash_partition_flush(primary);
+
               /* Erase the first sector of update partition. This marks the
                * partition as updated so we don't end up in an update loop.
                * The sector is written back again during the image
@@ -919,8 +922,7 @@ int nxboot_perform_update(bool check_only)
       return ERROR;
     }
 
-  get_image_header(primary, &header);
-  if (!validate_image_header(&header))
+  if (!validate_image(primary))
     {
       ret = ERROR;
     }
diff --git a/boot/nxboot/loader/flash.c b/boot/nxboot/loader/flash.c
index f1a359573..ab6a24320 100644
--- a/boot/nxboot/loader/flash.c
+++ b/boot/nxboot/loader/flash.c
@@ -76,6 +76,26 @@ int flash_partition_open(const char *path)
   return fd;
 }
 
+/****************************************************************************
+ * Name: flash_partition_flush
+ *
+ * Description:
+ *   Flushes any buffered writes to the underlying storage. This ensures
+ *   data is physically committed to flash before the caller proceeds.
+ *
+ * Input parameters:
+ *   fd: Valid file descriptor.
+ *
+ * Returned Value:
+ *   0 on success, -1 on failure.
+ *
+ ****************************************************************************/
+
+int flash_partition_flush(int fd)
+{
+  return fsync(fd);
+}
+
 /****************************************************************************
  * Name: flash_partition_close
  *
diff --git a/boot/nxboot/loader/flash.h b/boot/nxboot/loader/flash.h
index ef1dee09d..69906490d 100644
--- a/boot/nxboot/loader/flash.h
+++ b/boot/nxboot/loader/flash.h
@@ -79,6 +79,22 @@ int flash_partition_open(const char *path);
 
 int flash_partition_close(int fd);
 
+/****************************************************************************
+ * Name: flash_partition_flush
+ *
+ * Description:
+ *   Flushes any buffered writes to the underlying storage.
+ *
+ * Input parameters:
+ *   fd: Valid file descriptor.
+ *
+ * Returned Value:
+ *   0 on success, -1 on failure.
+ *
+ ****************************************************************************/
+
+int flash_partition_flush(int fd);
+
 /****************************************************************************
  * Name: flash_partition_write
  *