diff --git a/src/arch/i386/prefix/dskprefix.S b/src/arch/i386/prefix/dskprefix.S index 2716a16b..60d351f7 100644 --- a/src/arch/i386/prefix/dskprefix.S +++ b/src/arch/i386/prefix/dskprefix.S @@ -146,9 +146,9 @@ got_sectors: /* Jump to loaded copy */ ljmp $SYSSEG, $start_runtime -endseg: .word SYSSEG + _filesz_pgh +endseg: .word SYSSEG .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "SUBW" + .ascii "ADDW" .long endseg .long 16 .long 0 diff --git a/src/arch/i386/prefix/hdprefix.S b/src/arch/i386/prefix/hdprefix.S index a06f10c3..05767567 100644 --- a/src/arch/i386/prefix/hdprefix.S +++ b/src/arch/i386/prefix/hdprefix.S @@ -65,10 +65,10 @@ max_sector: max_head: .byte 0 load_length: - .long _filesz_sect + .long 0 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "SUBL" + .ascii "ADDL" .long load_length .long 512 .long 0 diff --git a/src/arch/i386/prefix/lkrnprefix.S b/src/arch/i386/prefix/lkrnprefix.S index 02249f7a..101d0388 100644 --- a/src/arch/i386/prefix/lkrnprefix.S +++ b/src/arch/i386/prefix/lkrnprefix.S @@ -94,10 +94,10 @@ setup_sects: root_flags: .word 0 syssize: - .long _filesz_pgh - PREFIXPGH + .long -PREFIXPGH .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "SUBL" + .ascii "ADDL" .long syssize .long 16 .long 0 diff --git a/src/arch/i386/prefix/nbiprefix.S b/src/arch/i386/prefix/nbiprefix.S index 4fb4acb1..607d80fb 100644 --- a/src/arch/i386/prefix/nbiprefix.S +++ b/src/arch/i386/prefix/nbiprefix.S @@ -30,16 +30,16 @@ segment_header: .byte 0 .byte 0x04 /* Last segment */ .long 0x00007e00 -imglen: .long _filesz - 512 -memlen: .long _filesz - 512 +imglen: .long -512 +memlen: .long -512 .size segment_header, . - segment_header .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "SUBL" + .ascii "ADDL" .long imglen .long 1 .long 0 - .ascii "SUBL" + .ascii "ADDL" .long memlen .long 1 .long 0 diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index 4b9d5447..cb474e81 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -33,7 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ) .org 0x00 romheader: .word 0xAA55 /* BIOS extension signature */ -romheader_size: .byte _filesz_sect /* Size in 512-byte blocks */ +romheader_size: .byte 0 /* Size in 512-byte blocks */ jmp init /* Initialisation vector */ checksum: .byte 0 @@ -46,7 +46,7 @@ checksum: .size romheader, . - romheader .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "SUBB" + .ascii "ADDB" .long romheader_size .long 512 .long 0 @@ -61,23 +61,23 @@ pciheader: .byte 0x03 /* PCI data structure revision */ .byte 0x02, 0x00, 0x00 /* Class code */ pciheader_image_length: - .word _filesz_sect /* Image length */ + .word 0 /* Image length */ .word 0x0001 /* Revision level */ .byte 0x00 /* Code type */ .byte 0x80 /* Last image indicator */ pciheader_runtime_length: - .word _filesz_sect /* Maximum run-time image length */ + .word 0 /* Maximum run-time image length */ .word 0x0000 /* Configuration utility code header */ .word 0x0000 /* DMTF CLP entry point */ .equ pciheader_len, . - pciheader .size pciheader, . - pciheader .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "SUBW" + .ascii "ADDW" .long pciheader_image_length .long 512 .long 0 - .ascii "SUBW" + .ascii "ADDW" .long pciheader_runtime_length .long 512 .long 0 diff --git a/src/arch/i386/scripts/i386.lds b/src/arch/i386/scripts/i386.lds index 8a0c6733..52f8eb4b 100644 --- a/src/arch/i386/scripts/i386.lds +++ b/src/arch/i386/scripts/i386.lds @@ -197,13 +197,4 @@ SECTIONS { _prefix_memsz_sect = ( ( _prefix_memsz + 511 ) / 512 ); _text16_memsz_pgh = ( ( _text16_memsz + 15 ) / 16 ); _data16_memsz_pgh = ( ( _data16_memsz + 15 ) / 16 ); - - /* - * File size in paragraphs and sectors. Note that wherever the - * _filesz variables are used, there must be a corresponding - * .zinfo.fixup section. - * - */ - _filesz_pgh = ( ( _filesz + 15 ) / 16 ); - _filesz_sect = ( ( _filesz + 511 ) / 512 ); } diff --git a/src/util/zbin.c b/src/util/zbin.c index 1513289e..2adc35c9 100644 --- a/src/util/zbin.c +++ b/src/util/zbin.c @@ -38,7 +38,7 @@ struct zinfo_pack { uint32_t align; }; -struct zinfo_subtract { +struct zinfo_add { char type[4]; uint32_t offset; uint32_t divisor; @@ -49,7 +49,7 @@ union zinfo_record { struct zinfo_common common; struct zinfo_copy copy; struct zinfo_pack pack; - struct zinfo_subtract subtract; + struct zinfo_add add; }; struct zinfo_file { @@ -157,8 +157,9 @@ static int process_zinfo_copy ( struct input_file *input, } if ( DEBUG ) { - fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n", offset, ( offset + len ), - output->len, ( output->len + len ) ); + fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n", + offset, ( offset + len ), output->len, + ( output->len + len ) ); } memcpy ( ( output->buf + output->len ), @@ -194,8 +195,9 @@ static int process_zinfo_pack ( struct input_file *input, } if ( DEBUG ) { - fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n", offset, ( offset + len ), - output->len, ( output->len + packed_len ) ); + fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n", + offset, ( offset + len ), output->len, + ( output->len + packed_len ) ); } output->len += packed_len; @@ -207,78 +209,102 @@ static int process_zinfo_pack ( struct input_file *input, return 0; } -static int process_zinfo_subtract ( struct input_file *input, - struct output_file *output, - struct zinfo_subtract *subtract, - size_t datasize ) { - size_t offset = subtract->offset; +static int process_zinfo_add ( struct input_file *input, + struct output_file *output, + struct zinfo_add *add, + size_t datasize ) { + size_t offset = add->offset; void *target; - signed long raw_delta; - signed long delta; - unsigned long old; - unsigned long new; + signed long addend; + unsigned long size; + signed long val; + unsigned long mask; if ( ( offset + datasize ) > output->len ) { - fprintf ( stderr, "Subtract at %#zx outside output buffer\n", + fprintf ( stderr, "Add at %#zx outside output buffer\n", offset ); return -1; } target = ( output->buf + offset ); - raw_delta = ( align ( output->len, subtract->divisor ) - - align ( input->len, subtract->divisor ) ); - delta = ( raw_delta / ( ( signed long ) subtract->divisor ) ); + size = ( align ( output->len, add->divisor ) / add->divisor ); switch ( datasize ) { - case 1: { - uint8_t *byte = target; - old = *byte; - *byte += delta; - new = *byte; - break; } - case 2: { - uint16_t *word = target; - old = *word; - *word += delta; - new = *word; - break; } - case 4: { - uint32_t *dword = target; - old = *dword; - *dword += delta; - new = *dword; - break; } + 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 subtract datasize %d\n", + fprintf ( stderr, "Unsupported add datasize %d\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%#lx+%#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%#lx+%#lx at %#zx overflows %d-byte " + "field (%d bytes too big)\n", + ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size, + offset, datasize, + ( ( 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, "SUBx [%#zx,%#zx) (%#lx+(%#lx/%#x)-(%#lx/%#x)) = %#lx\n", - offset, ( offset + datasize ), old, output->len, subtract->divisor, - input->len, subtract->divisor, new ); + fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#lx+(%#lx/%#x)) = " + "%#lx\n", offset, ( offset + datasize ), + ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), + output->len, add->divisor, val ); } return 0; } -static int process_zinfo_subb ( struct input_file *input, +static int process_zinfo_addb ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { - return process_zinfo_subtract ( input, output, &zinfo->subtract, 1 ); + return process_zinfo_add ( input, output, &zinfo->add, 1 ); } -static int process_zinfo_subw ( struct input_file *input, +static int process_zinfo_addw ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { - return process_zinfo_subtract ( input, output, &zinfo->subtract, 2 ); + return process_zinfo_add ( input, output, &zinfo->add, 2 ); } -static int process_zinfo_subl ( struct input_file *input, +static int process_zinfo_addl ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { - return process_zinfo_subtract ( input, output, &zinfo->subtract, 4 ); + return process_zinfo_add ( input, output, &zinfo->add, 4 ); } struct zinfo_processor { @@ -291,9 +317,9 @@ struct zinfo_processor { static struct zinfo_processor zinfo_processors[] = { { "COPY", process_zinfo_copy }, { "PACK", process_zinfo_pack }, - { "SUBB", process_zinfo_subb }, - { "SUBW", process_zinfo_subw }, - { "SUBL", process_zinfo_subl }, + { "ADDB", process_zinfo_addb }, + { "ADDW", process_zinfo_addw }, + { "ADDL", process_zinfo_addl }, }; static int process_zinfo ( struct input_file *input,