mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-26 19:29:04 +00:00
[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:
parent
12be8bc544
commit
9e8d431a0d
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user