On Thu, Dec 30, 2010 at 12:20:17PM -0500, Kevin O'Connor wrote:
On Thu, Dec 30, 2010 at 08:01:15AM +0200, Gleb Natapov wrote:
On Wed, Dec 29, 2010 at 08:23:13PM -0500, Kevin O'Connor wrote:
Playing around with this a little further, I came up with the below. I'm not sure if it's better.
For me it looks more complicated (may be because I am more familiar with my own code ;))
The basic idea is to completely build the search string in the bootprio_find_X() function and then have it call find_prio() to return the priority.
I understand the code, I just don't see why this is easier. Your code also uses a lot of stack is this OK? It also assumes that device path is no greater then 256 bytes long. With multiple bridges we can go over this limit.
I see that you are starting to add regular expressions engine!
Yes - I'm not happy about that. Ultimately, rom loading needs some "fuzzy" matching capability, though.
I added a "magic" syntax to support rom instances (eg, /rom2@genroms/linuxboot.bin, /pci@i0cf8/scsi@3/rom2). I also stubbed out some (admittedly wrong) pci bus path support.
For supporting multiple pci buses we need to keep track of pci bus topology in upper layers. Bus number in bdf is meaningless for device path purposes.
Agreed. I just need some way to make sure a bus2 device doesn't grab the priority of a bus0 request.
Ah yeah. This will do the trick.
To boot from a certain file on a device OpenFirmware uses following syntax: /path/to/device:filename i.e parameter goes after ':'.
Thanks.
qemu -drive file=/dev/null,if=none,id=d1,media=cdrom -device ide-drive,drive=d1,bootindex=0 \
Thanks.
I've updated the patch - see below.
-Kevin
diff --git a/src/boot.c b/src/boot.c index e83dcdc..b47f0fe 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')
@@ -48,38 +49,119 @@ loadBootOrder(void) do { Bootorder[i] = f; f = strchr(f, '\n');
if (f) {
*f = '\0';
f++;
dprintf(3, "%d: %s\n", i, Bootorder[i]);
i++;
}
if (f)
*(f++) = '\0';
dprintf(3, "%d: %s\n", i+1, Bootorder[i]);
} while(f);i++;
}
-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 -1;return i+1;
}
+#define FW_PCI_DOMAIN "/pci@i0cf8"
+static char * +build_pci_path(char *buf, int max, const char *devname, int bdf) +{
- // Build the string path of a bdf - for example: /pci@i0cf8/isa@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, max, "/bus%x", bus);
- int dev = pci_bdf_to_dev(bdf), fn = pci_bdf_to_fn(bdf);
- if (fn)
snprintf(p, buf+max-p, "%s/%s@%x,%x", FW_PCI_DOMAIN, devname, dev, fn);
- else
snprintf(p, buf+max-p, "%s/%s@%x", FW_PCI_DOMAIN, devname, dev);
- return buf;
+}
+int bootprio_find_pci_device(int bdf) +{
- // Find pci device - for example: /pci@i0cf8/ethernet@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@i0cf8/ide@1,1/drive@1/disk@0
- char pci[256], desc[256];
- build_pci_path(pci, sizeof(pci), "*", bdf);
- snprintf(desc, sizeof(desc), "%s/drive@%x/disk@%x", pci, 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@i0cf8/isa@1/fdc@03f1/floppy@0
- char pci[256], desc[256];
- build_pci_path(pci, sizeof(pci), "isa", bdf);
- snprintf(desc, sizeof(desc), "%s/fdc@%04x/floppy@%x", pci, port, fdid);
- return find_prio(desc);
}
int bootprio_find_pci_rom(int bdf, int instance) {
- return -1;
- // Find pci rom - for example: /pci@i0cf8/scsi@3:rom2
- char pci[256], desc[256];
- build_pci_path(pci, sizeof(pci), "*", bdf);
- if (instance) {
snprintf(desc, sizeof(desc), "%s:rom%d", pci, instance);
return find_prio(desc);
- }
- return find_prio(pci);
}
int bootprio_find_named_rom(const char *name, int instance) {
- return -1;
- // Find named rom - for example: /rom@genroms/linuxboot.bin
- char desc[256];
- if (instance)
snprintf(desc, sizeof(desc), "/rom@%s:rom%d", name, instance);
- else
snprintf(desc, sizeof(desc), "/rom@%s", name);
- return find_prio(desc);
}
@@ -167,6 +249,8 @@ bootentry_add(int type, int prio, u32 data, const char *desc) be->priority = prio; be->data = data; be->description = desc ?: "?";
dprintf(3, "Registering bootable: %s (type:%d prio:%d data:%x)\n"
, be->description, type, prio, data);
// Add entry in sorted order. struct bootentry_s **pprev;
-- Gleb.