david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[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>
This commit is contained in:
Michael Brown 2012-06-10 18:25:26 +01:00
parent 12be8bc544
commit 9e8d431a0d
5 changed files with 198 additions and 74 deletions

View File

@ -663,18 +663,22 @@ install_prealloc:
/* Save decompression temporary area physical address */
pushl %edi
/* Install .text16.early */
/* Install .text16.early and calculate %ecx as offset to next block */
progress " .text16.early\n"
pushl %esi
xorl %esi, %esi
movw %cs, %si
shll $4, %esi
pushl %esi /* Save original %cs:0000 */
addl $_text16_early_lma, %esi
movzwl %ax, %edi
shll $4, %edi
movl $_text16_early_filesz, %ecx
movl $_text16_early_memsz, %edx
call install_block /* .text16.early */
popl %ecx /* Calculate offset to next block */
subl %esi, %ecx
negl %ecx
popl %esi
#ifndef KEEP_IT_REAL
@ -729,7 +733,7 @@ payload_death_message:
jnz 1f
movw %cs, %si
shll $4, %esi
1: addl payload_lma, %esi
1: addl %ecx, %esi
/* Install .text16.late and .data16 */
progress " .text16.late\n"
@ -850,17 +854,6 @@ close_payload_vector:
.word 0
.size close_payload_vector, . - close_payload_vector
/* Payload address */
.section ".prefix.lib", "awx", @progbits
payload_lma:
.long 0
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "ADHL"
.long payload_lma
.long 1
.long 0
.previous
/* Dummy routines to open and close payload */
.section ".text16.early.data", "aw", @progbits
.weak open_payload
@ -914,6 +907,10 @@ uninstall:
.ascii "PAYL"
.long 0
.long 0
.long _payload_align
.ascii "COPY"
.long _pprefix_lma
.long _pprefix_filesz
.long _max_align
.ascii PACK_OR_COPY
.long _text16_late_lma
@ -927,3 +924,6 @@ uninstall:
.long _textdata_lma
.long _textdata_filesz
.long _max_align
.weak _payload_align
.equ _payload_align, 1

View File

@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
#define PCI_BAR_EXPROM 0x30
#define ROMPREFIX_EXCLUDE_PAYLOAD 1
#define ROMPREFIX_MORE_IMAGES 1
#define _rom_start _mrom_start
#include "romprefix.S"
@ -46,8 +47,10 @@ FILE_LICENCE ( GPL2_OR_LATER )
* Parameters:
* %ds:0000 : Prefix
* %esi : Buffer for copy of image source (or zero if no buffer available)
* %ecx : Expected offset within buffer of first payload block
* Returns:
* %esi : Valid image source address (buffered or unbuffered)
* %ecx : Actual offset within buffer of first payload block
* CF set on error
*/
.section ".text16.early", "awx", @progbits
@ -56,23 +59,25 @@ open_payload:
/* Preserve registers */
pushl %eax
pushw %bx
pushl %ecx
pushl %edx
pushl %edi
pushw %bp
pushw %es
pushw %ds
/* Retrieve bus:dev.fn and image source length from .prefix */
/* Retrieve bus:dev.fn from .prefix */
movw init_pci_busdevfn, %bx
movl image_source_len_dword, %ecx
/* Set up %ds for access to .text16.early */
pushw %cs
popw %ds
/* Store bus:dev.fn and image source length to .text16.early */
/* Set up %es for access to flat address space */
xorw %ax, %ax
movw %ax, %es
/* Store bus:dev.fn to .text16.early */
movw %bx, payload_pci_busdevfn
movl %ecx, rom_bar_copy_len_dword
/* Get expansion ROM BAR current value */
movw $PCI_BAR_EXPROM, %di
@ -159,27 +164,32 @@ find_mem_bar:
* properly support flat real mode, it will die horribly.)
*/
pushl %esi
pushw %es
movl %esi, %edi
movl %eax, %esi
movl rom_bar_copy_len_dword, %ecx
xorw %ax, %ax
movw %ax, %es
addr32 es movzbl 2(%esi), %ecx
shll $7, %ecx
addr32 es movzbl 2(%esi,%ecx,4), %edx
shll $7, %edx
addl %edx, %ecx
addr32 es rep movsl
popw %es
popl %esi
jmp 2f
1: /* We have no buffer; set %esi to the BAR address */
movl %eax, %esi
2:
/* Locate first payload block (after the dummy ROM header) */
addr32 es movzbl 2(%esi), %ecx
shll $9, %ecx
addl $_pprefix_skip, %ecx
clc
/* Restore registers and return */
99: popw %ds
popw %es
popw %bp
popl %edi
popl %edx
popl %ecx
popw %bx
popl %eax
lret
@ -200,11 +210,6 @@ rom_bar_size:
.long 0
.size rom_bar_size, . - rom_bar_size
.section ".text16.early.data", "aw", @progbits
rom_bar_copy_len_dword:
.long 0
.size rom_bar_copy_len_dword, . - rom_bar_copy_len_dword
.section ".text16.early.data", "aw", @progbits
stolen_bar_register:
.word 0
@ -419,16 +424,68 @@ pci_set_mem_access:
ret
.size pci_set_mem_access, . - pci_set_mem_access
/* Image source area length (in dwords)
/* Payload prefix
*
* We include a dummy ROM header to cover the "hidden" portion of the
* overall ROM image.
*/
.section ".prefix", "ax", @progbits
image_source_len_dword:
.long 0
.size image_source_len_dword, . - image_source_len_dword
.globl _payload_align
.equ _payload_align, 512
.section ".pprefix", "ax", @progbits
.org 0x00
mromheader:
.word 0xaa55 /* BIOS extension signature */
mromheader_size: .byte 0 /* Size in 512-byte blocks */
.org 0x18
.word mpciheader
.org 0x1a
.word 0
.size mromheader, . - mromheader
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "ADDL"
.long image_source_len_dword
.long 4
.ascii "APPB"
.long mromheader_size
.long 512
.long 0
.previous
mpciheader:
.ascii "PCIR" /* Signature */
.word pci_vendor_id /* Vendor identification */
.word pci_device_id /* Device identification */
.word 0x0000 /* Device list pointer */
.word mpciheader_len /* PCI data structure length */
.byte 0x03 /* PCI data structure revision */
.byte 0x02, 0x00, 0x00 /* Class code */
mpciheader_image_length:
.word 0 /* Image length */
.word 0x0001 /* Revision level */
.byte 0xff /* Code type */
.byte 0x80 /* Last image indicator */
mpciheader_runtime_length:
.word 0 /* Maximum run-time image length */
.word 0x0000 /* Configuration utility code header */
.word 0x0000 /* DMTF CLP entry point */
.equ mpciheader_len, . - mpciheader
.size mpciheader, . - mpciheader
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "APPW"
.long mpciheader_image_length
.long 512
.long 0
.ascii "APPW"
.long mpciheader_runtime_length
.long 512
.long 0
.previous
/* Fix up additional image source size
*
*/
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "ADPW"
.long extra_size
.long 512
.long 0
.previous

View File

@ -39,6 +39,14 @@ FILE_LICENCE ( GPL2_OR_LATER )
#else
#define ZINFO_TYPE_ADxB "ADDB"
#define ZINFO_TYPE_ADxW "ADDW"
#endif
/* Allow ROM to be marked as containing multiple images
*/
#if ROMPREFIX_MORE_IMAGES
#define INDICATOR 0x00
#else
#define INDICATOR 0x80
#endif
.text
@ -85,7 +93,7 @@ pciheader_image_length:
.word 0 /* Image length */
.word 0x0001 /* Revision level */
.byte 0x00 /* Code type */
.byte 0x80 /* Last image indicator */
.byte INDICATOR /* Last image indicator */
pciheader_runtime_length:
.word 0 /* Maximum run-time image length */
.word 0x0000 /* Configuration utility code header */
@ -98,7 +106,7 @@ pciheader_runtime_length:
.long pciheader_image_length
.long 512
.long 0
.ascii ZINFO_TYPE_ADxW
.ascii "ADHW"
.long pciheader_runtime_length
.long 512
.long 0
@ -327,7 +335,8 @@ pmm_scan:
/* We have PMM and so a 1kB stack: preserve whole registers */
pushal
/* Allocate image source PMM block */
movzwl image_source_size, %ecx
movzbl romheader_size, %ecx
addw extra_size, %cx
shll $5, %ecx
movl $PMM_HANDLE_BASE_IMAGE_SOURCE, %ebx
movw $get_pmm_image_source, %bp
@ -341,11 +350,11 @@ pmm_scan:
movl %esi, %edi
xorl %esi, %esi
movzbl romheader_size, %ecx
shll $9, %ecx
addr32 rep movsb /* PMM presence implies flat real mode */
shll $7, %ecx
addr32 rep movsl /* PMM presence implies flat real mode */
popw %es
/* Shrink ROM */
movb shrunk_rom_size, %al
movw pciheader_runtime_length, %ax
movb %al, romheader_size
1: /* Allocate decompression PMM block. Round up the size to the
* nearest 128kB and use the size within the PMM handle; this
@ -573,31 +582,12 @@ image_source:
.long 0
.size image_source, . - image_source
/* Image source size (in 512-byte sectors)
/* Additional image source size (in 512-byte sectors)
*
*/
image_source_size:
extra_size:
.word 0
.size image_source_size, . - image_source_size
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "ADDW"
.long image_source_size
.long 512
.long 0
.previous
/* Shrunk ROM size (in 512-byte sectors)
*
*/
shrunk_rom_size:
.byte 0
.size shrunk_rom_size, . - shrunk_rom_size
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "ADHB"
.long shrunk_rom_size
.long 512
.long 0
.previous
.size extra_size, . - extra_size
/* Temporary decompression area
*

View File

@ -1,4 +1,4 @@
/* -*- sh -*- */
/* -*- ld-script -*- */
/*
* Linker script for i386 images
@ -121,6 +121,23 @@ SECTIONS {
_textdata_filesz = ABSOLUTE ( _mtextdata ) - ABSOLUTE ( _textdata );
_textdata_memsz = ABSOLUTE ( _etextdata ) - ABSOLUTE ( _textdata );
/*
* Payload prefix
*
* If present, this will be placed between .text16.early and .text16.late.
*
*/
.pprefix 0x0 : AT ( _pprefix_lma ) {
_pprefix = .;
KEEP(*(.pprefix))
KEEP(*(.pprefix.*))
_mpprefix = .;
} .bss.pprefix (NOLOAD) : AT ( _end_lma ) {
_epprefix = .;
}
_pprefix_filesz = ABSOLUTE ( _mpprefix ) - ABSOLUTE ( _pprefix );
_pprefix_memsz = ABSOLUTE ( _epprefix ) - ABSOLUTE ( _pprefix );
/*
* Compressor information block
*
@ -187,8 +204,14 @@ SECTIONS {
_text16_early_lma = .;
. += _text16_early_filesz;
. = ALIGN ( _max_align );
. = ALIGN ( _payload_align );
_pprefix_lma = .;
. += _pprefix_filesz;
. = ALIGN ( _max_align );
_payload_lma = .;
_pprefix_skip = ABSOLUTE ( _payload_lma ) - ABSOLUTE ( _pprefix_lma );
_text16_late_lma = .;
. += _text16_late_filesz;

View File

@ -237,15 +237,15 @@ static int process_zinfo_add ( struct input_file *input
__attribute__ (( unused )),
struct output_file *output,
size_t len,
struct zinfo_add *add,
struct zinfo_add *add, size_t offset,
size_t datasize ) {
size_t offset = add->offset;
void *target;
signed long addend;
unsigned long size;
signed long val;
unsigned long mask;
offset += add->offset;
if ( ( offset + datasize ) > output->len ) {
fprintf ( stderr, "Add at %#zx outside output buffer\n",
offset );
@ -319,42 +319,90 @@ static int process_zinfo_addb ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output, output->len,
&zinfo->add, 1 );
&zinfo->add, 0, 1 );
}
static int process_zinfo_addw ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output, output->len,
&zinfo->add, 2 );
&zinfo->add, 0, 2 );
}
static int process_zinfo_addl ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output, output->len,
&zinfo->add, 4 );
&zinfo->add, 0, 4 );
}
static int process_zinfo_adhb ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output, output->hdr_len,
&zinfo->add, 1 );
&zinfo->add, 0, 1 );
}
static int process_zinfo_adhw ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output, output->hdr_len,
&zinfo->add, 2 );
&zinfo->add, 0, 2 );
}
static int process_zinfo_adhl ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output, output->hdr_len,
&zinfo->add, 4 );
&zinfo->add, 0, 4 );
}
static int process_zinfo_adpb ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output,
( output->len - output->hdr_len ),
&zinfo->add, 0, 1 );
}
static int process_zinfo_adpw ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output,
( output->len - output->hdr_len ),
&zinfo->add, 0, 2 );
}
static int process_zinfo_adpl ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output,
( output->len - output->hdr_len ),
&zinfo->add, 0, 4 );
}
static int process_zinfo_appb ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output,
( output->len - output->hdr_len ),
&zinfo->add, output->hdr_len, 1 );
}
static int process_zinfo_appw ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output,
( output->len - output->hdr_len ),
&zinfo->add, output->hdr_len, 2 );
}
static int process_zinfo_appl ( struct input_file *input,
struct output_file *output,
union zinfo_record *zinfo ) {
return process_zinfo_add ( input, output,
( output->len - output->hdr_len ),
&zinfo->add, output->hdr_len, 4 );
}
struct zinfo_processor {
@ -374,6 +422,12 @@ static struct zinfo_processor zinfo_processors[] = {
{ "ADHB", process_zinfo_adhb },
{ "ADHW", process_zinfo_adhw },
{ "ADHL", process_zinfo_adhl },
{ "ADPB", process_zinfo_adpb },
{ "ADPW", process_zinfo_adpw },
{ "ADPL", process_zinfo_adpl },
{ "APPB", process_zinfo_appb },
{ "APPW", process_zinfo_appw },
{ "APPL", process_zinfo_appl },
};
static int process_zinfo ( struct input_file *input,