Browse Source

[zbin] Change fixup semantics to support ROMs over 128k uncompressed

The option ROM header contains a one-byte field indicating the number
of 512-byte sectors in the ROM image.  Currently it is linked to
contain the number of uncompressed sectors, with an instruction to the
compressor to correct it.  This causes link failure when the
uncompressed size of the ROM image is over 128k.

Fix by replacing the SUBx compressor fixup with an ADDx fixup that
adds the total compressed output length, scaled as requested, to an
addend stored in the field where the final length value will be
placed.  This is similar to the behavior of ELF relocations, and
ensures that an overflow error will not be generated unless the
compressed size is still too large for the field.

This also allows us to do away with the _filesz_pgh and _filesz_sect
calculations exported by the linker script.

Output tested bitwise identical to the old SUBx mechanism on hd, dsk,
lkrn, and rom prefixes, on both 32-bit and 64-bit processors.

Modified-by: Michael Brown <mcb30@etherboot.org>
Signed-off-by: Michael Brown <mcb30@etherboot.org>
tags/v0.9.8
Joshua Oreman 14 years ago
parent
commit
d5d68b2e31

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

@@ -146,9 +146,9 @@ got_sectors:
146 146
 	/* Jump to loaded copy */
147 147
 	ljmp	$SYSSEG, $start_runtime
148 148
 
149
-endseg:	.word SYSSEG + _filesz_pgh
149
+endseg:	.word SYSSEG
150 150
 	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
151
-	.ascii	"SUBW"
151
+	.ascii	"ADDW"
152 152
 	.long	endseg
153 153
 	.long	16
154 154
 	.long	0

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

@@ -65,10 +65,10 @@ max_sector:
65 65
 max_head:
66 66
 	.byte	0
67 67
 load_length:
68
-	.long	_filesz_sect
68
+	.long	0
69 69
 	
70 70
 	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
71
-	.ascii	"SUBL"
71
+	.ascii	"ADDL"
72 72
 	.long	load_length
73 73
 	.long	512
74 74
 	.long	0

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

@@ -94,10 +94,10 @@ setup_sects:
94 94
 root_flags: 
95 95
 	.word	0
96 96
 syssize: 
97
-	.long	_filesz_pgh - PREFIXPGH
97
+	.long	-PREFIXPGH
98 98
 
99 99
 	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
100
-	.ascii	"SUBL"
100
+	.ascii	"ADDL"
101 101
 	.long	syssize
102 102
 	.long	16
103 103
 	.long	0

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

@@ -30,16 +30,16 @@ segment_header:
30 30
 	.byte	0
31 31
 	.byte	0x04		/* Last segment */
32 32
 	.long	0x00007e00
33
-imglen:	.long	_filesz - 512
34
-memlen:	.long	_filesz - 512
33
+imglen:	.long	-512
34
+memlen:	.long	-512
35 35
 	.size	segment_header, . - segment_header
36 36
 
37 37
 	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
38
-	.ascii	"SUBL"
38
+	.ascii	"ADDL"
39 39
 	.long	imglen
40 40
 	.long	1
41 41
 	.long	0
42
-	.ascii	"SUBL"
42
+	.ascii	"ADDL"
43 43
 	.long	memlen
44 44
 	.long	1
45 45
 	.long	0

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

@@ -33,7 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
33 33
 	.org	0x00
34 34
 romheader:
35 35
 	.word	0xAA55			/* BIOS extension signature */
36
-romheader_size:	.byte _filesz_sect	/* Size in 512-byte blocks */
36
+romheader_size:	.byte 0			/* Size in 512-byte blocks */
37 37
 	jmp	init			/* Initialisation vector */
38 38
 checksum:
39 39
 	.byte	0
@@ -46,7 +46,7 @@ checksum:
46 46
 	.size romheader, . - romheader
47 47
 	
48 48
 	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
49
-	.ascii	"SUBB"
49
+	.ascii	"ADDB"
50 50
 	.long	romheader_size
51 51
 	.long	512
52 52
 	.long	0
@@ -61,23 +61,23 @@ pciheader:
61 61
 	.byte	0x03			/* PCI data structure revision */
62 62
 	.byte	0x02, 0x00, 0x00	/* Class code */
63 63
 pciheader_image_length:
64
-	.word	_filesz_sect		/* Image length */
64
+	.word	0			/* Image length */
65 65
 	.word	0x0001			/* Revision level */
66 66
 	.byte	0x00			/* Code type */
67 67
 	.byte	0x80			/* Last image indicator */
68 68
 pciheader_runtime_length:
69
-	.word	_filesz_sect		/* Maximum run-time image length */
69
+	.word	0			/* Maximum run-time image length */
70 70
 	.word	0x0000			/* Configuration utility code header */
71 71
 	.word	0x0000			/* DMTF CLP entry point */
72 72
 	.equ pciheader_len, . - pciheader
73 73
 	.size pciheader, . - pciheader
74 74
 	
75 75
 	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
76
-	.ascii	"SUBW"
76
+	.ascii	"ADDW"
77 77
 	.long	pciheader_image_length
78 78
 	.long	512
79 79
 	.long	0
80
-	.ascii	"SUBW"
80
+	.ascii	"ADDW"
81 81
 	.long	pciheader_runtime_length
82 82
 	.long	512
83 83
 	.long	0

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

@@ -197,13 +197,4 @@ SECTIONS {
197 197
     _prefix_memsz_sect	= ( ( _prefix_memsz + 511 ) / 512 );
198 198
     _text16_memsz_pgh	= ( ( _text16_memsz + 15 ) / 16 );
199 199
     _data16_memsz_pgh	= ( ( _data16_memsz + 15 ) / 16 );
200
-
201
-    /*
202
-     * File size in paragraphs and sectors.  Note that wherever the
203
-     * _filesz variables are used, there must be a corresponding
204
-     * .zinfo.fixup section.
205
-     *
206
-     */
207
-    _filesz_pgh		= ( ( _filesz + 15 ) / 16 );
208
-    _filesz_sect	= ( ( _filesz + 511 ) / 512 );
209 200
 }

+ 76
- 50
src/util/zbin.c View File

@@ -38,7 +38,7 @@ struct zinfo_pack {
38 38
 	uint32_t align;
39 39
 };
40 40
 
41
-struct zinfo_subtract {
41
+struct zinfo_add {
42 42
 	char type[4];
43 43
 	uint32_t offset;
44 44
 	uint32_t divisor;
@@ -49,7 +49,7 @@ union zinfo_record {
49 49
 	struct zinfo_common common;
50 50
 	struct zinfo_copy copy;
51 51
 	struct zinfo_pack pack;
52
-	struct zinfo_subtract subtract;
52
+	struct zinfo_add add;
53 53
 };
54 54
 
55 55
 struct zinfo_file {
@@ -157,8 +157,9 @@ static int process_zinfo_copy ( struct input_file *input,
157 157
 	}
158 158
 
159 159
 	if ( DEBUG ) {
160
-		fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n", offset, ( offset + len ),
161
-			  output->len, ( output->len + len ) );
160
+		fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n",
161
+			  offset, ( offset + len ), output->len,
162
+			  ( output->len + len ) );
162 163
 	}
163 164
 
164 165
 	memcpy ( ( output->buf + output->len ),
@@ -194,8 +195,9 @@ static int process_zinfo_pack ( struct input_file *input,
194 195
 	}
195 196
 
196 197
 	if ( DEBUG ) {
197
-		fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n", offset, ( offset + len ),
198
-			  output->len, ( output->len + packed_len ) );
198
+		fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n",
199
+			  offset, ( offset + len ), output->len,
200
+			  ( output->len + packed_len ) );
199 201
 	}
200 202
 
201 203
 	output->len += packed_len;
@@ -207,78 +209,102 @@ static int process_zinfo_pack ( struct input_file *input,
207 209
 	return 0;
208 210
 }
209 211
 
210
-static int process_zinfo_subtract ( struct input_file *input,
211
-				    struct output_file *output,
212
-				    struct zinfo_subtract *subtract,
213
-				    size_t datasize ) {
214
-	size_t offset = subtract->offset;
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;
215 217
 	void *target;
216
-	signed long raw_delta;
217
-	signed long delta;
218
-	unsigned long old;
219
-	unsigned long new;
218
+	signed long addend;
219
+	unsigned long size;
220
+	signed long val;
221
+	unsigned long mask;
220 222
 
221 223
 	if ( ( offset + datasize ) > output->len ) {
222
-		fprintf ( stderr, "Subtract at %#zx outside output buffer\n",
224
+		fprintf ( stderr, "Add at %#zx outside output buffer\n",
223 225
 			  offset );
224 226
 		return -1;
225 227
 	}
226 228
 
227 229
 	target = ( output->buf + offset );
228
-	raw_delta = ( align ( output->len, subtract->divisor ) -
229
-		      align ( input->len, subtract->divisor ) );
230
-	delta = ( raw_delta / ( ( signed long ) subtract->divisor ) );
230
+	size = ( align ( output->len, add->divisor ) / add->divisor );
231 231
 
232 232
 	switch ( datasize ) {
233
-	case 1: {
234
-		uint8_t *byte = target;
235
-		old = *byte;
236
-		*byte += delta;
237
-		new = *byte;
238
-		break; }
239
-	case 2: {
240
-		uint16_t *word = target;
241
-		old = *word;
242
-		*word += delta;
243
-		new = *word;
244
-		break; }
245
-	case 4: {
246
-		uint32_t *dword = target;
247
-		old = *dword;
248
-		*dword += delta;
249
-		new = *dword;
250
-		break; }
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;
251 242
 	default:
252
-		fprintf ( stderr, "Unsupported subtract datasize %d\n",
243
+		fprintf ( stderr, "Unsupported add datasize %d\n",
253 244
 			  datasize );
254 245
 		return -1;
255 246
 	}
256 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%#lx+%#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%#lx+%#lx at %#zx overflows %d-byte "
263
+			  "field (%d bytes too big)\n",
264
+			  ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
265
+			  offset, datasize,
266
+			  ( ( 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
+
257 282
 	if ( DEBUG ) {
258
-		fprintf ( stderr, "SUBx [%#zx,%#zx) (%#lx+(%#lx/%#x)-(%#lx/%#x)) = %#lx\n",
259
-			  offset, ( offset + datasize ), old, output->len, subtract->divisor,
260
-			  input->len, subtract->divisor, new );
283
+		fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#lx+(%#lx/%#x)) = "
284
+			  "%#lx\n", offset, ( offset + datasize ),
285
+			  ( ( addend < 0 ) ? "-" : "" ), abs ( addend ),
286
+			  output->len, add->divisor, val );
261 287
 	}
262 288
 
263 289
 	return 0;
264 290
 }
265 291
 
266
-static int process_zinfo_subb ( struct input_file *input,
292
+static int process_zinfo_addb ( struct input_file *input,
267 293
 				struct output_file *output,
268 294
 				union zinfo_record *zinfo ) {
269
-	return process_zinfo_subtract ( input, output, &zinfo->subtract, 1 );
295
+	return process_zinfo_add ( input, output, &zinfo->add, 1 );
270 296
 }
271 297
 
272
-static int process_zinfo_subw ( struct input_file *input,
298
+static int process_zinfo_addw ( struct input_file *input,
273 299
 				struct output_file *output,
274 300
 				union zinfo_record *zinfo ) {
275
-	return process_zinfo_subtract ( input, output, &zinfo->subtract, 2 );
301
+	return process_zinfo_add ( input, output, &zinfo->add, 2 );
276 302
 }
277 303
 
278
-static int process_zinfo_subl ( struct input_file *input,
304
+static int process_zinfo_addl ( struct input_file *input,
279 305
 				struct output_file *output,
280 306
 				union zinfo_record *zinfo ) {
281
-	return process_zinfo_subtract ( input, output, &zinfo->subtract, 4 );
307
+	return process_zinfo_add ( input, output, &zinfo->add, 4 );
282 308
 }
283 309
 
284 310
 struct zinfo_processor {
@@ -291,9 +317,9 @@ struct zinfo_processor {
291 317
 static struct zinfo_processor zinfo_processors[] = {
292 318
 	{ "COPY", process_zinfo_copy },
293 319
 	{ "PACK", process_zinfo_pack },
294
-	{ "SUBB", process_zinfo_subb },
295
-	{ "SUBW", process_zinfo_subw },
296
-	{ "SUBL", process_zinfo_subl },
320
+	{ "ADDB", process_zinfo_addb },
321
+	{ "ADDW", process_zinfo_addw },
322
+	{ "ADDL", process_zinfo_addl },
297 323
 };
298 324
 
299 325
 static int process_zinfo ( struct input_file *input,

Loading…
Cancel
Save