blob: 4d98f8eceefab98dd405c5796c4506e5c75811ed [file] [log] [blame]
Eric Biederman8ca8d762003-04-22 19:02:15 +00001#include <stdio.h>
2#include <stdlib.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00003#include <string.h>
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +00004#include <unistd.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00005#include <ctype.h>
Eric Biederman5cd81732004-03-11 15:01:31 +00006#include <errno.h>
Stefan Reinauerb9b500f2008-12-02 12:26:17 +00007#include <libgen.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00008#include "../../src/include/pc80/mc146818rtc.h"
Stefan Reinauerca374d42008-01-18 16:16:45 +00009#include "../../src/include/boot/coreboot_tables.h"
Eric Biederman8ca8d762003-04-22 19:02:15 +000010
11#define CMOS_IMAGE_BUFFER_SIZE 128
12#define INPUT_LINE_MAX 256
13#define MAX_VALUE_BYTE_LENGTH 64
14
Stefan Reinauerb9b500f2008-12-02 12:26:17 +000015#define TMPFILE_LEN 256
16#define TMPFILE_TEMPLATE "/build_opt_tbl_XXXXXX"
Eric Biederman8ca8d762003-04-22 19:02:15 +000017
18static unsigned char cmos_table[4096];
19
20/* This array is used to isolate bits that are to be changed in a byte */
21static unsigned char clip[9]={0,1,3,7,0x0f,0x1f,0x3f,0x7f,0xff};
22
23
24/* This routine loops through the entried and tests if any of the fields overlap
25 input entry_start = the memory pointer to the start of the entries.
26 entry_end = the byte past the entries.
27 output none
28 if there is an overlap, the routine exits, other wise it returns.
29*/
Eric Biederman83b991a2003-10-11 06:20:25 +000030void test_for_entry_overlaps(void *entry_start, void *entry_end)
Eric Biederman8ca8d762003-04-22 19:02:15 +000031{
Eric Biederman83b991a2003-10-11 06:20:25 +000032 int ptr;
33 char *cptr;
Eric Biederman8ca8d762003-04-22 19:02:15 +000034 int buffer_bit_size;
35 int offset;
36 int byte;
37 int byte_length;
38 struct cmos_entries *ce;
39 unsigned char test[CMOS_IMAGE_BUFFER_SIZE];
40 unsigned char set;
41
42 /* calculate the size of the cmos buffer in bits */
43 buffer_bit_size=(CMOS_IMAGE_BUFFER_SIZE*8);
44 /* clear the temporary test buffer */
Eric Biederman83b991a2003-10-11 06:20:25 +000045 for(ptr=0; ptr < CMOS_IMAGE_BUFFER_SIZE; ptr++)
Eric Biederman8ca8d762003-04-22 19:02:15 +000046 test[ptr]=0;
Eric Biederman83b991a2003-10-11 06:20:25 +000047
Eric Biederman8ca8d762003-04-22 19:02:15 +000048 /* loop through each entry in the table testing for errors */
Eric Biederman83b991a2003-10-11 06:20:25 +000049 for(cptr = entry_start; cptr < (char *)entry_end; cptr += ce->size) {
50 ce=(struct cmos_entries *)cptr;
Eric Biederman8ca8d762003-04-22 19:02:15 +000051 /* test if entry goes past the end of the buffer */
52 if((ce->bit+ce->length)>buffer_bit_size) {
53 printf("Error - Entry %s start bit + length must be less than %d\n",
54 ce->name,buffer_bit_size);
55 exit(1);
56 }
57 byte=ce->bit/8;
58 offset=ce->bit%8;
59 byte_length=ce->length/8;
60 if(byte_length) { /* entry is 8 bits long or more */
61 if(offset) { /* if 8 bits or more long, it must be byte aligned */
62 printf("Error - Entry %s length over 8 must be byte aligned\n",
63 ce->name);
64 exit(1);
65 }
66 /* test if entries 8 or more in length are even bytes */
67 if(ce->length%8){
68 printf("Error - Entry %s length over 8 must be a multiple of 8\n",
69 ce->name);
70 exit(1);
71 }
72 /* test if any of the bits have been previously used */
73 for(;byte_length;byte_length--,byte++) {
74 if(test[byte]) {
Eric Biederman83b991a2003-10-11 06:20:25 +000075 printf("Error - Entry %s uses same bits previously used\n",
Eric Biederman8ca8d762003-04-22 19:02:15 +000076 ce->name);
Eric Biederman83b991a2003-10-11 06:20:25 +000077 exit(1);
Eric Biederman8ca8d762003-04-22 19:02:15 +000078 }
79 test[byte]=clip[8]; /* set the bits defined in test */
80 }
81 } else {
82 /* test if bits overlap byte boundaries */
83 if(ce->length>(8-offset)) {
Eric Biederman83b991a2003-10-11 06:20:25 +000084 printf("Error - Entry %s length overlaps a byte boundry\n",
85 ce->name);
Eric Biederman8ca8d762003-04-22 19:02:15 +000086 exit(1);
87 }
88 /* test for bits previously used */
89 set=(clip[ce->length]<<offset);
90 if(test[byte]&set) {
91 printf("Error - Entry %s uses same bits previously used\n",
92 ce->name);
93 exit(1);
94 }
95 test[byte]|=set; /* set the bits defined in test */
96 }
97 }
98 return;
99}
100
101/* This routine displays the usage options */
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000102void display_usage(char *name)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000103{
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000104 printf("Usage: %s [--config filename]\n", name);
105 printf(" [--option filename]\n");
106 printf(" [--header filename]\n\n");
107 printf("--config = Build the definitions table from the given file.\n");
108 printf("--option = Output a C source file with the definitions.\n");
109 printf("--header = Ouput a C header file with the definitions.\n");
110 exit(1);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000111}
112
113
114static void skip_spaces(char *line, char **ptr)
115{
116 if (!isspace(**ptr)) {
117 printf("Error missing whitespace in line\n%s\n", line);
118 exit(1);
119 }
120 while(isspace(**ptr)) {
121 (*ptr)++;
122 }
123 return;
124}
125static unsigned long get_number(char *line, char **ptr, int base)
126{
127 unsigned long value;
128 char *ptr2;
129 value = strtoul(*ptr, &ptr2, base);
130 if (ptr2 == *ptr) {
131 printf("Error missing digits at: \n%s\n in line:\n%s\n",
132 *ptr, line);
133 exit(1);
134 }
135 *ptr = ptr2;
136 return value;
137}
138
Eric Biederman5cd81732004-03-11 15:01:31 +0000139static int is_ident_digit(int c)
140{
141 int result;
142 switch(c) {
143 case '0': case '1': case '2': case '3':
144 case '4': case '5': case '6': case '7':
145 case '8': case '9':
146 result = 1;
147 break;
148 default:
149 result = 0;
150 break;
151 }
152 return result;
153}
154
155static int is_ident_nondigit(int c)
156{
157 int result;
158 switch(c) {
159 case 'A': case 'B': case 'C': case 'D':
160 case 'E': case 'F': case 'G': case 'H':
161 case 'I': case 'J': case 'K': case 'L':
162 case 'M': case 'N': case 'O': case 'P':
163 case 'Q': case 'R': case 'S': case 'T':
164 case 'U': case 'V': case 'W': case 'X':
165 case 'Y': case 'Z':
166 case 'a': case 'b': case 'c': case 'd':
167 case 'e': case 'f': case 'g': case 'h':
168 case 'i': case 'j': case 'k': case 'l':
169 case 'm': case 'n': case 'o': case 'p':
170 case 'q': case 'r': case 's': case 't':
171 case 'u': case 'v': case 'w': case 'x':
172 case 'y': case 'z':
173 case '_':
174 result = 1;
175 break;
176 default:
177 result = 0;
178 break;
179 }
180 return result;
181}
182
183static int is_ident(char *str)
184{
185 int result;
186 int ch;
187 ch = *str;
188 result = 0;
189 if (is_ident_nondigit(ch)) {
190 do {
191 str++;
192 ch = *str;
193 } while(ch && (is_ident_nondigit(ch) || (is_ident_digit(ch))));
194 result = (ch == '\0');
195 }
196 return result;
197}
198
199
Eric Biederman8ca8d762003-04-22 19:02:15 +0000200/* This routine builds the cmos definition table from the cmos layout file
201 input The input comes from the configuration file which contains two parts
202 entries and enumerations. Each section is started with the key words
203 entries and enumerations. Records then follow in their respective
204 formats.
205 output The output of this program is the cmos definitions table. It is stored
206 in the cmos_table array. If this module is called, and the global
207 table_file has been implimented by the user, the table is also written
208 to the specified file.
209 This program exits on and error. It returns a 1 on successful
210 completion
211*/
212int main(int argc, char **argv)
213{
214 int i;
215 char *config=0;
216 char *option=0;
Eric Biederman5cd81732004-03-11 15:01:31 +0000217 char *header=0;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000218 FILE *fp;
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000219 int tmpfile;
Stefan Reinauerb9b500f2008-12-02 12:26:17 +0000220 char tmpfilename[TMPFILE_LEN];
Eric Biederman8ca8d762003-04-22 19:02:15 +0000221 struct cmos_option_table *ct;
222 struct cmos_entries *ce;
223 struct cmos_enums *c_enums, *c_enums_start;
224 struct cmos_checksum *cs;
Stefan Reinauera9e58212007-10-24 11:12:15 +0000225 char line[INPUT_LINE_MAX];
Eric Biederman8ca8d762003-04-22 19:02:15 +0000226 unsigned char uc;
227 int entry_mode=0;
228 int enum_mode=0;
229 int checksum_mode=0;
Stefan Reinauer5e837b72003-09-26 09:47:41 +0000230 long ptr;
231 int cnt;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000232 char *cptr;
Eric Biederman83b991a2003-10-11 06:20:25 +0000233 void *entry_start, *entry_end;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000234 int entries_length;
235 int enum_length;
236 int len;
Stefan Reinauera9e58212007-10-24 11:12:15 +0000237 char buf[16];
Eric Biederman8ca8d762003-04-22 19:02:15 +0000238
239 for(i=1;i<argc;i++) {
240 if(argv[i][0]!='-') {
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000241 display_usage(argv[0]);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000242 }
243 switch(argv[i][1]) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000244 case '-': /* data is requested from a file */
245 switch(argv[i][2]) {
246 case 'c': /* use a configuration file */
247 if(strcmp(&argv[i][2],"config")) {
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000248 display_usage(argv[0]);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000249 }
250 config=argv[++i];
251 break;
252 case 'o': /* use a cmos definitions table file */
253 if(strcmp(&argv[i][2],"option")) {
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000254 display_usage(argv[0]);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000255 }
256 option=argv[++i];
257 break;
Eric Biederman5cd81732004-03-11 15:01:31 +0000258 case 'h': /* Output a header file */
259 if (strcmp(&argv[i][2], "header") != 0) {
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000260 display_usage(argv[0]);
Eric Biederman5cd81732004-03-11 15:01:31 +0000261 }
262 header=argv[++i];
263 break;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000264 default:
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000265 display_usage(argv[0]);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000266 break;
267 }
268 break;
Eric Biederman5cd81732004-03-11 15:01:31 +0000269
Eric Biederman8ca8d762003-04-22 19:02:15 +0000270 default:
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000271 display_usage(argv[0]);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000272 break;
273 }
274 }
275
276
277 /* Has the user specified a configuration file */
278 if(config) { /* if yes, open it */
279 if((fp=fopen(config,"r"))==NULL){
Eric Biederman5cd81732004-03-11 15:01:31 +0000280 fprintf(stderr, "Error - Can not open config file %s\n",config);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000281 exit(1); /* exit if it can not be opened */
282 }
283 }
284 else { /* no configuration file specified, so try the default */
285 if((fp=fopen("cmos.layout","r"))==NULL){
Eric Biederman5cd81732004-03-11 15:01:31 +0000286 fprintf(stderr, "Error - Can not open cmos.layout\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000287 exit(1); /* end of no configuration file is found */
288 }
289 }
290 /* type cast a pointer, so we can us the structure */
291 ct=(struct cmos_option_table*)cmos_table;
292 /* start the table with the type signature */
293 ct->tag = LB_TAG_CMOS_OPTION_TABLE;
294 /* put in the header length */
295 ct->header_length=sizeof(*ct);
296
297 /* Get the entry records */
298 ce=(struct cmos_entries*)(cmos_table+(ct->header_length));
299 cptr = (char*)ce;
300 for(;;){ /* this section loops through the entry records */
301 if(fgets(line,INPUT_LINE_MAX,fp)==NULL)
302 break; /* end if no more input */
303 if(!entry_mode) { /* skip input until the entries key word */
304 if (strstr(line,"entries") != 0) {
305 entry_mode=1;
306 continue;
307 }
308 }
309 else{ /* Test if we are done with entries and starting enumerations */
310 if (strstr(line,"enumerations") != 0){
311 entry_mode=0;
312 enum_mode=1;
313 break;
314 }
315 if (strstr(line, "checksums") != 0) {
316 enum_mode=0;
317 checksum_mode=1;
318 break;
319 }
320 }
321
322 /* skip commented and blank lines */
323 if(line[0]=='#') continue;
324 if(line[strspn(line," ")]=='\n') continue;
325 /* scan in the input data */
326 sscanf(line,"%d %d %c %d %s",
327 &ce->bit,&ce->length,&uc,&ce->config_id,&ce->name[0]);
328 ce->config=(int)uc;
329 /* check bit and length ranges */
330 if(ce->bit>(CMOS_IMAGE_BUFFER_SIZE*8)) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000331 fprintf(stderr, "Error - bit is to big in line \n%s\n",line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000332 exit(1);
333 }
334 if((ce->length>(MAX_VALUE_BYTE_LENGTH*8))&&(uc!='r')) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000335 fprintf(stderr, "Error - Length is to long in line \n%s\n",line);
336 exit(1);
337 }
Stefan Reinauera9e58212007-10-24 11:12:15 +0000338 if (!is_ident((char *)ce->name)) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000339 fprintf(stderr,
340 "Error - Name %s is an invalid identifier in line\n %s\n",
341 ce->name, line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000342 exit(1);
343 }
344 /* put in the record type */
345 ce->tag=LB_TAG_OPTION;
346 /* calculate and save the record length */
Stefan Reinauera9e58212007-10-24 11:12:15 +0000347 len=strlen((char *)ce->name)+1;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000348 /* make the record int aligned */
349 if(len%4)
350 len+=(4-(len%4));
351 ce->size=sizeof(struct cmos_entries)-32+len;
352 cptr = (char*)ce;
Eric Biederman83b991a2003-10-11 06:20:25 +0000353 cptr += ce->size; /* increment to the next table position */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000354 ce = (struct cmos_entries*) cptr;
355 }
356
357 /* put the length of the entries into the header section */
Eric Biederman83b991a2003-10-11 06:20:25 +0000358 entries_length = (cptr - (char *)&cmos_table) - ct->header_length;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000359
360 /* compute the start of the enumerations section */
Eric Biederman83b991a2003-10-11 06:20:25 +0000361 entry_start = ((char*)&cmos_table) + ct->header_length;
362 entry_end = ((char *)entry_start) + entries_length;
363 c_enums_start = c_enums = (struct cmos_enums*)entry_end;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000364 /* test for overlaps in the entry records */
Eric Biederman83b991a2003-10-11 06:20:25 +0000365 test_for_entry_overlaps(entry_start, entry_end);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000366
367 for(;enum_mode;){ /* loop to build the enumerations section */
368 if(fgets(line,INPUT_LINE_MAX,fp)==NULL)
369 break; /* go till end of input */
370
371 if (strstr(line, "checksums") != 0) {
372 enum_mode=0;
373 checksum_mode=1;
374 break;
375 }
376
377 /* skip commented and blank lines */
378 if(line[0]=='#') continue;
379 if(line[strspn(line," ")]=='\n') continue;
380
381 /* scan in the data */
382 for(ptr=0;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
383 c_enums->config_id=strtol(&line[ptr],(char**)NULL,10);
384 for(;(line[ptr]!=' ')&&(line[ptr]!='\t');ptr++);
385 for(;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
386 c_enums->value=strtol(&line[ptr],(char**)NULL,10);
387 for(;(line[ptr]!=' ')&&(line[ptr]!='\t');ptr++);
388 for(;(line[ptr]==' ')||(line[ptr]=='\t');ptr++);
389 for(cnt=0;(line[ptr]!='\n')&&(cnt<31);ptr++,cnt++)
390 c_enums->text[cnt]=line[ptr];
391 c_enums->text[cnt]=0;
392
393 /* make the record int aligned */
394 cnt++;
395 if(cnt%4)
396 cnt+=4-(cnt%4);
397 /* store the record length */
Eric Biederman83b991a2003-10-11 06:20:25 +0000398 c_enums->size=((char *)&c_enums->text[cnt]) - (char *)c_enums;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000399 /* store the record type */
400 c_enums->tag=LB_TAG_OPTION_ENUM;
401 /* increment to the next record */
402 c_enums=(struct cmos_enums*)&c_enums->text[cnt];
403 }
404 /* save the enumerations length */
Eric Biederman83b991a2003-10-11 06:20:25 +0000405 enum_length= (char *)c_enums - (char *)c_enums_start;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000406 ct->size=ct->header_length+enum_length+entries_length;
407
408 /* Get the checksum records */
409 cs=(struct cmos_checksum *)(cmos_table+(ct->size));
410 cptr = (char*)cs;
411 for(;checksum_mode;) { /* This section finds the checksums */
412 char *ptr;
413 if(fgets(line, INPUT_LINE_MAX,fp)==NULL)
414 break; /* end if no more input */
415
416 /* skip commented and blank lines */
417 if (line[0]=='#') continue;
418 if (line[strspn(line, " ")]=='\n') continue;
419 if (memcmp(line, "checksum", 8) != 0) continue;
420
421 /* get the information */
422 ptr = line + 8;
423 skip_spaces(line, &ptr);
424 cs->range_start = get_number(line, &ptr, 10);
425
426 skip_spaces(line, &ptr);
427 cs->range_end = get_number(line, &ptr, 10);
428
429 skip_spaces(line, &ptr);
430 cs->location = get_number(line, &ptr, 10);
431
432 /* Make certain there are spaces until the end of the line */
433 skip_spaces(line, &ptr);
434
435 if ((cs->range_start%8) != 0) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000436 fprintf(stderr, "Error - range start is not byte aligned in line\n%s\n", line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000437 exit(1);
438 }
439 if (cs->range_start >= (CMOS_IMAGE_BUFFER_SIZE*8)) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000440 fprintf(stderr, "Error - range start is to big in line\n%s\n", line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000441 exit(1);
442 }
443 if ((cs->range_end%8) != 7) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000444 fprintf(stderr, "Error - range end is not byte aligned in line\n%s\n", line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000445 exit(1);
446 }
447 if ((cs->range_end) >= (CMOS_IMAGE_BUFFER_SIZE*8)) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000448 fprintf(stderr, "Error - range end is to long in line\n%s\n", line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000449 exit(1);
450 }
451 if ((cs->location%8) != 0) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000452 fprintf(stderr, "Error - location is not byte aligned in line\n%s\n", line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000453 exit(1);
454 }
455 if ((cs->location >= (CMOS_IMAGE_BUFFER_SIZE*8)) ||
456 ((cs->location + 16) > (CMOS_IMAGE_BUFFER_SIZE*8)))
457 {
Eric Biederman5cd81732004-03-11 15:01:31 +0000458 fprintf(stderr, "Error - location is to big in line\n%s\n", line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000459 exit(1);
460 }
461 /* And since we are not ready to be fully general purpose yet.. */
462 if ((cs->range_start/8) != LB_CKS_RANGE_START) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000463 fprintf(stderr, "Error - Range start(%d) does not match define(%d) in line\n%s\n",
Eric Biederman8ca8d762003-04-22 19:02:15 +0000464 cs->range_start/8, LB_CKS_RANGE_START, line);
465 exit(1);
466 }
467 if ((cs->range_end/8) != LB_CKS_RANGE_END) {
Stefan Reinauerba430642007-04-06 12:14:51 +0000468 fprintf(stderr, "Error - Range end (%d) does not match define (%d) in line\n%s\n",
469 (cs->range_end/8), LB_CKS_RANGE_END, line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000470 exit(1);
471 }
472 if ((cs->location/8) != LB_CKS_LOC) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000473 fprintf(stderr, "Error - Location does not match define in line\n%s\n", line);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000474 exit(1);
475 }
476
477 cs->tag = LB_TAG_OPTION_CHECKSUM;
478 cs->size = sizeof(*cs);
479 cs->type = CHECKSUM_PCBIOS;
480 cptr = (char *)cs;
481 cptr += cs->size;
482 cs = (struct cmos_checksum *)cptr;
483
484 }
485 ct->size += (cptr - (char *)(cmos_table + ct->size));
486 fclose(fp);
487
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000488 /* See if we want to output a C source file */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000489 if(option) {
Stefan Reinauerb9b500f2008-12-02 12:26:17 +0000490 strncpy(tmpfilename, dirname(option), TMPFILE_LEN);
491 strncat(tmpfilename, TMPFILE_TEMPLATE, TMPFILE_LEN);
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000492 tmpfile = mkstemp(tmpfilename);
493 if(tmpfile == -1) {
494 perror("Error - Could not create temporary file");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000495 exit(1);
496 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000497
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000498 if((fp=fdopen(tmpfile,"w"))==NULL){
499 perror("Error - Could not open temporary file");
500 unlink(tmpfilename);
501 exit(1);
502 }
503
504 /* write the header */
505 if(!fwrite("unsigned char option_table[] = {",1,32,fp)) {
506 perror("Error - Could not write image file");
507 fclose(fp);
508 unlink(tmpfilename);
509 exit(1);
510 }
511 /* write the array values */
512 for(i=0;i<(ct->size-1);i++) {
513 if(!(i%10)) fwrite("\n\t",1,2,fp);
514 sprintf(buf,"0x%02x,",cmos_table[i]);
515 fwrite(buf,1,5,fp);
516 }
517 /* write the end */
518 sprintf(buf,"0x%02x\n",cmos_table[i]);
519 fwrite(buf,1,4,fp);
520 if(!fwrite("};\n",1,3,fp)) {
521 perror("Error - Could not write image file");
522 fclose(fp);
523 unlink(tmpfilename);
524 exit(1);
525 }
526
527 fclose(fp);
528 if (rename(tmpfilename, option)) {
529 fprintf(stderr, "Error - Could not write %s: ", option);
530 perror(NULL);
531 unlink(tmpfilename);
532 exit(1);
533 }
534 }
Eric Biederman5cd81732004-03-11 15:01:31 +0000535
536 /* See if we also want to output a C header file */
537 if (header) {
538 struct cmos_option_table *hdr;
539 struct lb_record *ptr, *end;
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000540
Stefan Reinauerb9b500f2008-12-02 12:26:17 +0000541 strncpy(tmpfilename, dirname(option), TMPFILE_LEN);
542 strncat(tmpfilename, TMPFILE_TEMPLATE, TMPFILE_LEN);
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000543 tmpfile = mkstemp(tmpfilename);
544 if(tmpfile == -1) {
545 perror("Error - Could not create temporary file");
Eric Biederman5cd81732004-03-11 15:01:31 +0000546 exit(1);
547 }
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000548
549 fp = fdopen(tmpfile, "w");
550 if (!fp) {
551 perror("Error - Could not open temporary file");
552 unlink(tmpfilename);
553 exit(1);
554 }
555
Eric Biederman5cd81732004-03-11 15:01:31 +0000556 /* Get the cmos table header */
557 hdr = (struct cmos_option_table *)cmos_table;
558 /* Walk through the entry records */
559 ptr = (struct lb_record *)(cmos_table + hdr->header_length);
560 end = (struct lb_record *)(cmos_table + hdr->size);
561 for(;ptr < end; ptr = (struct lb_record *)(((char *)ptr) + ptr->size)) {
562 if (ptr->tag != LB_TAG_OPTION) {
563 continue;
564 }
565 ce = (struct cmos_entries *)ptr;
566 if (ce->config == 'r') {
567 continue;
568 }
Stefan Reinauera9e58212007-10-24 11:12:15 +0000569 if (!is_ident((char *)ce->name)) {
Eric Biederman5cd81732004-03-11 15:01:31 +0000570 fprintf(stderr, "Invalid identifier: %s\n",
571 ce->name);
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000572 fclose(fp);
573 unlink(tmpfilename);
Eric Biederman5cd81732004-03-11 15:01:31 +0000574 exit(1);
575 }
576 fprintf(fp, "#define CMOS_VSTART_%s %d\n",
577 ce->name, ce->bit);
578 fprintf(fp, "#define CMOS_VLEN_%s %d\n",
579 ce->name, ce->length);
580 }
581 fclose(fp);
Stefan Reinauerb4eb4fb2008-11-30 14:52:46 +0000582
583 if (rename(tmpfilename, header)) {
584 fprintf(stderr, "Error - Could not write %s: ", header);
585 perror(NULL);
586 unlink(tmpfilename);
587 exit(1);
588 }
Eric Biederman5cd81732004-03-11 15:01:31 +0000589 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000590 return(0);
591}
592
593