diff options
author | Luc Verhaegen <libv@skynet.be> | 2009-06-03 10:47:19 +0000 |
---|---|---|
committer | Luc Verhaegen <libv@skynet.be> | 2009-06-03 10:47:19 +0000 |
commit | 9ceae905f10a555835db0af072c3adfff98b3a7b (patch) | |
tree | 1ea238ee0dbf2b4c4ed206326ed4bf2457f9a018 /util | |
parent | a922b3195b77a3cc82bafad20dd3dfcfd2a61bc0 (diff) | |
download | coreboot-9ceae905f10a555835db0af072c3adfff98b3a7b.tar.xz |
CMOS: Add set_option and rework get_option.
To ease some of my debugging pain on the unichrome, i decided i needed to
move FB size selection into cmos, so i could test a size and then reset it
to the default after loading this value so that the next reboot uses the
(working) default again. This meant implementing set_option in parallel to
get_option.
get_option was then found to have inversed argument ordering (like outb) and
passing char * and then depending on the cmos layout length, which made me
feel quite uncomfortable. Since we either have reserved space (which we
shouldn't do anything with in these two functions), an enum or a
hexadecimal value, unsigned int seemed like the way to go. So all users of
get_option now have their arguments inversed and switched from using ints
to unsigned ints now.
The way get_cmos_value was implemented forced us to not overlap byte and to
have multibyte values be byte aligned. This logic is now adapted to do a
full uint32_t read (when needed) at any offset and any length up to 32, and
the shifting all happens inside an uint32_t as well. set_cmos_value was
implemented similarly. Both routines have been extensively tested in a
quick separate little program as it is not easy to get this stuff right.
build_opt_tbl.c was altered to function correctly within these new
parameters. The enum value retrieval has been changed strol(..., NULL, 10)
to stroul(..., NULL, 0), so that we not only are able to use unsigned ints
now but so that we also interprete hex values correctly. The 32bit limit
gets imposed on all entries not marked reserved, an unused "user_data" field
that appeared in a lot of cmos.layouts has been changed to reserved as well.
Signed-off-by: Luc Verhaegen <libv@skynet.be>
Acked-by: Peter Stuge <peter@stuge.se>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4332 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'util')
-rw-r--r-- | util/options/build_opt_tbl.c | 139 |
1 files changed, 36 insertions, 103 deletions
diff --git a/util/options/build_opt_tbl.c b/util/options/build_opt_tbl.c index 075387d1d8..89d14ab799 100644 --- a/util/options/build_opt_tbl.c +++ b/util/options/build_opt_tbl.c @@ -17,85 +17,52 @@ static unsigned char cmos_table[4096]; -/* This array is used to isolate bits that are to be changed in a byte */ -static unsigned char clip[9]={0,1,3,7,0x0f,0x1f,0x3f,0x7f,0xff}; - - /* This routine loops through the entried and tests if any of the fields overlap input entry_start = the memory pointer to the start of the entries. entry_end = the byte past the entries. output none if there is an overlap, the routine exits, other wise it returns. */ + void test_for_entry_overlaps(void *entry_start, void *entry_end) { - int ptr; char *cptr; - int buffer_bit_size; - int offset; - int byte; - int byte_length; - struct cmos_entries *ce; + struct cmos_entries *ce = NULL; unsigned char test[CMOS_IMAGE_BUFFER_SIZE]; - unsigned char set; + int i; - /* calculate the size of the cmos buffer in bits */ - buffer_bit_size=(CMOS_IMAGE_BUFFER_SIZE*8); - /* clear the temporary test buffer */ - for(ptr=0; ptr < CMOS_IMAGE_BUFFER_SIZE; ptr++) - test[ptr]=0; + memset(test, 0, CMOS_IMAGE_BUFFER_SIZE); + + for (cptr = entry_start; cptr < (char *)entry_end; cptr += ce->size) { + ce = (struct cmos_entries *)cptr; + + /* Only reserved space can be larger than 32bits */ + if ((ce->length > 32) && (ce->config != 'r')) { + fprintf(stderr, "Error: Entry %s is longer than" + " 32bits.\n", ce->name); + exit(1); + } - /* loop through each entry in the table testing for errors */ - for(cptr = entry_start; cptr < (char *)entry_end; cptr += ce->size) { - ce=(struct cmos_entries *)cptr; /* test if entry goes past the end of the buffer */ - if((ce->bit+ce->length)>buffer_bit_size) { - printf("Error - Entry %s start bit + length must be less than %d\n", - ce->name,buffer_bit_size); + if ((ce->bit + ce->length) > (CMOS_IMAGE_BUFFER_SIZE * 8)) { + fprintf(stderr, "Error: Entry %s exceeds CMOS" + " space.\n", ce->name); exit(1); } - byte=ce->bit/8; - offset=ce->bit%8; - byte_length=ce->length/8; - if(byte_length) { /* entry is 8 bits long or more */ - if(offset) { /* if 8 bits or more long, it must be byte aligned */ - printf("Error - Entry %s length over 8 must be byte aligned\n", - ce->name); + + /* see whether our bits were marked before */ + for (i = ce->bit; i < (ce->bit + ce->length); i++) + if (test[i / 8] & (0x01 << (i % 8))) { + printf("Error: Entry %s overlaps at bit %d.\n", + ce->name, i); exit(1); } - /* test if entries 8 or more in length are even bytes */ - if(ce->length%8){ - printf("Error - Entry %s length over 8 must be a multiple of 8\n", - ce->name); - exit(1); - } - /* test if any of the bits have been previously used */ - for(;byte_length;byte_length--,byte++) { - if(test[byte]) { - printf("Error - Entry %s uses same bits previously used\n", - ce->name); - exit(1); - } - test[byte]=clip[8]; /* set the bits defined in test */ - } - } else { - /* test if bits overlap byte boundaries */ - if(ce->length>(8-offset)) { - printf("Error - Entry %s length overlaps a byte boundry\n", - ce->name); - exit(1); - } - /* test for bits previously used */ - set=(clip[ce->length]<<offset); - if(test[byte]&set) { - printf("Error - Entry %s uses same bits previously used\n", - ce->name); - exit(1); - } - test[byte]|=set; /* set the bits defined in test */ - } + + /* now mark our bits */ + for (i = ce->bit; i < (ce->bit + ce->length); i++) + test[i / 8] |= 0x01 << (i % 8); + } - return; } /* This routine displays the usage options */ @@ -136,48 +103,14 @@ static unsigned long get_number(char *line, char **ptr, int base) return value; } -static int is_ident_digit(int c) -{ - int result; - switch(c) { - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': - result = 1; - break; - default: - result = 0; - break; - } - return result; -} - static int is_ident_nondigit(int c) { - int result; - switch(c) { - case 'A': case 'B': case 'C': case 'D': - case 'E': case 'F': case 'G': case 'H': - case 'I': case 'J': case 'K': case 'L': - case 'M': case 'N': case 'O': case 'P': - case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': - case 'a': case 'b': case 'c': case 'd': - case 'e': case 'f': case 'g': case 'h': - case 'i': case 'j': case 'k': case 'l': - case 'm': case 'n': case 'o': case 'p': - case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': - case 'y': case 'z': - case '_': - result = 1; - break; - default: - result = 0; - break; - } - return result; + if (((c >= 'A') && (c <='Z')) || + ((c >= 'a') && (c <='z')) || + (c == '_')) + return 1; + else + return 0; } static int is_ident(char *str) @@ -190,7 +123,7 @@ static int is_ident(char *str) do { str++; ch = *str; - } while(ch && (is_ident_nondigit(ch) || (is_ident_digit(ch)))); + } while(ch && (is_ident_nondigit(ch) || isdigit(ch))); result = (ch == '\0'); } return result; @@ -383,7 +316,7 @@ int main(int argc, char **argv) c_enums->config_id=strtol(&line[ptr],(char**)NULL,10); for(;(line[ptr]!=' ')&&(line[ptr]!='\t');ptr++); for(;(line[ptr]==' ')||(line[ptr]=='\t');ptr++); - c_enums->value=strtol(&line[ptr],(char**)NULL,10); + c_enums->value = strtoul(&line[ptr],(char**)NULL,0); for(;(line[ptr]!=' ')&&(line[ptr]!='\t');ptr++); for(;(line[ptr]==' ')||(line[ptr]=='\t');ptr++); for(cnt=0;(line[ptr]!='\n')&&(cnt<31);ptr++,cnt++) |