Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / tools / gen-seeprom / gen-seeprom.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: gen-seeprom.c
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * id: @(#)gen-seeprom.c 1.12 05/11/15
46 * purpose:
47 * copyright: Copyright 2005 Sun Microsystems, Inc. All Rights Reserved
48 * copyright: Use is subject to license terms.
49 */
50
51/*
52 * Parse a config file and generate a binary file containing the cpu seeprom
53 * image.
54 */
55
56#include <stdio.h>
57#include <stdlib.h>
58#include <unistd.h>
59#include <fcntl.h>
60#include <string.h>
61#include <time.h>
62#include "gen-seeprom.h"
63#include "prototypes.h"
64
65#define MAX_IMAGE 0x800
66
67int system_type = EXCALIBUR;
68int system_type_init = 0;
69int config_type_init = 0;
70struct fixed_seeprom *seeprom_data;
71char *config_file;
72char err_string[MAXLINE];
73int type = CPU;
74int do_checksum = 0;
75static int quiet = 0, release = 0;
76int force_debug = 0;
77
78static struct unique_functions seeprom_func[] = {
79 SET_FUNC_ENTRY(cpu_dynamic, check_cpu, write_cpu, dump_cpu, reg_cpu)
80 SET_FUNC_ENTRY(sys_dynamic, check_sys, write_sys, dump_sys, reg_sys)
81 SET_FUNC_ENTRY(env_dynamic, check_env, write_env, dump_env, reg_env)
82 SET_FUNC_ENTRY(mem_dynamic, check_mem, write_mem, dump_mem, reg_mem)
83 SET_FUNC_ENTRY(cpu_dynamic, check_cpu, write_cpu, dump_cpu, reg_cpu)
84};
85
86static void
87usage(char *name)
88{
89 static struct tm tm_compiled = { COMPILE_TIME };
90 time_t compiled, expire;
91 compiled = mktime(&tm_compiled);
92 expire = compiled + ACTIVE_TIME;
93
94 /* -q option is quiet mode, no processing messages. */
95 fprintf(stderr,
96 "%s: [ -q ] <config_filename>\n", name);
97 fprintf(stderr, " -q Suppresses config file processing messages.\n");
98
99 fprintf(stderr, "\nTool will expire on %s\n", ctime(&expire));
100
101 exit(1);
102}
103
104static int
105usage_expired(void)
106{
107 int status = 0;
108
109 static struct tm tm_compiled = { COMPILE_TIME };
110 time_t compiled, now, expire;
111
112 compiled = mktime(&tm_compiled);
113 expire = compiled + ACTIVE_TIME;
114 now = time(NULL);
115 now = mktime(gmtime(&now));
116 status = (now > expire);
117 return (status);
118}
119
120void
121print_error(char *string)
122{
123 fprintf(stderr, "%s: ERROR: %s\n", config_file, string);
124}
125
126static void
127print_input_error(char *parameter)
128{
129 sprintf(err_string, "Input error for %s", parameter);
130 print_error(err_string);
131}
132
133/*
134 * Get seeprom parameter value from data structure
135 */
136unsigned long long
137get_seeprom(char *name)
138{
139 int i = 0;
140 char *parameter;
141
142 while ((parameter = seeprom_data[i].name) != NULL) {
143 if (strcmp(parameter, name) == 0) {
144 return (seeprom_data[i].value);
145 }
146 i++;
147 }
148 sprintf(err_string, "Cannot find value of %s", name);
149 print_error(err_string);
150 return (0);
151}
152
153static int
154update_reg(data_reg *cpu_reg, char *name, unsigned long long new,
155 unsigned long long *reg, int num_entries)
156{
157 int i, found;
158 unsigned long long data;
159
160 i = found = 0;
161
162 while (!found && (i < num_entries)) {
163 if (strcmp(cpu_reg[i].name, name) == 0) {
164 int bits, mask;
165 bits = cpu_reg[i].size-1;
166 mask = 1;
167 while (bits) {
168 mask |= (1 << bits);
169 bits--;
170 }
171 data = *reg &
172 (0xffffffffffffffffLL ^ (mask << cpu_reg[i].pos));
173 data |= ((new & mask) << cpu_reg[i].pos);
174 *reg = data;
175 found = 1;
176 }
177 i++;
178 }
179 return (!found);
180}
181
182/*
183 * Set seeprom parameter value in data structure
184 */
185int
186update_seeprom(char *name, unsigned long long value)
187{
188 int i = 0, retval = 0;
189 char *s1, *s2;
190 char parameter[MAXNAMESIZE];
191 void (*notify)(void *data);
192
193 strcpy(parameter, name);
194 if ((s1 = strtok(parameter, ".")) != NULL) {
195 while ((seeprom_data[i].name) != NULL) {
196 if (strcmp(seeprom_data[i].name, s1) == 0) {
197 s2 = strtok(NULL, ".");
198 notify = seeprom_data[i].notify;
199 if (s2 == NULL) {
200 seeprom_data[i].value = value;
201 } else {
202 int (*funcp)(), num_entries;
203 data_reg *cpu_reg;
204 funcp = seeprom_func[type].reg_func;
205 num_entries = funcp(s1, &cpu_reg);
206 if (num_entries) {
207 retval = update_reg(cpu_reg,
208 s2, value,
209 &seeprom_data[i].value,
210 num_entries);
211 } else {
212 retval = 1;
213 }
214 }
215 if (notify != NULL) notify((void *) value);
216 return (retval);
217 }
218 i++;
219 }
220 }
221 return (1);
222}
223
224/*
225 * Get one parameter value from config file
226 */
227static unsigned int
228get_one_input(int num_input, char *input_str, unsigned long long *input_val)
229{
230 unsigned int retval;
231
232 retval = 0;
233 if (--num_input) {
234 if ((strncmp(input_str, "0x", 2) == 0) ||
235 (strncmp(input_str, "0X", 2) == 0)) {
236 input_str += 2;
237 retval = sscanf(input_str, "%llx", input_val);
238 } else {
239 retval = sscanf(input_str, "%d", input_val);
240 *input_val >>= 32;
241 }
242 }
243 return (retval);
244}
245
246/*
247 * Check if parameter is from the fixed region
248 */
249int
250fixed_parameter(char *name)
251{
252 int i = 0;
253 char *c, parameter[MAXNAMESIZE];
254
255 strcpy(parameter, name);
256 if ((c = strtok(parameter, ".")) != NULL) {
257 while (seeprom_data[i].name != NULL) {
258 if (strcmp(seeprom_data[i++].name, c) == 0) {
259 return (1);
260 }
261 }
262 }
263 return (0);
264}
265
266/*
267 * Parse parameters
268 */
269static int
270process_line(char *line)
271{
272 char parameter[MAXNAMESIZE];
273 char input_str[MAXNAMESIZE];
274
275 int num_scanned, error;
276
277 error = 0;
278 num_scanned = sscanf(line, "%32s %32s", parameter, input_str);
279#if 0
280 if (num_scanned != 2) {
281 fprintf(stderr,
282 "WARNING: Ignoring following line:\n%s\n",
283 line);
284 return (0);
285 }
286#endif
287 if (strcmp(parameter, "cfg_type") == 0) {
288 if (!config_type_init) {
289 if (strcmp(input_str, "cpu") == 0) {
290 type = CPU;
291 seeprom_data = &cpu_seeprom_data[0];
292 } else if (strcmp(input_str, "sys") == 0) {
293 type = SYS;
294 seeprom_data = &sys_seeprom_data[0];
295 } else if (strcmp(input_str, "env") == 0) {
296 type = ENV;
297 seeprom_data = &env_seeprom_data[0];
298 } else if (strcmp(input_str, "mem") == 0) {
299 type = MEM;
300 seeprom_data = &mem_seeprom_data[0];
301 } else if (strcmp(input_str, "cpu_rw") == 0) {
302 type = CPU_RW;
303 seeprom_data = &cpu_rw_data[0];
304 } else {
305 fprintf(stderr, " invalid config type: %s\n",
306 input_str);
307 error = 1;
308 }
309 config_type_init = 1;
310 } else {
311 fprintf(stderr, "config type already initialized!\n");
312 error = 1;
313 }
314 return (error);
315 }
316
317 if (strcmp(parameter, "system") == 0) {
318 if (!system_type_init) {
319 if (strcmp(input_str, "fiesta") == 0) {
320 system_type = FIESTA;
321 } else if (strcmp(input_str, "gmfiesta") == 0) {
322 system_type = GMFIESTA;
323 if (type == CPU)
324 seeprom_data = &gm_cpu_seeprom_data[0];
325 } else if (strcmp(input_str, "excalibur") == 0) {
326 system_type = EXCALIBUR;
327 } else if (strcmp(input_str, "serrano") == 0) {
328 system_type = SERRANO;
329 if (type == CPU)
330 seeprom_data =
331 &serrano_cpu_seeprom_data[0];
332 } else {
333 fprintf(stderr, " invalid system type: %s\n",
334 input_str);
335 error = 1;
336 }
337 system_type_init = 1;
338 } else {
339 fprintf(stderr, "system type already initialized!\n");
340 error = 1;
341 }
342 if ((system_type == FIESTA || system_type == GMFIESTA ||
343 system_type == SERRANO) &&
344 type == SYS)
345 seeprom_data = &fiesta_sys_data[0];
346 return (error);
347 }
348
349 if (fixed_parameter(parameter)) {
350 unsigned long long input_val;
351 if (get_one_input(num_scanned, input_str, &input_val)) {
352 if (update_seeprom(parameter, input_val)) {
353 error = 1;
354 }
355 } else
356 error = 1;
357 } else {
358 int (*funcp)();
359
360 funcp = seeprom_func[type].dynamic_func;
361 switch (funcp(parameter, line)) {
362 case ERROR:
363 error = 1;
364 break;
365 case UNKNOWN:
366 fprintf(stderr,
367 "WARNING: Unknown parameter: %s\n", parameter);
368 break;
369 default:
370 break;
371 }
372 }
373 if (error)
374 print_input_error(parameter);
375 return (error);
376}
377
378/*
379 * Print config info
380 */
381static void
382dump_seeprom(void)
383{
384 char *string;
385 void (*funcp)();
386 int i = 0;
387
388 if (quiet)
389 return;
390
391 while (seeprom_data[i].name != NULL) {
392 if (strcmp(seeprom_data[i].name, "pad")) {
393 string = strdup(seeprom_data[i].name);
394 string = strcat(string, ":");
395 printf("%-20s", string);
396 printf(" 0x%llx\n", seeprom_data[i].value);
397 }
398 i++;
399 }
400 printf("\n");
401 funcp = seeprom_func[type].dump_func;
402 funcp();
403}
404
405/*
406 * Verify parameters are valid
407 */
408static int
409check_data(void)
410{
411 int (*funcp)();
412 funcp = seeprom_func[type].check_func;
413 return (funcp());
414}
415
416/*
417 * Write n bytes to string
418 */
419void
420store_bytes(unsigned short bytes, unsigned long long data,
421 unsigned char **store_ptr)
422{
423 unsigned short count;
424 unsigned char byte;
425
426 count = bytes;
427
428 while (count) {
429 byte = data >> ((count-1)*8);
430 byte &= 0xff;
431 **store_ptr = byte;
432 *store_ptr += 1;
433 count--;
434 }
435}
436
437/*
438Generate binary image
439*/
440static int
441write_image(char *out_file)
442{
443 int i, size;
444 unsigned char *image, *ptr;
445 void (*funcp)();
446 int file, retval = 0;
447 int checksum_offset = 0;
448 int found = 0;
449
450 ptr = image = malloc(MAX_IMAGE);
451
452 i = 0;
453 while (seeprom_data[i].name != NULL) {
454 if (strcmp(seeprom_data[i].name, "checksum")) {
455 if (!found)
456 checksum_offset += seeprom_data[i].size;
457 } else {
458 found = 1;
459 if (do_checksum && seeprom_data[i].size != 2) {
460 fprintf(stderr, "Cannot generate checksum,");
461 fprintf(stderr,
462 "checksum size must be 2 bytes!\n");
463 do_checksum = 0;
464 }
465 }
466 store_bytes(seeprom_data[i].size, seeprom_data[i].value, &ptr);
467 i++;
468 }
469
470 funcp = (void (*)()) seeprom_func[type].write_func;
471 funcp(&ptr);
472
473 size = ptr-image;
474 if (size > MAX_IMAGE) {
475 sprintf(err_string,
476 "SEEPROM image size of %d,"
477 "exceeds maximum size of %d bytes!",
478 size, MAX_IMAGE);
479 print_error(err_string);
480 retval = 1;
481 } else {
482 if (do_checksum) {
483 if (fixed_parameter("checksum")) {
484 /*
485 modify checksum for release images
486 so diff between debug and release
487 version is less obvious
488 */
489 unsigned short cksum =
490 checksum((unsigned short *) image, size);
491 if (release && type == CPU)
492 cksum *= 2;
493 image[checksum_offset] = (cksum >> 8) & 0xff;
494 image[checksum_offset+1] = cksum & 0xff;
495 }
496 }
497 file = open(out_file, O_CREAT|O_TRUNC|O_WRONLY, 0666);
498 if (file < 0) {
499 fprintf(stderr, "Can't open output file %s\n",
500 out_file);
501 retval = 1;
502 } else {
503 int tmp = write(file, image, size);
504 if (tmp != size) {
505 fprintf(stderr, "Short write on %s\n",
506 out_file);
507 retval = 1;
508 } else {
509 if (!quiet)
510 printf("Wrote %d bytes to %s\n",
511 size, out_file);
512 }
513 close(file);
514 }
515 }
516 free(image);
517 return (retval);
518}
519
520int
521main(int argc, char **argv)
522{
523 char *out_file;
524 char line[MAXLINE];
525 int c;
526 extern char *optarg;
527 extern int optind;
528 char *output_file, *endptr;
529 FILE *file;
530
531 if (usage_expired()) {
532 fprintf(stderr, "%s: tool expired. Need new copy.\n", argv[0]);
533 exit(1);
534 }
535
536 while ((c = getopt(argc, argv, "qr")) != EOF)
537 switch (c) {
538 case 'q':
539 quiet = 1;
540 break;
541#ifndef DEBUG
542 /* r option will clear high bit of id_magic */
543 /* as well as muddle up checksum. */
544 case 'r':
545 release = 1;
546 break;
547#endif
548 default:
549 usage(argv[0]);
550 }
551
552
553 if (optind < argc) {
554 config_file = argv[optind];
555 } else {
556 usage(argv[0]);
557 }
558
559 if (!quiet)
560 printf("config_file: %s\n", config_file);
561 if ((file = fopen(config_file, "r")) != NULL) {
562 while (fgets(line, MAXLINE, file)) {
563 if ((line[0] != '\n') && (line[0] != '#')) {
564 if (process_line(line)) {
565 exit(1);
566 }
567 }
568 }
569 fclose(file);
570 } else {
571 sprintf(err_string, "Can't open config file %s!", config_file);
572 print_error(err_string);
573 exit(1);
574 }
575
576 if (check_data()) {
577 fprintf(stderr, "Config file error!\n");
578 exit(1);
579 }
580
581 dump_seeprom();
582 output_file = strdup(config_file);
583 endptr = strrchr(output_file, '.');
584 if (endptr != NULL) *endptr = 0;
585 out_file = strcat(output_file, ".bin");
586 /* Debug images have the high bit of id_magic set */
587 if (force_debug)
588 release = 0;
589 if (type == CPU && !release) {
590 unsigned long long temp;
591 temp = get_seeprom("id_magic");
592 update_seeprom("id_magic", temp | 0x8000);
593 }
594 if (write_image(out_file)) {
595 sprintf(err_string, "Write to output file %s unsuccessful!",
596 out_file);
597 print_error(err_string);
598 exit(1);
599 }
600 exit(0);
601}