]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[romprefix] Add a dummy ROM header to cover the .mrom payload
authorMichael Brown <mcb30@ipxe.org>
Sun, 10 Jun 2012 17:25:26 +0000 (18:25 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 12 Jun 2012 14:15:03 +0000 (15:15 +0100)
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>
src/arch/i386/prefix/libprefix.S
src/arch/i386/prefix/mromprefix.S
src/arch/i386/prefix/romprefix.S
src/arch/i386/scripts/i386.lds
src/util/zbin.c

index 0962debbe792c7609387ce7026f8856493040b2d..e5bc7bb1d90c477ccfdbe1606f0bb9733a26c996 100644 (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
index 7bbe44c4ea1ceed59df97b1fb2b97e271abed386..d7b7fc3f78381bd8a5ee0f4d680351949f5a69fb 100644 (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:
+       .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
index 0f92415375eabd4727ce06598e8b6671f78ed3f2..950e08452f94c81c5c6f5bd9d9af32bbc2a95788 100644 (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
  *
index 763b80d6514d65de3db8801d530ca76b8ba20aba..fb763656ce4522eda0e97cb13ffd195e8e323640 100644 (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;
 
index a919516440733556516e17a76af8430751ec4963..0dabaf1e3ad1b47387dc474d0d4d850261d458c0 100644 (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,