mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
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 <timh@jti.uk.com>
This commit is contained in:
parent
4b8b96f060
commit
bcd1b46946
5 changed files with 454 additions and 20 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue