Home | History | Annotate | Download | only in util
      1 #include <stdio.h>
      2 #include <sys/stat.h>
      3 
      4 #define ENCODE
      5 #define VERBOSE
      6 #include "nrv2b.c"
      7 FILE *infile, *outfile;
      8 
      9 #define DEBUG 0
     10 
     11 struct input_file {
     12 	void *buf;
     13 	size_t len;
     14 };
     15 
     16 struct output_file {
     17 	void *buf;
     18 	size_t len;
     19 	size_t max_len;
     20 };
     21 
     22 struct zinfo_common {
     23 	char type[4];
     24 	char pad[12];
     25 };
     26 
     27 struct zinfo_copy {
     28 	char type[4];
     29 	uint32_t offset;
     30 	uint32_t len;
     31 	uint32_t align;
     32 };
     33 
     34 struct zinfo_pack {
     35 	char type[4];
     36 	uint32_t offset;
     37 	uint32_t len;
     38 	uint32_t align;
     39 };
     40 
     41 struct zinfo_add {
     42 	char type[4];
     43 	uint32_t offset;
     44 	uint32_t divisor;
     45 	uint32_t pad;
     46 };
     47 
     48 union zinfo_record {
     49 	struct zinfo_common common;
     50 	struct zinfo_copy copy;
     51 	struct zinfo_pack pack;
     52 	struct zinfo_add add;
     53 };
     54 
     55 struct zinfo_file {
     56 	union zinfo_record *zinfo;
     57 	unsigned int num_entries;
     58 };
     59 
     60 static unsigned long align ( unsigned long value, unsigned long align ) {
     61 	return ( ( value + align - 1 ) & ~( align - 1 ) );
     62 }
     63 
     64 static int read_file ( const char *filename, void **buf, size_t *len ) {
     65 	FILE *file;
     66 	struct stat stat;
     67 
     68 	file = fopen ( filename, "r" );
     69 	if ( ! file ) {
     70 		fprintf ( stderr, "Could not open %s: %s\n", filename,
     71 			  strerror ( errno ) );
     72 		goto err;
     73 	}
     74 
     75 	if ( fstat ( fileno ( file ), &stat ) < 0 ) {
     76 		fprintf ( stderr, "Could not stat %s: %s\n", filename,
     77 			  strerror ( errno ) );
     78 		goto err;
     79 	}
     80 
     81 	*len = stat.st_size;
     82 	*buf = malloc ( *len );
     83 	if ( ! *buf ) {
     84 		fprintf ( stderr, "Could not malloc() %zd bytes for %s: %s\n",
     85 			  *len, filename, strerror ( errno ) );
     86 		goto err;
     87 	}
     88 
     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 ) );
     92 		goto err;
     93 	}
     94 
     95 	fclose ( file );
     96 	return 0;
     97 
     98  err:
     99 	if ( file )
    100 		fclose ( file );
    101 	return -1;
    102 }
    103 
    104 static int read_input_file ( const char *filename,
    105 			     struct input_file *input ) {
    106 	return read_file ( filename, &input->buf, &input->len );
    107 }
    108 
    109 static int read_zinfo_file ( const char *filename,
    110 			     struct zinfo_file *zinfo ) {
    111 	void *buf;
    112 	size_t len;
    113 
    114 	if ( read_file ( filename, &buf, &len ) < 0 )
    115 		return -1;
    116 
    117 	if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) {
    118 		fprintf ( stderr, ".zinfo file %s has invalid length %zd\n",
    119 			  filename, len );
    120 		return -1;
    121 	}
    122 
    123 	zinfo->zinfo = buf;
    124 	zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) );
    125 	return 0;
    126 }
    127 
    128 static int alloc_output_file ( size_t max_len, struct output_file *output ) {
    129 	output->len = 0;
    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",
    134 			  max_len );
    135 		return -1;
    136 	}
    137 	memset ( output->buf, 0xff, sizeof ( output->buf ) );
    138 	return 0;
    139 }
    140 
    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;
    147 
    148 	if ( ( offset + len ) > input->len ) {
    149 		fprintf ( stderr, "Input buffer overrun on copy\n" );
    150 		return -1;
    151 	}
    152 
    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" );
    156 		return -1;
    157 	}
    158 
    159 	if ( DEBUG ) {
    160 		fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n",
    161 			  offset, ( offset + len ), output->len,
    162 			  ( output->len + len ) );
    163 	}
    164 
    165 	memcpy ( ( output->buf + output->len ),
    166 		 ( input->buf + offset ), len );
    167 	output->len += len;
    168 	return 0;
    169 }
    170 
    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;
    178 
    179 	if ( ( offset + len ) > input->len ) {
    180 		fprintf ( stderr, "Input buffer overrun on pack\n" );
    181 		return -1;
    182 	}
    183 
    184 	output->len = align ( output->len, pack->align );
    185 	if ( output->len > output->max_len ) {
    186 		fprintf ( stderr, "Output buffer overrun on pack\n" );
    187 		return -1;
    188 	}
    189 
    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" );
    194 		return -1;
    195 	}
    196 
    197 	if ( DEBUG ) {
    198 		fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n",
    199 			  offset, ( offset + len ), output->len,
    200 			  ( size_t )( output->len + packed_len ) );
    201 	}
    202 
    203 	output->len += packed_len;
    204 	if ( output->len > output->max_len ) {
    205 		fprintf ( stderr, "Output buffer overrun on pack\n" );
    206 		return -1;
    207 	}
    208 
    209 	return 0;
    210 }
    211 
    212 static int process_zinfo_add ( struct input_file *input,
    213 			       struct output_file *output,
    214 			       struct zinfo_add *add,
    215 			       size_t datasize ) {
    216 	size_t offset = add->offset;
    217 	void *target;
    218 	signed long addend;
    219 	unsigned long size;
    220 	signed long val;
    221 	unsigned long mask;
    222 
    223 	if ( ( offset + datasize ) > output->len ) {
    224 		fprintf ( stderr, "Add at %#zx outside output buffer\n",
    225 			  offset );
    226 		return -1;
    227 	}
    228 
    229 	target = ( output->buf + offset );
    230 	size = ( align ( output->len, add->divisor ) / add->divisor );
    231 
    232 	switch ( datasize ) {
    233 	case 1:
    234 		addend = *( ( int8_t * ) target );
    235 		break;
    236 	case 2:
    237 		addend = *( ( int16_t * ) target );
    238 		break;
    239 	case 4:
    240 		addend = *( ( int32_t * ) target );
    241 		break;
    242 	default:
    243 		fprintf ( stderr, "Unsupported add datasize %zd\n",
    244 			  datasize );
    245 		return -1;
    246 	}
    247 
    248 	val = size + addend;
    249 
    250 	/* The result of 1UL << ( 8 * sizeof(unsigned long) ) is undefined */
    251 	mask = ( ( datasize < sizeof ( mask ) ) ?
    252 		 ( ( 1UL << ( 8 * datasize ) ) - 1 ) : ~0UL );
    253 
    254 	if ( val < 0 ) {
    255 		fprintf ( stderr, "Add %s%#x+%#lx at %#zx %sflows field\n",
    256 			  ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
    257 			  offset, ( ( addend < 0 ) ? "under" : "over" ) );
    258 		return -1;
    259 	}
    260 
    261 	if ( val & ~mask ) {
    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,
    265 			  offset, datasize,
    266 			  ( int )( ( val - mask - 1 ) * add->divisor ) );
    267 		return -1;
    268 	}
    269 
    270 	switch ( datasize ) {
    271 	case 1:
    272 		*( ( uint8_t * ) target ) = val;
    273 		break;
    274 	case 2:
    275 		*( ( uint16_t * ) target ) = val;
    276 		break;
    277 	case 4:
    278 		*( ( uint32_t * ) target ) = val;
    279 		break;
    280 	}
    281 
    282 	if ( DEBUG ) {
    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 );
    287 	}
    288 
    289 	return 0;
    290 }
    291 
    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 );
    296 }
    297 
    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 );
    302 }
    303 
    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 );
    308 }
    309 
    310 struct zinfo_processor {
    311 	char *type;
    312 	int ( * process ) ( struct input_file *input,
    313 			    struct output_file *output,
    314 			    union zinfo_record *zinfo );
    315 };
    316 
    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 },
    323 };
    324 
    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 ] = "";
    331 	unsigned int i;
    332 
    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 );
    339 	}
    340 
    341 	fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] );
    342 	return -1;
    343 }
    344 
    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 ) );
    349 		return -1;
    350 	}
    351 	return 0;
    352 }
    353 
    354 int main ( int argc, char **argv ) {
    355 	struct input_file input;
    356 	struct output_file output;
    357 	struct zinfo_file zinfo;
    358 	unsigned int i;
    359 
    360 	if ( argc != 3 ) {
    361 		fprintf ( stderr, "Syntax: %s file.bin file.zinfo "
    362 			  "> file.zbin\n", argv[0] );
    363 		exit ( 1 );
    364 	}
    365 
    366 	if ( read_input_file ( argv[1], &input ) < 0 )
    367 		exit ( 1 );
    368 	if ( read_zinfo_file ( argv[2], &zinfo ) < 0 )
    369 		exit ( 1 );
    370 	if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 )
    371 		exit ( 1 );
    372 
    373 	for ( i = 0 ; i < zinfo.num_entries ; i++ ) {
    374 		if ( process_zinfo ( &input, &output,
    375 				     &zinfo.zinfo[i] ) < 0 )
    376 			exit ( 1 );
    377 	}
    378 
    379 	if ( write_output_file ( &output ) < 0 )
    380 		exit ( 1 );
    381 
    382 	return 0;
    383 }
    384