Browse Source

[romprefix] Add a dummy ROM header to cover the .mrom payload

The header of a .mrom image declares its length to be only a few
kilobytes; the remainder is accessed via a sideband mechanism.  This
makes it difficult to append an additional ROM image, such as an EFI
ROM.

Add a second, dummy ROM header covering the payload portion of the
.mrom image, allowing consumers to locate any appended ROM images in
the usual way.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
9e8d431a0d

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

@@ -663,18 +663,22 @@ install_prealloc:
663 663
 	/* Save decompression temporary area physical address */
664 664
 	pushl	%edi
665 665
 
666
-	/* Install .text16.early */
666
+	/* Install .text16.early and calculate %ecx as offset to next block */
667 667
 	progress "  .text16.early\n"
668 668
 	pushl	%esi
669 669
 	xorl	%esi, %esi
670 670
 	movw	%cs, %si
671 671
 	shll	$4, %esi
672
+	pushl	%esi			/* Save original %cs:0000 */
672 673
 	addl	$_text16_early_lma, %esi
673 674
 	movzwl	%ax, %edi
674 675
 	shll	$4, %edi
675 676
 	movl	$_text16_early_filesz, %ecx
676 677
 	movl	$_text16_early_memsz, %edx
677 678
 	call	install_block		/* .text16.early */
679
+	popl	%ecx			/* Calculate offset to next block */
680
+	subl	%esi, %ecx
681
+	negl	%ecx
678 682
 	popl	%esi
679 683
 
680 684
 #ifndef KEEP_IT_REAL
@@ -729,7 +733,7 @@ payload_death_message:
729 733
 	jnz	1f
730 734
 	movw	%cs, %si
731 735
 	shll	$4, %esi
732
-1:	addl	payload_lma, %esi
736
+1:	addl	%ecx, %esi
733 737
 
734 738
 	/* Install .text16.late and .data16 */
735 739
 	progress "  .text16.late\n"
@@ -850,17 +854,6 @@ close_payload_vector:
850 854
 	.word 0
851 855
 	.size close_payload_vector, . - close_payload_vector
852 856
 
853
-	/* Payload address */
854
-	.section ".prefix.lib", "awx", @progbits
855
-payload_lma:
856
-	.long 0
857
-	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
858
-	.ascii	"ADHL"
859
-	.long	payload_lma
860
-	.long	1
861
-	.long	0
862
-	.previous
863
-
864 857
 	/* Dummy routines to open and close payload */
865 858
 	.section ".text16.early.data", "aw", @progbits
866 859
 	.weak	open_payload
@@ -914,6 +907,10 @@ uninstall:
914 907
 	.ascii	"PAYL"
915 908
 	.long	0
916 909
 	.long	0
910
+	.long	_payload_align
911
+	.ascii	"COPY"
912
+	.long	_pprefix_lma
913
+	.long	_pprefix_filesz
917 914
 	.long	_max_align
918 915
 	.ascii	PACK_OR_COPY
919 916
 	.long	_text16_late_lma
@@ -927,3 +924,6 @@ uninstall:
927 924
 	.long	_textdata_lma
928 925
 	.long	_textdata_filesz
929 926
 	.long	_max_align
927
+
928
+	.weak	_payload_align
929
+	.equ	_payload_align, 1

+ 80
- 23
src/arch/i386/prefix/mromprefix.S View File

@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
30 30
 #define PCI_BAR_EXPROM			0x30
31 31
 
32 32
 #define ROMPREFIX_EXCLUDE_PAYLOAD 1
33
+#define ROMPREFIX_MORE_IMAGES 1
33 34
 #define _rom_start _mrom_start
34 35
 #include "romprefix.S"
35 36
 
@@ -46,8 +47,10 @@ FILE_LICENCE ( GPL2_OR_LATER )
46 47
  * Parameters:
47 48
  *   %ds:0000 : Prefix
48 49
  *   %esi : Buffer for copy of image source (or zero if no buffer available)
50
+ *   %ecx : Expected offset within buffer of first payload block
49 51
  * Returns:
50 52
  *   %esi : Valid image source address (buffered or unbuffered)
53
+ *   %ecx : Actual offset within buffer of first payload block
51 54
  *   CF set on error
52 55
  */
53 56
 	.section ".text16.early", "awx", @progbits
@@ -56,23 +59,25 @@ open_payload:
56 59
 	/* Preserve registers */
57 60
 	pushl	%eax
58 61
 	pushw	%bx
59
-	pushl	%ecx
60 62
 	pushl	%edx
61 63
 	pushl	%edi
62 64
 	pushw	%bp
65
+	pushw	%es
63 66
 	pushw	%ds
64 67
 
65
-	/* Retrieve bus:dev.fn and image source length from .prefix */
68
+	/* Retrieve bus:dev.fn from .prefix */
66 69
 	movw	init_pci_busdevfn, %bx
67
-	movl	image_source_len_dword, %ecx
68 70
 
69 71
 	/* Set up %ds for access to .text16.early */
70 72
 	pushw	%cs
71 73
 	popw	%ds
72 74
 
73
-	/* Store bus:dev.fn and image source length to .text16.early */
75
+	/* Set up %es for access to flat address space */
76
+	xorw	%ax, %ax
77
+	movw	%ax, %es
78
+
79
+	/* Store bus:dev.fn to .text16.early */
74 80
 	movw	%bx, payload_pci_busdevfn
75
-	movl	%ecx, rom_bar_copy_len_dword
76 81
 
77 82
 	/* Get expansion ROM BAR current value */
78 83
 	movw	$PCI_BAR_EXPROM, %di
@@ -159,27 +164,32 @@ find_mem_bar:
159 164
 	 * properly support flat real mode, it will die horribly.)
160 165
 	 */
161 166
 	pushl	%esi
162
-	pushw	%es
163 167
 	movl	%esi, %edi
164 168
 	movl	%eax, %esi
165
-	movl	rom_bar_copy_len_dword, %ecx
166
-	xorw	%ax, %ax
167
-	movw	%ax, %es
169
+	addr32 es movzbl 2(%esi), %ecx
170
+	shll	$7, %ecx
171
+	addr32 es movzbl 2(%esi,%ecx,4), %edx
172
+	shll	$7, %edx
173
+	addl	%edx, %ecx
168 174
 	addr32 es rep movsl
169
-	popw	%es
170 175
 	popl	%esi
171 176
 	jmp	2f
172 177
 1:	/* We have no buffer; set %esi to the BAR address */
173 178
 	movl	%eax, %esi
174 179
 2:
175 180
 
181
+	/* Locate first payload block (after the dummy ROM header) */
182
+	addr32 es movzbl 2(%esi), %ecx
183
+	shll	$9, %ecx
184
+	addl	$_pprefix_skip, %ecx
185
+
176 186
 	clc
177 187
 	/* Restore registers and return */
178 188
 99:	popw	%ds
189
+	popw	%es
179 190
 	popw	%bp
180 191
 	popl	%edi
181 192
 	popl	%edx
182
-	popl	%ecx
183 193
 	popw	%bx
184 194
 	popl	%eax
185 195
 	lret
@@ -200,11 +210,6 @@ rom_bar_size:
200 210
 	.long	0
201 211
 	.size	rom_bar_size, . - rom_bar_size
202 212
 
203
-	.section ".text16.early.data", "aw", @progbits
204
-rom_bar_copy_len_dword:
205
-	.long	0
206
-	.size	rom_bar_copy_len_dword, . - rom_bar_copy_len_dword
207
-
208 213
 	.section ".text16.early.data", "aw", @progbits
209 214
 stolen_bar_register:
210 215
 	.word	0
@@ -419,16 +424,68 @@ pci_set_mem_access:
419 424
 	ret
420 425
 	.size	pci_set_mem_access, . - pci_set_mem_access
421 426
 
422
-/* Image source area length (in dwords)
427
+/* Payload prefix
423 428
  *
429
+ * We include a dummy ROM header to cover the "hidden" portion of the
430
+ * overall ROM image.
424 431
  */
425
-	.section ".prefix", "ax", @progbits
426
-image_source_len_dword:
432
+	.globl	_payload_align
433
+	.equ	_payload_align, 512
434
+	.section ".pprefix", "ax", @progbits
435
+	.org	0x00
436
+mromheader:
437
+	.word	0xaa55			/* BIOS extension signature */
438
+mromheader_size: .byte 0		/* Size in 512-byte blocks */
439
+	.org	0x18
440
+	.word	mpciheader
441
+	.org	0x1a
442
+	.word	0
443
+	.size	mromheader, . - mromheader
444
+
445
+	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
446
+	.ascii	"APPB"
447
+	.long	mromheader_size
448
+	.long	512
449
+	.long	0
450
+	.previous
451
+
452
+mpciheader:
453
+	.ascii	"PCIR"			/* Signature */
454
+	.word	pci_vendor_id		/* Vendor identification */
455
+	.word	pci_device_id		/* Device identification */
456
+	.word	0x0000			/* Device list pointer */
457
+	.word	mpciheader_len		/* PCI data structure length */
458
+	.byte	0x03			/* PCI data structure revision */
459
+	.byte	0x02, 0x00, 0x00	/* Class code */
460
+mpciheader_image_length:
461
+	.word	0			/* Image length */
462
+	.word	0x0001			/* Revision level */
463
+	.byte	0xff			/* Code type */
464
+	.byte	0x80			/* Last image indicator */
465
+mpciheader_runtime_length:
466
+	.word	0			/* Maximum run-time image length */
467
+	.word	0x0000			/* Configuration utility code header */
468
+	.word	0x0000			/* DMTF CLP entry point */
469
+	.equ	mpciheader_len, . - mpciheader
470
+	.size	mpciheader, . - mpciheader
471
+
472
+	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
473
+	.ascii	"APPW"
474
+	.long	mpciheader_image_length
475
+	.long	512
427 476
 	.long	0
428
-	.size	image_source_len_dword, . - image_source_len_dword
477
+	.ascii	"APPW"
478
+	.long	mpciheader_runtime_length
479
+	.long	512
480
+	.long	0
481
+	.previous
482
+
483
+/* Fix up additional image source size
484
+ *
485
+ */
429 486
 	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
430
-	.ascii	"ADDL"
431
-	.long	image_source_len_dword
432
-	.long	4
487
+	.ascii	"ADPW"
488
+	.long	extra_size
489
+	.long	512
433 490
 	.long	0
434 491
 	.previous

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

@@ -39,6 +39,14 @@ FILE_LICENCE ( GPL2_OR_LATER )
39 39
 #else
40 40
 #define	ZINFO_TYPE_ADxB "ADDB"
41 41
 #define	ZINFO_TYPE_ADxW "ADDW"
42
+#endif
43
+
44
+/* Allow ROM to be marked as containing multiple images
45
+ */
46
+#if ROMPREFIX_MORE_IMAGES
47
+#define INDICATOR 0x00
48
+#else
49
+#define INDICATOR 0x80
42 50
 #endif
43 51
 
44 52
 	.text
@@ -85,7 +93,7 @@ pciheader_image_length:
85 93
 	.word	0			/* Image length */
86 94
 	.word	0x0001			/* Revision level */
87 95
 	.byte	0x00			/* Code type */
88
-	.byte	0x80			/* Last image indicator */
96
+	.byte	INDICATOR		/* Last image indicator */
89 97
 pciheader_runtime_length:
90 98
 	.word	0			/* Maximum run-time image length */
91 99
 	.word	0x0000			/* Configuration utility code header */
@@ -98,7 +106,7 @@ pciheader_runtime_length:
98 106
 	.long	pciheader_image_length
99 107
 	.long	512
100 108
 	.long	0
101
-	.ascii	ZINFO_TYPE_ADxW
109
+	.ascii	"ADHW"
102 110
 	.long	pciheader_runtime_length
103 111
 	.long	512
104 112
 	.long	0
@@ -327,7 +335,8 @@ pmm_scan:
327 335
 	/* We have PMM and so a 1kB stack: preserve whole registers */
328 336
 	pushal
329 337
 	/* Allocate image source PMM block */
330
-	movzwl	image_source_size, %ecx
338
+	movzbl	romheader_size, %ecx
339
+	addw	extra_size, %cx
331 340
 	shll	$5, %ecx
332 341
 	movl	$PMM_HANDLE_BASE_IMAGE_SOURCE, %ebx
333 342
 	movw	$get_pmm_image_source, %bp
@@ -341,11 +350,11 @@ pmm_scan:
341 350
 	movl	%esi, %edi
342 351
 	xorl	%esi, %esi
343 352
 	movzbl	romheader_size, %ecx
344
-	shll	$9, %ecx
345
-	addr32 rep movsb	/* PMM presence implies flat real mode */
353
+	shll	$7, %ecx
354
+	addr32 rep movsl	/* PMM presence implies flat real mode */
346 355
 	popw	%es
347 356
 	/* Shrink ROM */
348
-	movb	shrunk_rom_size, %al
357
+	movw	pciheader_runtime_length, %ax
349 358
 	movb	%al, romheader_size
350 359
 1:	/* Allocate decompression PMM block.  Round up the size to the
351 360
 	 * nearest 128kB and use the size within the PMM handle; this
@@ -573,31 +582,12 @@ image_source:
573 582
 	.long	0
574 583
 	.size	image_source, . - image_source
575 584
 
576
-/* Image source size (in 512-byte sectors)
585
+/* Additional image source size (in 512-byte sectors)
577 586
  *
578 587
  */
579
-image_source_size:
588
+extra_size:
580 589
 	.word	0
581
-	.size	image_source_size, . - image_source_size
582
-	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
583
-	.ascii	"ADDW"
584
-	.long	image_source_size
585
-	.long	512
586
-	.long	0
587
-	.previous
588
-
589
-/* Shrunk ROM size (in 512-byte sectors)
590
- *
591
- */
592
-shrunk_rom_size:
593
-	.byte	0
594
-	.size	shrunk_rom_size, . - shrunk_rom_size
595
-	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
596
-	.ascii	"ADHB"
597
-	.long	shrunk_rom_size
598
-	.long	512
599
-	.long	0
600
-	.previous
590
+	.size	extra_size, . - extra_size
601 591
 
602 592
 /* Temporary decompression area
603 593
  *

+ 24
- 1
src/arch/i386/scripts/i386.lds View File

@@ -1,4 +1,4 @@
1
-/* -*- sh -*- */
1
+/* -*- ld-script -*- */
2 2
 
3 3
 /*
4 4
  * Linker script for i386 images
@@ -121,6 +121,23 @@ SECTIONS {
121 121
     _textdata_filesz	= ABSOLUTE ( _mtextdata ) - ABSOLUTE ( _textdata );
122 122
     _textdata_memsz	= ABSOLUTE ( _etextdata ) - ABSOLUTE ( _textdata );
123 123
 
124
+    /*
125
+     * Payload prefix
126
+     *
127
+     * If present, this will be placed between .text16.early and .text16.late.
128
+     *
129
+     */
130
+    .pprefix 0x0 : AT ( _pprefix_lma ) {
131
+	_pprefix = .;
132
+	KEEP(*(.pprefix))
133
+	KEEP(*(.pprefix.*))
134
+	_mpprefix = .;
135
+    } .bss.pprefix (NOLOAD) : AT ( _end_lma ) {
136
+	_epprefix = .;
137
+    }
138
+    _pprefix_filesz	= ABSOLUTE ( _mpprefix ) - ABSOLUTE ( _pprefix );
139
+    _pprefix_memsz	= ABSOLUTE ( _epprefix ) - ABSOLUTE ( _pprefix );
140
+
124 141
     /*
125 142
      * Compressor information block
126 143
      *
@@ -187,8 +204,14 @@ SECTIONS {
187 204
     _text16_early_lma	= .;
188 205
     .			+= _text16_early_filesz;
189 206
 
207
+    .			= ALIGN ( _max_align );
208
+    .			= ALIGN ( _payload_align );
209
+    _pprefix_lma	= .;
210
+    .			+= _pprefix_filesz;
211
+
190 212
     .			= ALIGN ( _max_align );
191 213
     _payload_lma	= .;
214
+    _pprefix_skip	= ABSOLUTE ( _payload_lma ) - ABSOLUTE ( _pprefix_lma );
192 215
     _text16_late_lma	= .;
193 216
     .			+= _text16_late_filesz;
194 217
 

+ 62
- 8
src/util/zbin.c View File

@@ -237,15 +237,15 @@ static int process_zinfo_add ( struct input_file *input
237 237
 					__attribute__ (( unused )),
238 238
 			       struct output_file *output,
239 239
 			       size_t len,
240
-			       struct zinfo_add *add,
240
+			       struct zinfo_add *add, size_t offset,
241 241
 			       size_t datasize ) {
242
-	size_t offset = add->offset;
243 242
 	void *target;
244 243
 	signed long addend;
245 244
 	unsigned long size;
246 245
 	signed long val;
247 246
 	unsigned long mask;
248 247
 
248
+	offset += add->offset;
249 249
 	if ( ( offset + datasize ) > output->len ) {
250 250
 		fprintf ( stderr, "Add at %#zx outside output buffer\n",
251 251
 			  offset );
@@ -319,42 +319,90 @@ static int process_zinfo_addb ( struct input_file *input,
319 319
 				struct output_file *output,
320 320
 				union zinfo_record *zinfo ) {
321 321
 	return process_zinfo_add ( input, output, output->len,
322
-				   &zinfo->add, 1 );
322
+				   &zinfo->add, 0, 1 );
323 323
 }
324 324
 
325 325
 static int process_zinfo_addw ( struct input_file *input,
326 326
 				struct output_file *output,
327 327
 				union zinfo_record *zinfo ) {
328 328
 	return process_zinfo_add ( input, output, output->len,
329
-				   &zinfo->add, 2 );
329
+				   &zinfo->add, 0, 2 );
330 330
 }
331 331
 
332 332
 static int process_zinfo_addl ( struct input_file *input,
333 333
 				struct output_file *output,
334 334
 				union zinfo_record *zinfo ) {
335 335
 	return process_zinfo_add ( input, output, output->len,
336
-				   &zinfo->add, 4 );
336
+				   &zinfo->add, 0, 4 );
337 337
 }
338 338
 
339 339
 static int process_zinfo_adhb ( struct input_file *input,
340 340
 				struct output_file *output,
341 341
 				union zinfo_record *zinfo ) {
342 342
 	return process_zinfo_add ( input, output, output->hdr_len,
343
-				   &zinfo->add, 1 );
343
+				   &zinfo->add, 0, 1 );
344 344
 }
345 345
 
346 346
 static int process_zinfo_adhw ( struct input_file *input,
347 347
 				struct output_file *output,
348 348
 				union zinfo_record *zinfo ) {
349 349
 	return process_zinfo_add ( input, output, output->hdr_len,
350
-				   &zinfo->add, 2 );
350
+				   &zinfo->add, 0, 2 );
351 351
 }
352 352
 
353 353
 static int process_zinfo_adhl ( struct input_file *input,
354 354
 				struct output_file *output,
355 355
 				union zinfo_record *zinfo ) {
356 356
 	return process_zinfo_add ( input, output, output->hdr_len,
357
-				   &zinfo->add, 4 );
357
+				   &zinfo->add, 0, 4 );
358
+}
359
+
360
+static int process_zinfo_adpb ( struct input_file *input,
361
+				struct output_file *output,
362
+				union zinfo_record *zinfo ) {
363
+	return process_zinfo_add ( input, output,
364
+				   ( output->len - output->hdr_len ),
365
+				   &zinfo->add, 0, 1 );
366
+}
367
+
368
+static int process_zinfo_adpw ( struct input_file *input,
369
+				struct output_file *output,
370
+				union zinfo_record *zinfo ) {
371
+	return process_zinfo_add ( input, output,
372
+				   ( output->len - output->hdr_len ),
373
+				   &zinfo->add, 0, 2 );
374
+}
375
+
376
+static int process_zinfo_adpl ( struct input_file *input,
377
+				struct output_file *output,
378
+				union zinfo_record *zinfo ) {
379
+	return process_zinfo_add ( input, output,
380
+				   ( output->len - output->hdr_len ),
381
+				   &zinfo->add, 0, 4 );
382
+}
383
+
384
+static int process_zinfo_appb ( struct input_file *input,
385
+				struct output_file *output,
386
+				union zinfo_record *zinfo ) {
387
+	return process_zinfo_add ( input, output,
388
+				   ( output->len - output->hdr_len ),
389
+				   &zinfo->add, output->hdr_len, 1 );
390
+}
391
+
392
+static int process_zinfo_appw ( struct input_file *input,
393
+				struct output_file *output,
394
+				union zinfo_record *zinfo ) {
395
+	return process_zinfo_add ( input, output,
396
+				   ( output->len - output->hdr_len ),
397
+				   &zinfo->add, output->hdr_len, 2 );
398
+}
399
+
400
+static int process_zinfo_appl ( struct input_file *input,
401
+				struct output_file *output,
402
+				union zinfo_record *zinfo ) {
403
+	return process_zinfo_add ( input, output,
404
+				   ( output->len - output->hdr_len ),
405
+				   &zinfo->add, output->hdr_len, 4 );
358 406
 }
359 407
 
360 408
 struct zinfo_processor {
@@ -374,6 +422,12 @@ static struct zinfo_processor zinfo_processors[] = {
374 422
 	{ "ADHB", process_zinfo_adhb },
375 423
 	{ "ADHW", process_zinfo_adhw },
376 424
 	{ "ADHL", process_zinfo_adhl },
425
+	{ "ADPB", process_zinfo_adpb },
426
+	{ "ADPW", process_zinfo_adpw },
427
+	{ "ADPL", process_zinfo_adpl },
428
+	{ "APPB", process_zinfo_appb },
429
+	{ "APPW", process_zinfo_appw },
430
+	{ "APPL", process_zinfo_appl },
377 431
 };
378 432
 
379 433
 static int process_zinfo ( struct input_file *input,

Loading…
Cancel
Save