7 FILE *infile
, *outfile
;
49 struct zinfo_common common
;
50 struct zinfo_copy copy
;
51 struct zinfo_pack pack
;
56 union zinfo_record
*zinfo
;
57 unsigned int num_entries
;
60 static unsigned long align ( unsigned long value
, unsigned long align
) {
61 return ( ( value
+ align
- 1 ) & ~( align
- 1 ) );
64 static int read_file ( const char *filename
, void **buf
, size_t *len
) {
68 file
= fopen ( filename
, "r" );
70 fprintf ( stderr
, "Could not open %s: %s\n", filename
,
75 if ( fstat ( fileno ( file
), &stat
) < 0 ) {
76 fprintf ( stderr
, "Could not stat %s: %s\n", filename
,
82 *buf
= malloc ( *len
);
84 fprintf ( stderr
, "Could not malloc() %zd bytes for %s: %s\n",
85 *len
, filename
, strerror ( errno
) );
89 if ( fread ( *buf
, 1, *len
, file
) != *len
) {
90 fprintf ( stderr
, "Could not read %zd bytes from %s: %s\n",
91 *len
, filename
, strerror ( errno
) );
104 static int read_input_file ( const char *filename
,
105 struct input_file
*input
) {
106 return read_file ( filename
, &input
->buf
, &input
->len
);
109 static int read_zinfo_file ( const char *filename
,
110 struct zinfo_file
*zinfo
) {
114 if ( read_file ( filename
, &buf
, &len
) < 0 )
117 if ( ( len
% sizeof ( *(zinfo
->zinfo
) ) ) != 0 ) {
118 fprintf ( stderr
, ".zinfo file %s has invalid length %zd\n",
124 zinfo
->num_entries
= ( len
/ sizeof ( *(zinfo
->zinfo
) ) );
128 static int alloc_output_file ( size_t max_len
, struct output_file
*output
) {
130 output
->max_len
= ( max_len
);
131 output
->buf
= malloc ( max_len
);
132 if ( ! output
->buf
) {
133 fprintf ( stderr
, "Could not allocate %zd bytes for output\n",
137 memset ( output
->buf
, 0xff, sizeof ( output
->buf
) );
141 static int process_zinfo_copy ( struct input_file
*input
,
142 struct output_file
*output
,
143 union zinfo_record
*zinfo
) {
144 struct zinfo_copy
*copy
= &zinfo
->copy
;
145 size_t offset
= copy
->offset
;
146 size_t len
= copy
->len
;
148 if ( ( offset
+ len
) > input
->len
) {
149 fprintf ( stderr
, "Input buffer overrun on copy\n" );
153 output
->len
= align ( output
->len
, copy
->align
);
154 if ( ( output
->len
+ len
) > output
->max_len
) {
155 fprintf ( stderr
, "Output buffer overrun on copy\n" );
160 fprintf ( stderr
, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n",
161 offset
, ( offset
+ len
), output
->len
,
162 ( output
->len
+ len
) );
165 memcpy ( ( output
->buf
+ output
->len
),
166 ( input
->buf
+ offset
), len
);
171 static int process_zinfo_pack ( struct input_file
*input
,
172 struct output_file
*output
,
173 union zinfo_record
*zinfo
) {
174 struct zinfo_pack
*pack
= &zinfo
->pack
;
175 size_t offset
= pack
->offset
;
176 size_t len
= pack
->len
;
177 unsigned long packed_len
;
179 if ( ( offset
+ len
) > input
->len
) {
180 fprintf ( stderr
, "Input buffer overrun on pack\n" );
184 output
->len
= align ( output
->len
, pack
->align
);
185 if ( output
->len
> output
->max_len
) {
186 fprintf ( stderr
, "Output buffer overrun on pack\n" );
190 if ( ucl_nrv2b_99_compress ( ( input
->buf
+ offset
), len
,
191 ( output
->buf
+ output
->len
),
192 &packed_len
, 0 ) != UCL_E_OK
) {
193 fprintf ( stderr
, "Compression failure\n" );
198 fprintf ( stderr
, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n",
199 offset
, ( offset
+ len
), output
->len
,
200 ( size_t )( output
->len
+ packed_len
) );
203 output
->len
+= packed_len
;
204 if ( output
->len
> output
->max_len
) {
205 fprintf ( stderr
, "Output buffer overrun on pack\n" );
212 static int process_zinfo_add ( struct input_file
*input
,
213 struct output_file
*output
,
214 struct zinfo_add
*add
,
216 size_t offset
= add
->offset
;
223 if ( ( offset
+ datasize
) > output
->len
) {
224 fprintf ( stderr
, "Add at %#zx outside output buffer\n",
229 target
= ( output
->buf
+ offset
);
230 size
= ( align ( output
->len
, add
->divisor
) / add
->divisor
);
232 switch ( datasize
) {
234 addend
= *( ( int8_t * ) target
);
237 addend
= *( ( int16_t * ) target
);
240 addend
= *( ( int32_t * ) target
);
243 fprintf ( stderr
, "Unsupported add datasize %zd\n",
250 /* The result of 1UL << ( 8 * sizeof(unsigned long) ) is undefined */
251 mask
= ( ( datasize
< sizeof ( mask
) ) ?
252 ( ( 1UL << ( 8 * datasize
) ) - 1 ) : ~0UL );
255 fprintf ( stderr
, "Add %s%#x+%#lx at %#zx %sflows field\n",
256 ( ( addend
< 0 ) ? "-" : "" ), abs ( addend
), size
,
257 offset
, ( ( addend
< 0 ) ? "under" : "over" ) );
262 fprintf ( stderr
, "Add %s%#x+%#lx at %#zx overflows %zd-byte "
263 "field (%d bytes too big)\n",
264 ( ( addend
< 0 ) ? "-" : "" ), abs ( addend
), size
,
266 ( int )( ( val
- mask
- 1 ) * add
->divisor
) );
270 switch ( datasize
) {
272 *( ( uint8_t * ) target
) = val
;
275 *( ( uint16_t * ) target
) = val
;
278 *( ( uint32_t * ) target
) = val
;
283 fprintf ( stderr
, "ADDx [%#zx,%#zx) (%s%#x+(%#zx/%#x)) = "
284 "%#lx\n", offset
, ( offset
+ datasize
),
285 ( ( addend
< 0 ) ? "-" : "" ), abs ( addend
),
286 output
->len
, add
->divisor
, val
);
292 static int process_zinfo_addb ( struct input_file
*input
,
293 struct output_file
*output
,
294 union zinfo_record
*zinfo
) {
295 return process_zinfo_add ( input
, output
, &zinfo
->add
, 1 );
298 static int process_zinfo_addw ( struct input_file
*input
,
299 struct output_file
*output
,
300 union zinfo_record
*zinfo
) {
301 return process_zinfo_add ( input
, output
, &zinfo
->add
, 2 );
304 static int process_zinfo_addl ( struct input_file
*input
,
305 struct output_file
*output
,
306 union zinfo_record
*zinfo
) {
307 return process_zinfo_add ( input
, output
, &zinfo
->add
, 4 );
310 struct zinfo_processor
{
312 int ( * process
) ( struct input_file
*input
,
313 struct output_file
*output
,
314 union zinfo_record
*zinfo
);
317 static struct zinfo_processor zinfo_processors
[] = {
318 { "COPY", process_zinfo_copy
},
319 { "PACK", process_zinfo_pack
},
320 { "ADDB", process_zinfo_addb
},
321 { "ADDW", process_zinfo_addw
},
322 { "ADDL", process_zinfo_addl
},
325 static int process_zinfo ( struct input_file
*input
,
326 struct output_file
*output
,
327 union zinfo_record
*zinfo
) {
328 struct zinfo_common
*common
= &zinfo
->common
;
329 struct zinfo_processor
*processor
;
330 char type
[ sizeof ( common
->type
) + 1 ] = "";
333 strncat ( type
, common
->type
, sizeof ( type
) - 1 );
334 for ( i
= 0 ; i
< ( sizeof ( zinfo_processors
) /
335 sizeof ( zinfo_processors
[0] ) ) ; i
++ ) {
336 processor
= &zinfo_processors
[i
];
337 if ( strcmp ( processor
->type
, type
) == 0 )
338 return processor
->process ( input
, output
, zinfo
);
341 fprintf ( stderr
, "Unknown zinfo record type \"%s\"\n", &type
[0] );
345 static int write_output_file ( struct output_file
*output
) {
346 if ( fwrite ( output
->buf
, 1, output
->len
, stdout
) != output
->len
) {
347 fprintf ( stderr
, "Could not write %zd bytes of output: %s\n",
348 output
->len
, strerror ( errno
) );
354 int main ( int argc
, char **argv
) {
355 struct input_file input
;
356 struct output_file output
;
357 struct zinfo_file zinfo
;
361 fprintf ( stderr
, "Syntax: %s file.bin file.zinfo "
362 "> file.zbin\n", argv
[0] );
366 if ( read_input_file ( argv
[1], &input
) < 0 )
368 if ( read_zinfo_file ( argv
[2], &zinfo
) < 0 )
370 if ( alloc_output_file ( ( input
.len
* 4 ), &output
) < 0 )
373 for ( i
= 0 ; i
< zinfo
.num_entries
; i
++ ) {
374 if ( process_zinfo ( &input
, &output
,
375 &zinfo
.zinfo
[i
] ) < 0 )
379 if ( write_output_file ( &output
) < 0 )