* ========== Copyright Header Begin ==========================================
* Hypervisor Software File: output_bin.c
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* - Do no alter or remove copyright notices
* - Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* - Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of Sun Microsystems, Inc. or the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* You acknowledge that this software is not designed, licensed or
* intended for use in the design, construction, operation or maintenance of
* ========== Copyright Header End ============================================
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#pragma ident "@(#)output_bin.c 1.2 07/06/07 SMI"
#define ASSERT(_s) assert(_s)
#define hton16(_s) ((uint16_t)(_s))
#define hton32(_s) ((uint32_t)(_s))
#define hton64(_s) ((uint64_t)(_s))
#define ntoh16(_s) ((uint16_t)(_s))
#define ntoh32(_s) ((uint32_t)(_s))
#define ntoh64(_s) ((uint64_t)(_s))
#error FIXME: Define byte reversal functions for network byte ordering
* Currently spec defines namelen to be strlen, not size of entry in
#define SIZETONAMELEN(_s) ((_s)-1)
* Output in binary format for use in partitions
* We use this set of structs as a temporary list of the
* sub-blocks comprising the data block and the string block.
* We tag those that are strings, and search for duplicates
* each time we insert the string.
typedef struct MD_CHUNK md_chunk_t
;
static int bin_write(int fh
, void *ptrp
, int size
);
static md_chunk_t
*md_add_chunk(md_blk_t
*bp
, void *ptrp
, int size
);
static md_chunk_t
*md_insert_data(uint8_t *ptrp
, int size
, int align
);
static md_chunk_t
*md_insert_name(char *strp
);
* Step1: compute the offsets for the start of each node.
for (dnp
= dag_listp
; NULL
!= dnp
; dnp
= dnp
->nextp
) {
DBGN( fprintf(stderr
, "Node %d @ %d : %s %s\tprop=%d\n",
dnp
->idx
, offset
, dnp
->typep
, dnp
->namep
,
offset
+= BASE_TAG_COUNT
;
offset
+= dnp
->properties
.num
;
list_end_offset
= offset
;
* step through the list of nodes and compute the
* number of node entries and the size of the data block
* FIXME: scan properties to see if we need greater
* alignment at start of data block
for (dnp
= dag_listp
; NULL
!= dnp
; dnp
= dnp
->nextp
) {
/* string for node type */
dnp
->name_tmp
= (void*)md_insert_name(dnp
->typep
);
* go find the relevent sub-blocks of
* data and property names
pep
= dnp
->properties
.listp
;
for (i
= 0; i
< dnp
->properties
.num
; i
++) {
pep
->name_tmp
= md_insert_name(pep
->namep
);
md_insert_data((uint8_t *)pep
->u
.strp
,
strlen(pep
->u
.strp
)+1, 8);
md_insert_data(pep
->u
.data
.buffer
,
* Carefully align the data segment
pad
= name_blk
.total_size
% data_alignment
;
(void) md_add_chunk(&name_blk
, NULL
,
fprintf(stderr
, "Machine description holds %d elements\n",
list_end_offset
+ LAST_OFFSET
);
fprintf(stderr
, "node block size = %d bytes\n",
MD_ELEMENT_SIZE
* (list_end_offset
+ LAST_OFFSET
));
fprintf(stderr
, "name block size = %d bytes\n",
fprintf(stderr
, "data block size = %d bytes\n",
* Prepare the header and write it out
mdh
.transport_version
= hton32(MD_TRANSPORT_VERSION
);
mdh
.node_blk_sz
= hton32(MD_ELEMENT_SIZE
*
(list_end_offset
+ LAST_OFFSET
));
mdh
.name_blk_sz
= hton32(name_blk
.total_size
);
mdh
.data_blk_sz
= hton32(data_blk
.total_size
);
bin_write(fh
, &mdh
, sizeof (mdh
));
/* Now write out the node block */
for (dnp
= dag_listp
; NULL
!= dnp
; dnp
= dnp
->nextp
) {
memset(&mde
, 0, sizeof (mde
));
sbp
= (md_chunk_t
*)dnp
->name_tmp
;
mde
.namelen
= SIZETONAMELEN(sbp
->size
);
mde
.name
= hton32(sbp
->offset
);
if (NULL
== dnp
->nextp
) {
/* index points to END_OF_LIST element */
val
= dnp
->nextp
->offset
;
mde
.d
.prop_idx
= hton64(val
);
bin_write(fh
, &mde
, sizeof (mde
));
* Now write out the properties elements
pep
= dnp
->properties
.listp
;
for (i
= 0; i
< dnp
->properties
.num
; i
++) {
sbp
= (md_chunk_t
*)pep
->name_tmp
;
memset(&mde
, 0, sizeof (mde
));
mde
.namelen
= SIZETONAMELEN(sbp
->size
);
mde
.name
= hton32(sbp
->offset
);
fatal("PE_none found in node");
sbp
= (md_chunk_t
*)pep
->data_tmp
;
mde
.d
.prop_data
.len
= hton32(sbp
->size
);
mde
.d
.prop_data
.offset
= hton32(sbp
->offset
);
mde
.d
.prop_val
= pep
->u
.val
;
mde
.d
.prop_idx
= hton64(pep
->u
.dnp
->offset
);
fatal("PE_noderef found in node");
fatal("unknown property type found %d",
bin_write(fh
, &mde
, sizeof (mde
));
memset(&mde
, 0, sizeof (mde
));
bin_write(fh
, &mde
, sizeof (mde
));
/* Terminate the node block output */
memset(&mde
, 0, sizeof (mde
));
bin_write(fh
, &mde
, sizeof (mde
));
* Finally let's dump out the name & data sections.
for (sbp
= name_blk
.firstp
; NULL
!= sbp
; sbp
= sbp
->nextp
) {
bin_write(fh
, sbp
->datap
, sbp
->size
);
for (sbp
= data_blk
.firstp
; NULL
!= sbp
; sbp
= sbp
->nextp
) {
bin_write(fh
, sbp
->datap
, sbp
->size
);
* Now free up the allocated data section stuff.
for (sbp
= name_blk
.firstp
; NULL
!= sbp
; sbp
= nsbp
) {
for (sbp
= data_blk
.firstp
; NULL
!= sbp
; sbp
= nsbp
) {
bin_write(int fh
, void *ptrp
, int size
)
for (left
= size
, bp
= ptrp
; left
> 0; left
-= amt
, bp
+= amt
) {
amt
= write(fh
, bp
, left
);
if (amt
< 0 && EAGAIN
== errno
) goto loop
;
fatal("Failed writing binary file output");
md_add_chunk(md_blk_t
*bp
, void *ptrp
, int size
)
cp
= Xcalloc(1, md_chunk_t
);
cp
->datap
= Xmalloc(size
);
memcpy(cp
->datap
, ptrp
, size
);
memset(cp
->datap
, 0, size
);
cp
->offset
= bp
->total_size
;
if (NULL
== bp
->firstp
) {
md_insert_data(uint8_t *ptrp
, int size
, int align
)
pad
= data_blk
.total_size
% align
;
(void) md_add_chunk(&data_blk
, NULL
, pad
);
ASSERT((data_blk
.total_size
% align
) == 0);
return (md_add_chunk(&data_blk
, ptrp
, size
));
md_insert_name(char *ptrp
)
for (sbp
= name_blk
.firstp
; NULL
!= sbp
; sbp
= sbp
->nextp
) {
if (size
== sbp
->size
&& memcmp(ptrp
, sbp
->datap
, size
) == 0)
return (md_add_chunk(&name_blk
, ptrp
, size
));