dfu: mcuboot: add boot_read_bank_header()
This is an accessor function for the MCUboot image header of an image bank. The interface may seem a little cumbersome, but it is future-proof against MCUboot feature and incompatible header version changes. Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
This commit is contained in:
parent
01aa12bffd
commit
e2c9be1a18
2 changed files with 195 additions and 4 deletions
|
@ -9,6 +9,88 @@
|
||||||
#define __MCUBOOT_H__
|
#define __MCUBOOT_H__
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MCUboot image header representation for image version
|
||||||
|
*
|
||||||
|
* The header for an MCUboot firmware image contains an embedded
|
||||||
|
* version number, in semantic versioning format. This structure
|
||||||
|
* represents the information it contains.
|
||||||
|
*/
|
||||||
|
struct mcuboot_img_sem_ver {
|
||||||
|
u8_t major;
|
||||||
|
u8_t minor;
|
||||||
|
u16_t revision;
|
||||||
|
u32_t build_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Model for the MCUboot image header as of version 1
|
||||||
|
*
|
||||||
|
* This represents the data present in the image header, in version 1
|
||||||
|
* of the header format.
|
||||||
|
*
|
||||||
|
* Some information present in the header but not currently relevant
|
||||||
|
* to applications is omitted.
|
||||||
|
*/
|
||||||
|
struct mcuboot_img_header_v1 {
|
||||||
|
/** The size of the image, in bytes. */
|
||||||
|
u32_t image_size;
|
||||||
|
/** The image version. */
|
||||||
|
struct mcuboot_img_sem_ver sem_ver;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Model for the MCUBoot image header
|
||||||
|
*
|
||||||
|
* This contains the decoded image header, along with the major
|
||||||
|
* version of MCUboot that the header was built for.
|
||||||
|
*
|
||||||
|
* (The MCUboot project guarantees that incompatible changes to the
|
||||||
|
* image header will result in major version changes to the bootloader
|
||||||
|
* itself, and will be detectable in the persistent representation of
|
||||||
|
* the header.)
|
||||||
|
*/
|
||||||
|
struct mcuboot_img_header {
|
||||||
|
/**
|
||||||
|
* The version of MCUboot the header is built for.
|
||||||
|
*
|
||||||
|
* The value 1 corresponds to MCUboot versions 1.x.y.
|
||||||
|
*/
|
||||||
|
u32_t mcuboot_version;
|
||||||
|
/**
|
||||||
|
* The header information. It is only valid to access fields
|
||||||
|
* in the union member corresponding to the mcuboot_version
|
||||||
|
* field above.
|
||||||
|
*/
|
||||||
|
union {
|
||||||
|
/** Header information for MCUboot version 1. */
|
||||||
|
struct mcuboot_img_header_v1 v1;
|
||||||
|
} h;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the MCUboot image header information from an image bank.
|
||||||
|
*
|
||||||
|
* This attempts to parse the image header, which must begin at offset
|
||||||
|
* @a bank_offset from the beginning of the flash device used by
|
||||||
|
* MCUboot.
|
||||||
|
*
|
||||||
|
* @param bank_offset Offset of the image header from the start of the
|
||||||
|
* flash device used by MCUboot to store firmware.
|
||||||
|
* @param header On success, the returned header information is available
|
||||||
|
* in this structure.
|
||||||
|
* @param header_size Size of the header structure passed by the caller.
|
||||||
|
* If this is not large enough to contain all of the
|
||||||
|
* necessary information, an error is returned.
|
||||||
|
* @return Zero on success, a negative value on error.
|
||||||
|
*/
|
||||||
|
int boot_read_bank_header(u32_t bank_offset,
|
||||||
|
struct mcuboot_img_header *header,
|
||||||
|
size_t header_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the currently running image is confirmed as OK.
|
* @brief Check if the currently running image is confirmed as OK.
|
||||||
|
|
|
@ -13,22 +13,51 @@
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
|
||||||
#include <misc/__assert.h>
|
#include <misc/__assert.h>
|
||||||
|
#include <misc/byteorder.h>
|
||||||
#include <board.h>
|
#include <board.h>
|
||||||
#include <dfu/mcuboot.h>
|
#include <dfu/mcuboot.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers for image trailer, as defined by mcuboot.
|
* Helpers for image headers and trailers, as defined by mcuboot.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strict defines: Defines in block below must be equal to coresponding
|
* Strict defines: the definitions in the following block contain
|
||||||
* mcuboot defines
|
* values which are MCUboot implementation requirements.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Header: */
|
||||||
|
#define BOOT_HEADER_MAGIC_V1 0x96f3b83d
|
||||||
|
#define BOOT_HEADER_SIZE_V1 32
|
||||||
|
|
||||||
|
/* Trailer: */
|
||||||
#define BOOT_MAX_ALIGN 8
|
#define BOOT_MAX_ALIGN 8
|
||||||
#define BOOT_MAGIC_SZ 16
|
#define BOOT_MAGIC_SZ 16
|
||||||
#define BOOT_FLAG_SET 0x01
|
#define BOOT_FLAG_SET 0x01
|
||||||
#define BOOT_FLAG_UNSET 0xff
|
#define BOOT_FLAG_UNSET 0xff
|
||||||
/* end_of Strict defines */
|
|
||||||
|
/*
|
||||||
|
* Raw (on-flash) representation of the v1 image header.
|
||||||
|
*/
|
||||||
|
struct mcuboot_v1_raw_header {
|
||||||
|
u32_t header_magic;
|
||||||
|
u32_t image_load_address;
|
||||||
|
u16_t header_size;
|
||||||
|
u16_t pad;
|
||||||
|
u32_t image_size;
|
||||||
|
u32_t image_flags;
|
||||||
|
struct {
|
||||||
|
u8_t major;
|
||||||
|
u8_t minor;
|
||||||
|
u16_t revision;
|
||||||
|
u32_t build_num;
|
||||||
|
} version;
|
||||||
|
u32_t pad2;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End of strict defines
|
||||||
|
*/
|
||||||
|
|
||||||
#define BOOT_MAGIC_GOOD 1
|
#define BOOT_MAGIC_GOOD 1
|
||||||
#define BOOT_MAGIC_BAD 2
|
#define BOOT_MAGIC_BAD 2
|
||||||
|
@ -156,6 +185,86 @@ static int boot_magic_write(u32_t bank_offs)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int boot_read_v1_header(u32_t bank_offset,
|
||||||
|
struct mcuboot_v1_raw_header *v1_raw)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read and sanity-check the raw header.
|
||||||
|
*/
|
||||||
|
rc = flash_read(flash_dev, bank_offset, v1_raw, sizeof(*v1_raw));
|
||||||
|
if (rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
v1_raw->header_magic = sys_le32_to_cpu(v1_raw->header_magic);
|
||||||
|
v1_raw->image_load_address =
|
||||||
|
sys_le32_to_cpu(v1_raw->image_load_address);
|
||||||
|
v1_raw->header_size = sys_le16_to_cpu(v1_raw->header_size);
|
||||||
|
v1_raw->image_size = sys_le32_to_cpu(v1_raw->image_size);
|
||||||
|
v1_raw->image_flags = sys_le32_to_cpu(v1_raw->image_flags);
|
||||||
|
v1_raw->version.revision =
|
||||||
|
sys_le16_to_cpu(v1_raw->version.revision);
|
||||||
|
v1_raw->version.build_num =
|
||||||
|
sys_le32_to_cpu(v1_raw->version.build_num);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity checks.
|
||||||
|
*
|
||||||
|
* Larger values in header_size than BOOT_HEADER_SIZE_V1 are
|
||||||
|
* possible, e.g. if Zephyr was linked with
|
||||||
|
* CONFIG_TEXT_SECTION_OFFSET > BOOT_HEADER_SIZE_V1.
|
||||||
|
*/
|
||||||
|
if ((v1_raw->header_magic != BOOT_HEADER_MAGIC_V1) ||
|
||||||
|
(v1_raw->header_size < BOOT_HEADER_SIZE_V1)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int boot_read_bank_header(u32_t bank_offset,
|
||||||
|
struct mcuboot_img_header *header,
|
||||||
|
size_t header_size)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct mcuboot_v1_raw_header v1_raw;
|
||||||
|
struct mcuboot_img_sem_ver *sem_ver;
|
||||||
|
size_t v1_min_size = (sizeof(u32_t) +
|
||||||
|
sizeof(struct mcuboot_img_header_v1));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only version 1 image headers are supported.
|
||||||
|
*/
|
||||||
|
if (header_size < v1_min_size) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
rc = boot_read_v1_header(bank_offset, &v1_raw);
|
||||||
|
if (rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy just the fields we care about into the return parameter.
|
||||||
|
*
|
||||||
|
* - header_magic: skip (only used to check format)
|
||||||
|
* - image_load_address: skip (only matters for PIC code)
|
||||||
|
* - header_size: skip (only used to check format)
|
||||||
|
* - image_size: include
|
||||||
|
* - image_flags: skip (all unsupported or not relevant)
|
||||||
|
* - version: include
|
||||||
|
*/
|
||||||
|
header->mcuboot_version = 1;
|
||||||
|
header->h.v1.image_size = v1_raw.image_size;
|
||||||
|
sem_ver = &header->h.v1.sem_ver;
|
||||||
|
sem_ver->major = v1_raw.version.major;
|
||||||
|
sem_ver->minor = v1_raw.version.minor;
|
||||||
|
sem_ver->revision = v1_raw.version.revision;
|
||||||
|
sem_ver->build_num = v1_raw.version.build_num;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int boot_request_upgrade(int permanent)
|
int boot_request_upgrade(int permanent)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue