@@ -67,6 +67,47 @@ boot_setup(void)
if (!(inb_cmos(CMOS_BIOS_BOOTFLAG1) & 1))
IPL.checkfloppysig = 1;
}
+
+ u32 file = romfile_find("bootorder");
+ if (!file)
+ return;
+
+ int filesize = romfile_size(file);
+ char *f = malloc_tmphigh(filesize);
+ dprintf(3, "bootorder file found (len %d)\n", filesize);
+
+ if (!f) {
+ dprintf(1, "can't allocate memory for bootorder file\n");
+ return;
+ }
+
+ romfile_copy(file, f, filesize);
+ int i;
+ IPL.fw_bootorder_count = 1;
+ while(f[i]) {
+ if (f[i] == '\n')
+ IPL.fw_bootorder_count++;
+ i++;
+ }
+ IPL.fw_bootorder = malloc_tmphigh(IPL.fw_bootorder_count*sizeof(char*));
+ if (!IPL.fw_bootorder) {
+ dprintf(1, "can't allocate memory for bootorder\n");
+ free(f);
+ return;
+ }
+
+ dprintf(3, "boot order:\n");
+ i = 0;
+ do {
+ IPL.fw_bootorder[i] = f;
+ f = strchr(f, '\n');
+ if (*f) {
+ *f = '\0';
+ f++;
+ dprintf(3, "%d: %s\n", i, IPL.fw_bootorder[i]);
+ i++;
+ }
+ } while(f);
}
// Add a BEV vector for a given pnp compatible option rom.
@@ -506,3 +547,78 @@ handle_19(void)
SET_EBDA(boot_sequence, 0);
do_boot(0);
}
+
+/*
+ * function returns string representing firts device path element in 'dp'
+ * and puts pointer to the reset of the device path into 'end'
+ */
+static char *dev_path_get_node(const char *dp, const char **end)
+{
+ int len;
+ char *node;
+
+ dp += 1; /* skip '/' */
+
+ *end = strchr(dp, '/');
+
+ if (*end == NULL) {
+ len = strlen(dp); /* last path element */
+ *end = dp + len;
+ }
+ else
+ len = *end - dp;
+
+ if (len == 0)
+ return NULL;
+
+ node = malloc_tmphigh(len + 1);
+ memcpy(node, dp, len);
+ node[len] = '\0';
+
+ return node;
+}
+
+static int match_unit_address(const char *pe, const char *unit_address)
+{
+ char *s = strchr(pe, '@');
+
+ if (s == NULL)
+ return 0;
+
+ return !strcmp(s, unit_address);
+}
+
+#define FW_PCI_DOMAIN "/pci@i0cf8"
+
+int bootprio_match_pci_device(int dev, int fn)
+{
+ int i, l;
+ char pci[7];
+
+ if (!fn)
+ l = snprintf(pci, sizeof(pci), "@%x", dev);
+ else
+ l = snprintf(pci, sizeof(pci), "@%x,%x", dev, fn);
+
+ for (i = 0; i < IPL.fw_bootorder_count; i++) {
+ char *node;
+ const char *next, *path = IPL.fw_bootorder[i];
+ int r;
+
+ /* is pci domain? */
+ if (memcmp(path, FW_PCI_DOMAIN, strlen(FW_PCI_DOMAIN)))
+ continue;
+
+ node = dev_path_get_node(path + strlen(FW_PCI_DOMAIN), &next);
+ if (node == NULL)
+ continue;
+
+ r = match_unit_address(node, pci);
+
+ free(node);
+ if (r)
+ return i;
+ }
+
+ return -1;
+}
@@ -20,6 +20,8 @@ struct ipl_s {
int bevcount, bcvcount;
u32 bootorder;
int checkfloppysig;
+ char **fw_bootorder;
+ int fw_bootorder_count;
};
#define IPL_TYPE_FLOPPY 0x01
@@ -44,5 +46,6 @@ void add_bcv(u16 seg, u16 ip, u16 desc);
struct drive_s;
void add_bcv_internal(struct drive_s *drive_g);
void boot_prep(void);
+int bootprio_match_pci_device(int dev, int fn);
#endif // __BOOT_H
@@ -74,6 +74,13 @@ struct pnp_data {
// The end of the last deployed rom.
u32 RomEnd = BUILD_ROM_START;
+static struct rom_boot_prio {
+ u32 addr;
+ int prio;
+} rom2prio[92];
+
+static int rom2prio_index;
+
/****************************************************************
* Helper functions
@@ -342,7 +349,20 @@ init_pcirom(u16 bdf, int isvga)
if (! rom)
// No ROM present.
return -1;
- return init_optionrom(rom, bdf, isvga);
+
+ int r = init_optionrom(rom, bdf, isvga);
+
+ if (r || !is_valid_rom(rom))
+ return r;
+
+ rom2prio[rom2prio_index].addr = (u32)rom;
+ rom2prio[rom2prio_index].prio =
+ bootprio_match_pci_device(pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf));
+ dprintf(3, "pci rom at memory address %x has boot prio %d\n",
+ rom2prio[rom2prio_index].addr, rom2prio[rom2prio_index].prio);
+ rom2prio_index++;
+
+ return r;
}
@@ -253,6 +253,17 @@ strtcpy(char *dest, const char *src, size_t len)
return dest;
}
+// locate first occurance of character c in the string s
+char *
+strchr(const char *s, int c)
+{
+ int i = 0;
+
+ while(s[i] && s[i] != c)
+ i++;
+
+ return s[i] ? (char*)&s[i] : NULL;
+}
/****************************************************************
* Keyboard calls
@@ -208,6 +208,7 @@ void *memcpy(void *d1, const void *s1, size_t len);
void iomemcpy(void *d, const void *s, u32 len);
void *memmove(void *d, const void *s, size_t len);
char *strtcpy(char *dest, const char *src, size_t len);
+char *strchr(const char *s, int c);
int get_keystroke(int msec);
// stacks.c