[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 4/5] hvmloader: Move option ROM loading into a separate optionnal file
Make load_rom field in struct bios_config an optionnal callback rather than a boolean value. It allow BIOS specific code to implement it's own option ROM loading methods. Facilities to scan PCI devices, extract an deploy ROMs are moved into a separate file that can be compiled optionnaly. Signed-off-by: Julian Pidancet <julian.pidancet@xxxxxxxxx> --- tools/firmware/hvmloader/Makefile | 2 +- tools/firmware/hvmloader/config.h | 3 +- tools/firmware/hvmloader/hvmloader.c | 218 +-------------------------------- tools/firmware/hvmloader/option_rom.h | 7 + tools/firmware/hvmloader/optionroms.c | 189 ++++++++++++++++++++++++++++ tools/firmware/hvmloader/rombios.c | 63 +++++++++- tools/firmware/hvmloader/seabios.c | 5 +- 7 files changed, 259 insertions(+), 228 deletions(-) create mode 100644 tools/firmware/hvmloader/optionroms.c diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile index 1ea32db..5a5ee41 100644 --- a/tools/firmware/hvmloader/Makefile +++ b/tools/firmware/hvmloader/Makefile @@ -39,7 +39,7 @@ CIRRUSVGA_DEBUG ?= n ROMBIOS_DIR := ../rombios ifneq ($(ROMBIOS_DIR),) -OBJS += 32bitbios_support.o rombios.o +OBJS += optionroms.o 32bitbios_support.o rombios.o CFLAGS += -DENABLE_ROMBIOS ROMBIOS_ROM := $(ROMBIOS_DIR)/BIOS-bochs-latest endif diff --git a/tools/firmware/hvmloader/config.h b/tools/firmware/hvmloader/config.h index 9cac9c1..1f80263 100644 --- a/tools/firmware/hvmloader/config.h +++ b/tools/firmware/hvmloader/config.h @@ -18,8 +18,7 @@ struct bios_config { unsigned int bios_address; /* ROMS */ - int load_roms; - unsigned int optionrom_start, optionrom_end; + void (*load_roms)(void); void (*bios_load)(const struct bios_config *config); diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c index f120ffe..ad50189 100644 --- a/tools/firmware/hvmloader/hvmloader.c +++ b/tools/firmware/hvmloader/hvmloader.c @@ -24,16 +24,11 @@ #include "hypercall.h" #include "config.h" #include "pci_regs.h" -#include "option_rom.h" #include "apic_regs.h" #include "acpi/acpi2_0.h" #include <xen/version.h> #include <xen/hvm/params.h> -#define ROM_INCLUDE_VGABIOS -#define ROM_INCLUDE_ETHERBOOT -#include "roms.inc" - asm ( " .text \n" " .globl _start \n" @@ -147,169 +142,6 @@ static void init_hypercalls(void) printf("Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion); } -/* - * Scan the list of Option ROMs at @roms for one which supports - * PCI (@vendor_id, @device_id) found at slot @devfn. If one is found, - * copy it to @dest and return its size rounded up to a multiple 2kB. This - * function will not copy ROMs beyond address option_rom_end. - */ -#define round_option_rom(x) (((x) + 2047) & ~2047) -static int scan_option_rom( - unsigned int option_rom_end, - uint8_t devfn, uint16_t vendor_id, uint16_t device_id, - void *roms, uint32_t dest) -{ - struct option_rom_header *rom; - struct option_rom_pnp_header *pnph; - struct option_rom_pci_header *pcih; - uint8_t csum; - int i; - - static uint32_t orom_ids[64]; - static int nr_roms; - - /* Avoid duplicate ROMs. */ - for ( i = 0; i < nr_roms; i++ ) - if ( orom_ids[i] == (vendor_id | ((uint32_t)device_id << 16)) ) - return 0; - - rom = roms; - for ( ; ; ) - { - /* Invalid signature means we're out of option ROMs. */ - if ( strncmp((char *)rom->signature, "\x55\xaa", 2) || - (rom->rom_size == 0) ) - break; - - /* Invalid checksum means we're out of option ROMs. */ - csum = 0; - for ( i = 0; i < (rom->rom_size * 512); i++ ) - csum += ((uint8_t *)rom)[i]; - if ( csum != 0 ) - break; - - /* Check the PCI PnP header (if any) for a match. */ - pcih = (struct option_rom_pci_header *) - ((char *)rom + rom->pci_header_offset); - if ( (rom->pci_header_offset != 0) && - !strncmp((char *)pcih->signature, "PCIR", 4) && - (pcih->vendor_id == vendor_id) && - (pcih->device_id == device_id) ) - goto found; - - rom = (struct option_rom_header *) - ((char *)rom + rom->rom_size * 512); - } - - return 0; - - found: - /* Find the PnP expansion header (if any). */ - pnph = ((rom->expansion_header_offset != 0) - ? ((struct option_rom_pnp_header *) - ((char *)rom + rom->expansion_header_offset)) - : ((struct option_rom_pnp_header *)NULL)); - while ( (pnph != NULL) && strncmp((char *)pnph->signature, "$PnP", 4) ) - pnph = ((pnph->next_header_offset != 0) - ? ((struct option_rom_pnp_header *) - ((char *)rom + pnph->next_header_offset)) - : ((struct option_rom_pnp_header *)NULL)); - - printf("Loading PCI Option ROM ...\n"); - if ( (pnph != NULL) && (pnph->manufacturer_name_offset != 0) ) - printf(" - Manufacturer: %s\n", - (char *)rom + pnph->manufacturer_name_offset); - if ( (pnph != NULL) && (pnph->product_name_offset != 0) ) - printf(" - Product name: %s\n", - (char *)rom + pnph->product_name_offset); - - if ( (dest + rom->rom_size * 512 + 1) > option_rom_end ) - { - printf("Option ROM size %x exceeds available space\n", - rom->rom_size * 512); - return 0; - } - - orom_ids[nr_roms++] = vendor_id | ((uint32_t)device_id << 16); - memcpy((void *)dest, rom, rom->rom_size * 512); - *(uint8_t *)(dest + rom->rom_size * 512) = devfn; - return round_option_rom(rom->rom_size * 512 + 1); -} - -/* - * Scan the PCI bus for the first NIC supported by etherboot, and copy - * the corresponding rom data to *copy_rom_dest. Returns the length of the - * selected rom, or 0 if no NIC found. - */ -static int scan_etherboot_nic(unsigned int option_rom_end, - uint32_t copy_rom_dest) -{ - uint16_t class, vendor_id, device_id, devfn; - int rom_size = 0; - - for ( devfn = 0; (devfn < 256) && !rom_size; devfn++ ) - { - class = pci_readw(devfn, PCI_CLASS_DEVICE); - vendor_id = pci_readw(devfn, PCI_VENDOR_ID); - device_id = pci_readw(devfn, PCI_DEVICE_ID); - - /* We're only interested in NICs. */ - if ( (vendor_id != 0xffff) && - (device_id != 0xffff) && - (class == 0x0200) ) - rom_size = scan_option_rom( - option_rom_end, - devfn, vendor_id, device_id, etherboot, copy_rom_dest); - } - - return rom_size; -} - -/* - * Scan the PCI bus for the devices that have an option ROM, and copy - * the corresponding rom data to rom_phys_addr. - */ -static int pci_load_option_roms(unsigned int option_rom_end, - uint32_t rom_base_addr) -{ - uint32_t option_rom_addr, rom_phys_addr = rom_base_addr; - uint16_t vendor_id, device_id, devfn, class; - - for ( devfn = 0; devfn < 256; devfn++ ) - { - class = pci_readb(devfn, PCI_CLASS_DEVICE + 1); - vendor_id = pci_readw(devfn, PCI_VENDOR_ID); - device_id = pci_readw(devfn, PCI_DEVICE_ID); - - if ( (vendor_id == 0xffff) && (device_id == 0xffff) ) - continue; - - /* - * Currently only scan options from mass storage devices and serial - * bus controller (Fibre Channel included). - */ - if ( (class != 0x1) && (class != 0xc) ) - continue; - - option_rom_addr = pci_readl(devfn, PCI_ROM_ADDRESS); - if ( !option_rom_addr ) - continue; - - /* Ensure Expansion Bar is enabled before copying */ - pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr | 0x1); - - rom_phys_addr += scan_option_rom( - option_rom_end, - devfn, vendor_id, device_id, - (void *)(option_rom_addr & ~2047), rom_phys_addr); - - /* Restore the default original value of Expansion Bar */ - pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr); - } - - return rom_phys_addr - rom_base_addr; -} - /* Replace possibly erroneous memory-size CMOS fields with correct values. */ static void cmos_write_memory_size(void) { @@ -421,8 +253,6 @@ static void acpi_enable_sci(void) int main(void) { const struct bios_config *bios; - int option_rom_sz = 0, vgabios_sz = 0, etherboot_sz = 0; - uint32_t etherboot_phys_addr = 0, option_rom_phys_addr = 0; int acpi_enabled; /* Initialise hypercall stubs with RET, rendering them no-ops. */ @@ -471,41 +301,7 @@ int main(void) } if ( bios->load_roms ) - { - switch ( virtual_vga ) - { - case VGA_cirrus: - printf("Loading Cirrus VGABIOS ...\n"); - memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, - vgabios_cirrusvga, sizeof(vgabios_cirrusvga)); - vgabios_sz = round_option_rom(sizeof(vgabios_cirrusvga)); - break; - case VGA_std: - printf("Loading Standard VGABIOS ...\n"); - memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, - vgabios_stdvga, sizeof(vgabios_stdvga)); - vgabios_sz = round_option_rom(sizeof(vgabios_stdvga)); - break; - case VGA_pt: - printf("Loading VGABIOS of passthroughed gfx ...\n"); - vgabios_sz = round_option_rom( - (*(uint8_t *)(VGABIOS_PHYSICAL_ADDRESS+2)) * 512); - break; - default: - printf("No emulated VGA adaptor ...\n"); - break; - } - - etherboot_phys_addr = VGABIOS_PHYSICAL_ADDRESS + vgabios_sz; - if ( etherboot_phys_addr < bios->optionrom_start ) - etherboot_phys_addr = bios->optionrom_start; - etherboot_sz = scan_etherboot_nic(bios->optionrom_end, - etherboot_phys_addr); - - option_rom_phys_addr = etherboot_phys_addr + etherboot_sz; - option_rom_sz = pci_load_option_roms(bios->optionrom_end, - option_rom_phys_addr); - } + bios->load_roms(); acpi_enabled = !strncmp(xenstore_read("platform/acpi", "1"), "1", 1); @@ -536,18 +332,6 @@ int main(void) if ( SCRATCH_PHYSICAL_ADDRESS != scratch_start ) printf(" %05x-%05lx: Scratch space\n", SCRATCH_PHYSICAL_ADDRESS, scratch_start); - if ( vgabios_sz ) - printf(" %05x-%05x: VGA BIOS\n", - VGABIOS_PHYSICAL_ADDRESS, - VGABIOS_PHYSICAL_ADDRESS + vgabios_sz - 1); - if ( etherboot_sz ) - printf(" %05x-%05x: Etherboot ROM\n", - etherboot_phys_addr, - etherboot_phys_addr + etherboot_sz - 1); - if ( option_rom_sz ) - printf(" %05x-%05x: PCI Option ROMs\n", - option_rom_phys_addr, - option_rom_phys_addr + option_rom_sz - 1); printf(" %05x-%05x: Main BIOS\n", bios->bios_address, bios->bios_address + bios->image_size - 1); diff --git a/tools/firmware/hvmloader/option_rom.h b/tools/firmware/hvmloader/option_rom.h index f0c7ec4..1ada3e2 100644 --- a/tools/firmware/hvmloader/option_rom.h +++ b/tools/firmware/hvmloader/option_rom.h @@ -47,6 +47,13 @@ struct option_rom_pci_header { uint16_t reserved; } __attribute__ ((packed)); +#define round_option_rom(x) (((x) + 2047) & ~2047) +int scan_etherboot_nic(unsigned int option_rom_end, + uint32_t copy_rom_dest, + void *etherboot_rom); +int pci_load_option_roms(unsigned int option_rom_end, + uint32_t rom_base_addr); + #endif /* __HVMLOADER_OPTION_ROM_H__ */ /* diff --git a/tools/firmware/hvmloader/optionroms.c b/tools/firmware/hvmloader/optionroms.c new file mode 100644 index 0000000..e35aebc --- /dev/null +++ b/tools/firmware/hvmloader/optionroms.c @@ -0,0 +1,189 @@ +/* + * optionroms.c: Option ROM loading support. + * + * Leendert van Doorn, leendert@xxxxxxxxxxxxxx + * Copyright (c) 2005, International Business Machines Corporation. + * + * Copyright (c) 2006, Keir Fraser, XenSource Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "config.h" +#include "option_rom.h" +#include "util.h" +#include "pci_regs.h" + +/* + * Scan the list of Option ROMs at @roms for one which supports + * PCI (@vendor_id, @device_id) found at slot @devfn. If one is found, + * copy it to @dest and return its size rounded up to a multiple 2kB. This + * function will not copy ROMs beyond address option_rom_end. + */ +static int scan_option_rom( + unsigned int option_rom_end, + uint8_t devfn, uint16_t vendor_id, uint16_t device_id, + void *roms, uint32_t dest) +{ + struct option_rom_header *rom; + struct option_rom_pnp_header *pnph; + struct option_rom_pci_header *pcih; + uint8_t csum; + int i; + + static uint32_t orom_ids[64]; + static int nr_roms; + + /* Avoid duplicate ROMs. */ + for ( i = 0; i < nr_roms; i++ ) + if ( orom_ids[i] == (vendor_id | ((uint32_t)device_id << 16)) ) + return 0; + + rom = roms; + for ( ; ; ) + { + /* Invalid signature means we're out of option ROMs. */ + if ( strncmp((char *)rom->signature, "\x55\xaa", 2) || + (rom->rom_size == 0) ) + break; + + /* Invalid checksum means we're out of option ROMs. */ + csum = 0; + for ( i = 0; i < (rom->rom_size * 512); i++ ) + csum += ((uint8_t *)rom)[i]; + if ( csum != 0 ) + break; + + /* Check the PCI PnP header (if any) for a match. */ + pcih = (struct option_rom_pci_header *) + ((char *)rom + rom->pci_header_offset); + if ( (rom->pci_header_offset != 0) && + !strncmp((char *)pcih->signature, "PCIR", 4) && + (pcih->vendor_id == vendor_id) && + (pcih->device_id == device_id) ) + goto found; + + rom = (struct option_rom_header *) + ((char *)rom + rom->rom_size * 512); + } + + return 0; + + found: + /* Find the PnP expansion header (if any). */ + pnph = ((rom->expansion_header_offset != 0) + ? ((struct option_rom_pnp_header *) + ((char *)rom + rom->expansion_header_offset)) + : ((struct option_rom_pnp_header *)NULL)); + while ( (pnph != NULL) && strncmp((char *)pnph->signature, "$PnP", 4) ) + pnph = ((pnph->next_header_offset != 0) + ? ((struct option_rom_pnp_header *) + ((char *)rom + pnph->next_header_offset)) + : ((struct option_rom_pnp_header *)NULL)); + + printf("Loading PCI Option ROM ...\n"); + if ( (pnph != NULL) && (pnph->manufacturer_name_offset != 0) ) + printf(" - Manufacturer: %s\n", + (char *)rom + pnph->manufacturer_name_offset); + if ( (pnph != NULL) && (pnph->product_name_offset != 0) ) + printf(" - Product name: %s\n", + (char *)rom + pnph->product_name_offset); + + if ( (dest + rom->rom_size * 512 + 1) > option_rom_end ) + { + printf("Option ROM size %x exceeds available space\n", + rom->rom_size * 512); + return 0; + } + + orom_ids[nr_roms++] = vendor_id | ((uint32_t)device_id << 16); + memcpy((void *)dest, rom, rom->rom_size * 512); + *(uint8_t *)(dest + rom->rom_size * 512) = devfn; + return round_option_rom(rom->rom_size * 512 + 1); +} + +/* + * Scan the PCI bus for the first NIC supported by etherboot, and copy + * the corresponding rom data to *copy_rom_dest. Returns the length of the + * selected rom, or 0 if no NIC found. + */ +int scan_etherboot_nic(unsigned int option_rom_end, + uint32_t copy_rom_dest, + void *etherboot_rom) +{ + uint16_t class, vendor_id, device_id, devfn; + int rom_size = 0; + + for ( devfn = 0; (devfn < 256) && !rom_size; devfn++ ) + { + class = pci_readw(devfn, PCI_CLASS_DEVICE); + vendor_id = pci_readw(devfn, PCI_VENDOR_ID); + device_id = pci_readw(devfn, PCI_DEVICE_ID); + + /* We're only interested in NICs. */ + if ( (vendor_id != 0xffff) && + (device_id != 0xffff) && + (class == 0x0200) ) + rom_size = scan_option_rom( + option_rom_end, + devfn, vendor_id, device_id, etherboot_rom, copy_rom_dest); + } + + return rom_size; +} + +/* + * Scan the PCI bus for the devices that have an option ROM, and copy + * the corresponding rom data to rom_phys_addr. + */ +int pci_load_option_roms(unsigned int option_rom_end, + uint32_t rom_base_addr) +{ + uint32_t option_rom_addr, rom_phys_addr = rom_base_addr; + uint16_t vendor_id, device_id, devfn, class; + + for ( devfn = 0; devfn < 256; devfn++ ) + { + class = pci_readb(devfn, PCI_CLASS_DEVICE + 1); + vendor_id = pci_readw(devfn, PCI_VENDOR_ID); + device_id = pci_readw(devfn, PCI_DEVICE_ID); + + if ( (vendor_id == 0xffff) && (device_id == 0xffff) ) + continue; + + /* + * Currently only scan options from mass storage devices and serial + * bus controller (Fibre Channel included). + */ + if ( (class != 0x1) && (class != 0xc) ) + continue; + + option_rom_addr = pci_readl(devfn, PCI_ROM_ADDRESS); + if ( !option_rom_addr ) + continue; + + /* Ensure Expansion Bar is enabled before copying */ + pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr | 0x1); + + rom_phys_addr += scan_option_rom( + option_rom_end, + devfn, vendor_id, device_id, + (void *)(option_rom_addr & ~2047), rom_phys_addr); + + /* Restore the default original value of Expansion Bar */ + pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr); + } + + return rom_phys_addr - rom_base_addr; +} diff --git a/tools/firmware/hvmloader/rombios.c b/tools/firmware/hvmloader/rombios.c index d5831aa..e0d4182 100644 --- a/tools/firmware/hvmloader/rombios.c +++ b/tools/firmware/hvmloader/rombios.c @@ -29,10 +29,13 @@ #include "pci_regs.h" #include "util.h" #include "hypercall.h" +#include "option_rom.h" #include <xen/hvm/params.h> #define ROM_INCLUDE_ROMBIOS +#define ROM_INCLUDE_VGABIOS +#define ROM_INCLUDE_ETHERBOOT #include "roms.inc" #define ROMBIOS_BEGIN 0x000F0000 @@ -64,6 +67,61 @@ static void rombios_setup_bios_info(void) memset(info, 0, sizeof(*info)); } +static void rombios_load_roms(void) +{ + int option_rom_sz = 0, vgabios_sz = 0, etherboot_sz = 0; + uint32_t etherboot_phys_addr = 0, option_rom_phys_addr = 0; + + switch ( virtual_vga ) + { + case VGA_cirrus: + printf("Loading Cirrus VGABIOS ...\n"); + memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, + vgabios_cirrusvga, sizeof(vgabios_cirrusvga)); + vgabios_sz = round_option_rom(sizeof(vgabios_cirrusvga)); + break; + case VGA_std: + printf("Loading Standard VGABIOS ...\n"); + memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, + vgabios_stdvga, sizeof(vgabios_stdvga)); + vgabios_sz = round_option_rom(sizeof(vgabios_stdvga)); + break; + case VGA_pt: + printf("Loading VGABIOS of passthroughed gfx ...\n"); + vgabios_sz = round_option_rom( + (*(uint8_t *)(VGABIOS_PHYSICAL_ADDRESS+2)) * 512); + break; + default: + printf("No emulated VGA adaptor ...\n"); + break; + } + + etherboot_phys_addr = VGABIOS_PHYSICAL_ADDRESS + vgabios_sz; + if ( etherboot_phys_addr < OPTIONROM_PHYSICAL_ADDRESS ) + etherboot_phys_addr = OPTIONROM_PHYSICAL_ADDRESS; + etherboot_sz = scan_etherboot_nic(OPTIONROM_PHYSICAL_END, + etherboot_phys_addr, + etherboot); + + option_rom_phys_addr = etherboot_phys_addr + etherboot_sz; + option_rom_sz = pci_load_option_roms(OPTIONROM_PHYSICAL_END, + option_rom_phys_addr); + + printf("Option ROMs:\n"); + if ( vgabios_sz ) + printf(" %05x-%05x: VGA BIOS\n", + VGABIOS_PHYSICAL_ADDRESS, + VGABIOS_PHYSICAL_ADDRESS + vgabios_sz - 1); + if ( etherboot_sz ) + printf(" %05x-%05x: Etherboot ROM\n", + etherboot_phys_addr, + etherboot_phys_addr + etherboot_sz - 1); + if ( option_rom_sz ) + printf(" %05x-%05x: PCI Option ROMs\n", + option_rom_phys_addr, + option_rom_phys_addr + option_rom_sz - 1); +} + static void rombios_load(const struct bios_config *config) { uint32_t bioshigh; @@ -158,10 +216,7 @@ struct bios_config rombios_config = { .bios_address = ROMBIOS_PHYSICAL_ADDRESS, - .load_roms = 1, - - .optionrom_start = OPTIONROM_PHYSICAL_ADDRESS, - .optionrom_end = OPTIONROM_PHYSICAL_END, + .load_roms = rombios_load_roms, .bios_load = rombios_load, diff --git a/tools/firmware/hvmloader/seabios.c b/tools/firmware/hvmloader/seabios.c index 3045157..15ddf35 100644 --- a/tools/firmware/hvmloader/seabios.c +++ b/tools/firmware/hvmloader/seabios.c @@ -143,10 +143,7 @@ struct bios_config seabios_config = { .bios_address = SEABIOS_PHYSICAL_ADDRESS, - .load_roms = 0, - - .optionrom_start = 0, - .optionrom_end = 0, + .load_roms = NULL, .bios_load = NULL, -- Julian Pidancet _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |