#include "boot.h" // func defs
#include "cmos.h" // inb_cmos
#include "paravirt.h" // romfile_loadfile
+#include "pci.h" //pci_bdf_to_*
/****************************************************************
static void
loadBootOrder(void)
{
+ if (!CONFIG_BOOTORDER)
+ return;
+
char *f = romfile_loadfile("bootorder", NULL);
if (!f)
return;
- int i;
+ int i = 0;
BootorderCount = 1;
while (f[i]) {
if (f[i] == '\n')
if (!Bootorder) {
warn_noalloc();
free(f);
+ BootorderCount = 0;
return;
}
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';
+ nullTrailingSpace(Bootorder[i]);
+ dprintf(3, "%d: %s\n", i+1, Bootorder[i]);
+ i++;
+ } while (f);
+}
+
+// See if 'str' starts with '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 == '*') {
+ if (!*str || *str == '/' || *str == glob[1])
+ glob++;
+ else
+ str++;
+ continue;
}
- } while(f);
+ if (*glob != *str)
+ return NULL;
+ glob++;
+ str++;
+ }
}
-int bootprio_find_pci_device(int bdf)
+// Search the bootorder list for the given glob pattern.
+static int
+find_prio(const char *glob)
{
+ dprintf(1, "Searching bootorder for: %s\n", glob);
+ int i;
+ for (i = 0; i < BootorderCount; i++)
+ if (glob_prefix(glob, Bootorder[i]))
+ return i+1;
return -1;
}
-int bootprio_find_ata_device(int bdf, int chanid, int slave)
+#define FW_PCI_DOMAIN "/pci@i0cf8"
+
+static char *
+build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci)
{
- return -1;
+ // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2
+ char *p = buf;
+ if (pci->parent) {
+ p = build_pci_path(p, max, "pci-bridge", pci->parent);
+ } else {
+ if (pci->rootbus)
+ p += snprintf(p, max, "/pci-root@%x", pci->rootbus);
+ p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN);
+ }
+
+ int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf);
+ p += snprintf(p, buf+max-p, "/%s@%x", devname, dev);
+ if (fn)
+ p += snprintf(p, buf+max-p, ",%x", fn);
+ return p;
}
-int bootprio_find_fdc_device(int bfd, int port, int fdid)
+int bootprio_find_pci_device(struct pci_device *pci)
{
- return -1;
+ if (!CONFIG_BOOTORDER)
+ return -1;
+ // Find pci device - for example: /pci@i0cf8/ethernet@5
+ char desc[256];
+ build_pci_path(desc, sizeof(desc), "*", pci);
+ return find_prio(desc);
}
-int bootprio_find_pci_rom(int bdf, int instance)
+int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave)
{
- return -1;
+ if (!CONFIG_BOOTORDER)
+ return -1;
+ if (!pci)
+ // support only pci machine for now
+ return -1;
+ // Find ata drive - for example: /pci@i0cf8/ide@1,1/drive@1/disk@0
+ char desc[256], *p;
+ p = build_pci_path(desc, sizeof(desc), "*", pci);
+ snprintf(p, desc+sizeof(desc)-p, "/drive@%x/disk@%x", chanid, slave);
+ return find_prio(desc);
+}
+
+int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid)
+{
+ if (!CONFIG_BOOTORDER)
+ return -1;
+ if (!pci)
+ // support only pci machine for now
+ return -1;
+ // Find floppy - for example: /pci@i0cf8/isa@1/fdc@03f1/floppy@0
+ char desc[256], *p;
+ p = build_pci_path(desc, sizeof(desc), "isa", pci);
+ snprintf(p, desc+sizeof(desc)-p, "/fdc@%04x/floppy@%x", port, fdid);
+ return find_prio(desc);
+}
+
+int bootprio_find_pci_rom(struct pci_device *pci, int instance)
+{
+ if (!CONFIG_BOOTORDER)
+ return -1;
+ // Find pci rom - for example: /pci@i0cf8/scsi@3:rom2
+ char desc[256], *p;
+ p = build_pci_path(desc, sizeof(desc), "*", pci);
+ if (instance)
+ snprintf(p, desc+sizeof(desc)-p, ":rom%d", instance);
+ return find_prio(desc);
}
int bootprio_find_named_rom(const char *name, int instance)
{
- return -1;
+ if (!CONFIG_BOOTORDER)
+ return -1;
+ // Find named rom - for example: /rom@genroms/linuxboot.bin
+ char desc[256], *p;
+ p = desc + snprintf(desc, sizeof(desc), "/rom@%s", name);
+ if (instance)
+ snprintf(p, desc+sizeof(desc)-p, ":rom%d", instance);
+ return find_prio(desc);
+}
+
+int bootprio_find_usb(struct pci_device *pci, u64 path)
+{
+ if (!CONFIG_BOOTORDER)
+ return -1;
+ // Find usb - for example: /pci@i0cf8/usb@1,2/hub@1/network@0/ethernet@0
+ int i;
+ char desc[256], *p;
+ p = build_pci_path(desc, sizeof(desc), "usb", pci);
+ for (i=56; i>0; i-=8) {
+ int port = (path >> i) & 0xff;
+ if (port != 0xff)
+ p += snprintf(p, desc+sizeof(desc)-p, "/hub@%x", port+1);
+ }
+ snprintf(p, desc+sizeof(desc)-p, "/*@%x", (u32)(path & 0xff)+1);
+ return find_prio(desc);
}
be->type = type;
be->priority = prio;
be->data = data;
- be->description = desc;
+ 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;
}
void
-boot_add_floppy(struct drive_s *drive_g, int prio)
+boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio)
{
bootentry_add(IPL_TYPE_FLOPPY, defPrio(prio, DefaultFloppyPrio)
- , (u32)drive_g, drive_g->desc);
+ , (u32)drive_g, desc);
}
void
-boot_add_hd(struct drive_s *drive_g, int prio)
+boot_add_hd(struct drive_s *drive_g, const char *desc, int prio)
{
bootentry_add(IPL_TYPE_HARDDISK, defPrio(prio, DefaultHDPrio)
- , (u32)drive_g, drive_g->desc);
+ , (u32)drive_g, desc);
}
void
-boot_add_cd(struct drive_s *drive_g, int prio)
+boot_add_cd(struct drive_s *drive_g, const char *desc, int prio)
{
bootentry_add(IPL_TYPE_CDROM, defPrio(prio, DefaultCDPrio)
- , (u32)drive_g, drive_g->desc);
+ , (u32)drive_g, desc);
}
// Add a CBFS payload entry
* Boot menu and BCV execution
****************************************************************/
+#define DEFAULT_BOOTMENU_WAIT 2500
+
// Show IPL option menu.
static void
interactive_bootmenu(void)
printf("Press F12 for boot menu.\n\n");
+ u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT);
enable_bootsplash();
- int scan_code = get_keystroke(CONFIG_BOOTMENU_WAIT);
+ int scan_code = get_keystroke(menutime);
disable_bootsplash();
if (scan_code != 0x86)
/* not F12 */