diff options
author | Holger Brunck <holger.brunck@keymile.com> | 2011-09-13 22:41:02 +0000 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2011-11-03 22:56:23 +0100 |
commit | 37605c466d10ea49c8618d8a4cdfd0176efa8f68 (patch) | |
tree | dad48d568c32add9e3ab3ee0889fe0c6a130f3a4 | |
parent | c5dd9785173ca2118609868c7efb4f19dab00d6b (diff) | |
download | u-boot-imx-37605c466d10ea49c8618d8a4cdfd0176efa8f68.zip u-boot-imx-37605c466d10ea49c8618d8a4cdfd0176efa8f68.tar.gz u-boot-imx-37605c466d10ea49c8618d8a4cdfd0176efa8f68.tar.bz2 |
arm/km: adapt bootcounter evaluation
The bootcounter (stored in the RAM) is not enough protected with the 4 Bytes
BOOTCOUNT_MAGIC against bit errors due to short power loss or holding a system
in RESET. It has been seen, that the bootcounter value has been changed due to
a bit flip on a system holding in RESET, but the BOOTCOUNT_MAGIC was still valid.
A bit pattern with 4000 bytes (after BOOTCOUNT_MAGIC) has been implemented,
which should be enough to detect a bit error.
Signed-off-by: Holger Brunck <holger.brunck@keymile.com>
Signed-off-by: Valentin Longchamp <valentin.longchamp@keymile.com>
cc: Prafulla Wadaskar <prafulla@marvell.com>
-rw-r--r-- | board/keymile/km_arm/km_arm.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c index 3c9b917..ca33aae 100644 --- a/board/keymile/km_arm/km_arm.c +++ b/board/keymile/km_arm/km_arm.c @@ -405,6 +405,15 @@ int hush_init_var(void) #endif #if defined(CONFIG_BOOTCOUNT_LIMIT) +const ulong patterns[] = { 0x00000000, + 0xFFFFFFFF, + 0xFF00FF00, + 0x0F0F0F0F, + 0xF0F0F0F0}; +const ulong NBR_OF_PATTERNS = sizeof(patterns)/sizeof(*patterns); +const ulong OFFS_PATTERN = 3; +const ulong REPEAT_PATTERN = 1000; + void bootcount_store(ulong a) { volatile ulong *save_addr; @@ -416,21 +425,34 @@ void bootcount_store(ulong a) save_addr = (ulong*)(size - BOOTCOUNT_ADDR); writel(a, save_addr); writel(BOOTCOUNT_MAGIC, &save_addr[1]); + + for (i = 0; i < REPEAT_PATTERN; i++) + writel(patterns[i % NBR_OF_PATTERNS], + &save_addr[i+OFFS_PATTERN]); + } ulong bootcount_load(void) { volatile ulong *save_addr; volatile ulong size = 0; - int i; + ulong counter = 0; + int i, tmp; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { size += gd->bd->bi_dram[i].size; } save_addr = (ulong*)(size - BOOTCOUNT_ADDR); - if (readl(&save_addr[1]) != BOOTCOUNT_MAGIC) - return 0; - else - return readl(save_addr); + + counter = readl(&save_addr[0]); + + /* Is the counter reliable, check in the big pattern for bit errors */ + for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) { + tmp = readl(&save_addr[i+OFFS_PATTERN]); + if (tmp != patterns[i % NBR_OF_PATTERNS]) + counter = 0; + } + return counter; } #endif |