/* 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
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"
.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
.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
.long _textdata_lma
.long _textdata_filesz
.long _max_align
+
+ .weak _payload_align
+ .equ _payload_align, 1
#define PCI_BAR_EXPROM 0x30
#define ROMPREFIX_EXCLUDE_PAYLOAD 1
+#define ROMPREFIX_MORE_IMAGES 1
#define _rom_start _mrom_start
#include "romprefix.S"
* 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
/* 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
* 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
.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
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:
+ .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 "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
- .size image_source_len_dword, . - image_source_len_dword
+ .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 "ADDL"
- .long image_source_len_dword
- .long 4
+ .ascii "ADPW"
+ .long extra_size
+ .long 512
.long 0
.previous
#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
.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 */
.long pciheader_image_length
.long 512
.long 0
- .ascii ZINFO_TYPE_ADxW
+ .ascii "ADHW"
.long pciheader_runtime_length
.long 512
.long 0
/* 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
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
.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
*
-/* -*- sh -*- */
+/* -*- ld-script -*- */
/*
* Linker script for i386 images
_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
*
_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;
__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 );
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 {
{ "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,