]> git.sur5r.net Git - u-boot/commitdiff
arm/km: adapt bootcounter evaluation
authorHolger Brunck <holger.brunck@keymile.com>
Tue, 13 Sep 2011 22:41:02 +0000 (22:41 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Thu, 3 Nov 2011 21:56:23 +0000 (22:56 +0100)
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>

board/keymile/km_arm/km_arm.c

index 3c9b91768f3a37b39080c1216423083f61f1cbe5..ca33aaec534935bc2357652816a8532a73210055 100644 (file)
@@ -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