Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / tools / makeprom.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: makeprom.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: @(#)makeprom.c 1.18 03/04/01
46 * purpose:
47 * Copyright 1994-2001, 2003 Sun Microsystems, Inc. All Rights Reserved
48 * Use is subject to license terms.
49 */
50
51#include <sys/types.h>
52#include <sys/stat.h>
53#include <fcntl.h>
54#include <string.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <unistd.h>
58
59#include <sys/dropins.h>
60#define PROM_SIZE (8*1024*1024)
61
62static unsigned long header[] = {
63 0x01030107,
64 0,
65 0, 0, 0, 0, 0, 0
66};
67
68static int verbose = 0;
69static int aout = 0;
70static int verify = 0;
71static int force = 0;
72static int nopad = 0;
73static int usecrc = 0;
74static int recurselevel = 0;
75static int standalone = 0;
76static uchar_t *prom;
77static uchar_t *holding;
78
79static void
80usage(char *name)
81{
82 char *msg =
83 "%s: <flags> [-o output] input1 .. inputn\n"
84 " -p <pad> : pad input1 to <pad>Kb boundary\n"
85 " -c : Append CRC at end, assumes -p\n"
86 " -a : add a.out header\n"
87 " -f : (Force) Fix checksum\n"
88 " -s : create output files for standalone utility\n"
89 " -v : verbose mode\n"
90 " -d : descend into level2 dropins\n"
91 " -n : disable default pad to 512KB\n"
92 " -o <output> : output filename\n";
93 fprintf(stderr, msg, name);
94 exit(1);
95}
96
97static void
98show_dropin_info(int level, obmd_t *obmdp)
99{
100 int ctype = 0;
101 unsigned int *dptr = (unsigned int *) ((char *)obmdp + OBMD_HDR);
102
103 level = (level+1) * 2;
104 while (level--) putchar(' ');
105 printf("Name: %s size = %lx", obmdp->name, obmdp->size);
106
107 if ((dptr[0] == COMP_MAGIC) && (obmdp->size == dptr[1]))
108 ctype = dptr[2];
109
110 switch (ctype) {
111 case COMP_MAGIC:
112 {
113 char type[5];
114 unsigned int len = dptr[3];
115
116 strncpy(type, (char *)&dptr[2], 4);
117 type[4] = 0;
118
119 printf(", %s, len %x", type, len);
120 }
121 break;
122 default:
123 break;
124 }
125 printf(" checksum = %x", obmdp->chksum);
126}
127
128static int
129is_dropin(char *ptr)
130{
131 return ((strncmp(ptr, "OBMD", 4) == 0) ||
132 (strncmp(ptr, "OBME", 4) == 0));
133}
134
135static int
136do_dropin(int level, obmd_t *obmdp, int size)
137{
138 int rewrite = 0;
139 int ndropins = 0;
140 obmd_t *prev = obmdp;
141 char *start = (char *)obmdp;
142 int total = 0;
143
144retry:
145 while (is_dropin((char *)obmdp)) {
146 int crc;
147 unsigned int *dptr = (unsigned int *) ((char *)obmdp+OBMD_HDR);
148 ndropins++;
149
150 if (verbose) show_dropin_info(level, obmdp);
151
152 crc = checksum((ushort_t *)obmdp, obmdp->size+OBMD_HDR);
153
154 if ((obmdp->chksum != 0) && (!force)) {
155 if (crc != 0xffff) {
156 if (!verbose) show_dropin_info(level, obmdp);
157 printf(", Bad checksum: %s (%x != %x)\n",
158 (verbose ? "" : obmdp->name),
159 obmdp->chksum, crc);
160 if (!verify) exit(1);
161 } else {
162 if (verify && verbose)
163 printf(", checksum OK");
164 if (verbose) printf("\n");
165 }
166 } else {
167 if (verbose) printf("\n ");
168 if (obmdp->chksum != 0) {
169 if (verbose) printf("Forcing");
170 } else {
171 if (verbose) printf("Generating");
172 }
173
174 if (verbose) printf(" checksum of %s", obmdp->name);
175
176 rewrite++;
177 obmdp->chksum = 0;
178 obmdp->chksum = checksum((ushort_t *)obmdp,
179 obmdp->size+OBMD_HDR);
180 if (verbose) {
181 if (force || verify) {
182 printf(", checksum = %x",
183 obmdp->chksum);
184 }
185 printf("\n");
186 }
187 }
188
189 if ((recurselevel > level) && (dptr[0] == OBME_MAGIC)) {
190 /*
191 * A level 2 dropin..
192 */
193 do_dropin(level+1, (obmd_t *)(dptr+1), 0);
194 return;
195 }
196#if 0
197 if (strncmp(obmdp->name, "OBP", 3) == 0) {
198 obmdp->chksum = 0;
199 rewrite++;
200 }
201#endif
202
203 prev = obmdp;
204 obmdp = (obmd_t *)(((uchar_t *)obmdp) +
205 ROUNDUP(obmdp->size)+OBMD_HDR);
206 if (!is_dropin((char *)obmdp)) {
207 char *try = (char *)obmdp - 16;
208 int slide, fixed;
209
210 fixed = 0;
211 for (slide = 0; slide < 32; slide++, try++)
212 if (is_dropin(try)) {
213 fixed = 1;
214 break;
215 }
216 if (fixed) {
217 rewrite++;
218 prev->size += slide-16;
219 prev->chksum = 0;
220 prev->chksum = checksum((ushort_t *)prev,
221 prev->size + OBMD_HDR);
222 if (verbose) {
223 printf("Fixing %s length (%d)\n",
224 prev->name, slide-16);
225 printf("Fixing %s checksum (%x)\n",
226 prev->name, prev->chksum);
227 }
228
229 if (slide > 19) {
230 fprintf(stderr, "%s%s\n\n",
231 "ERROR: Need to adjust forward by",
232 " more than 3 bytes!");
233 exit(1);
234 }
235
236 obmdp = (obmd_t *)try;
237 }
238 }
239 total = ((char *)obmdp) - start;
240 obmdp = (obmd_t *)ROUNDUP(obmdp);
241 }
242 if ((verify) && (total < size)) {
243 char *here;
244
245 /* Scan forward looking for more headers.. */
246 here = (char *)ROUNDUP((char *)obmdp);
247 while (((here-start) < size) && (!is_dropin(here)))
248 here += 4;
249
250 obmdp = (obmd_t *)here;
251 if ((here-start) < size) {
252 if (verbose) printf("Skipping to: %x\n", here-start);
253 goto retry;
254 }
255 }
256
257 if ((force) && (ndropins == 1) && ((size-OBMD_HDR) != prev->size)) {
258 if (verbose)
259 printf("Fixing %s size (actual %lx, should be %x)\n",
260 prev->name, prev->size, (size-OBMD_HDR));
261 rewrite++;
262 prev->size = size-OBMD_HDR;
263 prev->chksum = 0;
264 prev->chksum = checksum((ushort_t *)prev,
265 prev->size+OBMD_HDR);
266 }
267 return (rewrite && !verify);
268}
269
270void
271main(int argc, char **argv)
272{
273 void open_failure();
274 int ifd;
275 int i;
276 int nfiles = 0;
277 int pad = 512;
278 struct stat statbuf;
279 int c;
280 uchar_t *insert_ptr;
281 extern char *optarg;
282 extern int optind;
283 char *ofile = NULL;
284
285 /* assume verify */
286 verify = 1;
287
288 while ((c = getopt(argc, argv, "asdnvfcp:o:")) != EOF)
289 switch (c) {
290 case 'a':
291 verify = 0;
292 aout = 1;
293 break;
294
295 case 'f':
296 verify = 0;
297 force = 1;
298 break;
299
300 case 'v':
301 verbose++;
302 break;
303
304 case 'd':
305 recurselevel++;
306 break;
307
308 case 'n':
309 verify = 0;
310 nopad = 1;
311 break;
312
313 case 'o':
314 verify = 0;
315 ofile = optarg;
316 break;
317
318 case 'p':
319 verify = 0;
320 pad = atoi(optarg);
321 if ((pad == 0) || (pad > 1024)) {
322 fprintf(stderr, "Bad pad size: %dKb\n", pad);
323 exit(1);
324 }
325 break;
326
327 case 'c':
328 usecrc = 1;
329 if (nopad) {
330 fprintf(stderr,
331 "-c and -n cannot be used together\n");
332 exit(1);
333 }
334 break;
335
336 case 's':
337 standalone = 1;
338 break;
339
340 default:
341 usage(argv[0]);
342 }
343
344 if ((ofile == NULL) && (!verify)) {
345 fprintf(stderr, "%s: Missing output filename\n", argv[0]);
346 usage(argv[0]);
347 }
348
349 pad *= 1024;
350 prom = (uchar_t *)malloc(PROM_SIZE);
351 if (prom == NULL) {
352 fprintf(stderr, "Malloc failed for prom image\n");
353 exit(1);
354 }
355
356 holding = (uchar_t *)malloc(PROM_SIZE);
357 if (holding == NULL) {
358 fprintf(stderr, "Malloc failed for holding buffer\n");
359 exit(1);
360 }
361
362 /* Fill with FF */
363 memset((void *)prom, 0xff, pad*2);
364
365 insert_ptr = prom;
366
367 for (i = optind; i < argc; i++) {
368 int rlen;
369
370 if (verbose)
371 printf("Scanning: %s @ %x\n", argv[i],
372 (insert_ptr-prom));
373 nfiles++;
374 ifd = open(argv[i], O_RDONLY);
375 if (ifd == -1) {
376 fprintf(stderr, "%s: Can't open input file %s\n",
377 argv[0], argv[i]);
378 exit(1);
379 }
380 fstat(ifd, &statbuf);
381 if ((statbuf.st_size > pad) && (!verify)) {
382 fprintf(stderr, "%s: Individual file too large"
383 " for current pad size\n", argv[0]);
384 exit(1);
385 }
386 memset((void *)holding, 0xff, pad);
387 rlen = read(ifd, holding, statbuf.st_size);
388 if (rlen != statbuf.st_size) {
389 printf("Short read: %d \n", rlen);
390 exit(1);
391 }
392 memcpy((void *)insert_ptr, (void *)holding, statbuf.st_size);
393 if (do_dropin(0, (obmd_t *)holding, statbuf.st_size)) {
394 memcpy((void *)insert_ptr, (void *)holding,
395 statbuf.st_size);
396 }
397 close(ifd);
398 if (nopad)
399 insert_ptr += ROUNDUP(statbuf.st_size);
400 else {
401 /* If we pad we only pad the first file. */
402 insert_ptr += pad;
403 nopad = 1;
404 }
405 }
406
407 if (!verify) {
408 if (usecrc) {
409 int mypad = pad;
410 uint32_t crc;
411 uint32_t *cptr = (uint32_t *)prom;
412
413 if (nfiles > 1) mypad = pad*2;
414 crc = crc32(mypad-sizeof (int32_t), prom, -1);
415 if (verbose) printf("Computed CRC32 %x\n", crc);
416 cptr[(mypad/sizeof (uint32_t))-1] = crc;
417 insert_ptr = prom+mypad;
418 }
419 if (!standalone) {
420 int ofd = open(ofile, (O_CREAT|O_RDWR|O_TRUNC), 0666);
421 if (ofd == -1) {
422 open_failure(argv[0], ofile);
423 exit(1);
424 }
425 if (aout) {
426 if (verbose) printf("Writing A.OUT header\n");
427 header[1] = (insert_ptr-prom);
428 write(ofd, header, 0x20);
429 } else {
430 if (verbose) printf("Writing binary file\n");
431 }
432 write(ofd, prom, (insert_ptr-prom));
433 close(ofd);
434 } else {
435 /*
436 * Create two files for standalone flash utility. Names
437 * will be <output>.openboot.bin and <output>.post.bin
438 */
439 char buff[400];
440 int ofd, d;
441
442 if (aout)
443 printf("\nIgnoring the -a flag since the "
444 "-s flag was also set.\n");
445
446 for (d = 0; d < 2; d++) {
447 (void) strcpy(buff, ofile);
448 if (d == 0)
449 (void) strcat(buff, ".openboot.bin");
450 else
451 (void) strcat(buff, ".post.bin");
452
453 ofd = open(buff,
454 (O_CREAT|O_RDWR|O_TRUNC), 0666);
455 if (ofd == -1)
456 open_failure(argv[0], ofile);
457 printf("Writing binary file %s.\n", buff);
458 if (d == 0)
459 write(ofd, prom, pad);
460 else
461 write(ofd, (prom+pad), pad);
462 close(ofd);
463 }
464 }
465 }
466 free(holding);
467 free(prom);
468 exit(0);
469}
470
471void
472open_failure(char *progname, char *ofilename)
473{
474 fprintf(stderr, "%s: open %s for writing failed.\n",
475 progname, ofilename);
476 exit(1);
477}