From patchwork Wed Apr 22 10:46:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Ferraris X-Patchwork-Id: 238275 List-Id: U-Boot discussion From: arnaud.ferraris at collabora.com (Arnaud Ferraris) Date: Wed, 22 Apr 2020 12:46:28 +0200 Subject: [PATCH 2/2] bootcount_flash: add redundancy support In-Reply-To: <20200422104629.88284-1-arnaud.ferraris@collabora.com> References: <20200422104629.88284-1-arnaud.ferraris@collabora.com> Message-ID: <20200422104629.88284-2-arnaud.ferraris@collabora.com> In order to deal with possible corruption of the flash memory storing the boot counter, this change adds optional redundancy support to the bootcount flash driver. When enabled, a backup copy of the bootcount structure is stored on the next flash sector, and written each time the main bootcount is saved. In case the primary bootcount is corrupted, the backup sector will be used to restore it to its previous state. Signed-off-by: Arnaud Ferraris --- drivers/bootcount/Kconfig | 7 +++++ drivers/bootcount/bootcount_flash.c | 47 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig index 94de3f5ef8..f247988641 100644 --- a/drivers/bootcount/Kconfig +++ b/drivers/bootcount/Kconfig @@ -170,6 +170,13 @@ config SYS_BOOTCOUNT_EXT_NAME help Set the filename and path of the file used to store the boot counter. +config BOOTCOUNT_FLASH_REDUNDANCY + bool "Boot counter on flash device" + depends on BOOTCOUNT_FLASH + help + Store the bootcounter on 2 consecutive flash sectors, and use the backup + sector in case the main one gets corrupted. + config SYS_BOOTCOUNT_ADDR hex "RAM address used for reading and writing the boot counter" default 0x44E3E000 if BOOTCOUNT_AM33XX diff --git a/drivers/bootcount/bootcount_flash.c b/drivers/bootcount/bootcount_flash.c index 1222bb4ae0..86ac7e0d03 100644 --- a/drivers/bootcount/bootcount_flash.c +++ b/drivers/bootcount/bootcount_flash.c @@ -23,8 +23,23 @@ static struct bootcount *bootcount = (void *)CONFIG_SYS_BOOTCOUNT_ADDR; static ulong bc_flash = CONFIG_SYS_BOOTCOUNT_FLASH_ADDR; + +#ifdef CONFIG_BOOTCOUNT_FLASH_REDUNDANCY +/* + * When using redundant bootcount storage, the backup bootcount resides: + * - immediately after the main bootcount in RAM + * - on the next sector in flash + */ +static struct bootcount *bootcount_backup = + (void *)(CONFIG_SYS_BOOTCOUNT_ADDR + sizeof(struct bootcount)); +static ulong bc_flash_backup = + CONFIG_SYS_BOOTCOUNT_FLASH_ADDR + CONFIG_SYS_FLASH_SECT_SIZE; +static ulong bc_flash_end = + CONFIG_SYS_BOOTCOUNT_FLASH_ADDR + (2 * CONFIG_SYS_FLASH_SECT_SIZE) - 1; +#else static ulong bc_flash_end = CONFIG_SYS_BOOTCOUNT_FLASH_ADDR + CONFIG_SYS_FLASH_SECT_SIZE - 1; +#endif static void bootcount_write(void) { @@ -39,6 +54,12 @@ static void bootcount_write(void) if (flash_write((char *)bootcount, bc_flash, sizeof(*bootcount))) return; +#ifdef CONFIG_BOOTCOUNT_FLASH_REDUNDANCY + puts("Writing redundant bootcount to Flash...\n"); + if (flash_write((char *)bootcount, bc_flash_backup, sizeof(*bootcount))) + return; +#endif + flash_sect_protect(1, bc_flash, bc_flash_end); } @@ -47,6 +68,9 @@ static void bootcount_init(void) memset(bootcount, 0, sizeof(*bootcount)); bootcount->magic = CONFIG_SYS_BOOTCOUNT_MAGIC; bootcount->crc = crc32(0, (uchar *)bootcount, BOOTCOUNT_CRC_SIZE); +#ifdef CONFIG_BOOTCOUNT_FLASH_REDUNDANCY + memcpy(bootcount_backup, bootcount, sizeof(*bootcount)); +#endif bootcount_write(); } @@ -54,6 +78,9 @@ void bootcount_store(ulong a) { bootcount->count = a; bootcount->crc = crc32(0, (uchar *)bootcount, BOOTCOUNT_CRC_SIZE); +#ifdef CONFIG_BOOTCOUNT_FLASH_REDUNDANCY + memcpy(bootcount_backup, bootcount, sizeof(*bootcount)); +#endif if (bootcount->flags & BOOTCOUNT_FLAGS_UPDATE) bootcount_write(); } @@ -65,13 +92,33 @@ ulong bootcount_load(void) if (!initialized) { memcpy(bootcount, (void *)bc_flash, sizeof(*bootcount)); +#ifdef CONFIG_BOOTCOUNT_FLASH_REDUNDANCY + memcpy(bootcount_backup, + (void *)bc_flash_backup, + sizeof(*bootcount)); +#endif initialized = 1; } crc = crc32(0, (uchar *)bootcount, BOOTCOUNT_CRC_SIZE); if (bootcount->magic != CONFIG_SYS_BOOTCOUNT_MAGIC || bootcount->crc != crc) { +#ifdef CONFIG_BOOTCOUNT_FLASH_REDUNDANCY + puts("Invalid bootcount, checking backup sector...\n"); + crc = crc32(0, (uchar *)bootcount_backup, BOOTCOUNT_CRC_SIZE); + if (bootcount_backup->magic != CONFIG_SYS_BOOTCOUNT_MAGIC || + bootcount_backup->crc != crc) { + puts("Invalid backup sector, initializing...\n"); + bootcount_init(); + } else { + puts("Using backup sector...\n"); + memcpy(bootcount, bootcount_backup, sizeof(*bootcount)); + bootcount_write(); + } +#else + puts("Invalid bootcount, initializing...\n"); bootcount_init(); +#endif } return bootcount->count;