WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] hvmloader: Load physical PCI option ROMs

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvmloader: Load physical PCI option ROMs where available.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 01 Dec 2008 03:50:19 -0800
Delivery-date: Mon, 01 Dec 2008 03:51:11 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1227534208 0
# Node ID 521d4d90f6e31c76a01546b91ad88960800114d9
# Parent  612218519cb5f27d6bcd967ddbe0c93236de5c05
hvmloader: Load physical PCI option ROMs where available.

Signed-off-by: Shan Haitao <Haitao.shan@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/firmware/hvmloader/hvmloader.c |  195 ++++++++++++++++++++++++-----------
 1 files changed, 138 insertions(+), 57 deletions(-)

diff -r 612218519cb5 -r 521d4d90f6e3 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Mon Nov 24 11:17:44 2008 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c      Mon Nov 24 13:43:28 2008 +0000
@@ -322,60 +322,55 @@ static void pci_setup(void)
 }
 
 /*
- * 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.
+ * Scan the list of Option ROMs at @roms for one which supports 
+ * PCI (@vendor_id, @device_id). 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 0xE0000.
  */
-static int scan_etherboot_nic(void *copy_rom_dest)
+#define round_option_rom(x) (((x) + 2047) & ~2047)
+static int scan_option_rom(
+    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;
-    uint32_t devfn;
-    uint16_t class, vendor_id, device_id;
     uint8_t csum;
     int i;
 
-    for ( devfn = 0; devfn < 128; devfn++ )
-    {
-        class     = pci_readw(devfn, PCI_CLASS_DEVICE);
-        vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
-        device_id = pci_readw(devfn, PCI_DEVICE_ID);
-
-        if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
-            continue;
-
-        /* We're only interested in NICs. */
-        if ( class != 0x0200 )
-            continue;
-
-        rom = (struct option_rom_header *)etherboot;
-        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);
-        }
+    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;
@@ -392,15 +387,95 @@ static int scan_etherboot_nic(void *copy
                    ((char *)rom + pnph->next_header_offset))
                 : ((struct option_rom_pnp_header *)NULL));
 
-    printf("Loading PXE ROM ...\n");
+    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);
-    memcpy(copy_rom_dest, rom, rom->rom_size * 512);
-    return rom->rom_size * 512;
+
+    if ( (dest + rom->rom_size * 512) > 0xe0000u )
+    {
+        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);
+    return round_option_rom(rom->rom_size * 512);
+}
+
+/*
+ * 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(uint32_t copy_rom_dest)
+{
+    uint32_t devfn;
+    uint16_t class, vendor_id, device_id;
+
+    for ( devfn = 0; devfn < 128; 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) )
+            return scan_option_rom(
+                vendor_id, device_id, etherboot, copy_rom_dest);
+    }
+
+    return 0;
+}
+
+/*
+ * 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(uint32_t rom_base_addr)
+{
+    uint32_t devfn, option_rom_addr, rom_phys_addr = rom_base_addr;
+    uint16_t vendor_id, device_id;
+    uint8_t class;
+
+    for ( devfn = 0; devfn < 128; 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(
+            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. */
@@ -461,8 +536,9 @@ static uint16_t init_xen_platform_io_bas
 
 int main(void)
 {
-    int vgabios_sz = 0, etherboot_sz = 0, rombios_sz, smbios_sz;
-    uint32_t etherboot_phys_addr, vga_ram = 0;
+    int option_rom_sz = 0, vgabios_sz = 0, etherboot_sz = 0;
+    int rombios_sz, smbios_sz;
+    uint32_t etherboot_phys_addr, option_rom_phys_addr, vga_ram = 0;
     uint16_t xen_pfiob;
 
     printf("HVM Loader\n");
@@ -497,13 +573,13 @@ int main(void)
         printf("Loading Cirrus VGABIOS ...\n");
         memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
                vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
-        vgabios_sz = 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 = sizeof(vgabios_stdvga);
+        vgabios_sz = round_option_rom(sizeof(vgabios_stdvga));
         break;
     default:
         printf("No emulated VGA adaptor ...\n");
@@ -516,10 +592,11 @@ int main(void)
         printf("VGA RAM at %08x\n", vga_ram);
     }
 
-    /* Ethernet ROM is placed after VGA ROM, on next 2kB boundary. */
-    etherboot_phys_addr =
-        (VGABIOS_PHYSICAL_ADDRESS + vgabios_sz + 2047) & ~2047;
-    etherboot_sz = scan_etherboot_nic((void *)etherboot_phys_addr);
+    etherboot_phys_addr = VGABIOS_PHYSICAL_ADDRESS + vgabios_sz;
+    etherboot_sz = scan_etherboot_nic(etherboot_phys_addr);
+
+    option_rom_phys_addr = etherboot_phys_addr + etherboot_sz;
+    option_rom_sz = pci_load_option_roms(option_rom_phys_addr);
 
     if ( get_acpi_enabled() )
     {
@@ -538,6 +615,10 @@ int main(void)
         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);
     if ( smbios_sz )
         printf(" %05x-%05x: SMBIOS tables\n",
                SMBIOS_PHYSICAL_ADDRESS,

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] hvmloader: Load physical PCI option ROMs where available., Xen patchbot-unstable <=