6 #include "../../src/include/pc80/mc146818rtc.h"
7 #include "../../src/include/boot/linuxbios_tables.h"
9 #define CMOS_IMAGE_BUFFER_SIZE 128
10 #define INPUT_LINE_MAX 256
11 #define MAX_VALUE_BYTE_LENGTH 64
14 static unsigned char cmos_table[4096];
16 /* This array is used to isolate bits that are to be changed in a byte */
17 static unsigned char clip[9]={0,1,3,7,0x0f,0x1f,0x3f,0x7f,0xff};
20 /* This routine loops through the entried and tests if any of the fields overlap
21 input entry_start = the memory pointer to the start of the entries.
22 entry_end = the byte past the entries.
24 if there is an overlap, the routine exits, other wise it returns.
26 void test_for_entry_overlaps(int entry_start,int entry_end)
33 struct cmos_entries *ce;
34 unsigned char test[CMOS_IMAGE_BUFFER_SIZE];
37 /* calculate the size of the cmos buffer in bits */
38 buffer_bit_size=(CMOS_IMAGE_BUFFER_SIZE*8);
39 /* clear the temporary test buffer */
40 for(ptr=0;ptr<CMOS_IMAGE_BUFFER_SIZE;ptr++)
42 /* loop through each entry in the table testing for errors */
43 for(ptr=entry_start;ptr<entry_end;ptr+=ce->size) {
44 ce=(struct cmos_entries *)ptr;
45 /* test if entry goes past the end of the buffer */
46 if((ce->bit+ce->length)>buffer_bit_size) {
47 printf("Error - Entry %s start bit + length must be less than %d\n",
48 ce->name,buffer_bit_size);
53 byte_length=ce->length/8;
54 if(byte_length) { /* entry is 8 bits long or more */
55 if(offset) { /* if 8 bits or more long, it must be byte aligned */
56 printf("Error - Entry %s length over 8 must be byte aligned\n",
60 /* test if entries 8 or more in length are even bytes */
62 printf("Error - Entry %s length over 8 must be a multiple of 8\n",
66 /* test if any of the bits have been previously used */
67 for(;byte_length;byte_length--,byte++) {
69 printf("Error - Entry %s uses same bits previously used\n",
73 test[byte]=clip[8]; /* set the bits defined in test */
76 /* test if bits overlap byte boundaries */
77 if(ce->length>(8-offset)) {
78 printf("Error - Entry %s length overlaps a byte boundry\n", ce->name);
81 /* test for bits previously used */
82 set=(clip[ce->length]<<offset);
84 printf("Error - Entry %s uses same bits previously used\n",
88 test[byte]|=set; /* set the bits defined in test */
94 /* This routine displays the usage options */
95 void display_usage(void)
97 printf("Usage build_opt_table [-b] [--option filename]\n");
98 printf(" [--config filename]\n");
99 printf("b = build option_table.c\n");
100 printf("--option = name of option table output file\n");
101 printf("--config = build the definitions table from the given file\n");
106 static void skip_spaces(char *line, char **ptr)
108 if (!isspace(**ptr)) {
109 printf("Error missing whitespace in line\n%s\n", line);
112 while(isspace(**ptr)) {
117 static unsigned long get_number(char *line, char **ptr, int base)
121 value = strtoul(*ptr, &ptr2, base);
123 printf("Error missing digits at: \n%s\n in line:\n%s\n",
131 /* This routine builds the cmos definition table from the cmos layout file
132 input The input comes from the configuration file which contains two parts
133 entries and enumerations. Each section is started with the key words
134 entries and enumerations. Records then follow in their respective
136 output The output of this program is the cmos definitions table. It is stored
137 in the cmos_table array. If this module is called, and the global
138 table_file has been implimented by the user, the table is also written
139 to the specified file.
140 This program exits on and error. It returns a 1 on successful
143 int main(int argc, char **argv)
149 struct cmos_option_table *ct;
150 struct cmos_entries *ce;
151 struct cmos_enums *c_enums, *c_enums_start;
152 struct cmos_checksum *cs;
153 unsigned char line[INPUT_LINE_MAX];
166 unsigned char buf[16];
168 for(i=1;i<argc;i++) {
169 if(argv[i][0]!='-') {
173 case 'b': /* build the table */
175 case '-': /* data is requested from a file */
177 case 'c': /* use a configuration file */
178 if(strcmp(&argv[i][2],"config")) {
183 case 'o': /* use a cmos definitions table file */
184 if(strcmp(&argv[i][2],"option")) {
201 /* Has the user specified a configuration file */
202 if(config) { /* if yes, open it */
203 if((fp=fopen(config,"r"))==NULL){
204 printf("Error - Can not open config file %s\n",config);
205 exit(1); /* exit if it can not be opened */
208 else { /* no configuration file specified, so try the default */
209 if((fp=fopen("cmos.layout","r"))==NULL){
210 printf("Error - Can not open cmos.layout\n");
211 exit(1); /* end of no configuration file is found */
214 /* type cast a pointer, so we can us the structure */
215 ct=(struct cmos_option_table*)cmos_table;
216 /* start the table with the type signature */
217 ct->tag = LB_TAG_CMOS_OPTION_TABLE;
218 /* put in the header length */
219 ct->header_length=sizeof(*ct);
221 /* Get the entry records */
222 ce=(struct cmos_entries*)(cmos_table+(ct->header_length));
224 for(;;){ /* this section loops through the entry records */
225 if(fgets(line,INPUT_LINE_MAX,fp)==NULL)
226 break; /* end if no more input */
227 if(!entry_mode) { /* skip input until the entries key word */
228 if (strstr(line,"entries") != 0) {
233 else{ /* Test if we are done with entries and starting enumerations */
234 if (strstr(line,"enumerations") != 0){
239 if (strstr(line, "checksums") != 0) {
246 /* skip commented and blank lines */
247 if(line[0]=='#') continue;
248 if(line[strspn(line," ")]=='\n') continue;
249 /* scan in the input data */
250 sscanf(line,"%d %d %c %d %s",
251 &ce->bit,&ce->length,&uc,&ce->config_id,&ce->name[0]);
253 /* check bit and length ranges */
254 if(ce->bit>(CMOS_IMAGE_BUFFER_SIZE*8)) {
255 printf("Error - bit is to big in line \n%s\n",line);
258 if((ce->length>(MAX_VALUE_BYTE_LENGTH*8))&&(uc!='r')) {
259 printf("Error - Length is to long in line \n%s\n",line);
262 /* put in the record type */
263 ce->tag=LB_TAG_OPTION;
264 /* calculate and save the record length */
265 len=strlen(ce->name)+1;
266 /* make the record int aligned */
269 ce->size=sizeof(struct cmos_entries)-32+len;
271 cptr+=ce->size; /* increment to the next table position */
272 ce = (struct cmos_entries*) cptr;
275 /* put the length of the entries into the header section */
276 entries_length=(long)cptr;
277 entries_length-=(long)(cmos_table+ct->header_length);
279 /* compute the start of the enumerations section */
280 entry_start=(int)cmos_table;
281 entry_start+=ct->header_length;
282 offset=entry_start+entries_length;
283 c_enums_start=c_enums=(struct cmos_enums*)offset;
284 /* test for overlaps in the entry records */
285 test_for_entry_overlaps(entry_start,offset);
287 for(;enum_mode;){ /* loop to build the enumerations section */
288 if(fgets(line,INPUT_LINE_MAX,fp)==NULL)
289 break; /* go till end of input */
291 if (strstr(line, "checksums") != 0) {
297 /* skip commented and blank lines */
298 if(line[0]=='#') continue;
299 if(line[strspn(line," ")]=='\n') continue;
301 /* scan in the data */
302 for(ptr=0;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
303 c_enums->config_id=strtol(&line[ptr],(char**)NULL,10);
304 for(;(line[ptr]!=' ')&&(line[ptr]!='\t');ptr++);
305 for(;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
306 c_enums->value=strtol(&line[ptr],(char**)NULL,10);
307 for(;(line[ptr]!=' ')&&(line[ptr]!='\t');ptr++);
308 for(;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
309 for(cnt=0;(line[ptr]!='\n')&&(cnt<31);ptr++,cnt++)
310 c_enums->text[cnt]=line[ptr];
311 c_enums->text[cnt]=0;
313 /* make the record int aligned */
317 /* store the record length */
318 c_enums->size=((long)&c_enums->text[cnt])-(long)c_enums;
319 /* store the record type */
320 c_enums->tag=LB_TAG_OPTION_ENUM;
321 /* increment to the next record */
322 c_enums=(struct cmos_enums*)&c_enums->text[cnt];
324 /* save the enumerations length */
325 enum_length=(long)c_enums-(long)c_enums_start;
326 ct->size=ct->header_length+enum_length+entries_length;
328 /* Get the checksum records */
329 cs=(struct cmos_checksum *)(cmos_table+(ct->size));
331 for(;checksum_mode;) { /* This section finds the checksums */
333 if(fgets(line, INPUT_LINE_MAX,fp)==NULL)
334 break; /* end if no more input */
336 /* skip commented and blank lines */
337 if (line[0]=='#') continue;
338 if (line[strspn(line, " ")]=='\n') continue;
339 if (memcmp(line, "checksum", 8) != 0) continue;
341 /* get the information */
343 skip_spaces(line, &ptr);
344 cs->range_start = get_number(line, &ptr, 10);
346 skip_spaces(line, &ptr);
347 cs->range_end = get_number(line, &ptr, 10);
349 skip_spaces(line, &ptr);
350 cs->location = get_number(line, &ptr, 10);
352 /* Make certain there are spaces until the end of the line */
353 skip_spaces(line, &ptr);
355 if ((cs->range_start%8) != 0) {
356 printf("Error - range start is not byte aligned in line\n%s\n", line);
359 if (cs->range_start >= (CMOS_IMAGE_BUFFER_SIZE*8)) {
360 printf("Error - range start is to big in line\n%s\n", line);
363 if ((cs->range_end%8) != 7) {
364 printf("Error - range end is not byte aligned in line\n%s\n", line);
367 if ((cs->range_end) >= (CMOS_IMAGE_BUFFER_SIZE*8)) {
368 printf("Error - range end is to long in line\n%s\n", line);
371 if ((cs->location%8) != 0) {
372 printf("Error - location is not byte aligned in line\n%s\n", line);
375 if ((cs->location >= (CMOS_IMAGE_BUFFER_SIZE*8)) ||
376 ((cs->location + 16) > (CMOS_IMAGE_BUFFER_SIZE*8)))
378 printf("Error - location is to big in line\n%s\n", line);
381 /* And since we are not ready to be fully general purpose yet.. */
382 if ((cs->range_start/8) != LB_CKS_RANGE_START) {
383 printf("Error - Range start(%d) does not match define(%d) in line\n%s\n",
384 cs->range_start/8, LB_CKS_RANGE_START, line);
387 if ((cs->range_end/8) != LB_CKS_RANGE_END) {
388 printf("Error - Range end does not match define in line\n%s\n", line);
391 if ((cs->location/8) != LB_CKS_LOC) {
392 printf("Error - Location does not match define in line\n%s\n", line);
396 cs->tag = LB_TAG_OPTION_CHECKSUM;
397 cs->size = sizeof(*cs);
398 cs->type = CHECKSUM_PCBIOS;
401 cs = (struct cmos_checksum *)cptr;
404 ct->size += (cptr - (char *)(cmos_table + ct->size));
407 /* test if an alternate file is to be created */
409 if((fp=fopen(option,"w"))==NULL){
410 printf("Error - Can not open %s\n",option);
414 else { /* no, so use the default option_table.c */
415 if((fp=fopen("option_table.c","w"))==NULL){
416 printf("Error - Can not open option_table.c\n");
420 /* write the header */
421 if(!fwrite("unsigned char option_table[] = {",1,32,fp)) {
422 printf("Error - Could not write image file\n");
426 /* write the array values */
427 for(i=0;i<(ct->size-1);i++) {
428 if(!(i%10)) fwrite("\n\t",1,2,fp);
429 sprintf(buf,"0x%02x,",cmos_table[i]);
433 sprintf(buf,"0x%02x",cmos_table[i]);
435 if(!fwrite("};\n",1,3,fp)) {
436 printf("Error - Could not write image file\n");