Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / support / mdgen / output_bin.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: output_bin.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 "@(#)output_bin.c 1.2 07/06/07 SMI"
50
51#include <stdio.h>
52#include <stdlib.h>
53#include <unistd.h>
54#include <fcntl.h>
55#include <sys/types.h>
56#include <ctype.h>
57#include <strings.h>
58#include <inttypes.h>
59#include <netinet/in.h>
60#include <errno.h>
61
62#include <assert.h>
63
64#include <md/md_impl.h>
65
66#include "basics.h"
67#include "allocate.h"
68#include "fatal.h"
69#include "lexer.h"
70
71#include "dagtypes.h"
72#include "outputtypes.h"
73
74
75#define ASSERT(_s) assert(_s)
76
77#define DBGN(_s)
78
79#if defined(_BIG_ENDIAN)
80#define hton16(_s) ((uint16_t)(_s))
81#define hton32(_s) ((uint32_t)(_s))
82#define hton64(_s) ((uint64_t)(_s))
83#define ntoh16(_s) ((uint16_t)(_s))
84#define ntoh32(_s) ((uint32_t)(_s))
85#define ntoh64(_s) ((uint64_t)(_s))
86#else
87#error FIXME: Define byte reversal functions for network byte ordering
88#endif
89
90
91
92
93 /*
94 * Currently spec defines namelen to be strlen, not size of entry in
95 * nametable.
96 */
97#define SIZETONAMELEN(_s) ((_s)-1)
98
99
100
101
102
103
104 /*
105 * Output in binary format for use in partitions
106 */
107
108
109 /*
110 * We use this set of structs as a temporary list of the
111 * sub-blocks comprising the data block and the string block.
112 * We tag those that are strings, and search for duplicates
113 * each time we insert the string.
114 */
115
116typedef struct MD_CHUNK md_chunk_t;
117
118struct MD_CHUNK {
119 uint8_t *datap;
120 uint32_t size;
121 uint32_t offset;
122 md_chunk_t *nextp;
123};
124
125typedef struct MD_BLK {
126 md_chunk_t *firstp;
127 md_chunk_t *lastp;
128 int total_size;
129} md_blk_t;
130
131
132md_blk_t name_blk;
133md_blk_t data_blk;
134
135
136 /* predefines */
137
138
139static int bin_write(int fh, void *ptrp, int size);
140
141static md_chunk_t *md_add_chunk(md_blk_t *bp, void *ptrp, int size);
142static md_chunk_t *md_insert_data(uint8_t *ptrp, int size, int align);
143static md_chunk_t *md_insert_name(char *strp);
144
145#define BASE_TAG_COUNT 2
146#define LAST_OFFSET 1
147
148
149
150void
151output_bin(FILE *fp)
152{
153 md_hdr_t mdh;
154 dag_node_t *dnp;
155 int fh;
156 int offset;
157 int list_end_offset;
158 md_chunk_t *sbp, *nsbp;
159 md_element_t mde;
160 int data_alignment;
161
162 fflush(fp);
163 fh = fileno(fp);
164
165 /*
166 * Step1: compute the offsets for the start of each node.
167 */
168
169 offset = 0;
170 for (dnp = dag_listp; NULL != dnp; dnp = dnp->nextp) {
171 dnp->offset = offset;
172
173/* BEGIN CSTYLED */
174DBGN( fprintf(stderr, "Node %d @ %d : %s %s\tprop=%d\n",
175 dnp->idx, offset, dnp->typep, dnp->namep,
176 dnp->properties.num); );
177/* END CSTYLED */
178
179 offset += BASE_TAG_COUNT;
180 offset += dnp->properties.num;
181 }
182 list_end_offset = offset;
183
184 /*
185 * step through the list of nodes and compute the
186 * number of node entries and the size of the data block
187 */
188
189 name_blk.firstp = NULL;
190 name_blk.lastp = NULL;
191 name_blk.total_size = 0;
192
193 data_blk.firstp = NULL;
194 data_blk.lastp = NULL;
195 data_blk.total_size = 0;
196
197 /*
198 * FIXME: scan properties to see if we need greater
199 * alignment at start of data block
200 */
201 data_alignment = 16;
202
203 for (dnp = dag_listp; NULL != dnp; dnp = dnp->nextp) {
204 int i;
205 pair_entry_t *pep;
206
207 /* string for node type */
208 dnp->name_tmp = (void*)md_insert_name(dnp->typep);
209
210 /*
211 * go find the relevent sub-blocks of
212 * data and property names
213 */
214
215 pep = dnp->properties.listp;
216 for (i = 0; i < dnp->properties.num; i++) {
217 pep->name_tmp = md_insert_name(pep->namep);
218
219 switch (pep->utype) {
220 case PE_string:
221 pep->data_tmp =
222 md_insert_data((uint8_t *)pep->u.strp,
223 strlen(pep->u.strp)+1, 8);
224 break;
225
226 case PE_data:
227 pep->data_tmp =
228 md_insert_data(pep->u.data.buffer,
229 pep->u.data.len, 8);
230 break;
231
232 default:;
233 /* nada */
234 }
235 pep ++;
236 }
237 }
238
239 /*
240 * Carefully align the data segment
241 */
242
243 do {
244 int pad;
245
246 pad = name_blk.total_size % data_alignment;
247
248 if (pad != 0) {
249 (void) md_add_chunk(&name_blk, NULL,
250 data_alignment - pad);
251 }
252 } while (0);
253
254
255 /*
256 * Output noise if needed
257 */
258 if (flag_verbose) {
259 fprintf(stderr, "Machine description holds %d elements\n",
260 list_end_offset + LAST_OFFSET);
261 fprintf(stderr, "node block size = %d bytes\n",
262 MD_ELEMENT_SIZE * (list_end_offset + LAST_OFFSET));
263 fprintf(stderr, "name block size = %d bytes\n",
264 name_blk.total_size);
265 fprintf(stderr, "data block size = %d bytes\n",
266 name_blk.total_size);
267 }
268
269
270 /*
271 * Prepare the header and write it out
272 */
273
274 mdh.transport_version = hton32(MD_TRANSPORT_VERSION);
275 mdh.node_blk_sz = hton32(MD_ELEMENT_SIZE *
276 (list_end_offset + LAST_OFFSET));
277 mdh.name_blk_sz = hton32(name_blk.total_size);
278 mdh.data_blk_sz = hton32(data_blk.total_size);
279
280 bin_write(fh, &mdh, sizeof (mdh));
281
282 /* Now write out the node block */
283
284 for (dnp = dag_listp; NULL != dnp; dnp = dnp->nextp) {
285 int i;
286 pair_entry_t *pep;
287 uint64_t val;
288
289 memset(&mde, 0, sizeof (mde));
290
291 mde.tag = DT_NODE;
292
293 sbp = (md_chunk_t *)dnp->name_tmp;
294 ASSERT(sbp->size < 256);
295
296 mde.namelen = SIZETONAMELEN(sbp->size);
297 mde.name = hton32(sbp->offset);
298
299 if (NULL == dnp->nextp) {
300 /* index points to END_OF_LIST element */
301 val = list_end_offset;
302 } else {
303 val = dnp->nextp->offset;
304 }
305 mde.d.prop_idx = hton64(val);
306
307 bin_write(fh, &mde, sizeof (mde));
308
309 /*
310 * Now write out the properties elements
311 */
312
313 pep = dnp->properties.listp;
314 for (i = 0; i < dnp->properties.num; i++) {
315
316 sbp = (md_chunk_t *)pep->name_tmp;
317 ASSERT(sbp->size < 256);
318
319 memset(&mde, 0, sizeof (mde));
320 mde.namelen = SIZETONAMELEN(sbp->size);
321 mde.name = hton32(sbp->offset);
322
323 switch (pep->utype) {
324 case PE_none:
325 fatal("PE_none found in node");
326 break;
327
328 case PE_string:
329 mde.tag = DT_PROP_STR;
330 goto data_elem;
331 case PE_data:
332 mde.tag = DT_PROP_DAT;
333data_elem:;
334 sbp = (md_chunk_t *)pep->data_tmp;
335 mde.d.prop_data.len = hton32(sbp->size);
336 mde.d.prop_data.offset = hton32(sbp->offset);
337 break;
338
339 case PE_int:
340 mde.tag = DT_PROP_VAL;
341 mde.d.prop_val = pep->u.val;
342 break;
343
344 case PE_arc:
345 mde.tag = DT_PROP_ARC;
346 mde.d.prop_idx = hton64(pep->u.dnp->offset);
347 break;
348
349 case PE_noderef:
350 fatal("PE_noderef found in node");
351 break;
352
353 default:
354 fatal("unknown property type found %d",
355 pep->utype);
356 }
357 bin_write(fh, &mde, sizeof (mde));
358
359 pep ++;
360 }
361
362 memset(&mde, 0, sizeof (mde));
363 mde.tag = DT_NODE_END;
364 bin_write(fh, &mde, sizeof (mde));
365 }
366
367 /* Terminate the node block output */
368 memset(&mde, 0, sizeof (mde));
369 mde.tag = DT_LIST_END;
370 bin_write(fh, &mde, sizeof (mde));
371
372
373 /*
374 * Finally let's dump out the name & data sections.
375 */
376
377 for (sbp = name_blk.firstp; NULL != sbp; sbp = sbp->nextp) {
378 bin_write(fh, sbp->datap, sbp->size);
379 }
380
381 for (sbp = data_blk.firstp; NULL != sbp; sbp = sbp->nextp) {
382 bin_write(fh, sbp->datap, sbp->size);
383 }
384
385 /*
386 * Now free up the allocated data section stuff.
387 */
388 for (sbp = name_blk.firstp; NULL != sbp; sbp = nsbp) {
389 nsbp = sbp->nextp;
390
391 Xfree(sbp->datap);
392 Xfree(sbp);
393 }
394
395 for (sbp = data_blk.firstp; NULL != sbp; sbp = nsbp) {
396 nsbp = sbp->nextp;
397
398 Xfree(sbp->datap);
399 Xfree(sbp);
400 }
401
402 /*
403 * sanity
404 */
405
406 name_blk.firstp = NULL;
407 name_blk.lastp = NULL;
408 name_blk.total_size = 0;
409
410 data_blk.firstp = NULL;
411 data_blk.lastp = NULL;
412 data_blk.total_size = 0;
413}
414
415
416
417
418
419static int
420bin_write(int fh, void *ptrp, int size)
421{
422 uint8_t *bp;
423 int left;
424 int amt;
425
426 for (left = size, bp = ptrp; left > 0; left -= amt, bp += amt) {
427loop:;
428 amt = write(fh, bp, left);
429 if (amt <= 0) {
430 if (amt < 0 && EAGAIN == errno) goto loop;
431 fatal("Failed writing binary file output");
432 }
433 }
434
435 return (size);
436}
437
438
439
440
441
442
443
444
445static md_chunk_t *
446md_add_chunk(md_blk_t *bp, void *ptrp, int size)
447{
448 md_chunk_t *cp;
449
450 cp = Xcalloc(1, md_chunk_t);
451
452 cp->datap = Xmalloc(size);
453 if (ptrp != NULL) {
454 memcpy(cp->datap, ptrp, size);
455 } else {
456 memset(cp->datap, 0, size);
457 }
458
459 cp->size = size;
460 cp->offset = bp->total_size;
461 cp->nextp = NULL;
462 if (NULL == bp->firstp) {
463 bp->firstp = cp;
464 bp->lastp = cp;
465 } else {
466 bp->lastp->nextp = cp;
467 bp->lastp = cp;
468 }
469 bp->total_size += size;
470
471 return (cp);
472}
473
474
475static md_chunk_t *
476md_insert_data(uint8_t *ptrp, int size, int align)
477{
478 int pad;
479
480 pad = data_blk.total_size % align;
481 if (pad != 0) {
482 pad = align-pad;
483 (void) md_add_chunk(&data_blk, NULL, pad);
484 }
485
486 ASSERT((data_blk.total_size % align) == 0);
487
488 return (md_add_chunk(&data_blk, ptrp, size));
489}
490
491
492static md_chunk_t *
493md_insert_name(char *ptrp)
494{
495 md_chunk_t *sbp;
496 int size;
497
498 size = strlen(ptrp)+1;
499
500 for (sbp = name_blk.firstp; NULL != sbp; sbp = sbp->nextp) {
501 if (size == sbp->size && memcmp(ptrp, sbp->datap, size) == 0)
502 return (sbp);
503 }
504
505 return (md_add_chunk(&name_blk, ptrp, size));
506}