Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / support / mdlint / mdlint.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: mdlint.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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
46 * Use is subject to license terms.
47 */
48
49#pragma ident "@(#)mdlint.c 1.3 07/06/07 SMI"
50
51#include <stdlib.h>
52#include <stdio.h>
53#include <unistd.h>
54#include <sys/types.h>
55#include <malloc.h>
56#include <sys/mman.h>
57#include <sys/stat.h>
58#include <errno.h>
59#include <fcntl.h>
60#include <string.h>
61
62#include <netinet/in.h>
63#include <inttypes.h>
64
65
66#include <assert.h>
67
68#define ASSERT(_s) assert(_s)
69
70#include <md/md_impl.h>
71
72#include "basics.h"
73#include "allocate.h"
74#include "fatal.h"
75
76
77 /*
78 * NOTE:
79 * Deliberate attempt to not borrow code and
80 * be able to lint the MD based on the spec.
81 * That way when things get broken in other
82 * pieces of code we dont lint them as correct anyway.
83 */
84
85typedef struct {
86 int fh;
87 int size;
88 caddr_t caddr;
89
90 md_header_t *headerp;
91 md_element_t *mdep;
92 char *namep;
93 uint8_t *datap;
94
95 int node_blk_size;
96 int name_blk_size;
97 int data_blk_size;
98
99 int element_count;
100 int node_count;
101} md_t;
102
103struct {
104 bool_t textdump;
105} option;
106
107
108
109md_t *md_init(char *fnamep);
110int md_close(md_t *mdp);
111int process_options(int argc, char **argv);
112void md_lint(md_t *mdp);
113void output_text(md_t *mdp, FILE *fp);
114void brief_sanity(md_t *mdp, FILE *fp);
115void output_text_data(FILE *fp, char *propp, uint8_t *datap, int len);
116
117
118
119
120int
121main(int argc, char **argv)
122{
123 md_t *mdp;
124 int i;
125
126 i = process_options(argc, argv);
127
128 if (i != argc-1) fatal("Machine description filename expected");
129
130 mdp = md_init(argv[i]);
131 if (mdp == NULL) fatal("Unable to open MD");
132
133 md_lint(mdp);
134
135 return (0);
136}
137
138
139
140
141void
142usage(char *namep)
143{
144 fprintf(stderr, "usage: %s [-t|--text] <mdfile>\n", namep);
145 exit(1);
146}
147
148
149int
150process_options(int argc, char **argv)
151{
152 int i;
153
154 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
155 if (strcmp(argv[i], "-h") == 0 ||
156 strcmp(argv[i], "--help") == 0) {
157 usage(argv[0]);
158 } else
159 if ((strcmp(argv[i], "-t") == 0) ||
160 (strcmp(argv[i], "--text") == 0)) {
161 option.textdump = true;
162 } else
163 fatal("Unrecognised option %s\n", argv[i]);
164 }
165
166 return (i);
167}
168
169
170
171
172void
173md_lint(md_t *mdp)
174{
175 if (option.textdump) {
176 output_text(mdp, stdout);
177 fflush(stdout);
178 }
179
180 fflush(stderr);
181
182 brief_sanity(mdp, stderr);
183}
184
185
186
187
188
189
190void
191output_text(md_t *mdp, FILE *fp)
192{
193 int idx;
194 int count;
195 bool_t done;
196
197 count = 0;
198 done = false;
199
200 for (idx = 0; !done; idx++) {
201 md_element_t *np;
202 uint32_t stro;
203 uint64_t nextidx;
204 uint64_t val;
205 uint32_t offset;
206 uint32_t len;
207
208 np = &(mdp->mdep[idx]);
209 switch (np->tag) {
210 case DT_LIST_END:
211 fprintf(fp, "\t\t/* The end @ 0x%x */\n", idx);
212 done = true;
213 break;
214
215 case DT_NULL:
216 fprintf(fp, "\t\t/* NULL */\n");
217 break;
218
219 case DT_NODE:
220 nextidx = ntoh64(np->d.prop_idx);
221 stro = ntoh32(np->name);
222
223 fprintf(fp, "node %s node_0x%x {\t\t\t/* next "
224 "@ 0x%llx */\n",
225 mdp->namep + stro, idx, nextidx);
226 count ++;
227 break;
228
229 case DT_NODE_END:
230 fprintf(fp, "}\t\t\t\t\t/* @ 0x%x */\n", idx);
231 break;
232
233 case DT_PROP_ARC:
234 nextidx = ntoh64(np->d.prop_idx);
235 stro = ntoh32(np->name);
236
237 fprintf(fp, "\t%s -> node_0x%llx;\n",
238 mdp->namep + stro, nextidx);
239 break;
240
241 case DT_PROP_VAL:
242 val = ntoh64(np->d.prop_val);
243 stro = ntoh32(np->name);
244
245 fprintf(fp, "\t%s = 0x%llx;\t\t/* %lld */\n",
246 mdp->namep + stro, val, val);
247 break;
248
249 case DT_PROP_STR:
250 offset = ntoh32(np->d.prop_data.offset);
251 len = ntoh32(np->d.prop_data.len);
252 stro = ntoh32(np->name);
253
254 fprintf(fp, "\t%s = \"%s\";\n",
255 mdp->namep + stro, mdp->datap + offset);
256 break;
257
258 case DT_PROP_DAT:
259 offset = ntoh32(np->d.prop_data.offset);
260 len = ntoh32(np->d.prop_data.len);
261 stro = ntoh32(np->name);
262
263 output_text_data(fp, mdp->namep + stro,
264 &(mdp->datap[offset]), len);
265 break;
266
267 default:
268 fatal("At index %d found unexpected node type %d"
269 " (0x%x : '%c') while searching for nodes",
270 idx, np->tag, np->tag, np->tag);
271 }
272 }
273}
274
275
276
277
278 /*
279 * Data properties are a little special since in some cases
280 * we have an array of strings.
281 * First scan the data looking for legal string characters
282 * and ensuring that there are no null strings and the last
283 * string is correctly terminated
284 */
285
286void
287output_text_data(FILE *fp, char *propp, uint8_t *datap, int len)
288{
289 int i;
290 int step;
291 bool_t new_string;
292
293 /* array of strings check */
294
295 fprintf(fp, "\t%s = {\n", propp);
296
297 new_string = true;
298
299 for (i = 0; i < len; i++) {
300 int ch;
301
302 ch = datap[i];
303 if (ch != 0 && (ch < ' ' || ch >= 126))
304 goto non_sarray;
305
306 if (ch == '\0') {
307 /* back-to-back nulls not allowed */
308 if (new_string)
309 goto non_sarray;
310 new_string = true;
311 } else {
312 new_string = false;
313 }
314 }
315 if (!new_string)
316 goto non_sarray;
317
318 /* looks like safe to assume an array of strings */
319
320 for (i = 0; i < len; i += step) {
321 char *p;
322
323 p = ((char *)(datap + i));
324 step = strlen(p)+1;
325
326 fprintf(fp, "\t\t\"%s\"%s", p, (i+step) == len ? "\n" : ",\n");
327 }
328 fprintf(fp, "\t}; \n");
329
330 return;
331
332non_sarray:;
333
334 for (i = 0; i < len-1; i++) {
335 fprintf(fp, "%s0x%02x,",
336 ((i&7) == 0) ? "\n\t\t" : " ", datap[i]);
337 }
338 fprintf(fp, " 0x%02x };\n", datap[i]);
339}
340
341
342
343
344
345
346
347void
348brief_sanity(md_t *mdp, FILE *fp)
349{
350 int idx;
351 int count;
352 bool_t done;
353 bool_t in_node;
354 int nodeidx;
355
356 count = 0;
357 done = false;
358 in_node = false;
359 nodeidx = -1;
360
361 for (idx = 0; !done; idx++) {
362 md_element_t *np;
363 uint32_t stro;
364 bool_t check_name = false;
365
366 np = &(mdp->mdep[idx]);
367 switch (np->tag) {
368 case DT_LIST_END:
369 done = true;
370 break;
371
372 case DT_NULL:
373 break;
374
375 case DT_NODE:
376 stro = ntoh32(np->name);
377
378 if (in_node)
379 fatal("Node element @ 0x%x (%s) "
380 "defined within node @ 0x%x (%s)\n",
381 idx, mdp->namep + stro, nodeidx,
382 mdp->namep +
383 ntoh32(mdp->mdep[nodeidx].name));
384 in_node = true;
385 nodeidx = idx;
386 check_name = true;
387 count ++;
388 break;
389
390 case DT_NODE_END:
391 if (!in_node)
392 fatal("Node end element @ 0x%x "
393 "defined outside a node\n", idx);
394 in_node = false;
395 break;
396
397 case DT_PROP_ARC:
398 stro = ntoh32(np->name);
399 check_name = true;
400 break;
401
402 case DT_PROP_VAL:
403 stro = ntoh32(np->name);
404 check_name = true;
405 break;
406
407 case DT_PROP_STR:
408 stro = ntoh32(np->name);
409 check_name = true;
410 break;
411
412 case DT_PROP_DAT:
413 stro = ntoh32(np->name);
414 check_name = true;
415
416 break;
417
418 default:
419 fatal("At index %d found unexpected node type %d"
420 " (0x%x : '%c') while searching for nodes",
421 idx, np->tag, np->tag, np->tag);
422 }
423
424 if (check_name) {
425 int nlen;
426
427 nlen = strlen((char *)(mdp->namep + stro));
428 if (np->namelen != nlen)
429 fatal("Element @ 0x%x (%s): "
430 "name length (%d) doesnt match strlen (%d)"
431 " of name in table",
432 idx, mdp->datap + stro, np->namelen, nlen);
433 }
434 }
435}
436
437
438
439
440
441
442
443
444
445md_t *
446md_init(char *fnamep)
447{
448 md_t *mdp;
449 struct stat sb;
450 int idx, count;
451
452 mdp = (md_t *)Xcalloc(1, md_t);
453 if (mdp == NULL)
454 return (NULL);
455
456 if (stat(fnamep, &sb) < 0)
457 return (NULL);
458
459 if ((sb.st_mode & S_IFMT) != S_IFREG ||
460 sb.st_size < sizeof (md_hdr_t)) {
461 errno = EIO;
462 return (NULL);
463 }
464
465 mdp->fh = open(fnamep, O_RDONLY, 0);
466 if (mdp->fh < 0)
467 return (NULL);
468
469 mdp->caddr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, mdp->fh,
470 (off_t)0);
471 if (mdp->headerp == MAP_FAILED) {
472 int res;
473 res = errno;
474 close(mdp->fh);
475 mdp->fh = -1;
476 errno = res;
477 return (NULL);
478 }
479
480 mdp->size = sb.st_size;
481
482 /* setup internal structures */
483 mdp->headerp = (md_hdr_t *)mdp->caddr;
484
485 mdp->node_blk_size = ntoh32(mdp->headerp->node_blk_sz);
486 mdp->name_blk_size = ntoh32(mdp->headerp->name_blk_sz);
487 mdp->data_blk_size = ntoh32(mdp->headerp->data_blk_sz);
488
489 mdp->mdep = (md_element_t *)(mdp->caddr + sizeof (md_header_t));
490 mdp->namep = (char *)(mdp->caddr + sizeof (md_header_t) +
491 mdp->node_blk_size);
492 mdp->datap = (uint8_t *)(mdp->caddr + sizeof (md_header_t) +
493 mdp->name_blk_size + mdp->node_blk_size);
494
495
496 /*
497 * should do a lot more sanity checking here.
498 */
499
500 if (mdp->headerp->transport_version != MD_TRANSPORT_VERSION)
501 fatal("Unrecognised transport version");
502
503 /*
504 * One more property we need is the count of nodes in the
505 * DAG, not just the number of elements.
506 */
507
508 idx = 0;
509 count = 0;
510 do {
511 md_element_t *np;
512
513 np = &(mdp->mdep[idx]);
514 switch (np->tag) {
515 case DT_LIST_END:
516 goto the_end;
517 case DT_NULL:
518 idx++;
519 break;
520 case DT_NODE:
521 idx = ntoh64(np->d.prop_idx);
522 count ++;
523 break;
524 default:
525 fatal("At index %d found unexpected node type "
526 "%d (0x%x : '%c') while searching for nodes",
527 idx, np->tag, np->tag, np->tag);
528 }
529 } while (1);
530
531the_end:
532 mdp->element_count = idx+1; /* include DT_LIST_END */
533 mdp->node_count = count;
534
535 ASSERT(mdp->element_count == (mdp->node_blk_size / MD_ELEMENT_SIZE));
536
537 return (mdp);
538}
539
540
541
542
543int
544md_close(md_t *mdp)
545{
546 munmap(mdp->caddr, mdp->size);
547 close(mdp->fh);
548
549 Xfree(mdp);
550
551 return (0);
552}