[SeaBIOS] [PATCH 0/9] Misc boot related cleanups

Kevin O'Connor kevin at koconnor.net
Thu Dec 30 02:23:13 CET 2010


On Wed, Dec 29, 2010 at 10:29:57PM +0200, Gleb Natapov wrote:
> On Wed, Dec 29, 2010 at 02:10:16PM -0500, Kevin O'Connor wrote:
> > BTW, I was thinking of ways to try and simplify this code.  What if we
> > tried doing an exact string match for the device, but if that fails
> > and a BDF is known for the device then do a prefix string search for
> > the PCI device?
> > 
> I don't see why this would be simpler. Also how can you do exact string
> match if BDF is not knows? You can't create device path without knowing
> BDF (well DF). My code works like OpenFirmware device path was designed
> to work: match device path one node at a time. This also allows for
> greater flexibility in qemu<->seabios interface.

Playing around with this a little further, I came up with the below.
I'm not sure if it's better.

I added a "magic" syntax to support rom instances (eg,
/rom2 at genroms/linuxboot.bin, /pci at i0cf8/scsi at 3/rom2).  I also stubbed
out some (admittedly wrong) pci bus path support.

Do you know what the magic qemu command-line options are to enable
bootindex for roms, floppies, scsi, etc is?

-Kevin


diff --git a/src/boot.c b/src/boot.c
index e83dcdc..836a8b2 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -13,6 +13,7 @@
 #include "boot.h" // func defs
 #include "cmos.h" // inb_cmos
 #include "paravirt.h" // romfile_loadfile
+#include "pci.h" //pci_bdf_to_*
 
 
 /****************************************************************
@@ -29,7 +30,7 @@ loadBootOrder(void)
     if (!f)
         return;
 
-    int i;
+    int i = 0;
     BootorderCount = 1;
     while (f[i]) {
         if (f[i] == '\n')
@@ -51,35 +52,122 @@ loadBootOrder(void)
         if (f) {
             *f = '\0';
             f++;
-            dprintf(3, "%d: %s\n", i, Bootorder[i]);
             i++;
         }
+        dprintf(3, "%d: %s\n", i, Bootorder[i]);
     } while(f);
 }
 
-int bootprio_find_pci_device(int bdf)
+// See if 'str' matches 'glob' - if glob contains an '*' character it
+// will match any number of characters in str that aren't a '/' or the
+// next glob character.
+static char *
+glob_prefix(const char *glob, const char *str)
 {
+    for (;;) {
+        if (!*glob && (!*str || *str == '/'))
+            return (char*)str;
+        if (*glob == *str) {
+            glob++;
+            str++;
+            continue;
+        }
+        if (*glob != '*')
+            return NULL;
+        if (*str && *str != '/' && *str != glob[1])
+            str++;
+        else
+            glob++;
+    }
+}
+
+// Search the bootorder list for the given glob pattern.
+static int
+find_prio(const char *glob)
+{
+    int i;
+    for (i = 0; i < BootorderCount; i++)
+        if (glob_prefix(glob, Bootorder[i]))
+            return i;
     return -1;
 }
 
+#define FW_PCI_DOMAIN "/pci at i0cf8"
+
+static char *
+build_pci_path(char *buf, int max, int bdf)
+{
+    // Build a glob string for a bdf - for example: /pci at i0cf8/*@1,2
+    char *p = buf;
+    int bus = pci_bdf_to_bus(bdf);
+    if (bus)
+        // XXX - this isn't the correct path syntax
+        p += snprintf(p, buf+max-p, "/bus%x", bus);
+
+    int dev = pci_bdf_to_dev(bdf), fn = pci_bdf_to_fn(bdf);
+    if (!fn)
+        snprintf(buf, buf+max-p, "%s/*@%x", FW_PCI_DOMAIN, dev);
+    else
+        snprintf(buf, buf+max-p, "%s/*@%x,%x", FW_PCI_DOMAIN, dev, fn);
+    return buf;
+}
+
+int bootprio_find_pci_device(int bdf)
+{
+    // Find pci device - for example: /pci at i0cf8/ethernet at 5
+    char pci[256];
+    return find_prio(build_pci_path(pci, sizeof(pci), bdf));
+}
+
 int bootprio_find_ata_device(int bdf, int chanid, int slave)
 {
-    return -1;
+    if (bdf == -1)
+        // support only pci machine for now
+        return -1;
+    // Find ata drive - for example: /pci at i0cf8/ide at 1,1/drive at 1/disk at 0
+    char pci[256], desc[256];
+    snprintf(desc, sizeof(desc), "%s/drive@%x/disk@%x"
+             , build_pci_path(pci, sizeof(pci), bdf), chanid, slave);
+    return find_prio(desc);
 }
 
-int bootprio_find_fdc_device(int bfd, int port, int fdid)
+int bootprio_find_fdc_device(int bdf, int port, int fdid)
 {
-    return -1;
+    if (bdf == -1)
+        // support only pci machine for now
+        return -1;
+    // Find floppy - for example: /pci at i0cf8/isa at 1/fdc at 03f1/floppy at 0
+    char pci[256], desc[256];
+    snprintf(desc, sizeof(desc), "%s/fdc@%04x/floppy@%x"
+             , build_pci_path(pci, sizeof(pci), bdf), port, fdid);
+    return find_prio(desc);
 }
 
 int bootprio_find_pci_rom(int bdf, int instance)
 {
-    return -1;
+    // Find pci rom - for example: /pci at i0cf8/scsi at 3/rom2
+    char pci[256], desc[256];
+    build_pci_path(pci, sizeof(pci), bdf);
+    if (instance)
+        snprintf(desc, sizeof(desc), "%s/rom%x", pci, instance);
+    else
+        snprintf(desc, sizeof(desc), "%s/rom", pci);
+    int prio = find_prio(desc);
+    if (prio >= 0)
+        return prio;
+    // Didn't find rom string - try to match just the pci device.
+    return find_prio(pci);
 }
 
 int bootprio_find_named_rom(const char *name, int instance)
 {
-    return -1;
+    // Find named rom - for example: /rom at genroms/linuxboot.bin
+    char desc[256];
+    if (instance)
+        snprintf(desc, sizeof(desc), "/rom@%s", name);
+    else
+        snprintf(desc, sizeof(desc), "/rom%d@%s", instance, name);
+    return find_prio(desc);
 }
 
 



More information about the SeaBIOS mailing list