Browse Source

Compressed ROM images now work.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
048bbeeebc

+ 1
- 0
src/Makefile View File

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

+ 22
- 4
src/Makefile.housekeeping View File

@@ -307,11 +307,23 @@ $(BIN)/%.tmp : $(BLIB) $(MAKEDEPS) $(LDSCRIPT)
307 307
 $(BIN)/%.map : $(BIN)/%.tmp
308 308
 	@less $(BIN)/$*.tmp.map
309 309
 
310
+# Extract compression information from intermediate object file
311
+#
312
+$(BIN)/%.zinfo : $(BIN)/%.tmp
313
+	$(QM)echo "  [ZINFO] $@"
314
+	$(Q)$(OBJCOPY) -O binary -j .zinfo $< $@
315
+
310 316
 # Build raw binary file from intermediate object file
311 317
 #
312 318
 $(BIN)/%.bin : $(BIN)/%.tmp
313 319
 	$(QM)echo "  [BIN] $@"
314
-	$(Q)$(OBJCOPY) -O binary $< $@
320
+	$(Q)$(OBJCOPY) -O binary -R .zinfo $< $@
321
+
322
+# Compress raw binary file
323
+#
324
+$(BIN)/%.zbin : $(BIN)/%.bin $(BIN)/%.zinfo $(ZBIN)
325
+	$(QM)echo "  [ZBIN] $@"
326
+	$(Q)$(ZBIN) $(BIN)/$*.bin $(BIN)/$*.zinfo > $@
315 327
 
316 328
 # Build bochs symbol table
317 329
 $(BIN)/%.bxs : $(BIN)/%.tmp
@@ -356,7 +368,7 @@ define media_template
356 368
 	@$(MKDIR) -p $(dir $(2))
357 369
 	@$(RM) $(2)
358 370
 	@$(TOUCH) $(2)
359
-	@echo -e '$$(BIN)/%$(1) : $$(BIN)/%$(1).bin' \
371
+	@echo -e '$$(BIN)/%$(1) : $$(BIN)/%$(1).zbin' \
360 372
 		  '\n\t$$(QM)echo "  [FINISH] $$@"' \
361 373
 		  '\n\t$$(Q)$$(CP) $$< $$@' \
362 374
 		  '\n\t$$(Q)$$(FINALISE_$(1))' \
@@ -383,13 +395,19 @@ include $(MEDIA_DEPS)
383 395
 allroms allzroms : all%s : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).%)
384 396
 all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%)
385 397
 
386
-# The compressor utility
398
+# The compression utilities
387 399
 #
388 400
 $(NRV2B) : util/nrv2b.c $(MAKEDEPS)
389
-	$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG \
401
+	$(QM)echo "  [HOSTCC] $@"
402
+	$(Q)$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG \
390 403
 		       -DBITSIZE=32 -DENDIAN=0 -o $@ $<
391 404
 CLEANUP	+= $(NRV2B)
392 405
 
406
+$(ZBIN) : util/zbin.c util/nrv2b.c $(MAKEDEPS)
407
+	$(QM)echo "  [HOSTCC] $@"
408
+	$(Q)$(HOST_CC) -O2 -o $@ $<
409
+CLEANUP += $(ZBIN)
410
+
393 411
 # Auto-incrementing build serial number.  Append "bs" to your list of
394 412
 # build targets to get a serial number printed at the end of the
395 413
 # build.  Enable -DBUILD_SERIAL in order to see it when the code runs.

+ 8
- 1
src/arch/i386/prefix/libprefix.S View File

@@ -37,6 +37,9 @@
37 37
  */
38 38
 #define HIGHMEM_LOADPOINT ( 4 << 20 )
39 39
 
40
+/* Image compression enabled */
41
+#define COMPRESS 1
42
+
40 43
 #define CR0_PE 1
41 44
 
42 45
 	.arch i386
@@ -81,7 +84,11 @@ install_block:
81 84
 	
82 85
 	/* Do the copy */
83 86
 	cld
84
-	rep addr32 movsb /* or "call decompress16" */
87
+#if COMPRESS
88
+	call	decompress16
89
+#else
90
+	call	nodecompress16
91
+#endif
85 92
 
86 93
 	/* Zero remaining space */
87 94
 	movl	%eax, %edi

+ 18
- 0
src/arch/i386/prefix/nonrv2b.S View File

@@ -0,0 +1,18 @@
1
+/* Placeholder for decompress16 in non-compressed images */
2
+
3
+	.text
4
+	.arch i386
5
+	.section ".prefix.lib", "ax", @progbits
6
+
7
+	.code16
8
+	.globl	nodecompress16
9
+nodecompress16:
10
+	rep addr32 movsb
11
+	ret
12
+
13
+	/* File split information for the compressor */
14
+	.section ".zinfo", "a"
15
+	.ascii	"COPY"
16
+	.long	_prefix_load_offset
17
+	.long	_load_size
18
+	.long	_max_align

+ 14
- 2
src/arch/i386/prefix/romprefix.S View File

@@ -14,7 +14,7 @@
14 14
 	.org	0x00
15 15
 romheader:
16 16
 	.word	0xAA55			/* BIOS extension signature */
17
-	.byte	_rom_size		/* Size in 512-byte blocks */
17
+romheader_size:	.byte	_rom_size	/* Size in 512-byte blocks */
18 18
 	jmp	init_vector		/* Initialisation vector */
19 19
 	.org	0x16
20 20
 	.word	undiheader
@@ -34,7 +34,7 @@ pciheader:
34 34
 	.byte	0x02			/* Device Base Type code */
35 35
 	.byte	0x00			/* Device Sub-Type code */
36 36
 	.byte	0x00			/* Device Interface Type code */
37
-	.word	_rom_size		/* Image length same as offset 02h */
37
+pciheader_size:	.word	_rom_size	/* Image length same as offset 02h */
38 38
 	.word	0x0001			/* revision level of code/data */
39 39
 	.byte	0x00			/* code type */
40 40
 	.byte	0x80			/* Flags (last PCI data structure) */
@@ -215,3 +215,15 @@ print_message:
215 215
 	popw	%ax
216 216
 	ret
217 217
 	.size print_message, . - print_message
218
+
219
+
220
+	/* Data update information for the compressor */
221
+	.section ".zinfo.fixup", "a"
222
+	.ascii	"SUBB"
223
+	.long	romheader_size
224
+	.long	512
225
+	.long	0
226
+	.ascii	"SUBW"
227
+	.long	pciheader_size
228
+	.long	512
229
+	.long	0

+ 25
- 4
src/arch/i386/prefix/unnrv2b.S View File

@@ -35,7 +35,7 @@
35 35
 
36 36
 	.text
37 37
 	.arch i386
38
-	.section ".prefix", "ax", @progbits
38
+	.section ".prefix.lib", "ax", @progbits
39 39
 
40 40
 #ifdef CODE16
41 41
 /****************************************************************************
@@ -54,6 +54,7 @@
54 54
  * NOTE: It would be possible to build a smaller version of the
55 55
  * decompression code for -DKEEP_IT_REAL by using
56 56
  *    #define REG(x) x
57
+ *    #define MOVSB movsb
57 58
  * to use 16-bit registers where possible.  This would impose limits
58 59
  * that the compressed data size must be in the range [1,65533-%si]
59 60
  * and the uncompressed data size must be in the range [1,65536-%di]
@@ -66,6 +67,7 @@
66 67
  */
67 68
 
68 69
 #define REG(x) e ## x
70
+#define MOVSB addr32 movsb
69 71
 
70 72
 	.code16
71 73
 	.globl	decompress16
@@ -109,11 +111,10 @@ decompress:
109 111
 	cld
110 112
 	xor	%xBP, %xBP
111 113
 	dec	%xBP		/* last_m_off = -1 */
112
-	add	$4, %xSI	/* Skip "file length" field */
113 114
 	jmp	dcl1_n2b
114 115
 	
115 116
 decompr_literals_n2b:
116
-	movsb
117
+	MOVSB
117 118
 decompr_loop_n2b:
118 119
 	addl	%ebx, %ebx
119 120
 	jnz	dcl2_n2b
@@ -157,7 +158,7 @@ decompr_got_mlen_n2b:
157 158
 	push	%xSI
158 159
 	lea	(%xBP,%xDI), %xSI	/* m_pos = dst + olen + -m_off  */
159 160
 	rep
160
-	es movsb		/* dst[olen++] = *m_pos++ while(m_len > 0) */
161
+	es MOVSB		/* dst[olen++] = *m_pos++ while(m_len > 0) */
161 162
 	pop	%xSI
162 163
 	jmp	decompr_loop_n2b
163 164
 
@@ -179,3 +180,23 @@ decompr_end_n2b:
179 180
 	popl	%ebx
180 181
 	pop	%xAX
181 182
 	ret
183
+
184
+
185
+	/* File split information for the compressor */
186
+	.section ".zinfo", "a"
187
+	.ascii	"COPY"
188
+	.long	_prefix_load_offset
189
+	.long	_prefix_progbits_size
190
+	.long	_max_align
191
+	.ascii	"PACK"
192
+	.long	_text16_load_offset
193
+	.long	_text16_progbits_size
194
+	.long	_max_align
195
+	.ascii	"PACK"
196
+	.long	_data16_load_offset
197
+	.long	_data16_progbits_size
198
+	.long	_max_align
199
+	.ascii	"PACK"
200
+	.long	_textdata_load_offset
201
+	.long	_textdata_progbits_size
202
+	.long	_max_align

+ 25
- 0
src/arch/i386/scripts/i386.lds View File

@@ -164,6 +164,24 @@ SECTIONS {
164 164
 
165 165
     _end = .;
166 166
 
167
+    /*
168
+     * Compressor information block
169
+     */
170
+
171
+    _zinfo_link_addr = 0;
172
+    . = _zinfo_link_addr;
173
+    _zinfo = .;
174
+
175
+    .zinfo : AT ( _zinfo_load_offset + __zinfo ) {
176
+	__zinfo = .;
177
+	_entry = .;
178
+	*(.zinfo)
179
+	*(.zinfo.*)
180
+	_ezinfo_progbits = .;
181
+    }
182
+    
183
+    _ezinfo = .;
184
+
167 185
     /*
168 186
      * Dispose of the comment and note sections to make the link map
169 187
      * easier to read
@@ -215,6 +233,13 @@ SECTIONS {
215 233
 
216 234
     _load_size		    = . - _load_addr;
217 235
 
236
+    .			   -= _zinfo_link_addr;
237
+    _zinfo_load_offset	    = ALIGN ( _max_align );
238
+    _zinfo_load_addr	    = _zinfo_link_addr + _zinfo_load_offset;
239
+    _zinfo_size		    = _ezinfo - _zinfo;
240
+    _zinfo_progbits_size    = _ezinfo_progbits - _zinfo;
241
+    .			    = _zinfo_load_addr + _zinfo_progbits_size;
242
+
218 243
     _payload_offset	    = _text16_load_offset;
219 244
 
220 245
     /*

+ 1
- 0
src/util/.gitignore View File

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

+ 325
- 0
src/util/zbin.c View File

@@ -0,0 +1,325 @@
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
+struct input_file {
10
+	void *buf;
11
+	size_t len;
12
+};
13
+
14
+struct output_file {
15
+	void *buf;
16
+	size_t len;
17
+	size_t max_len;
18
+};
19
+
20
+struct zinfo_common {
21
+	char type[4];
22
+	char pad[12];
23
+};
24
+
25
+struct zinfo_copy {
26
+	char type[4];
27
+	uint32_t offset;
28
+	uint32_t len;
29
+	uint32_t align;
30
+};
31
+
32
+struct zinfo_pack {
33
+	char type[4];
34
+	uint32_t offset;
35
+	uint32_t len;
36
+	uint32_t align;
37
+};
38
+
39
+struct zinfo_subtract {
40
+	char type[4];
41
+	uint32_t offset;
42
+	uint32_t divisor;
43
+	uint32_t pad;
44
+};
45
+
46
+union zinfo_record {
47
+	struct zinfo_common common;
48
+	struct zinfo_copy copy;
49
+	struct zinfo_pack pack;
50
+	struct zinfo_subtract subtract;
51
+};
52
+
53
+struct zinfo_file {
54
+	union zinfo_record *zinfo;
55
+	unsigned int num_entries;
56
+};
57
+
58
+static int read_file ( const char *filename, void **buf, size_t *len ) {
59
+	FILE *file;
60
+	struct stat stat;
61
+
62
+	file = fopen ( filename, "r" );
63
+	if ( ! file ) {
64
+		fprintf ( stderr, "Could not open %s: %s\n", filename,
65
+			  strerror ( errno ) );
66
+		goto err;
67
+	}
68
+
69
+	if ( fstat ( fileno ( file ), &stat ) < 0 ) {
70
+		fprintf ( stderr, "Could not stat %s: %s\n", filename,
71
+			  strerror ( errno ) );
72
+		goto err;
73
+	}
74
+
75
+	*len = stat.st_size;
76
+	*buf = malloc ( *len );
77
+	if ( ! *buf ) {
78
+		fprintf ( stderr, "Could not malloc() %d bytes for %s: %s\n",
79
+			  *len, filename, strerror ( errno ) );
80
+		goto err;
81
+	}
82
+
83
+	if ( fread ( *buf, 1, *len, file ) != *len ) {
84
+		fprintf ( stderr, "Could not read %d bytes from %s: %s\n",
85
+			  *len, filename, strerror ( errno ) );
86
+		goto err;
87
+	}
88
+
89
+	fclose ( file );
90
+	return 0;
91
+
92
+ err:
93
+	fclose ( file );
94
+	return -1;
95
+}
96
+
97
+static int read_input_file ( const char *filename,
98
+			     struct input_file *input ) {
99
+	return read_file ( filename, &input->buf, &input->len );
100
+}
101
+
102
+static int read_zinfo_file ( const char *filename,
103
+			     struct zinfo_file *zinfo ) {
104
+	void *buf;
105
+	size_t len;
106
+
107
+	if ( read_file ( filename, &buf, &len ) < 0 )
108
+		return -1;
109
+
110
+	if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) {
111
+		fprintf ( stderr, ".zinfo file %s has invalid length %d\n",
112
+			  filename, len );
113
+		return -1;
114
+	}
115
+
116
+	zinfo->zinfo = buf;
117
+	zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) );
118
+	return 0;
119
+}
120
+
121
+static int alloc_output_file ( size_t max_len, struct output_file *output ) {
122
+	output->len = 0;
123
+	output->max_len = ( max_len );
124
+	output->buf = malloc ( max_len );
125
+	if ( ! output->buf ) {
126
+		fprintf ( stderr, "Could not allocate %d bytes for output\n",
127
+			  max_len );
128
+		return -1;
129
+	}
130
+	memset ( output->buf, 0xff, sizeof ( output->buf ) );
131
+	return 0;
132
+}
133
+
134
+static int process_zinfo_copy ( struct input_file *input,
135
+				struct output_file *output,
136
+				union zinfo_record *zinfo ) {
137
+	struct zinfo_copy *copy = &zinfo->copy;
138
+	size_t offset = copy->offset;
139
+	size_t len = copy->len;
140
+	unsigned int align = copy->align;
141
+
142
+	if ( ( offset + len ) > input->len ) {
143
+		fprintf ( stderr, "Input buffer overrun on copy\n" );
144
+		return -1;
145
+	}
146
+
147
+	output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
148
+	if ( ( output->len + len ) > output->max_len ) {
149
+		fprintf ( stderr, "Output buffer overrun on copy\n" );
150
+		return -1;
151
+	}
152
+
153
+	memcpy ( ( output->buf + output->len ),
154
+		 ( input->buf + offset ), len );
155
+	output->len += len;
156
+	return 0;
157
+}
158
+
159
+static int process_zinfo_pack ( struct input_file *input,
160
+				struct output_file *output,
161
+				union zinfo_record *zinfo ) {
162
+	struct zinfo_pack *pack = &zinfo->pack;
163
+	size_t offset = pack->offset;
164
+	size_t len = pack->len;
165
+	unsigned int align = pack->align;
166
+	unsigned long packed_len;
167
+
168
+	if ( ( offset + len ) > input->len ) {
169
+		fprintf ( stderr, "Input buffer overrun on pack\n" );
170
+		return -1;
171
+	}
172
+
173
+	output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
174
+	if ( output->len > output->max_len ) {
175
+		fprintf ( stderr, "Output buffer overrun on pack\n" );
176
+		return -1;
177
+	}
178
+
179
+	if ( ucl_nrv2b_99_compress ( ( input->buf + offset ), len,
180
+				     ( output->buf + output->len ),
181
+				     &packed_len, 0 ) != UCL_E_OK ) {
182
+		fprintf ( stderr, "Compression failure\n" );
183
+		return -1;
184
+	}
185
+
186
+	output->len += packed_len;
187
+	if ( output->len > output->max_len ) {
188
+		fprintf ( stderr, "Output buffer overrun on pack\n" );
189
+		return -1;
190
+	}
191
+
192
+	return 0;
193
+}
194
+
195
+static int process_zinfo_subtract ( struct input_file *input,
196
+				    struct output_file *output,
197
+				    struct zinfo_subtract *subtract,
198
+				    size_t datasize ) {
199
+	size_t offset = subtract->offset;
200
+	void *target;
201
+	long delta;
202
+
203
+	if ( ( offset + datasize ) > output->len ) {
204
+		fprintf ( stderr, "Subtract at %#zx outside output buffer\n",
205
+			  offset );
206
+		return -1;
207
+	}
208
+
209
+	target = ( output->buf + offset );
210
+	delta = ( ( output->len / subtract->divisor ) -
211
+		  ( input->len / subtract->divisor ) );
212
+
213
+	switch ( datasize ) {
214
+	case 1: {
215
+		uint8_t *byte = target;
216
+		*byte += delta;
217
+		break; }
218
+	case 2: {
219
+		uint16_t *word = target;
220
+		*word += delta;
221
+		break; }
222
+	case 4: {
223
+		uint32_t *dword = target;
224
+		*dword += delta;
225
+		break; }
226
+	default:
227
+		fprintf ( stderr, "Unsupported subtract datasize %d\n",
228
+			  datasize );
229
+		return -1;
230
+	}
231
+	return 0;
232
+}
233
+
234
+static int process_zinfo_subb ( struct input_file *input,
235
+				struct output_file *output,
236
+				union zinfo_record *zinfo ) {
237
+	return process_zinfo_subtract ( input, output, &zinfo->subtract, 1 );
238
+}
239
+
240
+static int process_zinfo_subw ( struct input_file *input,
241
+				struct output_file *output,
242
+				union zinfo_record *zinfo ) {
243
+	return process_zinfo_subtract ( input, output, &zinfo->subtract, 2 );
244
+}
245
+
246
+static int process_zinfo_subl ( struct input_file *input,
247
+				struct output_file *output,
248
+				union zinfo_record *zinfo ) {
249
+	return process_zinfo_subtract ( input, output, &zinfo->subtract, 4 );
250
+}
251
+
252
+struct zinfo_processor {
253
+	char *type;
254
+	int ( * process ) ( struct input_file *input,
255
+			    struct output_file *output,
256
+			    union zinfo_record *zinfo );
257
+};
258
+
259
+static struct zinfo_processor zinfo_processors[] = {
260
+	{ "COPY", process_zinfo_copy },
261
+	{ "PACK", process_zinfo_pack },
262
+	{ "SUBB", process_zinfo_subb },
263
+	{ "SUBW", process_zinfo_subw },
264
+	{ "SUBL", process_zinfo_subl },
265
+};
266
+
267
+static int process_zinfo ( struct input_file *input,
268
+			   struct output_file *output,
269
+			   union zinfo_record *zinfo ) {
270
+	struct zinfo_common *common = &zinfo->common;
271
+	struct zinfo_processor *processor;
272
+	char type[ sizeof ( common->type ) + 1 ] = "";
273
+	unsigned int i;
274
+
275
+	strncat ( type, common->type, sizeof ( type ) - 1 );
276
+	for ( i = 0 ; i < ( sizeof ( zinfo_processors ) /
277
+			    sizeof ( zinfo_processors[0] ) ) ; i++ ) {
278
+		processor = &zinfo_processors[i];
279
+		if ( strcmp ( processor->type, type ) == 0 )
280
+			return processor->process ( input, output, zinfo );
281
+	}
282
+
283
+	fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] );
284
+	return -1;
285
+}
286
+
287
+static int write_output_file ( struct output_file *output ) {
288
+	if ( fwrite ( output->buf, 1, output->len, stdout ) != output->len ) {
289
+		fprintf ( stderr, "Could not write %d bytes of output: %s\n",
290
+			  output->len, strerror ( errno ) );
291
+		return -1;
292
+	}
293
+	return 0;
294
+}
295
+
296
+int main ( int argc, char **argv ) {
297
+	struct input_file input;
298
+	struct output_file output;
299
+	struct zinfo_file zinfo;
300
+	unsigned int i;
301
+
302
+	if ( argc != 3 ) {
303
+		fprintf ( stderr, "Syntax: %s file.bin file.zinfo "
304
+			  "> file.zbin\n", argv[0] );
305
+		exit ( 1 );
306
+	}
307
+
308
+	if ( read_input_file ( argv[1], &input ) < 0 )
309
+		exit ( 1 );
310
+	if ( read_zinfo_file ( argv[2], &zinfo ) < 0 )
311
+		exit ( 1 );
312
+	if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 )
313
+		exit ( 1 );
314
+
315
+	for ( i = 0 ; i < zinfo.num_entries ; i++ ) {
316
+		if ( process_zinfo ( &input, &output,
317
+				     &zinfo.zinfo[i] ) < 0 )
318
+			exit ( 1 );
319
+	}
320
+
321
+	if ( write_output_file ( &output ) < 0 )
322
+		exit ( 1 );
323
+
324
+	return 0;
325
+}

Loading…
Cancel
Save