summaryrefslogtreecommitdiff
path: root/board/keymile
diff options
context:
space:
mode:
authorHolger Brunck <holger.brunck@keymile.com>2011-09-13 22:41:02 +0000
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2011-11-03 22:56:23 +0100
commit37605c466d10ea49c8618d8a4cdfd0176efa8f68 (patch)
treedad48d568c32add9e3ab3ee0889fe0c6a130f3a4 /board/keymile
parentc5dd9785173ca2118609868c7efb4f19dab00d6b (diff)
downloadu-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>
Diffstat (limited to 'board/keymile')
-rw-r--r--board/keymile/km_arm/km_arm.c32
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