[romprefix] Remove .xrom prefix
authorMichael Brown <mcb30@ipxe.org>
Mon, 19 Apr 2010 19:32:25 +0000 (20:32 +0100)
committerStefan Hajnoczi <stefanha@gmail.com>
Wed, 7 Jul 2010 19:14:35 +0000 (20:14 +0100)
The .xrom prefix provides an experimental mechanism for loading ROM
images greater than 64kB in size by mapping the expansion ROM BAR in
at a hopefully-unused address.  This is unreliable, and potentially
dangerous.  In particular, there is no guarantee that any PCI bridges
between the CPU and the device will respond to accesses for the
"unused" memory region that is chosen, and it is possible that the
process of scanning for the "unused" memory region may end up issuing
reads to other PCI devices.  If this ends up trampling on a register
with read side-effects belonging to an unrelated PCI device, this may
cause undefined behaviour.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
src/Makefile.housekeeping
src/arch/i386/Makefile.pcbios
src/arch/i386/prefix/romprefix.S
src/arch/i386/prefix/xromprefix.S [deleted file]
src/arch/i386/scripts/i386.lds
src/util/makerom.pl

index c5b15d6..95e4e25 100644 (file)
@@ -869,8 +869,6 @@ endif # defined(BIN)
 FINALISE_rom   = $(MAKEROM) $(MAKEROM_FLAGS) $(TGT_MAKEROM_FLAGS) \
                  -i$(IDENT) -s 0 $@
 FINALISE_hrom  = $(FINALISE_rom)
-FINALISE_xrom  = $(MAKEROM) $(MAKEROM_FLAGS) $(TGT_MAKEROM_FLAGS) \
-                 -i$(IDENT) -n -s 0 $@
 
 # Some ROMs require specific flags to be passed to makerom.pl
 #
index e38fbca..dcabbdf 100644 (file)
@@ -12,7 +12,6 @@ LDFLAGS               += -N --no-check-sections
 #
 MEDIA          += rom
 MEDIA          += hrom
-MEDIA          += xrom
 MEDIA          += pxe
 MEDIA          += kpxe
 MEDIA          += kkpxe
@@ -26,7 +25,6 @@ MEDIA         += raw
 #
 PAD_rom                = $(PADIMG) --blksize=512 --byte=0xff $@
 PAD_hrom       = $(PAD_rom)
-PAD_xrom       = $(PAD_rom)
 PAD_dsk                = $(PADIMG) --blksize=512 $@
 PAD_hd         = $(PADIMG) --blksize=32768 $@
 
index 02e5497..43fcd64 100644 (file)
@@ -25,19 +25,6 @@ FILE_LICENCE ( GPL2_OR_LATER )
  */
 #define ROM_BANNER_TIMEOUT ( 2 * ( 18 * BANNER_TIMEOUT ) / 10 )
 
-/* We can load a ROM in two ways: have the BIOS load all of it (.rom prefix)
- * or have the BIOS load a stub that loads the rest using PCI (.xrom prefix).
- * The latter is not as widely supported, but allows the use of large ROMs
- * on some systems with crowded option ROM space.
- */
-
-#ifdef LOAD_ROM_FROM_PCI
-#define ROM_SIZE_VALUE _prefix_filesz_sect /* Amount to load in BIOS */
-#else
-#define ROM_SIZE_VALUE 0               /* Load amount (before compr. fixup) */
-#endif
-
-
        .text
        .code16
        .arch i386
@@ -46,12 +33,10 @@ FILE_LICENCE ( GPL2_OR_LATER )
        .org    0x00
 romheader:
        .word   0xAA55                  /* BIOS extension signature */
-romheader_size:        .byte ROM_SIZE_VALUE    /* Size in 512-byte blocks */
+romheader_size:        .byte 0                 /* Size in 512-byte blocks */
        jmp     init                    /* Initialisation vector */
 checksum:
-       .byte   0, 0
-real_size:
-       .word   0
+       .byte   0
        .org    0x16
        .word   undiheader
        .org    0x18
@@ -61,16 +46,10 @@ real_size:
        .size romheader, . - romheader
 
        .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
-#ifndef LOAD_ROM_FROM_PCI
        .ascii  "ADDB"
        .long   romheader_size
        .long   512
        .long   0
-#endif
-       .ascii  "ADDB"
-       .long   real_size
-       .long   512
-       .long   0
        .previous
 
 pciheader:
@@ -82,18 +61,17 @@ pciheader:
        .byte   0x03                    /* PCI data structure revision */
        .byte   0x02, 0x00, 0x00        /* Class code */
 pciheader_image_length:
-       .word   ROM_SIZE_VALUE          /* Image length */
+       .word   0                       /* Image length */
        .word   0x0001                  /* Revision level */
        .byte   0x00                    /* Code type */
        .byte   0x80                    /* Last image indicator */
 pciheader_runtime_length:
-       .word   ROM_SIZE_VALUE          /* Maximum run-time image length */
+       .word   0                       /* Maximum run-time image length */
        .word   0x0000                  /* Configuration utility code header */
        .word   0x0000                  /* DMTF CLP entry point */
        .equ pciheader_len, . - pciheader
        .size pciheader, . - pciheader
 
-#ifndef LOAD_ROM_FROM_PCI
        .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
        .ascii  "ADDW"
        .long   pciheader_image_length
@@ -104,7 +82,6 @@ pciheader_runtime_length:
        .long   512
        .long   0
        .previous
-#endif
 
 pnpheader:
        .ascii  "$PnP"                  /* Signature */
@@ -198,11 +175,6 @@ init:
        call    print_message
        call    print_pci_busdevfn
 
-#ifdef LOAD_ROM_FROM_PCI
-       /* Save PCI bus:dev.fn for later use */
-       movw    %ax, pci_busdevfn
-#endif
-
        /* Fill in product name string, if possible */
        movw    $prodstr_pci_id, %di
        call    print_pci_busdevfn
@@ -227,9 +199,6 @@ init:
        jne     no_pci3
        testb   %ah, %ah
        jnz     no_pci3
-#ifdef LOAD_ROM_FROM_PCI
-       incb    pcibios_present
-#endif
        movw    $init_message_pci, %si
        xorw    %di, %di
        call    print_message
@@ -341,7 +310,7 @@ pmm_scan:
        /* We have PMM and so a 1kB stack: preserve upper register halves */
        pushal
        /* Calculate required allocation size in %esi */
-       movzwl  real_size, %eax
+       movzbl  romheader_size, %eax
        shll    $9, %eax
        addl    $_textdata_memsz, %eax
        orw     $0xffff, %ax    /* Ensure allocation size is at least 64kB */
@@ -395,7 +364,7 @@ pmm_copy:
        movl    %edi, decompress_to
        /* Shrink ROM */
        movb    $_prefix_memsz_sect, romheader_size
-#if defined(SHRINK_WITHOUT_PMM) || defined(LOAD_ROM_FROM_PCI)
+#ifdef SHRINK_WITHOUT_PMM
        jmp     pmm_done
 pmm_fail:
        /* Print marker and copy ourselves to high memory */
@@ -410,28 +379,8 @@ pmm_fail:
 #endif
        /* Restore upper register halves */
        popal
-#if defined(LOAD_ROM_FROM_PCI)
-       call    load_from_pci
-       jc      load_err
-       jmp     load_ok
 no_pmm:
-       /* Cannot continue without PMM - print error message */
-       xorw    %di, %di
-       movw    $init_message_no_pmm, %si
-       call    print_message
-load_err:
-       /* Wait for five seconds to let user see message */
-       movw    $90, %cx
-1:     call    wait_for_tick
-       loop    1b
-       /* Mark environment as invalid and return */
-       movl    $0, decompress_to
-       jmp     out
 
-load_ok:
-#else
-no_pmm:
-#endif
        /* Update checksum */
        xorw    %bx, %bx
        xorw    %si, %si
@@ -476,14 +425,14 @@ no_pmm:
        movw    $init_message_done, %si
        call    print_message
        popf
-       jnz     out
+       jnz     2f
        /* Ctrl-B was pressed: invoke gPXE.  The keypress will be
         * picked up by the initial shell prompt, and we will drop
         * into a shell.
         */
        pushw   %cs
        call    exec
-out:
+2:
        /* Restore registers */
        popw    %gs
        popw    %fs
@@ -530,11 +479,6 @@ init_message_bbs:
 init_message_pmm:
        .asciz  " PMM"
        .size   init_message_pmm, . - init_message_pmm
-#ifdef LOAD_ROM_FROM_PCI
-init_message_no_pmm:
-       .asciz  "\nPMM required but not present!\n"
-       .size   init_message_no_pmm, . - init_message_no_pmm
-#endif
 init_message_int19:
        .asciz  " INT19"
        .size   init_message_int19, . - init_message_int19
@@ -560,32 +504,12 @@ image_source:
 /* Temporary decompression area
  *
  * May be either at HIGHMEM_LOADPOINT, or within PMM-allocated block.
- * If a PCI ROM load fails, this will be set to zero.
  */
        .globl  decompress_to
 decompress_to:
        .long   HIGHMEM_LOADPOINT
        .size   decompress_to, . - decompress_to
 
-#ifdef LOAD_ROM_FROM_PCI
-
-/* Set if the PCI BIOS is present, even <3.0 */
-pcibios_present:
-       .byte   0
-       .byte   0               /* for alignment */
-       .size   pcibios_present, . - pcibios_present
-
-/* PCI bus:device.function word
- *
- * Filled in by init in the .xrom case, so the remainder of the ROM
- * can be located.
- */
-pci_busdevfn:
-       .word   0
-       .size   pci_busdevfn, . - pci_busdevfn
-
-#endif
-
 /* BBS version
  *
  * Filled in by BBS BIOS.  We ignore the value.
@@ -604,289 +528,6 @@ bev_entry:
        lret
        .size   bev_entry, . - bev_entry
 
-
-#ifdef LOAD_ROM_FROM_PCI
-
-#define PCI_ROM_ADDRESS                0x30    /* Bits 31:11 address, 10:1 reserved */
-#define PCI_ROM_ADDRESS_ENABLE  0x00000001
-#define PCI_ROM_ADDRESS_MASK    0xfffff800
-
-#define PCIBIOS_READ_WORD      0xb109
-#define PCIBIOS_READ_DWORD     0xb10a
-#define PCIBIOS_WRITE_WORD     0xb10c
-#define PCIBIOS_WRITE_DWORD    0xb10d
-
-/* Determine size of PCI BAR
- *
- *  %bx : PCI bus:dev.fn to probe
- *  %di : Address of BAR to find size of
- * %edx : Mask of address bits within BAR
- *
- * %ecx : Size for a memory resource,
- *       1 for an I/O resource (bit 0 set).
- *   CF : Set on error or nonexistent device (all-ones read)
- *
- * All other registers saved.
- */
-pci_bar_size:
-       /* Save registers */
-       pushw   %ax
-       pushl   %esi
-       pushl   %edx
-
-       /* Read current BAR value */
-       movw    $PCIBIOS_READ_DWORD, %ax
-       int     $0x1a
-
-       /* Check for device existence and save it */
-       testb   $1, %cl         /* I/O bit? */
-       jz      1f
-       andl    $1, %ecx        /* If so, exit with %ecx = 1 */
-       jmp     99f
-1:     notl    %ecx
-       testl   %ecx, %ecx      /* Set ZF iff %ecx was all-ones */
-       notl    %ecx
-       jnz     1f
-       stc                     /* All ones - exit with CF set */
-       jmp     99f
-1:     movl    %ecx, %esi      /* Save in %esi */
-
-       /* Write all ones to BAR */
-       movl    %edx, %ecx
-       movw    $PCIBIOS_WRITE_DWORD, %ax
-       int     $0x1a
-
-       /* Read back BAR */
-       movw    $PCIBIOS_READ_DWORD, %ax
-       int     $0x1a
-
-       /* Find decode size from least set bit in mask BAR */
-       bsfl    %ecx, %ecx      /* Find least set bit, log2(decode size) */
-       jz      1f              /* Mask BAR should not be zero */
-       xorl    %edx, %edx
-       incl    %edx
-       shll    %cl, %edx       /* %edx = decode size */
-       jmp     2f
-1:     xorl    %edx, %edx      /* Return zero size for mask BAR zero */
-
-       /* Restore old BAR value */
-2:     movl    %esi, %ecx
-       movw    $PCIBIOS_WRITE_DWORD, %ax
-       int     $0x1a
-
-       movl    %edx, %ecx      /* Return size in %ecx */
-
-       /* Restore registers and return */
-99:    popl    %edx
-       popl    %esi
-       popw    %ax
-       ret
-
-       .size   pci_bar_size, . - pci_bar_size
-
-/* PCI ROM loader
- *
- * Called from init in the .xrom case to load the non-prefix code
- * using the PCI ROM BAR.
- *
- * Returns with carry flag set on error. All registers saved.
- */
-load_from_pci:
-       /*
-        * Use PCI BIOS access to config space. The calls take
-        *
-        *   %ah : 0xb1         %al : function
-        *   %bx : bus/dev/fn
-        *   %di : config space address
-        *  %ecx : value to write (for writes)
-        *
-        *  %ecx : value read (for reads)
-        *   %ah : return code
-        *    CF : error indication
-        *
-        * All registers not used for return are preserved.
-        */
-
-       /* Save registers and set up %es for big real mode */
-       pushal
-       pushw   %es
-       xorw    %ax, %ax
-       movw    %ax, %es
-
-       /* Check PCI BIOS presence */
-       cmpb    $0, pcibios_present
-       jz      err_pcibios
-
-       /* Load existing PCI ROM BAR */
-       movw    $PCIBIOS_READ_DWORD, %ax
-       movw    pci_busdevfn, %bx
-       movw    $PCI_ROM_ADDRESS, %di
-       int     $0x1a
-
-       /* Maybe it's already enabled? */
-       testb   $PCI_ROM_ADDRESS_ENABLE, %cl
-       jz      1f
-       movb    $1, %dl         /* Flag indicating no deinit required */
-       movl    %ecx, %ebp
-       jmp     check_rom
-
-       /* Determine PCI BAR decode size */
-1:     movl    $PCI_ROM_ADDRESS_MASK, %edx
-       call    pci_bar_size    /* Returns decode size in %ecx */
-       jc      err_size_insane /* CF => no ROM BAR, %ecx == ffffffff */
-
-       /* Check sanity of decode size */
-       xorl    %eax, %eax
-       movw    real_size, %ax
-       shll    $9, %eax        /* %eax = ROM size */
-       cmpl    %ecx, %eax
-       ja      err_size_insane /* Insane if decode size < ROM size */
-       cmpl    $0x100000, %ecx
-       jae     err_size_insane /* Insane if decode size >= 1MB */
-
-       /* Find a place to map the BAR
-        * In theory we should examine e820 and all PCI BARs to find a
-        * free region. However, we run at POST when e820 may not be
-        * available, and memory reads of an unmapped location are
-        * de facto standardized to return all-ones. Thus, we can get
-        * away with searching high memory (0xf0000000 and up) on
-        * multiples of the ROM BAR decode size for a sufficiently
-        * large all-ones region.
-        */
-       movl    %ecx, %edx      /* Save ROM BAR size in %edx */
-       movl    $0xf0000000, %ebp
-       xorl    %eax, %eax
-       notl    %eax            /* %eax = all ones */
-bar_search:
-       movl    %ebp, %edi
-       movl    %edx, %ecx
-       shrl    $2, %ecx
-       addr32 repe scasl       /* Scan %es:edi for anything not all-ones */
-       jz      bar_found
-       addl    %edx, %ebp
-       testl   $0x80000000, %ebp
-       jz      err_no_bar
-       jmp     bar_search
-
-bar_found:
-       movl    %edi, %ebp
-       /* Save current BAR value on stack to restore later */
-       movw    $PCIBIOS_READ_DWORD, %ax
-       movw    $PCI_ROM_ADDRESS, %di
-       int     $0x1a
-       pushl   %ecx
-
-       /* Map the ROM */
-       movw    $PCIBIOS_WRITE_DWORD, %ax
-       movl    %ebp, %ecx
-       orb     $PCI_ROM_ADDRESS_ENABLE, %cl
-       int     $0x1a
-
-       xorb    %dl, %dl        /* %dl = 0 : ROM was not already mapped */
-check_rom:
-       /* Check and copy ROM - enter with %dl set to skip unmapping,
-        * %ebp set to mapped ROM BAR address.
-        * We check up to prodstr_separator for equality, since anything past
-        * that may have been modified. Since our check includes the checksum
-        * byte over the whole ROM stub, that should be sufficient.
-        */
-       xorb    %dh, %dh        /* %dh = 0 : ROM did not fail integrity check */
-
-       /* Verify ROM integrity */
-       xorl    %esi, %esi
-       movl    %ebp, %edi
-       movl    $prodstr_separator, %ecx
-       addr32 repe cmpsb
-       jz      copy_rom
-       incb    %dh             /* ROM failed integrity check */
-       movl    %ecx, %ebp      /* Save number of bytes left */
-       jmp     skip_load
-
-copy_rom:
-       /* Print BAR address and indicate whether we mapped it ourselves */
-       movb    $( ' ' ), %al
-       xorw    %di, %di
-       call    print_character
-       movl    %ebp, %eax
-       call    print_hex_dword
-       movb    $( '-' ), %al   /* '-' for self-mapped */
-       subb    %dl, %al
-       subb    %dl, %al        /* '+' = '-' - 2 for BIOS-mapped */
-       call    print_character
-
-       /* Copy ROM at %ebp to PMM or highmem block */
-       movl    %ebp, %esi
-       movl    image_source, %edi
-       movzwl  real_size, %ecx
-       shll    $9, %ecx
-       addr32 es rep movsb
-       movl    %edi, decompress_to
-skip_load:
-       testb   %dl, %dl        /* Was ROM already mapped? */
-       jnz     skip_unmap
-
-       /* Unmap the ROM by restoring old ROM BAR */
-       movw    $PCIBIOS_WRITE_DWORD, %ax
-       movw    $PCI_ROM_ADDRESS, %di
-       popl    %ecx
-       int     $0x1a
-
-skip_unmap:
-       /* Error handling */
-       testb   %dh, %dh
-       jnz     err_rom_invalid
-       clc
-       jmp     99f
-
-err_pcibios:                   /* No PCI BIOS available */
-       movw    $load_message_no_pcibios, %si
-       xorl    %eax, %eax      /* "error code" is zero */
-       jmp     1f
-err_size_insane:               /* BAR has size (%ecx) that is insane */
-       movw    $load_message_size_insane, %si
-       movl    %ecx, %eax
-       jmp     1f
-err_no_bar:                    /* No space of sufficient size (%edx) found */
-       movw    $load_message_no_bar, %si
-       movl    %edx, %eax
-       jmp     1f
-err_rom_invalid:               /* Loaded ROM does not match (%ebp bytes left) */
-       movw    $load_message_rom_invalid, %si
-       movzbl  romheader_size, %eax
-       shll    $9, %eax
-       subl    %ebp, %eax
-       decl    %eax            /* %eax is now byte index of failure */
-
-1:     /* Error handler - print message at %si and dword in %eax */
-       xorw    %di, %di
-       call    print_message
-       call    print_hex_dword
-       stc
-99:    popw    %es
-       popal
-       ret
-
-       .size   load_from_pci, . - load_from_pci
-
-load_message_no_pcibios:
-       .asciz  "\nNo PCI BIOS found! "
-       .size   load_message_no_pcibios, . - load_message_no_pcibios
-
-load_message_size_insane:
-       .asciz  "\nROM resource has invalid size "
-       .size   load_message_size_insane, . - load_message_size_insane
-
-load_message_no_bar:
-       .asciz  "\nNo memory hole of sufficient size "
-       .size   load_message_no_bar, . - load_message_no_bar
-
-load_message_rom_invalid:
-       .asciz  "\nLoaded ROM is invalid at "
-       .size   load_message_rom_invalid, . - load_message_rom_invalid
-
-#endif /* LOAD_ROM_FROM_PCI */
-
-
 /* INT19 entry point
  *
  * Called via the hooked INT 19 if we detected a non-PnP BIOS.  We
@@ -947,14 +588,6 @@ exec:      /* Set %ds = %cs */
        pushw   %cs
        popw    %ds
 
-#ifdef LOAD_ROM_FROM_PCI
-       /* Don't execute if load was invalid */
-       cmpl    $0, decompress_to
-       jne     1f
-       lret
-1:
-#endif
-
        /* Print message as soon as possible */
        movw    $prodstr, %si
        xorw    %di, %di
diff --git a/src/arch/i386/prefix/xromprefix.S b/src/arch/i386/prefix/xromprefix.S
deleted file mode 100644 (file)
index d7c861f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * ROM prefix that loads the bulk of the ROM using direct PCI accesses,
- * so as not to take up much option ROM space on PCI <3.0 systems.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER )
-
-#define LOAD_ROM_FROM_PCI
-#include "romprefix.S"
index 33c75f9..77e8c7e 100644 (file)
@@ -194,7 +194,6 @@ SECTIONS {
      * Values calculated to save code from doing it
      *
      */
-    _prefix_filesz_sect = ( ( _prefix_filesz + 511 ) / 512 );
     _prefix_memsz_pgh  = ( ( _prefix_memsz + 15 ) / 16 );
     _prefix_memsz_sect = ( ( _prefix_memsz + 511 ) / 512 );
     _text16_memsz_pgh  = ( ( _text16_memsz + 15 ) / 16 );
index 68c3be9..aed3a56 100755 (executable)
@@ -130,14 +130,14 @@ sub writerom ($$) {
        close(R);
 }
 
-sub checksum ($$) {
-       my ($romref, $romsize) = @_;
+sub checksum ($) {
+       my ($romref) = @_;
 
        substr($$romref, 6, 1) = "\x00";
-       my $sum = unpack('%8C*', substr($$romref, 0, $romsize));
+       my $sum = unpack('%8C*', $$romref);
        substr($$romref, 6, 1) = chr(256 - $sum);
        # Double check
-       $sum = unpack('%8C*', substr($$romref, 0, $romsize));
+       $sum = unpack('%8C*', $$romref);
        if ($sum != 0) {
                print "Checksum fails\n"
        } elsif ($opts{'v'}) {
@@ -146,10 +146,10 @@ sub checksum ($$) {
 }
 
 sub makerom () {
-       my ($rom, $romsize, $stubsize);
+       my ($rom, $romsize);
 
-       getopts('3xni:p:s:v', \%opts);
-       $ARGV[0] or die "Usage: $0 [-s romsize] [-i ident] [-p vendorid,deviceid] [-n] [-x] [-3] rom-file\n";
+       getopts('3xi:p:s:v', \%opts);
+       $ARGV[0] or die "Usage: $0 [-s romsize] [-i ident] [-p vendorid,deviceid] [-x] [-3] rom-file\n";
        open(R, $ARGV[0]) or die "$ARGV[0]: $!\n";
        # Read in the whole ROM in one gulp
        my $filesize = read(R, $rom, MAXROMSIZE+1);
@@ -183,16 +183,10 @@ sub makerom () {
        }
        # Pad with 0xFF to $romsize
        $rom .= "\xFF" x ($romsize - length($rom));
-       # If this is a stub ROM, don't force header size to the full amount
-       if (!$opts{'n'}) {
-               if ($romsize >= 128 * 1024) {
-                       print "Warning: ROM size exceeds extension BIOS limit\n";
-               }
-               substr($rom, 2, 1) = chr(($romsize / 512) % 256);
-       } else {
-               $stubsize = ord(substr($rom, 2, 1)) * 512;
-               print "Stub size is $stubsize\n" if $opts{'v'};
+       if ($romsize >= 128 * 1024) {
+               print "Warning: ROM size exceeds extension BIOS limit\n";
        }
+       substr($rom, 2, 1) = chr(($romsize / 512) % 256);
        print "ROM size is $romsize\n" if $opts{'v'};
        # set the product string only if we don't have one yet
        my $pnp_hdr_offset = unpack('v', substr($rom, PNP_PTR_LOC, 2));
@@ -202,7 +196,7 @@ sub makerom () {
        # 3c503 requires last two bytes to be 0x80
        substr($rom, MINROMSIZE-2, 2) = "\x80\x80"
                if ($opts{'3'} and $romsize == MINROMSIZE);
-       checksum(\$rom, $opts{'n'} ? $stubsize : $romsize);
+       checksum(\$rom);
        writerom($ARGV[0], \$rom);
 }
 
@@ -219,7 +213,7 @@ sub modrom () {
        print "$filesize bytes read\n" if $opts{'v'};
        pcipnpheaders(\$rom, undef);
        undiheaders(\$rom);
-       checksum(\$rom, ord(substr($rom, 2, 1)) * 512);
+       checksum(\$rom);
        writerom($ARGV[0], \$rom);
 }