zephyr: warn on boot if flash areas are still open

Add reference counting to the flash areas, and a zephyr-only routine
which warns when areas are still open when none should be. Call the
warn routine right before chain-loading.

This prints warnings due to code in loader.c. Future work will be
needed to clean this up.

Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
This commit is contained in:
Marti Bolivar 2017-05-05 11:59:49 -04:00
parent eb9408051e
commit 83a3cef34d
2 changed files with 61 additions and 16 deletions

View File

@ -40,29 +40,46 @@ extern struct device *boot_flash_device;
#define FLASH_DEVICE_ID 100
#define FLASH_DEVICE_BASE CONFIG_FLASH_BASE_ADDRESS
#define FLASH_MAP_ENTRY_MAGIC 0xd00dbeef
struct flash_map_entry {
const uint32_t magic;
const struct flash_area area;
unsigned int ref_count;
};
/*
* The flash area describes essentially the partition table of the
* flash. In this case, it starts with FLASH_AREA_IMAGE_0.
*/
static const struct flash_area part_map[] = {
static struct flash_map_entry part_map[] = {
{
.fa_id = FLASH_AREA_IMAGE_0,
.fa_device_id = FLASH_DEVICE_ID,
.fa_off = FLASH_AREA_IMAGE_0_OFFSET,
.fa_size = FLASH_AREA_IMAGE_0_SIZE,
.magic = FLASH_MAP_ENTRY_MAGIC,
.area = {
.fa_id = FLASH_AREA_IMAGE_0,
.fa_device_id = FLASH_DEVICE_ID,
.fa_off = FLASH_AREA_IMAGE_0_OFFSET,
.fa_size = FLASH_AREA_IMAGE_0_SIZE,
},
},
{
.fa_id = FLASH_AREA_IMAGE_1,
.fa_device_id = FLASH_DEVICE_ID,
.fa_off = FLASH_AREA_IMAGE_1_OFFSET,
.fa_size = FLASH_AREA_IMAGE_1_SIZE,
.magic = FLASH_MAP_ENTRY_MAGIC,
.area = {
.fa_id = FLASH_AREA_IMAGE_1,
.fa_device_id = FLASH_DEVICE_ID,
.fa_off = FLASH_AREA_IMAGE_1_OFFSET,
.fa_size = FLASH_AREA_IMAGE_1_SIZE,
},
},
{
.fa_id = FLASH_AREA_IMAGE_SCRATCH,
.fa_device_id = FLASH_DEVICE_ID,
.fa_off = FLASH_AREA_IMAGE_SCRATCH_OFFSET,
.fa_size = FLASH_AREA_IMAGE_SCRATCH_SIZE,
},
.magic = FLASH_MAP_ENTRY_MAGIC,
.area = {
.fa_id = FLASH_AREA_IMAGE_SCRATCH,
.fa_device_id = FLASH_DEVICE_ID,
.fa_off = FLASH_AREA_IMAGE_SCRATCH_OFFSET,
.fa_size = FLASH_AREA_IMAGE_SCRATCH_SIZE,
},
}
};
int flash_device_base(uint8_t fd_id, uintptr_t *ret)
@ -87,7 +104,7 @@ int flash_area_open(uint8_t id, const struct flash_area **area)
BOOT_LOG_DBG("area %d", id);
for (i = 0; i < ARRAY_SIZE(part_map); i++) {
if (id == part_map[i].fa_id) {
if (id == part_map[i].area.fa_id) {
break;
}
}
@ -95,7 +112,8 @@ int flash_area_open(uint8_t id, const struct flash_area **area)
return -1;
}
*area = &part_map[i];
*area = &part_map[i].area;
part_map[i].ref_count++;
return 0;
}
@ -104,6 +122,30 @@ int flash_area_open(uint8_t id, const struct flash_area **area)
*/
void flash_area_close(const struct flash_area *area)
{
struct flash_map_entry *entry = CONTAINER_OF(area, struct flash_map_entry,
area);
if (entry->magic != FLASH_MAP_ENTRY_MAGIC) {
BOOT_LOG_ERR("invalid area %p (id %u)", area, area->fa_id);
return;
}
if (entry->ref_count == 0) {
BOOT_LOG_ERR("area %u use count underflow", area->fa_id);
return;
}
entry->ref_count--;
}
void zephyr_flash_area_warn_on_open(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(part_map); i++) {
struct flash_map_entry *entry = &part_map[i];
if (entry->ref_count) {
BOOT_LOG_WRN("area %u has %u users",
entry->area.fa_id, entry->ref_count);
}
}
}
int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,

View File

@ -38,6 +38,8 @@ struct arm_vector_table {
uint32_t reset;
};
extern void zephyr_flash_area_warn_on_open(void);
static void do_boot(struct boot_rsp *rsp)
{
struct arm_vector_table *vt;
@ -108,6 +110,7 @@ void main(void)
BOOT_LOG_INF("Bootloader chainload address offset: 0x%x",
rsp.br_image_off);
zephyr_flash_area_warn_on_open();
BOOT_LOG_INF("Jumping to the first image slot");
do_boot(&rsp);