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, /r...@genroms/linuxboot.bin, /p...@i0cf8/s...@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 "/p...@i0cf8" + +static char * +build_pci_path(char *buf, int max, int bdf) +{ + // Build a glob string for a bdf - for example: /p...@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: /p...@i0cf8/ether...@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: /p...@i0cf8/i...@1,1/dr...@1/d...@0 + char pci[256], desc[256]; + snprintf(desc, sizeof(desc), "%s/dr...@%x/d...@%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: /p...@i0cf8/i...@1/f...@03f1/flo...@0 + char pci[256], desc[256]; + snprintf(desc, sizeof(desc), "%s/f...@%04x/flo...@%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: /p...@i0cf8/s...@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: /r...@genroms/linuxboot.bin + char desc[256]; + if (instance) + snprintf(desc, sizeof(desc), "/r...@%s", name); + else + snprintf(desc, sizeof(desc), "/ro...@%s", instance, name); + return find_prio(desc); } _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org http://www.seabios.org/mailman/listinfo/seabios