X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=util%2Foptions%2Fbuild_opt_tbl.c;h=b89bb4f1d52be4e834d43c284a2430fe96ade93e;hb=a8f0f5120b69e02eff5337932b92771363d159a5;hp=d9089e73279352460f5e32539fc38aea7913f312;hpb=b4eb4fb6b06878c25a43458ff11cd3939d97c60e;p=coreboot.git diff --git a/util/options/build_opt_tbl.c b/util/options/build_opt_tbl.c index d9089e732..b89bb4f1d 100644 --- a/util/options/build_opt_tbl.c +++ b/util/options/build_opt_tbl.c @@ -1,31 +1,70 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2003 Eric Biederman (ebiederm@xmission.com) + * Copyright (C) 2007-2010 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + #include #include #include #include #include #include +#include +#define UTIL_BUILD_OPTION_TABLE #include "../../src/include/pc80/mc146818rtc.h" #include "../../src/include/boot/coreboot_tables.h" -#define CMOS_IMAGE_BUFFER_SIZE 128 +#define CMOS_IMAGE_BUFFER_SIZE 256 #define INPUT_LINE_MAX 256 #define MAX_VALUE_BYTE_LENGTH 64 -#define TMPFILE_TEMPLATE "/tmp/build_opt_tbl_XXXXXX" +#define TMPFILE_LEN 25600 +#define TMPFILE_TEMPLATE "/build_opt_tbl_XXXXXX" 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) +#ifdef WIN32 +#include +char *mkstemp(char* name) +{ + static char val='0'; + char *c=name; + while (*c!='X') c++; + *c=val++; + return open(name,O_CREAT | O_RDWR); +} +#define UNLINK_IF_NECESSARY(x) unlink(x) +#else +#define UNLINK_IF_NECESSARY(x) +#endif + +/** + * This routine loops through the entried and tests if any of the fields + * overlap. + * If there is an overlap, the routine exits, otherwise it returns. + * + * @param entry_start memory pointer to the start of the entries. + * @param entry_end memory pointer to the byte past the entries. + */ +static void test_for_entry_overlaps(void *entry_start, void *entry_end) { int ptr; char *cptr; @@ -47,7 +86,7 @@ void test_for_entry_overlaps(void *entry_start, void *entry_end) 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) { + if((int)(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); exit(1); @@ -61,7 +100,7 @@ void test_for_entry_overlaps(void *entry_start, void *entry_end) ce->name); exit(1); } - /* test if entries 8 or more in length are even bytes */ + /* 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); @@ -78,7 +117,7 @@ void test_for_entry_overlaps(void *entry_start, void *entry_end) } } else { /* test if bits overlap byte boundaries */ - if(ce->length>(8-offset)) { + if((int)ce->length > (8-offset)) { printf("Error - Entry %s length overlaps a byte boundry\n", ce->name); exit(1); @@ -97,18 +136,18 @@ void test_for_entry_overlaps(void *entry_start, void *entry_end) } /* This routine displays the usage options */ -void display_usage(char *name) +static void display_usage(char *name) { printf("Usage: %s [--config filename]\n", name); printf(" [--option filename]\n"); printf(" [--header filename]\n\n"); printf("--config = Build the definitions table from the given file.\n"); + printf("--binary = Output a binary file with the definitions.\n"); printf("--option = Output a C source file with the definitions.\n"); - printf("--header = Ouput a C header file with the definitions.\n"); + printf("--header = Output a C header file with the definitions.\n"); exit(1); } - static void skip_spaces(char *line, char **ptr) { if (!isspace(**ptr)) { @@ -120,13 +159,14 @@ static void skip_spaces(char *line, char **ptr) } return; } + static unsigned long get_number(char *line, char **ptr, int base) { unsigned long value; char *ptr2; value = strtoul(*ptr, &ptr2, base); if (ptr2 == *ptr) { - printf("Error missing digits at: \n%s\n in line:\n%s\n", + printf("Error missing digits at: \n%s\n in line:\n%s\n", *ptr, line); exit(1); } @@ -194,38 +234,41 @@ static int is_ident(char *str) return result; } - -/* This routine builds the cmos definition table from the cmos layout file - input The input comes from the configuration file which contains two parts - entries and enumerations. Each section is started with the key words - entries and enumerations. Records then follow in their respective - formats. - output The output of this program is the cmos definitions table. It is stored - in the cmos_table array. If this module is called, and the global - table_file has been implimented by the user, the table is also written - to the specified file. - This program exits on and error. It returns a 1 on successful - completion -*/ +/** + * This routine builds the cmos definition table from the cmos layout file + * + * The input comes from the configuration file which contains two parts + * entries and enumerations. Each section is started with the key words + * entries and enumerations. Records then follow in their respective + * formats. + * + * The output of this program is the cmos definitions table. It is stored + * in the cmos_table array. If this module is called, and the global + * table_file has been implimented by the user, the table is also written + * to the specified file. + * + * This program exits with a return code of 1 on error. It returns 0 on + * successful completion + */ int main(int argc, char **argv) { int i; char *config=0; + char *binary=0; char *option=0; char *header=0; FILE *fp; - int tmpfile; - char tmpfilename[32]; + int tempfile; + char tempfilename[TMPFILE_LEN]; struct cmos_option_table *ct; struct cmos_entries *ce; struct cmos_enums *c_enums, *c_enums_start; - struct cmos_checksum *cs; + struct cmos_checksum *cs, *new_cs; char line[INPUT_LINE_MAX]; unsigned char uc; int entry_mode=0; int enum_mode=0; int checksum_mode=0; - long ptr; int cnt; char *cptr; void *entry_start, *entry_end; @@ -233,6 +276,7 @@ int main(int argc, char **argv) int enum_length; int len; char buf[16]; + char val; for(i=1;iheader_length)); cptr = (char*)ce; for(;;){ /* this section loops through the entry records */ - if(fgets(line,INPUT_LINE_MAX,fp)==NULL) + if(fgets(line,INPUT_LINE_MAX,fp)==NULL) break; /* end if no more input */ + // FIXME mode should be a single enum. if(!entry_mode) { /* skip input until the entries key word */ if (strstr(line,"entries") != 0) { entry_mode=1; + enum_mode=0; + checksum_mode=0; continue; } - } - else{ /* Test if we are done with entries and starting enumerations */ + } else { /* Test if we are done with entries and starting enumerations */ if (strstr(line,"enumerations") != 0){ entry_mode=0; enum_mode=1; + checksum_mode=0; break; } if (strstr(line, "checksums") != 0) { + entry_mode=0; enum_mode=0; checksum_mode=1; break; @@ -318,8 +372,9 @@ int main(int argc, char **argv) } /* skip commented and blank lines */ - if(line[0]=='#') continue; - if(line[strspn(line," ")]=='\n') continue; + val = line[strspn(line," ")]; + /* takes care of *nix, Mac and Windows line ending formats */ + if (val=='#' || val=='\n' || val=='\r') continue; /* scan in the input data */ sscanf(line,"%d %d %c %d %s", &ce->bit,&ce->length,&uc,&ce->config_id,&ce->name[0]); @@ -334,8 +389,8 @@ int main(int argc, char **argv) exit(1); } if (!is_ident((char *)ce->name)) { - fprintf(stderr, - "Error - Name %s is an invalid identifier in line\n %s\n", + fprintf(stderr, + "Error - Name %s is an invalid identifier in line\n %s\n", ce->name, line); exit(1); } @@ -363,7 +418,8 @@ int main(int argc, char **argv) test_for_entry_overlaps(entry_start, entry_end); for(;enum_mode;){ /* loop to build the enumerations section */ - if(fgets(line,INPUT_LINE_MAX,fp)==NULL) + long ptr; + if(fgets(line,INPUT_LINE_MAX,fp)==NULL) break; /* go till end of input */ if (strstr(line, "checksums") != 0) { @@ -387,7 +443,7 @@ int main(int argc, char **argv) for(cnt=0;(line[ptr]!='\n')&&(cnt<31);ptr++,cnt++) c_enums->text[cnt]=line[ptr]; c_enums->text[cnt]=0; - + /* make the record int aligned */ cnt++; if(cnt%4) @@ -404,8 +460,7 @@ int main(int argc, char **argv) ct->size=ct->header_length+enum_length+entries_length; /* Get the checksum records */ - cs=(struct cmos_checksum *)(cmos_table+(ct->size)); - cptr = (char*)cs; + new_cs = (struct cmos_checksum *)(cmos_table+(ct->size)); for(;checksum_mode;) { /* This section finds the checksums */ char *ptr; if(fgets(line, INPUT_LINE_MAX,fp)==NULL) @@ -416,6 +471,9 @@ int main(int argc, char **argv) if (line[strspn(line, " ")]=='\n') continue; if (memcmp(line, "checksum", 8) != 0) continue; + /* We actually found a new cmos checksum entry */ + cs = new_cs; + /* get the information */ ptr = line + 8; skip_spaces(line, &ptr); @@ -426,7 +484,7 @@ int main(int argc, char **argv) skip_spaces(line, &ptr); cs->location = get_number(line, &ptr, 10); - + /* Make certain there are spaces until the end of the line */ skip_spaces(line, &ptr); @@ -451,81 +509,102 @@ int main(int argc, char **argv) exit(1); } if ((cs->location >= (CMOS_IMAGE_BUFFER_SIZE*8)) || - ((cs->location + 16) > (CMOS_IMAGE_BUFFER_SIZE*8))) + ((cs->location + 16) > (CMOS_IMAGE_BUFFER_SIZE*8))) { fprintf(stderr, "Error - location is to big in line\n%s\n", line); exit(1); } - /* And since we are not ready to be fully general purpose yet.. */ - if ((cs->range_start/8) != LB_CKS_RANGE_START) { - fprintf(stderr, "Error - Range start(%d) does not match define(%d) in line\n%s\n", - cs->range_start/8, LB_CKS_RANGE_START, line); - exit(1); - } - if ((cs->range_end/8) != LB_CKS_RANGE_END) { - fprintf(stderr, "Error - Range end (%d) does not match define (%d) in line\n%s\n", - (cs->range_end/8), LB_CKS_RANGE_END, line); - exit(1); - } - if ((cs->location/8) != LB_CKS_LOC) { - fprintf(stderr, "Error - Location does not match define in line\n%s\n", line); - exit(1); - } cs->tag = LB_TAG_OPTION_CHECKSUM; cs->size = sizeof(*cs); cs->type = CHECKSUM_PCBIOS; + cptr = (char *)cs; cptr += cs->size; - cs = (struct cmos_checksum *)cptr; - + new_cs = (struct cmos_checksum *)cptr; } ct->size += (cptr - (char *)(cmos_table + ct->size)); fclose(fp); /* See if we want to output a C source file */ if(option) { - strcpy(tmpfilename, TMPFILE_TEMPLATE); - tmpfile = mkstemp(tmpfilename); - if(tmpfile == -1) { + int err=0; + snprintf(tempfilename, TMPFILE_LEN, "%s%s", dirname(strdup(option)), TMPFILE_TEMPLATE); + tempfile = mkstemp(tempfilename); + if(tempfile == -1) { perror("Error - Could not create temporary file"); exit(1); } - if((fp=fdopen(tmpfile,"w"))==NULL){ + if((fp=fdopen(tempfile,"w"))==NULL){ perror("Error - Could not open temporary file"); - unlink(tmpfilename); + unlink(tempfilename); exit(1); } /* write the header */ - if(!fwrite("unsigned char option_table[] = {",1,32,fp)) { + if(fwrite("unsigned char option_table[] = {",1,32,fp) != 32) { perror("Error - Could not write image file"); fclose(fp); - unlink(tmpfilename); + unlink(tempfilename); exit(1); } /* write the array values */ - for(i=0;i<(ct->size-1);i++) { - if(!(i%10)) fwrite("\n\t",1,2,fp); + for(i=0; i<(int)(ct->size-1); i++) { + if(!(i%10) && !err) err=(fwrite("\n\t",1,2,fp) != 2); sprintf(buf,"0x%02x,",cmos_table[i]); - fwrite(buf,1,5,fp); + if(!err) err=(fwrite(buf,1,5,fp) != 5); } /* write the end */ sprintf(buf,"0x%02x\n",cmos_table[i]); - fwrite(buf,1,4,fp); - if(!fwrite("};\n",1,3,fp)) { + if(!err) err=(fwrite(buf,1,4,fp) != 4); + if(fwrite("};\n",1,3,fp) != 3) { perror("Error - Could not write image file"); fclose(fp); - unlink(tmpfilename); + unlink(tempfilename); exit(1); } fclose(fp); - if (rename(tmpfilename, option)) { + UNLINK_IF_NECESSARY(option); + if (rename(tempfilename, option)) { fprintf(stderr, "Error - Could not write %s: ", option); perror(NULL); - unlink(tmpfilename); + unlink(tempfilename); + exit(1); + } + } + + /* See if we also want to output a binary file */ + if(binary) { + int err=0; + snprintf(tempfilename, TMPFILE_LEN, "%s%s", dirname(strdup(binary)), TMPFILE_TEMPLATE); + tempfile = mkstemp(tempfilename); + if(tempfile == -1) { + perror("Error - Could not create temporary file"); + exit(1); + } + + if((fp=fdopen(tempfile,"wb"))==NULL){ + perror("Error - Could not open temporary file"); + unlink(tempfilename); + exit(1); + } + + /* write the array values */ + if(fwrite(cmos_table, (int)(ct->size-1), 1, fp) != 1) { + perror("Error - Could not write image file"); + fclose(fp); + unlink(tempfilename); + exit(1); + } + + fclose(fp); + UNLINK_IF_NECESSARY(binary); + if (rename(tempfilename, binary)) { + fprintf(stderr, "Error - Could not write %s: ", binary); + perror(NULL); + unlink(tempfilename); exit(1); } } @@ -535,17 +614,17 @@ int main(int argc, char **argv) struct cmos_option_table *hdr; struct lb_record *ptr, *end; - strcpy(tmpfilename, TMPFILE_TEMPLATE); - tmpfile = mkstemp(tmpfilename); - if(tmpfile == -1) { + snprintf(tempfilename, TMPFILE_LEN, "%s%s", dirname(strdup(header)), TMPFILE_TEMPLATE); + tempfile = mkstemp(tempfilename); + if(tempfile == -1) { perror("Error - Could not create temporary file"); exit(1); } - fp = fdopen(tmpfile, "w"); + fp = fdopen(tempfile, "w"); if (!fp) { perror("Error - Could not open temporary file"); - unlink(tmpfilename); + unlink(tempfilename); exit(1); } @@ -554,19 +633,21 @@ int main(int argc, char **argv) /* Walk through the entry records */ ptr = (struct lb_record *)(cmos_table + hdr->header_length); end = (struct lb_record *)(cmos_table + hdr->size); + fprintf(fp, "/* This file is autogenerated.\n" + " * See mainboard's cmos.layout file.\n */\n\n" + "#ifndef __OPTION_TABLE_H\n#define __OPTION_TABLE_H\n\n"); + for(;ptr < end; ptr = (struct lb_record *)(((char *)ptr) + ptr->size)) { if (ptr->tag != LB_TAG_OPTION) { continue; } ce = (struct cmos_entries *)ptr; - if (ce->config == 'r') { - continue; - } + if (!is_ident((char *)ce->name)) { fprintf(stderr, "Invalid identifier: %s\n", ce->name); fclose(fp); - unlink(tmpfilename); + unlink(tempfilename); exit(1); } fprintf(fp, "#define CMOS_VSTART_%s %d\n", @@ -574,16 +655,30 @@ int main(int argc, char **argv) fprintf(fp, "#define CMOS_VLEN_%s %d\n", ce->name, ce->length); } + + if (cs != NULL) { + fprintf(fp, "\n#define LB_CKS_RANGE_START %d\n", cs->range_start / 8); + fprintf(fp, "#define LB_CKS_RANGE_END %d\n", cs->range_end / 8); + fprintf(fp, "#define LB_CKS_LOC %d\n", cs->location / 8); + } else { + fprintf(stderr, "Error - No checksums defined.\n"); + fclose(fp); + unlink(tempfilename); + exit(1); + } + fprintf(fp, "\n#endif // __OPTION_TABLE_H\n"); fclose(fp); - if (rename(tmpfilename, header)) { + UNLINK_IF_NECESSARY(header); + if (rename(tempfilename, header)) { fprintf(stderr, "Error - Could not write %s: ", header); perror(NULL); - unlink(tmpfilename); + unlink(tempfilename); exit(1); } } - return(0); + + return 0; }