diff options
Diffstat (limited to 'qemu/roms/ipxe/src/util/zbin.c')
-rw-r--r-- | qemu/roms/ipxe/src/util/zbin.c | 567 |
1 files changed, 0 insertions, 567 deletions
diff --git a/qemu/roms/ipxe/src/util/zbin.c b/qemu/roms/ipxe/src/util/zbin.c deleted file mode 100644 index 1862a3827..000000000 --- a/qemu/roms/ipxe/src/util/zbin.c +++ /dev/null @@ -1,567 +0,0 @@ -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/stat.h> -#include <lzma.h> - -#define DEBUG 0 - -/* LZMA filter choices. Must match those used by unlzma.S */ -#define LZMA_LC 2 -#define LZMA_LP 0 -#define LZMA_PB 0 - -/* LZMA preset choice. This is a policy decision */ -#define LZMA_PRESET ( LZMA_PRESET_DEFAULT | LZMA_PRESET_EXTREME ) - -struct input_file { - void *buf; - size_t len; -}; - -struct output_file { - void *buf; - size_t len; - size_t hdr_len; - size_t max_len; -}; - -struct zinfo_common { - char type[4]; - char pad[12]; -}; - -struct zinfo_copy { - char type[4]; - uint32_t offset; - uint32_t len; - uint32_t align; -}; - -struct zinfo_pack { - char type[4]; - uint32_t offset; - uint32_t len; - uint32_t align; -}; - -struct zinfo_payload { - char type[4]; - uint32_t pad1; - uint32_t pad2; - uint32_t align; -}; - -struct zinfo_add { - char type[4]; - uint32_t offset; - uint32_t divisor; - uint32_t pad; -}; - -union zinfo_record { - struct zinfo_common common; - struct zinfo_copy copy; - struct zinfo_pack pack; - struct zinfo_payload payload; - struct zinfo_add add; -}; - -struct zinfo_file { - union zinfo_record *zinfo; - unsigned int num_entries; -}; - -static unsigned long align ( unsigned long value, unsigned long align ) { - return ( ( value + align - 1 ) & ~( align - 1 ) ); -} - -static int read_file ( const char *filename, void **buf, size_t *len ) { - FILE *file; - struct stat stat; - - file = fopen ( filename, "r" ); - if ( ! file ) { - fprintf ( stderr, "Could not open %s: %s\n", filename, - strerror ( errno ) ); - goto err; - } - - if ( fstat ( fileno ( file ), &stat ) < 0 ) { - fprintf ( stderr, "Could not stat %s: %s\n", filename, - strerror ( errno ) ); - goto err; - } - - *len = stat.st_size; - *buf = malloc ( *len ); - if ( ! *buf ) { - fprintf ( stderr, "Could not malloc() %zd bytes for %s: %s\n", - *len, filename, strerror ( errno ) ); - goto err; - } - - if ( fread ( *buf, 1, *len, file ) != *len ) { - fprintf ( stderr, "Could not read %zd bytes from %s: %s\n", - *len, filename, strerror ( errno ) ); - goto err; - } - - fclose ( file ); - return 0; - - err: - if ( file ) - fclose ( file ); - return -1; -} - -static int read_input_file ( const char *filename, - struct input_file *input ) { - return read_file ( filename, &input->buf, &input->len ); -} - -static int read_zinfo_file ( const char *filename, - struct zinfo_file *zinfo ) { - void *buf; - size_t len; - - if ( read_file ( filename, &buf, &len ) < 0 ) - return -1; - - if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) { - fprintf ( stderr, ".zinfo file %s has invalid length %zd\n", - filename, len ); - return -1; - } - - zinfo->zinfo = buf; - zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) ); - return 0; -} - -static int alloc_output_file ( size_t max_len, struct output_file *output ) { - output->len = 0; - output->max_len = ( max_len ); - output->buf = malloc ( max_len ); - if ( ! output->buf ) { - fprintf ( stderr, "Could not allocate %zd bytes for output\n", - max_len ); - return -1; - } - memset ( output->buf, 0xff, max_len ); - return 0; -} - -static int process_zinfo_copy ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - struct zinfo_copy *copy = &zinfo->copy; - size_t offset = copy->offset; - size_t len = copy->len; - - if ( ( offset + len ) > input->len ) { - fprintf ( stderr, "Input buffer overrun on copy\n" ); - return -1; - } - - output->len = align ( output->len, copy->align ); - if ( ( output->len + len ) > output->max_len ) { - fprintf ( stderr, "Output buffer overrun on copy\n" ); - return -1; - } - - if ( DEBUG ) { - fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n", - offset, ( offset + len ), output->len, - ( output->len + len ) ); - } - - memcpy ( ( output->buf + output->len ), - ( input->buf + offset ), len ); - output->len += len; - return 0; -} - -#define OPCODE_CALL 0xe8 -#define OPCODE_JMP 0xe9 - -static void bcj_filter ( void *data, size_t len ) { - struct { - uint8_t opcode; - int32_t target; - } __attribute__ (( packed )) *jump; - ssize_t limit = ( len - sizeof ( *jump ) ); - ssize_t offset; - - /* liblzma does include an x86 BCJ filter, but it's hideously - * convoluted and undocumented. This BCJ filter is - * substantially simpler and achieves the same compression (at - * the cost of requiring the decompressor to know the size of - * the decompressed data, which we already have in iPXE). - */ - for ( offset = 0 ; offset <= limit ; offset++ ) { - jump = ( data + offset ); - - /* Skip instructions that are not followed by a rel32 address */ - if ( ( jump->opcode != OPCODE_CALL ) && - ( jump->opcode != OPCODE_JMP ) ) - continue; - - /* Convert rel32 address to an absolute address. To - * avoid false positives (which damage the compression - * ratio), we should check that the jump target is - * within the range [0,limit). - * - * Some output values would then end up being mapped - * from two distinct input values, making the - * transformation irreversible. To solve this, we - * transform such values back into the part of the - * range which would otherwise correspond to no input - * values. - */ - if ( ( jump->target >= -offset ) && - ( jump->target < ( limit - offset ) ) ) { - /* Convert relative addresses in the range - * [-offset,limit-offset) to absolute - * addresses in the range [0,limit). - */ - jump->target += offset; - } else if ( ( jump->target >= ( limit - offset ) ) && - ( jump->target < limit ) ) { - /* Convert positive numbers in the range - * [limit-offset,limit) to negative numbers in - * the range [-offset,0). - */ - jump->target -= limit; - } - offset += sizeof ( jump->target ); - }; -} - -static int process_zinfo_pack ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - struct zinfo_pack *pack = &zinfo->pack; - size_t offset = pack->offset; - size_t len = pack->len; - size_t packed_len = 0; - size_t remaining = ( output->max_len - output->len ); - lzma_options_lzma options; - const lzma_filter filters[] = { - { .id = LZMA_FILTER_LZMA1, .options = &options }, - { .id = LZMA_VLI_UNKNOWN } - }; - - if ( ( offset + len ) > input->len ) { - fprintf ( stderr, "Input buffer overrun on pack\n" ); - return -1; - } - - output->len = align ( output->len, pack->align ); - if ( output->len > output->max_len ) { - fprintf ( stderr, "Output buffer overrun on pack\n" ); - return -1; - } - - bcj_filter ( ( input->buf + offset ), len ); - - lzma_lzma_preset ( &options, LZMA_PRESET ); - options.lc = LZMA_LC; - options.lp = LZMA_LP; - options.pb = LZMA_PB; - if ( lzma_raw_buffer_encode ( filters, NULL, ( input->buf + offset ), - len, ( output->buf + output->len ), - &packed_len, remaining ) != LZMA_OK ) { - fprintf ( stderr, "Compression failure\n" ); - return -1; - } - - if ( DEBUG ) { - fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n", - offset, ( offset + len ), output->len, - ( output->len + packed_len ) ); - } - - output->len += packed_len; - if ( output->len > output->max_len ) { - fprintf ( stderr, "Output buffer overrun on pack\n" ); - return -1; - } - - return 0; -} - -static int process_zinfo_payl ( struct input_file *input - __attribute__ (( unused )), - struct output_file *output, - union zinfo_record *zinfo ) { - struct zinfo_payload *payload = &zinfo->payload; - - output->len = align ( output->len, payload->align ); - output->hdr_len = output->len; - - if ( DEBUG ) { - fprintf ( stderr, "PAYL at %#zx\n", output->hdr_len ); - } - return 0; -} - -static int process_zinfo_add ( struct input_file *input - __attribute__ (( unused )), - struct output_file *output, - size_t len, - struct zinfo_add *add, size_t offset, - size_t datasize ) { - void *target; - signed long addend; - unsigned long size; - signed long val; - unsigned long mask; - - offset += add->offset; - if ( ( offset + datasize ) > output->len ) { - fprintf ( stderr, "Add at %#zx outside output buffer\n", - offset ); - return -1; - } - - target = ( output->buf + offset ); - size = ( align ( len, add->divisor ) / add->divisor ); - - switch ( datasize ) { - case 1: - addend = *( ( int8_t * ) target ); - break; - case 2: - addend = *( ( int16_t * ) target ); - break; - case 4: - addend = *( ( int32_t * ) target ); - break; - default: - fprintf ( stderr, "Unsupported add datasize %zd\n", - datasize ); - return -1; - } - - val = size + addend; - - /* The result of 1UL << ( 8 * sizeof(unsigned long) ) is undefined */ - mask = ( ( datasize < sizeof ( mask ) ) ? - ( ( 1UL << ( 8 * datasize ) ) - 1 ) : ~0UL ); - - if ( val < 0 ) { - fprintf ( stderr, "Add %s%#x+%#lx at %#zx %sflows field\n", - ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size, - offset, ( ( addend < 0 ) ? "under" : "over" ) ); - return -1; - } - - if ( val & ~mask ) { - fprintf ( stderr, "Add %s%#x+%#lx at %#zx overflows %zd-byte " - "field (%d bytes too big)\n", - ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size, - offset, datasize, - ( int )( ( val - mask - 1 ) * add->divisor ) ); - return -1; - } - - switch ( datasize ) { - case 1: - *( ( uint8_t * ) target ) = val; - break; - case 2: - *( ( uint16_t * ) target ) = val; - break; - case 4: - *( ( uint32_t * ) target ) = val; - break; - } - - if ( DEBUG ) { - fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#x+(%#zx/%#x)) = " - "%#lx\n", offset, ( offset + datasize ), - ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), - len, add->divisor, val ); - } - - return 0; -} - -static int process_zinfo_addb ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, output->len, - &zinfo->add, 0, 1 ); -} - -static int process_zinfo_addw ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, output->len, - &zinfo->add, 0, 2 ); -} - -static int process_zinfo_addl ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, output->len, - &zinfo->add, 0, 4 ); -} - -static int process_zinfo_adhb ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, output->hdr_len, - &zinfo->add, 0, 1 ); -} - -static int process_zinfo_adhw ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, output->hdr_len, - &zinfo->add, 0, 2 ); -} - -static int process_zinfo_adhl ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, output->hdr_len, - &zinfo->add, 0, 4 ); -} - -static int process_zinfo_adpb ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, - ( output->len - output->hdr_len ), - &zinfo->add, 0, 1 ); -} - -static int process_zinfo_adpw ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, - ( output->len - output->hdr_len ), - &zinfo->add, 0, 2 ); -} - -static int process_zinfo_adpl ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, - ( output->len - output->hdr_len ), - &zinfo->add, 0, 4 ); -} - -static int process_zinfo_appb ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, - ( output->len - output->hdr_len ), - &zinfo->add, output->hdr_len, 1 ); -} - -static int process_zinfo_appw ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, - ( output->len - output->hdr_len ), - &zinfo->add, output->hdr_len, 2 ); -} - -static int process_zinfo_appl ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - return process_zinfo_add ( input, output, - ( output->len - output->hdr_len ), - &zinfo->add, output->hdr_len, 4 ); -} - -struct zinfo_processor { - char *type; - int ( * process ) ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ); -}; - -static struct zinfo_processor zinfo_processors[] = { - { "COPY", process_zinfo_copy }, - { "PACK", process_zinfo_pack }, - { "PAYL", process_zinfo_payl }, - { "ADDB", process_zinfo_addb }, - { "ADDW", process_zinfo_addw }, - { "ADDL", process_zinfo_addl }, - { "ADHB", process_zinfo_adhb }, - { "ADHW", process_zinfo_adhw }, - { "ADHL", process_zinfo_adhl }, - { "ADPB", process_zinfo_adpb }, - { "ADPW", process_zinfo_adpw }, - { "ADPL", process_zinfo_adpl }, - { "APPB", process_zinfo_appb }, - { "APPW", process_zinfo_appw }, - { "APPL", process_zinfo_appl }, -}; - -static int process_zinfo ( struct input_file *input, - struct output_file *output, - union zinfo_record *zinfo ) { - struct zinfo_common *common = &zinfo->common; - struct zinfo_processor *processor; - char type[ sizeof ( common->type ) + 1 ] = ""; - unsigned int i; - - strncat ( type, common->type, sizeof ( type ) - 1 ); - for ( i = 0 ; i < ( sizeof ( zinfo_processors ) / - sizeof ( zinfo_processors[0] ) ) ; i++ ) { - processor = &zinfo_processors[i]; - if ( strcmp ( processor->type, type ) == 0 ) - return processor->process ( input, output, zinfo ); - } - - fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] ); - return -1; -} - -static int write_output_file ( struct output_file *output ) { - if ( fwrite ( output->buf, 1, output->len, stdout ) != output->len ) { - fprintf ( stderr, "Could not write %zd bytes of output: %s\n", - output->len, strerror ( errno ) ); - return -1; - } - return 0; -} - -int main ( int argc, char **argv ) { - struct input_file input; - struct output_file output; - struct zinfo_file zinfo; - unsigned int i; - - if ( argc != 3 ) { - fprintf ( stderr, "Syntax: %s file.bin file.zinfo " - "> file.zbin\n", argv[0] ); - exit ( 1 ); - } - - if ( read_input_file ( argv[1], &input ) < 0 ) - exit ( 1 ); - if ( read_zinfo_file ( argv[2], &zinfo ) < 0 ) - exit ( 1 ); - if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 ) - exit ( 1 ); - - for ( i = 0 ; i < zinfo.num_entries ; i++ ) { - if ( process_zinfo ( &input, &output, - &zinfo.zinfo[i] ) < 0 ) - exit ( 1 ); - } - - if ( write_output_file ( &output ) < 0 ) - exit ( 1 ); - - return 0; -} |