grml...
[seabios.git] / src / boot.c
index 5bb179d261c53a2cf4a0c8d0bc96c73c5b3cf85b..9dd37fd57478d7522fb5251f85f64db88f9b479e 100644 (file)
@@ -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_*
 
 
 /****************************************************************
@@ -25,11 +26,14 @@ static int BootorderCount;
 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')
@@ -40,6 +44,7 @@ loadBootOrder(void)
     if (!Bootorder) {
         warn_noalloc();
         free(f);
+        BootorderCount = 0;
         return;
     }
 
@@ -48,38 +53,148 @@ 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';
+        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);
 }
 
 
@@ -166,7 +281,9 @@ bootentry_add(int type, int prio, u32 data, const char *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;
@@ -209,30 +326,30 @@ boot_add_bev(u16 seg, u16 bev, u16 desc, int prio)
 void
 boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio)
 {
-    bootentry_add(IPL_TYPE_BCV, defPrio(prio, DEFAULT_PRIO)
+    bootentry_add(IPL_TYPE_BCV, defPrio(prio, DefaultHDPrio)
                   , SEGOFF(seg, ip).segoff
                   , desc ? MAKE_FLATPTR(seg, desc) : "Legacy option rom");
 }
 
 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
@@ -247,6 +364,8 @@ boot_add_cbfs(void *data, const char *desc, int prio)
  * Boot menu and BCV execution
  ****************************************************************/
 
+#define DEFAULT_BOOTMENU_WAIT 2500
+
 // Show IPL option menu.
 static void
 interactive_bootmenu(void)
@@ -259,8 +378,12 @@ 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);
+       if (1 == 1) {
+               return;
+       }
+    int scan_code = get_keystroke(menutime);
     disable_bootsplash();
     if (scan_code != 0x86)
         /* not F12 */
@@ -341,11 +464,14 @@ boot_prep(void)
     // XXX - show available drives?
 
     // Allow user to modify BCV/IPL order.
+       dprintf(3, "[wurm] bp1\n");
     interactive_bootmenu();
+       dprintf(3, "[wurm] bp2\n");
     wait_threads();
 
     // Map drives and populate BEV list
     struct bootentry_s *pos = BootList;
+       dprintf(3, "[wurm] bp3\n");
     while (pos) {
         switch (pos->type) {
         case IPL_TYPE_BCV:
@@ -369,10 +495,12 @@ boot_prep(void)
         }
         pos = pos->next;
     }
+       dprintf(3, "[wurm] bp4\n");
 
     // If nothing added a floppy/hd boot - add it manually.
     add_bev(IPL_TYPE_FLOPPY, 0);
     add_bev(IPL_TYPE_HARDDISK, 0);
+       dprintf(3, "[wurm] bp5\n");
 }