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

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


The following commit(s) were added to refs/heads/master by this push:
     new bcd1b4694 apps/boot/nxboot: Enhancements to add progress messages and 
copy-to-RAM feature
bcd1b4694 is described below

commit bcd1b46946dc8d2ff86f8edbd59f880fd6556a94
Author: Tim Hardisty <56726697+tim...@users.noreply.github.com>
AuthorDate: Thu Apr 24 11:15:26 2025 +0100

    apps/boot/nxboot: Enhancements to add progress messages and copy-to-RAM 
feature
    
    This adds Kconfig-enabled progress messages that are output to stdout.
    
    It also adds Kconfig-enabled option to copy the validated and bootable 
image to RAM
    
    Signed-off by: Tim Hardisty <t...@jti.uk.com>
---
 boot/nxboot/Kconfig          |  55 +++++++++-
 boot/nxboot/include/nxboot.h |  66 ++++++++++--
 boot/nxboot/loader/boot.c    | 111 ++++++++++++++++++++-
 boot/nxboot/loader/flash.c   |   9 +-
 boot/nxboot/nxboot_main.c    | 233 ++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 454 insertions(+), 20 deletions(-)

diff --git a/boot/nxboot/Kconfig b/boot/nxboot/Kconfig
index f8e817b5a..6f51370ea 100644
--- a/boot/nxboot/Kconfig
+++ b/boot/nxboot/Kconfig
@@ -64,6 +64,36 @@ config NXBOOT_BOOTLOADER
 
 if NXBOOT_BOOTLOADER
 
+config NXBOOT_COPY_TO_RAM
+       bool "Copy bootable image to RAM before calling board boot-image 
function"
+       default n
+       ---help---
+               The is a board and/or arch specific option that may be used 
when running
+               directly from flash, especially if external flash, even in XIP 
mode, is too
+               slow.
+               Running from RAM usually results in faster execution but the 
board must, of
+               course, have sufficient RAM available for the application 
image, stack
+               and heap.
+
+config NXBOOT_RAMSTART
+       hex "Start address in RAM that the application is to be loaded"
+       default 0x0
+       depends on NXBOOT_COPY_TO_RAM
+       ---help---
+               This will be board specific. A check of the board's linker 
script
+               may be informative. For example the SAMA5D2-XULT eval board's 
uboot
+               linker script - boards/arm/sama5/sama5d2-xult/scripts/uboot.ld 
- has:
+               
+               sdram (W!RX) : ORIGIN = 0x20008000, LENGTH = 256M - 32K
+
+               This shows the load address to be 0x20008000 and would be the 
address
+               to use here if the same linker script is to be be used for 
NXboot.
+
+               Typically the address is the base address of the RAM to be 
used, plus the
+               size of the NXboot image itself. The example above has reserved
+               32KiB (0x8000) for this from the 256MiB available on the board 
at
+               address 0x20000000.
+
 config NXBOOT_SWRESET_ONLY
        bool "Perform update/revert only on SW reset"
        default n
@@ -86,12 +116,35 @@ config NXBOOT_PREVENT_DOWNGRADE
                NXboot uses Semantic Version 2.0.0 (without build metadata). By 
default
                the update is performed for every version that doesn't match the
                currently running one. If NXBOOT_PREVENT_DOWNGRADE selected, 
update is
-               performed only for newer versions  (according to Semantic 
Version
+               performed only for newer versions (according to Semantic Version
                preference rules).
 
                WARNING: NXboot currently implements preferences only for
                MAJOR.MINOR.PATCH and ignores prerelease.
 
+config NXBOOT_PRINTF_PROGRESS
+       bool "Enable progress messages to be sent to STDOUT"
+       default y
+       ---help---
+               This will display progress during typically lengthy operations:
+                       - Calculating checksums
+                       - copying images between slots
+
+               Note: the NXboot binary will be approximately 2KiB larger with 
this enabled.
+
+choice
+       prompt "Choose preferred progress indication type"
+       depends on NXBOOT_PRINTF_PROGRESS
+       default NXBOOT_PRINTF_PROGRESS_PERCENT
+
+config NXBOOT_PRINTF_PROGRESS_DOTS
+       bool "Display progress using sequential dots"
+
+config NXBOOT_PRINTF_PROGRESS_PERCENT
+       bool "Display progress using percentage remaining"
+
+endchoice
+
 endif # NXBOOT_BOOTLOADER
 
 endif # BOOT_NXBOOT
diff --git a/boot/nxboot/include/nxboot.h b/boot/nxboot/include/nxboot.h
index 5370c2ee6..6c4a89b32 100644
--- a/boot/nxboot/include/nxboot.h
+++ b/boot/nxboot/include/nxboot.h
@@ -35,6 +35,8 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define ERROR                      -1
+
 #define NXBOOT_PRIMARY_SLOT_NUM   (0)
 #define NXBOOT_SECONDARY_SLOT_NUM (1)
 #define NXBOOT_TERTIARY_SLOT_NUM  (2)
@@ -117,6 +119,7 @@ struct nxboot_img_header
 
   struct nxboot_img_version img_version; /* Image version */
 };
+
 static_assert(CONFIG_NXBOOT_HEADER_SIZE > sizeof(struct nxboot_img_header),
               "CONFIG_NXBOOT_HEADER_SIZE has to be larger than"
               "sizeof(struct nxboot_img_header)");
@@ -131,10 +134,42 @@ struct nxboot_state
   enum nxboot_update_type next_boot;  /* nxboot_update_type with next 
operation */
 };
 
+enum progress_type_e
+{
+  nxboot_info = 0,         /* Prefixes arg. string with "INFO:" */
+  nxboot_error,            /* Prefixes arg. string with "ERR:" */
+  nxboot_progress_start,   /* Prints arg. string with no newline to allow 
..... sequence to follow */
+  nxboot_progress_dot,     /* Prints of a "." to the ..... progress sequence */
+  nxboot_progress_percent, /* Displays progress as % remaining */
+  nxboot_progress_end,     /* Flags end of a "..." progrees sequence and 
prints newline */
+};
+
+enum progress_msg_e
+{
+  startup_msg              = 0,
+  power_reset,
+  soft_reset,
+  found_bootable_image,
+  no_bootable_image,
+  boardioc_image_boot_fail,
+  ramcopy_started,
+  recovery_revert,
+  recovery_create,
+  update_from_update,
+  validate_primary,
+  validate_recovery,
+  validate_update,
+  recovery_created,
+  recovery_invalid,
+  update_failed,
+};
+
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
 
+void nxboot_progress(enum progress_type_e type, ...);
+
 /****************************************************************************
  * Name: nxboot_get_state
  *
@@ -148,7 +183,7 @@ struct nxboot_state
  *   state: The pointer to nxboot_state structure. The state is stored here.
  *
  * Returned Value:
- *   0 on success, -1 and sets errno on failure.
+ *   OK (0) on success, ERROR (-1) and sets errno on failure.
  *
  ****************************************************************************/
 
@@ -164,7 +199,7 @@ int nxboot_get_state(struct nxboot_state *state);
  *   if afterwards.
  *
  * Returned Value:
- *   Valid file descriptor on success, -1 and sets errno on failure.
+ *   Valid file descriptor on success, ERROR (-1) and sets errno on failure.
  *
  ****************************************************************************/
 
@@ -180,7 +215,7 @@ int nxboot_open_update_partition(void);
  *   state of the bootloader.
  *
  * Returned Value:
- *   1 means confirmed, 0 not confirmed, -1 and sets errno on failure.
+ *   1 if confirmed, OK (0) on success, ERROR (-1) and sets errno on failure.
  *
  ****************************************************************************/
 
@@ -194,14 +229,14 @@ int nxboot_get_confirm(void);
  *   its copy in update partition as a recovery.
  *
  * Returned Value:
- *   0 on success, -1 and sets errno on failure.
+ *   OK (0) on success, ERROR (-1) and sets errno on failure.
  *
  ****************************************************************************/
 
 int nxboot_confirm(void);
 
 /****************************************************************************
- * Name: nxboot_perform_swap
+ * Name: nxboot_perform_update
  *
  * Description:
  *   Checks for the possible firmware update and performs it by copying
@@ -216,10 +251,29 @@ int nxboot_confirm(void);
  *   check_only: Only repairs corrupted update, but do not start another one
  *
  * Returned Value:
- *   0 on success, -1 and sets errno on failure.
+ *   OK (0) on success, ERROR (-1) and sets errno on failure.
  *
  ****************************************************************************/
 
 int nxboot_perform_update(bool check_only);
 
+/****************************************************************************
+ * Name: nxboot_ramcopy
+ *
+ * Description:
+ *   Copies the (already) validate bootable image to RAM memory
+ *
+ *   NOTE - no checking that the RAM location is correct, nor that the
+ *          image size is appropriate for that RAM address!
+ *
+ * Input parameters:
+ *   none
+ *
+ * Returned Value:
+ *   OK (0) on success, ERROR (-1) on fail
+ *
+ ****************************************************************************/
+
+int nxboot_ramcopy(void);
+
 #endif /* __BOOT_NXBOOT_INCLUDE_NXBOOT_H */
diff --git a/boot/nxboot/loader/boot.c b/boot/nxboot/loader/boot.c
index 9a43f4cb6..9364ba16f 100644
--- a/boot/nxboot/loader/boot.c
+++ b/boot/nxboot/loader/boot.c
@@ -79,6 +79,9 @@ static uint32_t calculate_crc(int fd, struct 
nxboot_img_header *header)
   off_t off;
   uint32_t crc;
   struct flash_partition_info info;
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT
+  int total_size;
+#endif  
 
   if (flash_partition_info(fd, &info) < 0)
     {
@@ -94,6 +97,9 @@ static uint32_t calculate_crc(int fd, struct 
nxboot_img_header *header)
   crc = 0xffffffff;
   off = offsetof(struct nxboot_img_header, crc) + sizeof crc;
   remain = header->size + header->header_size - off;
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT
+  total_size = remain;
+#endif
   while (remain > 0)
     {
       readsiz = remain > info.blocksize ? info.blocksize : remain;
@@ -106,6 +112,15 @@ static uint32_t calculate_crc(int fd, struct 
nxboot_img_header *header)
       off += readsiz;
       remain -= readsiz;
       crc = crc32part((uint8_t *)buf, readsiz, crc);
+      if ((remain % 25) == 0)
+        {
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT
+          nxboot_progress(nxboot_progress_percent,
+                          ((total_size - remain) * 100) / total_size);
+#else
+          nxboot_progress(nxboot_progress_dot);
+#endif
+        }
     }
 
   free(buf);
@@ -124,6 +139,9 @@ static int copy_partition(int from, int where, struct 
nxboot_state *state,
   int blocksize;
   off_t off;
   char *buf;
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT  
+  int total_size;
+#endif
 
   get_image_header(from, &header);
 
@@ -143,6 +161,9 @@ static int copy_partition(int from, int where, struct 
nxboot_state *state,
       return ERROR;
     }
 
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT
+  total_size = remain * 100;
+#endif
   blocksize = MAX(info_from.blocksize, info_where.blocksize);
 
   buf = malloc(blocksize);
@@ -202,6 +223,15 @@ static int copy_partition(int from, int where, struct 
nxboot_state *state,
 
       off += readsiz;
       remain -= readsiz;
+      if ((remain % 25) == 0)
+        {
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT
+          nxboot_progress(nxboot_progress_percent,
+                          ((total_size - remain) * 100) / total_size);
+#else
+          nxboot_progress(nxboot_progress_dot);
+#endif
+        }
     }
 
   free(buf);
@@ -218,6 +248,7 @@ static bool validate_image(int fd)
       return false;
     }
 
+  syslog(LOG_INFO, "Validating image.\n");
   return calculate_crc(fd, &header) == header.crc;
 }
 
@@ -268,18 +299,24 @@ static enum nxboot_update_type
                   struct nxboot_img_header *update_header,
                   struct nxboot_img_header *recovery_header)
 {
+  nxboot_progress(nxboot_progress_start, validate_primary);
   bool primary_valid = validate_image(primary);
+  nxboot_progress(nxboot_progress_end);
 
+  nxboot_progress(nxboot_progress_start, validate_update);
   if (update_header->magic == NXBOOT_HEADER_MAGIC && validate_image(update))
     {
       if (primary_header->crc != update_header->crc ||
           !compare_versions(&primary_header->img_version,
           &update_header->img_version) || !primary_valid)
         {
+          nxboot_progress(nxboot_progress_end);
           return NXBOOT_UPDATE_TYPE_UPDATE;
         }
     }
 
+  nxboot_progress(nxboot_progress_end);
+
   if (IS_INTERNAL_MAGIC(recovery_header->magic) && state->recovery_valid &&
       ((IS_INTERNAL_MAGIC(primary_header->magic) &&
       !state->primary_confirmed) || !primary_valid))
@@ -292,6 +329,7 @@ static enum nxboot_update_type
 
 static int perform_update(struct nxboot_state *state, bool check_only)
 {
+  int successful;
   int update;
   int recovery;
   int primary;
@@ -331,18 +369,25 @@ static int perform_update(struct nxboot_state *state, 
bool check_only)
       recovery = secondary;
     }
 
+  nxboot_progress(nxboot_progress_start, validate_primary);
   if (state->next_boot == NXBOOT_UPDATE_TYPE_REVERT &&
       (!check_only || !validate_image(primary)))
     {
+      nxboot_progress(nxboot_progress_end);
       if (state->recovery_valid)
         {
           syslog(LOG_INFO, "Reverting image to recovery.\n");
+          nxboot_progress(nxboot_progress_start, recovery_revert);
           copy_partition(recovery, primary, state, false);
+          nxboot_progress(nxboot_progress_end);
         }
     }
   else
     {
+      nxboot_progress(nxboot_progress_end);
+      nxboot_progress(nxboot_progress_start, validate_primary);
       primary_valid = validate_image(primary);
+      nxboot_progress(nxboot_progress_end);
       if (primary_valid && check_only)
         {
           /* Skip if primary image is valid (does not mather whether
@@ -368,21 +413,33 @@ 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);
-          if (!validate_image(recovery))
+          nxboot_progress(nxboot_progress_end);
+          nxboot_progress(nxboot_progress_start, validate_recovery);
+          successful = validate_image(recovery);
+          nxboot_progress(nxboot_progress_end);
+          if (!successful)
             {
-              syslog(LOG_INFO, "New recovery is not valid, stop update.\n");
+              syslog(LOG_INFO,
+                            "New recovery is not valid,stop update.\n");
+              nxboot_progress(nxboot_info, recovery_invalid);
               goto perform_update_done;
             }
 
           syslog(LOG_INFO, "Recovery image created.\n");
+          nxboot_progress(nxboot_info, recovery_created);
         }
 
-      if (validate_image(update))
+      nxboot_progress(nxboot_progress_start, validate_update);
+      successful = validate_image(update);
+      nxboot_progress(nxboot_progress_end);
+      if (successful)
         {
           /* Perform update only if update slot contains valid image. */
 
           syslog(LOG_INFO, "Updating from update image.\n");
+          nxboot_progress(nxboot_progress_start, update_from_update);
           if (copy_partition(update, primary, state, true) >= 0)
             {
               /* Erase the first sector of update partition. This marks the
@@ -393,6 +450,8 @@ static int perform_update(struct nxboot_state *state, bool 
check_only)
 
               flash_partition_erase_first_sector(update);
             }
+
+          nxboot_progress(nxboot_progress_end);
         }
     }
 
@@ -403,6 +462,46 @@ perform_update_done:
   return OK;
 }
 
+#ifdef CONFIG_NXBOOT_COPY_TO_RAM
+int nxboot_ramcopy(void)
+{
+  int ret = OK;
+  int primary;
+  struct nxboot_img_header header;
+  ssize_t bytes;
+  static uint8_t *buf;
+
+  primary = flash_partition_open(CONFIG_NXBOOT_PRIMARY_SLOT_PATH);
+  if (primary < 0)
+    {
+      return ERROR;
+    }
+
+  get_image_header(primary, &header);
+  buf = malloc(header.size);
+  if (!buf)
+    {
+      ret = ERROR;
+      goto exit_with_error;
+    }
+
+  bytes = pread(primary, buf, header.size, header.header_size);
+  if (bytes != header.size)
+    {
+      ret = ERROR;
+      goto exit_with_error;
+    }
+
+  memcpy((uint32_t *)CONFIG_NXBOOT_RAMSTART, buf, header.size);
+
+exit_with_error:
+  flash_partition_close(primary);
+  free(buf);
+
+  return ret;
+}
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -528,7 +627,9 @@ int nxboot_get_state(struct nxboot_state *state)
       state->update = NXBOOT_TERTIARY_SLOT_NUM;
     }
 
+  nxboot_progress(nxboot_progress_start, validate_recovery);
   state->recovery_valid = validate_image(recovery);
+  nxboot_progress(nxboot_progress_end);
   state->recovery_present = primary_header.crc == recovery_header->crc;
 
   /* The image is confirmed if it has either NXBOOT_HEADER_MAGIC or a
@@ -611,7 +712,7 @@ int nxboot_get_confirm(void)
   int recovery;
   int recovery_pointer;
   char *path;
-  int ret = 0;
+  int ret = OK;
   struct nxboot_img_header primary_header;
   struct nxboot_img_header recovery_header;
 
@@ -799,6 +900,7 @@ int nxboot_perform_update(bool check_only)
            */
 
           syslog(LOG_ERR, "Update process failed: %s\n", strerror(errno));
+          nxboot_progress(nxboot_error, update_failed);
         }
     }
 
@@ -823,3 +925,4 @@ int nxboot_perform_update(bool check_only)
 
   return ret;
 }
+
diff --git a/boot/nxboot/loader/flash.c b/boot/nxboot/loader/flash.c
index e7a53b83c..fdbab4bb9 100644
--- a/boot/nxboot/loader/flash.c
+++ b/boot/nxboot/loader/flash.c
@@ -202,8 +202,8 @@ int flash_partition_read(int fd, void *buf, size_t count, 
off_t off)
   nbytes = read(fd, buf, count);
   if (nbytes != count)
     {
-      syslog(LOG_ERR, "Read from offset %ld failed %s\n",
-              off, strerror(errno));
+      syslog(LOG_ERR, "Read from offset %ld failed %s\n", off,
+                      strerror(errno));
       return ERROR;
     }
 
@@ -265,7 +265,7 @@ int flash_partition_erase_first_sector(int fd)
   if (ret < 0)
     {
       syslog(LOG_ERR, "Could not erase the partition: %s\n",
-              strerror(errno));
+                      strerror(errno));
       return ERROR;
     }
 
@@ -295,7 +295,8 @@ int flash_partition_info(int fd, struct 
flash_partition_info *info)
   ret = ioctl(fd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geometry));
   if (ret < 0)
     {
-      syslog(LOG_ERR, "ioctl MTDIOC_GEOMETRY failed: %s\n", strerror(errno));
+      syslog(LOG_ERR, "ioctl MTDIOC_GEOMETRY failed: %s\n",
+                              strerror(errno));
       return ERROR;
     }
 
diff --git a/boot/nxboot/nxboot_main.c b/boot/nxboot/nxboot_main.c
index 09e556b2b..0d0084ad0 100644
--- a/boot/nxboot/nxboot_main.c
+++ b/boot/nxboot/nxboot_main.c
@@ -28,28 +28,235 @@
 
 #include <stdio.h>
 #include <syslog.h>
-
+#include <nuttx/ascii.h>
+#include <sys/param.h>
 #include <nxboot.h>
 #include <sys/boardctl.h>
 
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+static bool g_progress_started = false;
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT
+static bool g_progress_percent_started = false;
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS
+
+#  ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT  
+static const char backtab[] =
+{
+  ASCII_BS, ASCII_BS, ASCII_BS, ASCII_BS, '\0',
+};
+#  endif
+
+static const char *progress_msgs[] =
+{
+  [startup_msg]              = "*** nxboot ***",
+  [power_reset]              = "Power Reset detected, check images only",
+  [soft_reset]               = "Soft reset detected, check for update",
+  [found_bootable_image]     = "Found bootable image, boot from primary",
+  [no_bootable_image]        = "No bootable image found",
+  [boardioc_image_boot_fail] = "Board failed to boot bootable image",
+  [ramcopy_started]          = "Copying bootable image to RAM",
+  [recovery_revert]          = "Reverting image to recovery",
+  [recovery_create]          = "Creating recovery image",
+  [update_from_update]       = "Updating from update image",
+  [validate_primary]         = "Validating primary image",
+  [validate_recovery]        = "Validating recovery image",
+  [validate_update]          = "Validating update image",
+  [recovery_created]         = "Recovery image created",
+  [recovery_invalid]         = "Recovery image invalid, update stopped",
+  [update_failed]            = "Update failed",
+};
+#endif /* CONFIG_NXBOOT_PRINTF_PROGRESS */
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: nxboot_progress
+ *
+ * Description:
+ *   If enabled, this function prints progress messages to stdout.
+ *   Messages are handled via integer enums, allowing this function to be
+ *   easily replaced if required with no changes needed to the underlying
+ *   code
+ *
+ * Input Parameters:
+ *   type - the progress message type to be printed, as per progress_type_e:
+ *          - nxboot_info:             Prefixes arg. string with "INFO:"
+ *          - nxboot_error:            Prefixes arg. string with "ERR:"
+ *          - nxboot_progress_start:   Prints arg. string with no newline
+ *                                     to allow a ..... sequence
+ *                                     or % remaining to follow
+ *          - nxboot_progress_dot:     Prints a "." to the ..... sequence
+ *          - nxboot_progress_percent: Displays progress as % remaining
+ *          - nxboot_progress_end,     Flags end of a progrees sequence
+ *
+ *   ... - variadic argument:
+ *          - the enum (int) reference to the message string or
+ *          - the % remaining in the case of type: nxboot_progress_percent
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void nxboot_progress(enum progress_type_e type, ...)
+{
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS
+  va_list arg;
+
+  va_start(arg, type);
+
+  switch (type)
+    {
+      case nxboot_info:
+        {
+          int idx = va_arg(arg, int);
+          assert(progress_msgs[idx]);
+          if (strlen(progress_msgs[idx]) == 0)
+            {
+              syslog(LOG_ERR, "No progress message for idx: %d\n", idx);
+              break;
+            }
+
+          dprintf(STDOUT_FILENO, "%s\n", progress_msgs[idx]);
+        }
+      break;
+      case nxboot_error:
+        {
+          int idx = va_arg(arg, int);
+          assert(progress_msgs[idx]);
+          if (strlen(progress_msgs[idx]) == 0)
+            {
+              syslog(LOG_ERR, "No progress message for idx: %d\n", idx);
+              break;
+            }
+
+          dprintf(STDOUT_FILENO, "ERROR: %s\n", progress_msgs[idx]);
+        }
+      break;
+      case nxboot_progress_start:
+        {
+          int idx = va_arg(arg, int);
+          assert(progress_msgs[idx]);
+          if (strlen(progress_msgs[idx]) == 0)
+            {
+              syslog(LOG_ERR, "No progress message for idx: %d\n", idx);
+              break;
+            }
+
+          dprintf(STDOUT_FILENO, "%s", progress_msgs[idx]);
+          g_progress_started = true;
+        }
+      break;
+      case nxboot_progress_dot:
+        {
+          assert(g_progress_started);
+          if (!g_progress_started)
+            {
+              syslog(LOG_ERR, "Progress dot requested "
+                              "but no previous progress start\n");
+            }
+          else
+            {
+              dprintf(STDOUT_FILENO, ".");
+            }
+        }
+      break;
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT      
+      case nxboot_progress_percent:
+        {
+          assert(g_progress_started);
+          if (!g_progress_started)
+            {
+              syslog(LOG_ERR, "Progress percent requested "
+                              "but no previous progress start\n");
+            }
+          else
+            {
+              int percent = va_arg(arg, int);
+              if (!g_progress_percent_started)
+                {
+                  g_progress_percent_started = true;
+                  dprintf(STDOUT_FILENO, ": ");
+                }
+              else
+                {
+                  dprintf(STDOUT_FILENO, "%s", backtab);
+                }
+
+              dprintf(STDOUT_FILENO, "%3d%%", MIN(percent, 100));
+            }
+        }
+      break;
+#endif
+      case nxboot_progress_end:
+        {
+          assert(g_progress_started);
+          if (!g_progress_started)
+            {
+              syslog(LOG_ERR, "Progress dot stop requested "
+                              "but no previous progress start\n");
+            }
+          else
+            {
+              dprintf(STDOUT_FILENO, "\n");
+            }
+
+          g_progress_started = false;
+#ifdef CONFIG_NXBOOT_PRINTF_PROGRESS_PERCENT   
+          g_progress_percent_started = false;
+#endif
+        }
+      break;
+      default:
+        {
+          assert(false);
+          syslog(LOG_ERR, "Invalid progress message type: %d\n", type);
+          dprintf(STDOUT_FILENO, "progress: unknown type!\n");
+        }
+      break;
+    }
+
+  va_end(arg);
+#endif /* CONFIG_NXBOOT_PRINTF_PROGRESS */
+}
+
 /****************************************************************************
  * Name: nxboot_main
  *
  * Description:
- *   NuttX bootlaoder entry point.
+ *   NuttX bootloader entry point.
  *
  ****************************************************************************/
 
 int main(int argc, FAR char *argv[])
 {
+  int ret;
   struct boardioc_boot_info_s info;
   bool check_only;
 #ifdef CONFIG_NXBOOT_SWRESET_ONLY
-  int ret;
   FAR struct boardioc_reset_cause_s cause;
 #endif
 
@@ -66,6 +273,7 @@ int main(int argc, FAR char *argv[])
 #endif
 
   syslog(LOG_INFO, "*** nxboot ***\n");
+  nxboot_progress(nxboot_info, startup_msg);
 
 #ifdef CONFIG_NXBOOT_SWRESET_ONLY
   check_only = true;
@@ -77,10 +285,12 @@ int main(int argc, FAR char *argv[])
           cause.cause == BOARDIOC_RESETCAUSE_PIN)
         {
           check_only = false;
+          nxboot_progress(nxboot_info, soft_reset);
         }
       else
         {
           syslog(LOG_INFO, "Power reset detected, performing check only.\n");
+          nxboot_progress(nxboot_info, power_reset);
         }
     }
 #else
@@ -90,15 +300,28 @@ int main(int argc, FAR char *argv[])
   if (nxboot_perform_update(check_only) < 0)
     {
       syslog(LOG_ERR, "Could not find bootable image.\n");
-      return 0;
+      nxboot_progress(nxboot_error, no_bootable_image);
+      return OK;
     }
 
   syslog(LOG_INFO, "Found bootable image, boot from primary.\n");
+  nxboot_progress(nxboot_info, found_bootable_image);
+
+#ifdef CONFIG_NXBOOT_COPY_TO_RAM
+  syslog(LOG_INFO, "Copying image to RAM.\n");
+  nxboot_ramcopy();
+#endif
 
   /* Call board specific image boot */
 
   info.path        = CONFIG_NXBOOT_PRIMARY_SLOT_PATH;
   info.header_size = CONFIG_NXBOOT_HEADER_SIZE;
 
-  return boardctl(BOARDIOC_BOOT_IMAGE, (uintptr_t)&info);
+  ret = boardctl(BOARDIOC_BOOT_IMAGE, (uintptr_t)&info);
+
+  /* Only get here if the board boot fails */
+
+  nxboot_progress(nxboot_error, boardioc_image_boot_fail);
+
+  return ret;
 }

Reply via email to