Skip to content

Commit

Permalink
[build] Allow ISA ROMs to be built
Browse files Browse the repository at this point in the history
The build process has for a long time assumed that every ROM is a PCI
ROM, and will always include the PCI header and PCI-related
functionality (such as checking the PCI BIOS version, including the
PCI bus:dev.fn address within the ROM product name string, etc.).

While real ISA cards are no longer in use, some virtualisation
environments (notably VirtualBox) have support only for ISA ROMs.
This can cause problems: in particular, VirtualBox will call our
initialisation entry point with random garbage in %ax, which we then
treat as the PCI bus:dev.fn address of the autoboot device: this
generally prevents the default boot sequence from using any network
devices.

Create .isarom and .pcirom prefixes which can be used to explicitly
specify the type of ROM to be created.  (Note that the .mrom prefix
always implies a PCI ROM, since the .mrom mechanism relies on
reconfiguring PCI BARs.)

Make .rom a magic prefix which will automatically select the
appropriate PCI or ISA ROM prefix for ROMs defined via a PCI_ROM() or
ISA_ROM() macro.  To maintain backwards compatibility, we default to
building a PCI ROM for anything which is not directly derived from a
PCI_ROM() or ISA_ROM() macro (e.g. bin/intel.rom).

Add a selection of targets to "make everything" to ensure that the
(relatively obscure) ISA ROM build process is included within the
per-commit QA checks.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Aug 22, 2014
1 parent 5b72cf0 commit 705907f
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 30 deletions.
1 change: 1 addition & 0 deletions src/Makefile
Expand Up @@ -147,6 +147,7 @@ all : $(ALL)
#
everything :
$(Q)$(MAKE) --no-print-directory $(ALL) \
bin/3c509.rom bin/intel.rom bin/intel.mrom \
bin-i386-efi/ipxe.efi bin-i386-efi/ipxe.efidrv \
bin-i386-efi/ipxe.efirom \
bin-x86_64-efi/ipxe.efi bin-x86_64-efi/ipxe.efidrv \
Expand Down
7 changes: 5 additions & 2 deletions src/Makefile.housekeeping
Expand Up @@ -902,19 +902,22 @@ CLEANUP += $(BIN)/NIC # Doesn't match the $(BIN)/*.* pattern
# derive the variables:
#
# TGT_ELEMENTS : the elements of the target (e.g. "dfe538 prism2_pci")
# TGT_PREFIX : the prefix type (e.g. "rom")
# TGT_PREFIX : the prefix type (e.g. "pcirom")
# TGT_DRIVERS : the driver for each element (e.g. "rtl8139 prism2_pci")
# TGT_ROM_NAME : the ROM name (e.g. "dfe538")
#
DRIVERS_ipxe = $(DRIVERS)
CARD_DRIVER = $(firstword $(DRIVER_$(1)) $(1))
TGT_ELEMENTS = $(subst --, ,$(firstword $(subst ., ,$(notdir $@))))
TGT_PREFIX = $(word 2,$(subst ., ,$(notdir $@)))
TGT_ROM_NAME = $(firstword $(TGT_ELEMENTS))
TGT_DRIVERS = $(strip $(if $(DRIVERS_$(TGT_ROM_NAME)), \
$(DRIVERS_$(TGT_ROM_NAME)), \
$(foreach TGT_ELEMENT,$(TGT_ELEMENTS), \
$(call CARD_DRIVER,$(TGT_ELEMENT))) ))
TGT_PREFIX_NAME = $(word 2,$(subst ., ,$(notdir $@)))
TGT_PREFIX = $(strip $(if $(filter rom,$(TGT_PREFIX_NAME)), \
$(ROM_TYPE_$(TGT_ROM_NAME))rom, \
$(TGT_PREFIX_NAME)))

# Look up ROM IDs for the current target
# (e.g. "bin/dfe538--prism2_pci.rom.tmp") and derive the variables:
Expand Down
10 changes: 9 additions & 1 deletion src/arch/i386/Makefile.pcbios
Expand Up @@ -16,6 +16,8 @@ SRCDIRS += arch/i386/drivers/net
#
MEDIA += rom
MEDIA += mrom
MEDIA += pcirom
MEDIA += isarom
MEDIA += pxe
MEDIA += kpxe
MEDIA += kkpxe
Expand All @@ -31,6 +33,8 @@ MEDIA += exe
#
PAD_rom = $(PERL) $(PADIMG) --blksize=512 --byte=0xff
PAD_mrom = $(PAD_rom)
PAD_pcirom = $(PAD_rom)
PAD_isarom = $(PAD_rom)
PAD_dsk = $(PERL) $(PADIMG) --blksize=512
PAD_hd = $(PERL) $(PADIMG) --blksize=32768
PAD_exe = $(PERL) $(PADIMG) --blksize=512
Expand All @@ -39,11 +43,15 @@ PAD_exe = $(PERL) $(PADIMG) --blksize=512
#
FINALISE_rom = $(PERL) $(FIXROM)
FINALISE_mrom = $(FINALISE_rom)
FINALISE_pcirom = $(FINALISE_rom)
FINALISE_isarom = $(FINALISE_rom)

# Use $(ROMS) rather than $(DRIVERS) for "allroms" and "allmroms"
# Use $(ROMS) rather than $(DRIVERS) for "allroms", "allmroms", etc.
#
LIST_NAME_rom := ROMS
LIST_NAME_mrom := ROMS
LIST_NAME_pcirom := ROMS
LIST_NAME_isarom := ROMS

# rule to make a non-emulation ISO boot image
NON_AUTO_MEDIA += iso
Expand Down
25 changes: 25 additions & 0 deletions src/arch/i386/prefix/isaromprefix.S
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/

FILE_LICENCE ( GPL2_OR_LATER )

#define BUSTYPE "ISAR"
#define _rom_start _isarom_start
#include "romprefix.S"
27 changes: 24 additions & 3 deletions src/arch/i386/prefix/libprefix.S
Expand Up @@ -94,6 +94,29 @@ print_character:
ret
.size print_character, . - print_character

/*****************************************************************************
* Utility function: print space
*
* Parameters:
* %ds:di : output buffer (or %di=0 to print to console)
* Returns:
* %ds:di : next character in output buffer (if applicable)
*****************************************************************************
*/
.section ".prefix.lib", "awx", @progbits
.code16
.globl print_space
print_space:
/* Preserve registers */
pushw %ax
/* Print space */
movb $( ' ' ), %al
call print_character
/* Restore registers and return */
popw %ax
ret
.size print_space, . - print_space

/*****************************************************************************
* Utility function: print a NUL-terminated string
*
Expand Down Expand Up @@ -231,12 +254,10 @@ print_kill_line:
movb $( '\r' ), %al
call print_character
/* Print 79 spaces */
movb $( ' ' ), %al
movw $79, %cx
1: call print_character
1: call print_space
loop 1b
/* Print CR */
movb $( '\r' ), %al
call print_character
/* Restore registers and return */
popw %cx
Expand Down
4 changes: 2 additions & 2 deletions src/arch/i386/prefix/mromprefix.S
Expand Up @@ -32,8 +32,8 @@ FILE_LICENCE ( GPL2_OR_LATER )

#define ROMPREFIX_EXCLUDE_PAYLOAD 1
#define ROMPREFIX_MORE_IMAGES 1
#define _rom_start _mrom_start
#include "romprefix.S"
#define _pcirom_start _mrom_start
#include "pciromprefix.S"

.text
.arch i386
Expand Down
25 changes: 25 additions & 0 deletions src/arch/i386/prefix/pciromprefix.S
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/

FILE_LICENCE ( GPL2_OR_LATER )

#define BUSTYPE "PCIR"
#define _rom_start _pcirom_start
#include "romprefix.S"
77 changes: 55 additions & 22 deletions src/arch/i386/prefix/romprefix.S
Expand Up @@ -44,6 +44,12 @@ FILE_LICENCE ( GPL2_OR_LATER )
#define INDICATOR 0x00
#else
#define INDICATOR 0x80
#endif

/* Default to building a PCI ROM if no bus type is specified
*/
#ifndef BUSTYPE
#define BUSTYPE "PCIR"
#endif

.text
Expand All @@ -64,8 +70,10 @@ checksum:
.word ipxeheader
.org 0x16
.word undiheader
.ifeqs BUSTYPE, "PCIR"
.org 0x18
.word pciheader
.endif
.org 0x1a
.word pnpheader
.size romheader, . - romheader
Expand All @@ -77,6 +85,7 @@ checksum:
.long 0
.previous

.ifeqs BUSTYPE, "PCIR"
pciheader:
.ascii "PCIR" /* Signature */
.word pci_vendor_id /* Vendor identification */
Expand Down Expand Up @@ -107,6 +116,7 @@ pciheader_runtime_length:
.long 512
.long 0
.previous
.endif /* PCIR */

/* PnP doesn't require any particular alignment, but IBM
* BIOSes will scan on 16-byte boundaries rather than using
Expand Down Expand Up @@ -148,11 +158,14 @@ mfgstr:
*/
prodstr:
.ascii PRODUCT_SHORT_NAME
.ifeqs BUSTYPE, "PCIR"
prodstr_separator:
.byte 0
.ascii "(PCI "
prodstr_pci_id:
.asciz "xx:xx.x)" /* Filled in by init code */
.ascii "xx:xx.x)" /* Filled in by init code */
.endif /* PCIR */
.byte 0
.size prodstr, . - prodstr

.globl undiheader
Expand All @@ -167,7 +180,7 @@ undiheader:
.word _data16_memsz /* Stack segment size */
.word _data16_memsz /* Data segment size */
.word _text16_memsz /* Code segment size */
.ascii "PCIR" /* Bus type */
.ascii BUSTYPE /* Bus type */
.equ undiheader_len, . - undiheader
.size undiheader, . - undiheader

Expand Down Expand Up @@ -208,31 +221,39 @@ init:
pushw %cs
popw %ds

/* Store PCI 3.0 runtime segment address for later use */
movw %bx, %gs

/* Store PCI bus:dev.fn address */
movw %ax, init_pci_busdevfn

/* Print message as early as possible */
movw $init_message, %si
xorw %di, %di
call print_message
call print_pci_busdevfn

/* Fill in product name string, if possible */
/* Store PCI 3.0 runtime segment address for later use, if
* applicable.
*/
.ifeqs BUSTYPE, "PCIR"
movw %bx, %gs
.endif

/* Store PCI bus:dev.fn address, print PCI bus:dev.fn, and add
* PCI bus:dev.fn to product name string, if applicable.
*/
.ifeqs BUSTYPE, "PCIR"
xorw %di, %di
call print_space
movw %ax, init_pci_busdevfn
call print_pci_busdevfn
movw $prodstr_pci_id, %di
call print_pci_busdevfn
movb $( ' ' ), prodstr_separator
.endif

/* Print segment address */
movb $( ' ' ), %al
xorw %di, %di
call print_character
call print_space
movw %cs, %ax
call print_hex_word

/* Check for PCI BIOS version */
/* Check for PCI BIOS version, if applicable */
.ifeqs BUSTYPE, "PCIR"
pushl %ebx
pushl %edx
pushl %edi
Expand Down Expand Up @@ -283,6 +304,7 @@ no_pci3:
1: popl %edi
popl %edx
popl %ebx
.endif /* PCIR */

/* Check for PnP BIOS. Although %es:di should point to the
* PnP BIOS signature on entry, some BIOSes fail to do this.
Expand Down Expand Up @@ -396,13 +418,13 @@ no_pmm:
loop 1b
subb %bl, checksum

/* Copy self to option ROM space. Required for PCI3.0, which
* loads us to a temporary location in low memory. Will be a
* no-op for lower PCI versions.
/* Copy self to option ROM space, if applicable. Required for
* PCI3.0, which loads us to a temporary location in low
* memory. Will be a no-op for lower PCI versions.
*/
movb $( ' ' ), %al
.ifeqs BUSTYPE, "PCIR"
xorw %di, %di
call print_character
call print_space
movw %gs, %ax
call print_hex_word
movzbw romheader_size, %cx
Expand All @@ -411,10 +433,13 @@ no_pmm:
xorw %si, %si
xorw %di, %di
cs rep movsb
.endif

/* Skip prompt if this is not the first PCI function */
/* Skip prompt if this is not the first PCI function, if applicable */
.ifeqs BUSTYPE, "PCIR"
testb $PCI_FUNC_MASK, init_pci_busdevfn
jnz no_shell
.endif
/* Prompt for POST-time shell */
movw $init_message_prompt, %si
xorw %di, %di
Expand Down Expand Up @@ -564,11 +589,13 @@ init_message:
.ascii "\n"
.ascii PRODUCT_NAME
.ascii "\n"
.asciz "iPXE (http://ipxe.org) "
.asciz "iPXE (http://ipxe.org)"
.size init_message, . - init_message
.ifeqs BUSTYPE, "PCIR"
init_message_pci:
.asciz " PCI"
.size init_message_pci, . - init_message_pci
.endif /* PCIR */
init_message_pnp:
.asciz " PnP"
.size init_message_pnp, . - init_message_pnp
Expand All @@ -591,9 +618,11 @@ init_message_done:
/* PCI bus:dev.fn
*
*/
.ifeqs BUSTYPE, "PCIR"
init_pci_busdevfn:
.word 0
.size init_pci_busdevfn, . - init_pci_busdevfn
.endif /* PCIR */

/* Image source area
*
Expand Down Expand Up @@ -732,14 +761,18 @@ exec: /* Set %ds = %cs */
lret
.section ".text16", "awx", @progbits
1:
/* Retrieve PCI bus:dev.fn */
/* Retrieve PCI bus:dev.fn, if applicable */
.ifeqs BUSTYPE, "PCIR"
movw init_pci_busdevfn, %ax
.endif

/* Set up %ds for access to .data16 */
movw %bx, %ds

/* Store PCI bus:dev.fn */
/* Store PCI bus:dev.fn, if applicable */
.ifeqs BUSTYPE, "PCIR"
movw %ax, autoboot_busdevfn
.endif

/* Call main() */
pushl $main
Expand Down

0 comments on commit 705907f

Please sign in to comment.