7 FILE *infile, *outfile;
42 struct zinfo_payload {
57 struct zinfo_common common;
58 struct zinfo_copy copy;
59 struct zinfo_pack pack;
60 struct zinfo_payload payload;
65 union zinfo_record *zinfo;
66 unsigned int num_entries;
69 static unsigned long align ( unsigned long value, unsigned long align ) {
70 return ( ( value + align - 1 ) & ~( align - 1 ) );
73 static int read_file ( const char *filename, void **buf, size_t *len ) {
77 file = fopen ( filename, "r" );
79 fprintf ( stderr, "Could not open %s: %s\n", filename,
84 if ( fstat ( fileno ( file ), &stat ) < 0 ) {
85 fprintf ( stderr, "Could not stat %s: %s\n", filename,
91 *buf = malloc ( *len );
93 fprintf ( stderr, "Could not malloc() %zd bytes for %s: %s\n",
94 *len, filename, strerror ( errno ) );
98 if ( fread ( *buf, 1, *len, file ) != *len ) {
99 fprintf ( stderr, "Could not read %zd bytes from %s: %s\n",
100 *len, filename, strerror ( errno ) );
113 static int read_input_file ( const char *filename,
114 struct input_file *input ) {
115 return read_file ( filename, &input->buf, &input->len );
118 static int read_zinfo_file ( const char *filename,
119 struct zinfo_file *zinfo ) {
123 if ( read_file ( filename, &buf, &len ) < 0 )
126 if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) {
127 fprintf ( stderr, ".zinfo file %s has invalid length %zd\n",
133 zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) );
137 static int alloc_output_file ( size_t max_len, struct output_file *output ) {
139 output->max_len = ( max_len );
140 output->buf = malloc ( max_len );
141 if ( ! output->buf ) {
142 fprintf ( stderr, "Could not allocate %zd bytes for output\n",
146 memset ( output->buf, 0xff, max_len );
150 static int process_zinfo_copy ( struct input_file *input,
151 struct output_file *output,
152 union zinfo_record *zinfo ) {
153 struct zinfo_copy *copy = &zinfo->copy;
154 size_t offset = copy->offset;
155 size_t len = copy->len;
157 if ( ( offset + len ) > input->len ) {
158 fprintf ( stderr, "Input buffer overrun on copy\n" );
162 output->len = align ( output->len, copy->align );
163 if ( ( output->len + len ) > output->max_len ) {
164 fprintf ( stderr, "Output buffer overrun on copy\n" );
169 fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n",
170 offset, ( offset + len ), output->len,
171 ( output->len + len ) );
174 memcpy ( ( output->buf + output->len ),
175 ( input->buf + offset ), len );
180 static int process_zinfo_pack ( struct input_file *input,
181 struct output_file *output,
182 union zinfo_record *zinfo ) {
183 struct zinfo_pack *pack = &zinfo->pack;
184 size_t offset = pack->offset;
185 size_t len = pack->len;
186 unsigned long packed_len;
188 if ( ( offset + len ) > input->len ) {
189 fprintf ( stderr, "Input buffer overrun on pack\n" );
193 output->len = align ( output->len, pack->align );
194 if ( output->len > output->max_len ) {
195 fprintf ( stderr, "Output buffer overrun on pack\n" );
199 if ( ucl_nrv2b_99_compress ( ( input->buf + offset ), len,
200 ( output->buf + output->len ),
201 &packed_len, 0 ) != UCL_E_OK ) {
202 fprintf ( stderr, "Compression failure\n" );
207 fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n",
208 offset, ( offset + len ), output->len,
209 ( size_t )( output->len + packed_len ) );
212 output->len += packed_len;
213 if ( output->len > output->max_len ) {
214 fprintf ( stderr, "Output buffer overrun on pack\n" );
221 static int process_zinfo_payl ( struct input_file *input
222 __attribute__ (( unused )),
223 struct output_file *output,
224 union zinfo_record *zinfo ) {
225 struct zinfo_payload *payload = &zinfo->payload;
227 output->len = align ( output->len, payload->align );
228 output->hdr_len = output->len;
231 fprintf ( stderr, "PAYL at %#zx\n", output->hdr_len );
236 static int process_zinfo_add ( struct input_file *input
237 __attribute__ (( unused )),
238 struct output_file *output,
240 struct zinfo_add *add, size_t offset,
248 offset += add->offset;
249 if ( ( offset + datasize ) > output->len ) {
250 fprintf ( stderr, "Add at %#zx outside output buffer\n",
255 target = ( output->buf + offset );
256 size = ( align ( len, add->divisor ) / add->divisor );
258 switch ( datasize ) {
260 addend = *( ( int8_t * ) target );
263 addend = *( ( int16_t * ) target );
266 addend = *( ( int32_t * ) target );
269 fprintf ( stderr, "Unsupported add datasize %zd\n",
276 /* The result of 1UL << ( 8 * sizeof(unsigned long) ) is undefined */
277 mask = ( ( datasize < sizeof ( mask ) ) ?
278 ( ( 1UL << ( 8 * datasize ) ) - 1 ) : ~0UL );
281 fprintf ( stderr, "Add %s%#x+%#lx at %#zx %sflows field\n",
282 ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
283 offset, ( ( addend < 0 ) ? "under" : "over" ) );
288 fprintf ( stderr, "Add %s%#x+%#lx at %#zx overflows %zd-byte "
289 "field (%d bytes too big)\n",
290 ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
292 ( int )( ( val - mask - 1 ) * add->divisor ) );
296 switch ( datasize ) {
298 *( ( uint8_t * ) target ) = val;
301 *( ( uint16_t * ) target ) = val;
304 *( ( uint32_t * ) target ) = val;
309 fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#x+(%#zx/%#x)) = "
310 "%#lx\n", offset, ( offset + datasize ),
311 ( ( addend < 0 ) ? "-" : "" ), abs ( addend ),
312 len, add->divisor, val );
318 static int process_zinfo_addb ( struct input_file *input,
319 struct output_file *output,
320 union zinfo_record *zinfo ) {
321 return process_zinfo_add ( input, output, output->len,
325 static int process_zinfo_addw ( struct input_file *input,
326 struct output_file *output,
327 union zinfo_record *zinfo ) {
328 return process_zinfo_add ( input, output, output->len,
332 static int process_zinfo_addl ( struct input_file *input,
333 struct output_file *output,
334 union zinfo_record *zinfo ) {
335 return process_zinfo_add ( input, output, output->len,
339 static int process_zinfo_adhb ( struct input_file *input,
340 struct output_file *output,
341 union zinfo_record *zinfo ) {
342 return process_zinfo_add ( input, output, output->hdr_len,
346 static int process_zinfo_adhw ( struct input_file *input,
347 struct output_file *output,
348 union zinfo_record *zinfo ) {
349 return process_zinfo_add ( input, output, output->hdr_len,
353 static int process_zinfo_adhl ( struct input_file *input,
354 struct output_file *output,
355 union zinfo_record *zinfo ) {
356 return process_zinfo_add ( input, output, output->hdr_len,
360 static int process_zinfo_adpb ( struct input_file *input,
361 struct output_file *output,
362 union zinfo_record *zinfo ) {
363 return process_zinfo_add ( input, output,
364 ( output->len - output->hdr_len ),
368 static int process_zinfo_adpw ( struct input_file *input,
369 struct output_file *output,
370 union zinfo_record *zinfo ) {
371 return process_zinfo_add ( input, output,
372 ( output->len - output->hdr_len ),
376 static int process_zinfo_adpl ( struct input_file *input,
377 struct output_file *output,
378 union zinfo_record *zinfo ) {
379 return process_zinfo_add ( input, output,
380 ( output->len - output->hdr_len ),
384 static int process_zinfo_appb ( struct input_file *input,
385 struct output_file *output,
386 union zinfo_record *zinfo ) {
387 return process_zinfo_add ( input, output,
388 ( output->len - output->hdr_len ),
389 &zinfo->add, output->hdr_len, 1 );
392 static int process_zinfo_appw ( struct input_file *input,
393 struct output_file *output,
394 union zinfo_record *zinfo ) {
395 return process_zinfo_add ( input, output,
396 ( output->len - output->hdr_len ),
397 &zinfo->add, output->hdr_len, 2 );
400 static int process_zinfo_appl ( struct input_file *input,
401 struct output_file *output,
402 union zinfo_record *zinfo ) {
403 return process_zinfo_add ( input, output,
404 ( output->len - output->hdr_len ),
405 &zinfo->add, output->hdr_len, 4 );
408 struct zinfo_processor {
410 int ( * process ) ( struct input_file *input,
411 struct output_file *output,
412 union zinfo_record *zinfo );
415 static struct zinfo_processor zinfo_processors[] = {
416 { "COPY", process_zinfo_copy },
417 { "PACK", process_zinfo_pack },
418 { "PAYL", process_zinfo_payl },
419 { "ADDB", process_zinfo_addb },
420 { "ADDW", process_zinfo_addw },
421 { "ADDL", process_zinfo_addl },
422 { "ADHB", process_zinfo_adhb },
423 { "ADHW", process_zinfo_adhw },
424 { "ADHL", process_zinfo_adhl },
425 { "ADPB", process_zinfo_adpb },
426 { "ADPW", process_zinfo_adpw },
427 { "ADPL", process_zinfo_adpl },
428 { "APPB", process_zinfo_appb },
429 { "APPW", process_zinfo_appw },
430 { "APPL", process_zinfo_appl },
433 static int process_zinfo ( struct input_file *input,
434 struct output_file *output,
435 union zinfo_record *zinfo ) {
436 struct zinfo_common *common = &zinfo->common;
437 struct zinfo_processor *processor;
438 char type[ sizeof ( common->type ) + 1 ] = "";
441 strncat ( type, common->type, sizeof ( type ) - 1 );
442 for ( i = 0 ; i < ( sizeof ( zinfo_processors ) /
443 sizeof ( zinfo_processors[0] ) ) ; i++ ) {
444 processor = &zinfo_processors[i];
445 if ( strcmp ( processor->type, type ) == 0 )
446 return processor->process ( input, output, zinfo );
449 fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] );
453 static int write_output_file ( struct output_file *output ) {
454 if ( fwrite ( output->buf, 1, output->len, stdout ) != output->len ) {
455 fprintf ( stderr, "Could not write %zd bytes of output: %s\n",
456 output->len, strerror ( errno ) );
462 int main ( int argc, char **argv ) {
463 struct input_file input;
464 struct output_file output;
465 struct zinfo_file zinfo;
469 fprintf ( stderr, "Syntax: %s file.bin file.zinfo "
470 "> file.zbin\n", argv[0] );
474 if ( read_input_file ( argv[1], &input ) < 0 )
476 if ( read_zinfo_file ( argv[2], &zinfo ) < 0 )
478 if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 )
481 for ( i = 0 ; i < zinfo.num_entries ; i++ ) {
482 if ( process_zinfo ( &input, &output,
483 &zinfo.zinfo[i] ) < 0 )
487 if ( write_output_file ( &output ) < 0 )