aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2012-06-10 18:25:26 +0100
committerMichael Brown <mcb30@ipxe.org>2012-06-12 15:15:03 +0100
commit9e8d431a0d58caba3c5f65d4e30fd259d2f782e1 (patch)
tree357391dd1bbd9b6f0d98dd099aafec60f9bdf80e /src/arch
parent12be8bc544b25fbed1fa5ef6c89cad42aaa268ea (diff)
downloadipxe-9e8d431a0d58caba3c5f65d4e30fd259d2f782e1.zip
ipxe-9e8d431a0d58caba3c5f65d4e30fd259d2f782e1.tar.gz
ipxe-9e8d431a0d58caba3c5f65d4e30fd259d2f782e1.tar.bz2
[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>
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/i386/prefix/libprefix.S26
-rw-r--r--src/arch/i386/prefix/mromprefix.S103
-rw-r--r--src/arch/i386/prefix/romprefix.S46
-rw-r--r--src/arch/i386/scripts/i386.lds25
4 files changed, 135 insertions, 65 deletions
diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S
index 0962deb..e5bc7bb 100644
--- a/src/arch/i386/prefix/libprefix.S
+++ b/src/arch/i386/prefix/libprefix.S
@@ -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
diff --git a/src/arch/i386/prefix/mromprefix.S b/src/arch/i386/prefix/mromprefix.S
index 7bbe44c..d7b7fc3 100644
--- a/src/arch/i386/prefix/mromprefix.S
+++ b/src/arch/i386/prefix/mromprefix.S
@@ -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
@@ -201,11 +211,6 @@ rom_bar_size:
.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
.size stolen_bar_register, . - stolen_bar_register
@@ -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:
+ .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
diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S
index 0f92415..950e084 100644
--- a/src/arch/i386/prefix/romprefix.S
+++ b/src/arch/i386/prefix/romprefix.S
@@ -41,6 +41,14 @@ FILE_LICENCE ( GPL2_OR_LATER )
#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
.code16
.arch i386
@@ -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
*
diff --git a/src/arch/i386/scripts/i386.lds b/src/arch/i386/scripts/i386.lds
index 763b80d..fb76365 100644
--- a/src/arch/i386/scripts/i386.lds
+++ b/src/arch/i386/scripts/i386.lds
@@ -1,4 +1,4 @@
-/* -*- sh -*- */
+/* -*- ld-script -*- */
/*
* Linker script for i386 images
@@ -122,6 +122,23 @@ SECTIONS {
_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
*
*/
@@ -188,7 +205,13 @@ SECTIONS {
. += _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;