[U-Boot] U-Boot Scripting suggestions to decrement counter in EEPROM. Alignment bug in itest on ARM.

Tom Evans tom at ceos.com.au
Tue Mar 3 07:40:28 CET 2009


I'm implementing a rather complex boot that involves flags and counters 
in EEPROM.

This is to detect multiple boot failures and to then revert to a 
previous Linux kernel and sysroot.

The Hush shell and applications almost support this by using scripts 
(even autoscripting), but not quite.

"ee read" and "ee write" let me read and write the counters and flags to 
memory.

 From there, "if itest *$buf_addr == 1" (and so on) can be used to test 
the values of flags in the EEPROM (except for bad bug in itest, listed 
later). "mw.b" can write flags into memory to then be written to eeprom.

The only way I can currently think of to "read" a byte from EEPROM into 
a shell variable so it can be decremented (with setexpr) and then 
written back is to use something like the following:

     READ_ADDR=0x82000000
     setenv FN_READ_BYTE 'setenv DATA; DATA=0; while itest \
     *$READ_ADDR != $DATA; do setexp DATA $DATA + 1; done'
     mw.l 0x82000000 254
     run FN_READ_BYTE
     echo $DATA

Yes, it is comparing every value from zero and incrementing until it 
gets a match! That results in $DATA being set to "254" (the value I 
wrote to memory) but it takes 9 seconds to run on an 800MHz ARM core!

Am I missing a simpler way or am I going to have to add some new 
commands, like a "memory read" variant that reads into an environment 
variable. If setexpr took a "*" to be a pointer (to be consistent with 
itest) it might be the easiest addition.


BUG IN ITEST
------------
itest crashes ARM chips. I can "iread.b *82000000 == 0", but
"iread.b *82000001 == 0" throws an alignment exception that kills the 
box. The code in itest.c is:

static long evalexp(char *s, int w)
{
     long l, *p;

     /* if the parameter starts with a * then assume is a
        pointer to the value we want */
     if (s[0] == '*') {
         p = (long *)simple_strtoul(&s[1], NULL, 16);
         l = *p;
     } else {
         l = simple_strtoul(s, NULL, 16);
     }

     return (l & ((1 << (w * 8)) - 1));
}

"l = *p" works on a 486 but not on an ARM. It is a simple change - a 
three-way case on the width reading through the "right pointer".

Yes, I should fix this and submit a patch, but I'm not working on 
anything close to the distribution tree unfortunately. I'm pretty sure 
this hasn't been fixed lately though.

-- 
===
Tom Evans      Tom.Evans at ceos.com.au
CEOS Pty Ltd   www.ceos.com.au
3/17 Burgundy St, Heidelberg,
Victoria 3084, Australia



More information about the U-Boot mailing list