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];
160 int offset,entry_start;
164 unsigned char buf[16];
166 for(i=1;i<argc;i++) {
167 if(argv[i][0]!='-') {
171 case 'b': /* build the table */
173 case '-': /* data is requested from a file */
175 case 'c': /* use a configuration file */
176 if(strcmp(&argv[i][2],"config")) {
181 case 'o': /* use a cmos definitions table file */
182 if(strcmp(&argv[i][2],"option")) {
199 /* Has the user specified a configuration file */
200 if(config) { /* if yes, open it */
201 if((fp=fopen(config,"r"))==NULL){
202 printf("Error - Can not open config file %s\n",config);
203 exit(1); /* exit if it can not be opened */
206 else { /* no configuration file specified, so try the default */
207 if((fp=fopen("cmos.layout","r"))==NULL){
208 printf("Error - Can not open cmos.layout\n");
209 exit(1); /* end of no configuration file is found */
212 /* type cast a pointer, so we can us the structure */
213 ct=(struct cmos_option_table*)cmos_table;
214 /* start the table with the type signature */
215 ct->tag = LB_TAG_CMOS_OPTION_TABLE;
216 /* put in the header length */
217 ct->header_length=sizeof(*ct);
219 /* Get the entry records */
220 ce=(struct cmos_entries*)(cmos_table+(ct->header_length));
222 for(;;){ /* this section loops through the entry records */
223 if(fgets(line,INPUT_LINE_MAX,fp)==NULL)
224 break; /* end if no more input */
225 if(!entry_mode) { /* skip input until the entries key word */
226 if (strstr(line,"entries") != 0) {
231 else{ /* Test if we are done with entries and starting enumerations */
232 if (strstr(line,"enumerations") != 0){
237 if (strstr(line, "checksums") != 0) {
244 /* skip commented and blank lines */
245 if(line[0]=='#') continue;
246 if(line[strspn(line," ")]=='\n') continue;
247 /* scan in the input data */
248 sscanf(line,"%d %d %c %d %s",
249 &ce->bit,&ce->length,&uc,&ce->config_id,&ce->name[0]);
251 /* check bit and length ranges */
252 if(ce->bit>(CMOS_IMAGE_BUFFER_SIZE*8)) {
253 printf("Error - bit is to big in line \n%s\n",line);
256 if((ce->length>(MAX_VALUE_BYTE_LENGTH*8))&&(uc!='r')) {
257 printf("Error - Length is to long in line \n%s\n",line);
260 /* put in the record type */
261 ce->tag=LB_TAG_OPTION;
262 /* calculate and save the record length */
263 len=strlen(ce->name)+1;
264 /* make the record int aligned */
267 ce->size=sizeof(struct cmos_entries)-32+len;
269 cptr+=ce->size; /* increment to the next table position */
270 ce = (struct cmos_entries*) cptr;
273 /* put the length of the entries into the header section */
274 entries_length=(int)cptr;
275 entries_length-=(int)(cmos_table+ct->header_length);
277 /* compute the start of the enumerations section */
278 entry_start=(int)cmos_table;
279 entry_start+=ct->header_length;
280 offset=entry_start+entries_length;
281 c_enums_start=c_enums=(struct cmos_enums*)offset;
282 /* test for overlaps in the entry records */
283 test_for_entry_overlaps(entry_start,offset);
285 for(;enum_mode;){ /* loop to build the enumerations section */
286 if(fgets(line,INPUT_LINE_MAX,fp)==NULL)
287 break; /* go till end of input */
289 if (strstr(line, "checksums") != 0) {
295 /* skip commented and blank lines */
296 if(line[0]=='#') continue;
297 if(line[strspn(line," ")]=='\n') continue;
299 /* scan in the data */
300 for(ptr=0;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
301 c_enums->config_id=strtol(&line[ptr],(char**)NULL,10);
302 for(;(line[ptr]!=' ')&&(line[ptr]!='\t');ptr++);
303 for(;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
304 c_enums->value=strtol(&line[ptr],(char**)NULL,10);
305 for(;(line[ptr]!=' ')&&(line[ptr]!='\t');ptr++);
306 for(;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
307 for(cnt=0;(line[ptr]!='\n')&&(cnt<31);ptr++,cnt++)
308 c_enums->text[cnt]=line[ptr];
309 c_enums->text[cnt]=0;
311 /* make the record int aligned */
315 /* store the record length */
316 c_enums->size=((int)&c_enums->text[cnt])-(int)c_enums;
317 /* store the record type */
318 c_enums->tag=LB_TAG_OPTION_ENUM;
319 /* increment to the next record */
320 c_enums=(struct cmos_enums*)&c_enums->text[cnt];
322 /* save the enumerations length */
323 enum_length=(int)c_enums-(int)c_enums_start;
324 ct->size=ct->header_length+enum_length+entries_length;
326 /* Get the checksum records */
327 cs=(struct cmos_checksum *)(cmos_table+(ct->size));
329 for(;checksum_mode;) { /* This section finds the checksums */
331 if(fgets(line, INPUT_LINE_MAX,fp)==NULL)
332 break; /* end if no more input */
334 /* skip commented and blank lines */
335 if (line[0]=='#') continue;
336 if (line[strspn(line, " ")]=='\n') continue;
337 if (memcmp(line, "checksum", 8) != 0) continue;
339 /* get the information */
341 skip_spaces(line, &ptr);
342 cs->range_start = get_number(line, &ptr, 10);
344 skip_spaces(line, &ptr);
345 cs->range_end = get_number(line, &ptr, 10);
347 skip_spaces(line, &ptr);
348 cs->location = get_number(line, &ptr, 10);
350 /* Make certain there are spaces until the end of the line */
351 skip_spaces(line, &ptr);
353 if ((cs->range_start%8) != 0) {
354 printf("Error - range start is not byte aligned in line\n%s\n", line);
357 if (cs->range_start >= (CMOS_IMAGE_BUFFER_SIZE*8)) {
358 printf("Error - range start is to big in line\n%s\n", line);
361 if ((cs->range_end%8) != 7) {
362 printf("Error - range end is not byte aligned in line\n%s\n", line);
365 if ((cs->range_end) >= (CMOS_IMAGE_BUFFER_SIZE*8)) {
366 printf("Error - range end is to long in line\n%s\n", line);
369 if ((cs->location%8) != 0) {
370 printf("Error - location is not byte aligned in line\n%s\n", line);
373 if ((cs->location >= (CMOS_IMAGE_BUFFER_SIZE*8)) ||
374 ((cs->location + 16) > (CMOS_IMAGE_BUFFER_SIZE*8)))
376 printf("Error - location is to big in line\n%s\n", line);
379 /* And since we are not ready to be fully general purpose yet.. */
380 if ((cs->range_start/8) != LB_CKS_RANGE_START) {
381 printf("Error - Range start(%d) does not match define(%d) in line\n%s\n",
382 cs->range_start/8, LB_CKS_RANGE_START, line);
385 if ((cs->range_end/8) != LB_CKS_RANGE_END) {
386 printf("Error - Range end does not match define in line\n%s\n", line);
389 if ((cs->location/8) != LB_CKS_LOC) {
390 printf("Error - Location does not match define in line\n%s\n", line);
394 cs->tag = LB_TAG_OPTION_CHECKSUM;
395 cs->size = sizeof(*cs);
396 cs->type = CHECKSUM_PCBIOS;
399 cs = (struct cmos_checksum *)cptr;
402 ct->size += (cptr - (char *)(cmos_table + ct->size));
405 /* test if an alternate file is to be created */
407 if((fp=fopen(option,"w"))==NULL){
408 printf("Error - Can not open %s\n",option);
412 else { /* no, so use the default option_table.c */
413 if((fp=fopen("option_table.c","w"))==NULL){
414 printf("Error - Can not open option_table.c\n");
418 /* write the header */
419 if(!fwrite("unsigned char option_table[] = {",1,32,fp)) {
420 printf("Error - Could not write image file\n");
424 /* write the array values */
425 for(i=0;i<(ct->size-1);i++) {
426 if(!(i%10)) fwrite("\n\t",1,2,fp);
427 sprintf(buf,"0x%02x,",cmos_table[i]);
431 sprintf(buf,"0x%02x",cmos_table[i]);
433 if(!fwrite("};\n",1,3,fp)) {
434 printf("Error - Could not write image file\n");