Add additional PCI option rom checks.
authorKevin O'Connor <kevin@koconnor.net>
Sat, 6 Dec 2008 16:57:45 +0000 (11:57 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sat, 6 Dec 2008 16:57:45 +0000 (11:57 -0500)
PCI_ROM_ADDRESS is only valid for PCI_HEADER_TYPE_NORMAL devices.
Don't attempt to run a rom with address less than 16MiB.
Don't run roms for IDE code when native IDE support is available.
Also, move hardcode option rom defs to config.h.
Also, add some minor code cleanups.

src/config.h
src/optionroms.c

index 1a22cd86ae4b3744cdcfaa19f0feaf4442eb4e21..f6280a5e71ab2021a54a23c4bd98334dfd4676a1 100644 (file)
@@ -27,7 +27,7 @@
 #define CONFIG_PS2_MOUSE 1
 // Support for IDE disk code
 #define CONFIG_ATA 1
-// Support calling int155f on each keyboard press
+// Support calling int155f on each keyboard event
 #define CONFIG_KBD_CALL_INT15_4F 1
 // Support for booting from a CD
 #define CONFIG_CDROM_BOOT 1
@@ -39,7 +39,7 @@
 #define CONFIG_APMBIOS 1
 // Support int 19/18 system bootup support
 #define CONFIG_BOOT 1
-// Support int 14 parallel port calls
+// Support int 14 serial port calls
 #define CONFIG_SERIAL 1
 // Support int 17 parallel port calls
 #define CONFIG_LPT 1
 #define CONFIG_OPTIONROMS 1
 // Set if option roms are already copied to 0xc0000-0xf0000
 #define CONFIG_OPTIONROMS_DEPLOYED 1
+// When option roms are not pre-deployed, SeaBIOS can copy an optionrom
+// from flash for up to 2 devices.
+#define OPTIONROM_BDF_1 0x0000
+#define OPTIONROM_MEM_1 0x00000000
+#define OPTIONROM_BDF_2 0x0000
+#define OPTIONROM_MEM_2 0x00000000
 // Support an interactive boot menu at end of post.
 #define CONFIG_BOOTMENU 1
 
index 32a1f95bbe11fb7b6073023b2e6d9276ac1663ca..7783f8467180e277b7d70ecd8cdc08243daba1d4 100644 (file)
@@ -65,16 +65,12 @@ struct pnp_data {
     u16 staticresource;
 } PACKED;
 
-#define OPTIONROM_BDF_1 0x0000
-#define OPTIONROM_MEM_1 0x00000000
-#define OPTIONROM_BDF_2 0x0000
-#define OPTIONROM_MEM_2 0x00000000
-
 #define OPTION_ROM_START 0xc0000
 #define OPTION_ROM_SIGNATURE 0xaa55
 #define OPTION_ROM_ALIGN 2048
 #define OPTION_ROM_INITVECTOR offsetof(struct rom_header, initVector[0])
 #define PCI_ROM_SIGNATURE 0x52494350 // PCIR
+#define PCIROM_CODETYPE_X86 0
 
 // Next available position for an option rom.
 static u32 next_rom;
@@ -136,6 +132,16 @@ get_pnp_rom(struct rom_header *rom)
     return pnp;
 }
 
+// Check if a valid option rom has a pci struct; return it if so.
+static struct pci_data *
+get_pci_rom(struct rom_header *rom)
+{
+    struct pci_data *pci = (struct pci_data *)((u32)rom + rom->pcioffset);
+    if (pci->signature != PCI_ROM_SIGNATURE)
+        return NULL;
+    return pci;
+}
+
 // Add a BEV vector for a given pnp compatible option rom.
 static void
 add_ipl(struct rom_header *rom, struct pnp_data *pnp)
@@ -195,6 +201,12 @@ map_optionrom(u16 bdf)
 {
     dprintf(6, "Attempting to map option rom on dev %x\n", bdf);
 
+    u8 htype = pci_config_readb(bdf, PCI_HEADER_TYPE);
+    if ((htype & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
+        dprintf(6, "Skipping non-normal pci device (type=%x)\n", htype);
+        return NULL;
+    }
+
     u32 orig = pci_config_readl(bdf, PCI_ROM_ADDRESS);
     pci_config_writel(bdf, PCI_ROM_ADDRESS, ~PCI_ROM_ADDRESS_ENABLE);
     u32 sz = pci_config_readl(bdf, PCI_ROM_ADDRESS);
@@ -204,6 +216,11 @@ map_optionrom(u16 bdf)
     if (!sz || sz == 0xffffffff)
         goto fail;
 
+    if (orig < 16*1024*1024) {
+        dprintf(6, "Preset rom address doesn't look valid\n");
+        goto fail;
+    }
+
     // Looks like a rom - enable it.
     pci_config_writel(bdf, PCI_ROM_ADDRESS, orig | PCI_ROM_ADDRESS_ENABLE);
 
@@ -216,17 +233,14 @@ map_optionrom(u16 bdf)
             dprintf(6, "No option rom signature (got %x)\n", rom->signature);
             goto fail;
         }
-        if (!rom->pcioffset) {
-            dprintf(6, "No PCI offset\n");
-            goto fail;
-        }
-        struct pci_data *pci = (struct pci_data *)((u32)rom + rom->pcioffset);
-        if (pci->signature != PCI_ROM_SIGNATURE) {
-            dprintf(6, "Invalid pci signature (got %x)\n", pci->signature);
+        struct pci_data *pci = get_pci_rom(rom);
+        if (! pci) {
+            dprintf(6, "No valid pci signature found\n");
             goto fail;
         }
+
         u32 vd = (pci->device << 16) | pci->vendor;
-        if (vd == vendev && pci->type == 0)
+        if (vd == vendev && pci->type == PCIROM_CODETYPE_X86)
             // A match
             break;
         dprintf(6, "Didn't match vendev (got %x) or type (got %d)\n"
@@ -305,7 +319,8 @@ optionrom_setup()
         int bdf, max;
         foreachpci(bdf, max) {
             u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
-            if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA)
+            if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA
+                || (CONFIG_ATA && v == PCI_CLASS_STORAGE_IDE))
                 continue;
             init_optionrom(bdf);
         }