david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Compressed ROM images now work.

This commit is contained in:
Michael Brown 2007-07-16 16:58:38 +01:00
parent 37fa9a8706
commit 048bbeeebc
9 changed files with 439 additions and 11 deletions

View File

@ -90,6 +90,7 @@ MKCONFIG ?= $(PERL) ./util/mkconfig.pl
SYMCHECK ?= $(PERL) ./util/symcheck.pl
SORTOBJDUMP ?= $(PERL) ./util/sortobjdump.pl
NRV2B ?= ./util/nrv2b
ZBIN ?= ./util/zbin
DOXYGEN ?= doxygen
# Location to place generated files

View File

@ -307,11 +307,23 @@ $(BIN)/%.tmp : $(BLIB) $(MAKEDEPS) $(LDSCRIPT)
$(BIN)/%.map : $(BIN)/%.tmp
@less $(BIN)/$*.tmp.map
# Extract compression information from intermediate object file
#
$(BIN)/%.zinfo : $(BIN)/%.tmp
$(QM)echo " [ZINFO] $@"
$(Q)$(OBJCOPY) -O binary -j .zinfo $< $@
# Build raw binary file from intermediate object file
#
$(BIN)/%.bin : $(BIN)/%.tmp
$(QM)echo " [BIN] $@"
$(Q)$(OBJCOPY) -O binary $< $@
$(Q)$(OBJCOPY) -O binary -R .zinfo $< $@
# Compress raw binary file
#
$(BIN)/%.zbin : $(BIN)/%.bin $(BIN)/%.zinfo $(ZBIN)
$(QM)echo " [ZBIN] $@"
$(Q)$(ZBIN) $(BIN)/$*.bin $(BIN)/$*.zinfo > $@
# Build bochs symbol table
$(BIN)/%.bxs : $(BIN)/%.tmp
@ -356,7 +368,7 @@ define media_template
@$(MKDIR) -p $(dir $(2))
@$(RM) $(2)
@$(TOUCH) $(2)
@echo -e '$$(BIN)/%$(1) : $$(BIN)/%$(1).bin' \
@echo -e '$$(BIN)/%$(1) : $$(BIN)/%$(1).zbin' \
'\n\t$$(QM)echo " [FINISH] $$@"' \
'\n\t$$(Q)$$(CP) $$< $$@' \
'\n\t$$(Q)$$(FINALISE_$(1))' \
@ -383,13 +395,19 @@ include $(MEDIA_DEPS)
allroms allzroms : all%s : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).%)
all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%)
# The compressor utility
# The compression utilities
#
$(NRV2B) : util/nrv2b.c $(MAKEDEPS)
$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG \
$(QM)echo " [HOSTCC] $@"
$(Q)$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG \
-DBITSIZE=32 -DENDIAN=0 -o $@ $<
CLEANUP += $(NRV2B)
$(ZBIN) : util/zbin.c util/nrv2b.c $(MAKEDEPS)
$(QM)echo " [HOSTCC] $@"
$(Q)$(HOST_CC) -O2 -o $@ $<
CLEANUP += $(ZBIN)
# Auto-incrementing build serial number. Append "bs" to your list of
# build targets to get a serial number printed at the end of the
# build. Enable -DBUILD_SERIAL in order to see it when the code runs.

View File

@ -37,6 +37,9 @@
*/
#define HIGHMEM_LOADPOINT ( 4 << 20 )
/* Image compression enabled */
#define COMPRESS 1
#define CR0_PE 1
.arch i386
@ -81,7 +84,11 @@ install_block:
/* Do the copy */
cld
rep addr32 movsb /* or "call decompress16" */
#if COMPRESS
call decompress16
#else
call nodecompress16
#endif
/* Zero remaining space */
movl %eax, %edi

View File

@ -0,0 +1,18 @@
/* Placeholder for decompress16 in non-compressed images */
.text
.arch i386
.section ".prefix.lib", "ax", @progbits
.code16
.globl nodecompress16
nodecompress16:
rep addr32 movsb
ret
/* File split information for the compressor */
.section ".zinfo", "a"
.ascii "COPY"
.long _prefix_load_offset
.long _load_size
.long _max_align

View File

@ -14,7 +14,7 @@
.org 0x00
romheader:
.word 0xAA55 /* BIOS extension signature */
.byte _rom_size /* Size in 512-byte blocks */
romheader_size: .byte _rom_size /* Size in 512-byte blocks */
jmp init_vector /* Initialisation vector */
.org 0x16
.word undiheader
@ -34,7 +34,7 @@ pciheader:
.byte 0x02 /* Device Base Type code */
.byte 0x00 /* Device Sub-Type code */
.byte 0x00 /* Device Interface Type code */
.word _rom_size /* Image length same as offset 02h */
pciheader_size: .word _rom_size /* Image length same as offset 02h */
.word 0x0001 /* revision level of code/data */
.byte 0x00 /* code type */
.byte 0x80 /* Flags (last PCI data structure) */
@ -215,3 +215,15 @@ print_message:
popw %ax
ret
.size print_message, . - print_message
/* Data update information for the compressor */
.section ".zinfo.fixup", "a"
.ascii "SUBB"
.long romheader_size
.long 512
.long 0
.ascii "SUBW"
.long pciheader_size
.long 512
.long 0

View File

@ -35,7 +35,7 @@
.text
.arch i386
.section ".prefix", "ax", @progbits
.section ".prefix.lib", "ax", @progbits
#ifdef CODE16
/****************************************************************************
@ -54,6 +54,7 @@
* NOTE: It would be possible to build a smaller version of the
* decompression code for -DKEEP_IT_REAL by using
* #define REG(x) x
* #define MOVSB movsb
* to use 16-bit registers where possible. This would impose limits
* that the compressed data size must be in the range [1,65533-%si]
* and the uncompressed data size must be in the range [1,65536-%di]
@ -66,6 +67,7 @@
*/
#define REG(x) e ## x
#define MOVSB addr32 movsb
.code16
.globl decompress16
@ -109,11 +111,10 @@ decompress:
cld
xor %xBP, %xBP
dec %xBP /* last_m_off = -1 */
add $4, %xSI /* Skip "file length" field */
jmp dcl1_n2b
decompr_literals_n2b:
movsb
MOVSB
decompr_loop_n2b:
addl %ebx, %ebx
jnz dcl2_n2b
@ -157,7 +158,7 @@ decompr_got_mlen_n2b:
push %xSI
lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
rep
es movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
es MOVSB /* dst[olen++] = *m_pos++ while(m_len > 0) */
pop %xSI
jmp decompr_loop_n2b
@ -179,3 +180,23 @@ decompr_end_n2b:
popl %ebx
pop %xAX
ret
/* File split information for the compressor */
.section ".zinfo", "a"
.ascii "COPY"
.long _prefix_load_offset
.long _prefix_progbits_size
.long _max_align
.ascii "PACK"
.long _text16_load_offset
.long _text16_progbits_size
.long _max_align
.ascii "PACK"
.long _data16_load_offset
.long _data16_progbits_size
.long _max_align
.ascii "PACK"
.long _textdata_load_offset
.long _textdata_progbits_size
.long _max_align

View File

@ -164,6 +164,24 @@ SECTIONS {
_end = .;
/*
* Compressor information block
*/
_zinfo_link_addr = 0;
. = _zinfo_link_addr;
_zinfo = .;
.zinfo : AT ( _zinfo_load_offset + __zinfo ) {
__zinfo = .;
_entry = .;
*(.zinfo)
*(.zinfo.*)
_ezinfo_progbits = .;
}
_ezinfo = .;
/*
* Dispose of the comment and note sections to make the link map
* easier to read
@ -215,6 +233,13 @@ SECTIONS {
_load_size = . - _load_addr;
. -= _zinfo_link_addr;
_zinfo_load_offset = ALIGN ( _max_align );
_zinfo_load_addr = _zinfo_link_addr + _zinfo_load_offset;
_zinfo_size = _ezinfo - _zinfo;
_zinfo_progbits_size = _ezinfo_progbits - _zinfo;
. = _zinfo_load_addr + _zinfo_progbits_size;
_payload_offset = _text16_load_offset;
/*

1
src/util/.gitignore vendored
View File

@ -1,3 +1,4 @@
nrv2b
zbin
hijack
prototester

325
src/util/zbin.c Normal file
View File

@ -0,0 +1,325 @@
#include <stdio.h>
#include <sys/stat.h>
#define ENCODE
#define VERBOSE
#include "nrv2b.c"
FILE *infile, *outfile;
struct input_file {
void *buf;
size_t len;
};
struct output_file {
void *buf;
size_t 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_subtract {
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_subtract subtract;
};
struct zinfo_file {
union zinfo_record *zinfo;
unsigned int num_entries;
};
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() %d bytes for %s: %s\n",
*len, filename, strerror ( errno ) );
goto err;
}
if ( fread ( *buf, 1, *len, file ) != *len ) {
fprintf ( stderr, "Could not read %d bytes from %s: %s\n",
*len, filename, strerror ( errno ) );
goto err;
}
fclose ( file );
return 0;
err:
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 %d\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 %d bytes for output\n",
max_len );
return -1;
}
memset ( output->buf, 0xff, sizeof ( output->buf ) );
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;
unsigned int align = copy->align;
if ( ( offset + len ) > input->len ) {
fprintf ( stderr, "Input buffer overrun on copy\n" );
return -1;
}
output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
if ( ( output->len + len ) > output->max_len ) {
fprintf ( stderr, "Output buffer overrun on copy\n" );
return -1;
}
memcpy ( ( output->buf + output->len ),
( input->buf + offset ), len );
output->len += len;
return 0;
}
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;
unsigned int align = pack->align;
unsigned long packed_len;
if ( ( offset + len ) > input->len ) {
fprintf ( stderr, "Input buffer overrun on pack\n" );
return -1;
}
output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
if ( output->len > output->max_len ) {
fprintf ( stderr, "Output buffer overrun on pack\n" );
return -1;
}
if ( ucl_nrv2b_99_compress ( ( input->buf + offset ), len,
( output->buf + output->len ),
&packed_len, 0 ) != UCL_E_OK ) {
fprintf ( stderr, "Compression failure\n" );
return -1;
}
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_subtract ( struct input_file *input,
struct output_file *output,
struct zinfo_subtract *subtract,
size_t datasize ) {
size_t offset = subtract->offset;
void *target;
long delta;
if ( ( offset + datasize ) > output->len ) {
fprintf ( stderr, "Subtract at %#zx outside output buffer\n",
offset );
return -1;
}
target = ( output->buf + offset );
delta = ( ( output->len / subtract->divisor ) -
( input->len / subtract->divisor ) );
switch ( datasize ) {
case 1: {
uint8_t *byte = target;
*byte += delta;
break; }
case 2: {
uint16_t *word = target;
*word += delta;
break; }
case 4: {
uint32_t *dword = target;
*dword += delta;
break; }
default:
fprintf ( stderr, "Unsupported subtract datasize %d\n",
datasize );
return -1;
}
return 0;
}
static int process_zinfo_subb ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_subtract ( input, output, &zinfo->subtract, 1 );
}
static int process_zinfo_subw ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_subtract ( input, output, &zinfo->subtract, 2 );
}
static int process_zinfo_subl ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_subtract ( input, output, &zinfo->subtract, 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 },
{ "SUBB", process_zinfo_subb },
{ "SUBW", process_zinfo_subw },
{ "SUBL", process_zinfo_subl },
};
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 %d 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;
}