For each BAID/BCV/BEV lookup its boot priority in boot order file. If there is no entry for a device there assign it the lowest boot priority.
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/ahci.c | 4 ++-- src/ata.c | 13 ++++++++++--- src/boot.c | 47 +++++++++++++++++++++++++++++++++++------------ src/boot.h | 16 ++++++++++------ src/coreboot.c | 2 +- src/floppy.c | 8 +++++++- src/optionroms.c | 18 +++++++++++++++--- src/usb-msc.c | 4 ++-- src/virtio-blk.c | 2 +- 9 files changed, 83 insertions(+), 31 deletions(-)
diff --git a/src/ahci.c b/src/ahci.c index 03e39ad..a7f458f 100644 --- a/src/ahci.c +++ b/src/ahci.c @@ -382,7 +382,7 @@ ahci_port_init(struct ahci_ctrl_s *ctrl, u32 pnr) // Setup disk geometry translation. setup_translation(&port->drive); // Register with bcv system. - boot_add_hd(&port->drive); + boot_add_hd(&port->drive, -1); } else { // found cdrom (atapi) port->drive.blksize = CDROM_SECTOR_SIZE; @@ -397,7 +397,7 @@ ahci_port_init(struct ahci_ctrl_s *ctrl, u32 pnr)
// fill cdidmap if (iscd) - boot_add_cd(&port->drive); + boot_add_cd(&port->drive, -1); } dprintf(1, "%s\n", port->drive.desc);
diff --git a/src/ata.c b/src/ata.c index e01f842..872c5e3 100644 --- a/src/ata.c +++ b/src/ata.c @@ -783,8 +783,12 @@ init_drive_atapi(struct atadrive_s *dummy, u16 *buffer) dprintf(1, "%s\n", adrive_g->drive.desc);
// fill cdidmap - if (iscd) - boot_add_cd(&adrive_g->drive); + if (iscd) { + int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_bdf, + adrive_g->chan_gf->chanid, + adrive_g->slave); + boot_add_cd(&adrive_g->drive, prio); + }
return adrive_g; } @@ -833,8 +837,11 @@ init_drive_ata(struct atadrive_s *dummy, u16 *buffer) // Setup disk geometry translation. setup_translation(&adrive_g->drive);
+ int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_bdf, + adrive_g->chan_gf->chanid, + adrive_g->slave); // Register with bcv system. - boot_add_hd(&adrive_g->drive); + boot_add_hd(&adrive_g->drive, prio);
return adrive_g; } diff --git a/src/boot.c b/src/boot.c index 73ac5c8..e43d1a5 100644 --- a/src/boot.c +++ b/src/boot.c @@ -152,51 +152,54 @@ bootentry_add(int type, int prio, u32 data, const char *desc) *pprev = be; }
+#define P(P, DP) (((P) == -1) ? (DP) : (P)) + // Add a BEV vector for a given pnp compatible option rom. void -boot_add_bev(u16 seg, u16 bev, u16 desc) +boot_add_bev(u16 seg, u16 bev, u16 desc, int prio) { - bootentry_add(IPL_TYPE_BEV, DefaultBEVPrio, SEGOFF(seg, bev).segoff + bootentry_add(IPL_TYPE_BEV, P(prio, DefaultBEVPrio), SEGOFF(seg, bev).segoff , desc ? MAKE_FLATPTR(seg, desc) : "Unknown"); DefaultBEVPrio = DEFAULT_PRIO; }
// Add a bcv entry for an expansion card harddrive or legacy option rom void -boot_add_bcv(u16 seg, u16 ip, u16 desc) +boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio) { - bootentry_add(IPL_TYPE_BCV, DEFAULT_PRIO, SEGOFF(seg, ip).segoff + bootentry_add(IPL_TYPE_BCV, P(prio, DEFAULT_PRIO), SEGOFF(seg, ip).segoff , desc ? MAKE_FLATPTR(seg, desc) : "Legacy option rom"); }
void -boot_add_floppy(struct drive_s *drive_g) +boot_add_floppy(struct drive_s *drive_g, int prio) { - bootentry_add(IPL_TYPE_FLOPPY, DefaultFloppyPrio, (u32)drive_g + bootentry_add(IPL_TYPE_FLOPPY, P(prio, DefaultFloppyPrio), (u32)drive_g , drive_g->desc); }
void -boot_add_hd(struct drive_s *drive_g) +boot_add_hd(struct drive_s *drive_g, int prio) { - bootentry_add(IPL_TYPE_HARDDISK, DefaultHDPrio, (u32)drive_g + bootentry_add(IPL_TYPE_HARDDISK, P(prio, DefaultHDPrio), (u32)drive_g , drive_g->desc); }
void -boot_add_cd(struct drive_s *drive_g) +boot_add_cd(struct drive_s *drive_g, int prio) { - bootentry_add(IPL_TYPE_CDROM, DefaultCDPrio, (u32)drive_g + bootentry_add(IPL_TYPE_CDROM, P(prio, DefaultCDPrio), (u32)drive_g , drive_g->desc); }
// Add a CBFS payload entry void -boot_add_cbfs(void *data, const char *desc) +boot_add_cbfs(void *data, const char *desc, int prio) { - bootentry_add(IPL_TYPE_CBFS, DEFAULT_PRIO, (u32)data, desc); + bootentry_add(IPL_TYPE_CBFS, P(prio, DEFAULT_PRIO), (u32)data, desc); }
+#undef P
/**************************************************************** * Boot menu and BCV execution @@ -489,3 +492,23 @@ handle_19(void) SET_EBDA(boot_sequence, 0); do_boot(0); } + +int bootprio_find_pci_device(int bdf) +{ + return -1; +} + +int bootprio_find_ata_device(int bdf, int chanid, int slave) +{ + return -1; +} + +int bootprio_find_fdc_device(int bfd, int port, int fdid) +{ + return -1; +} + +int bootprio_find_named_rom(const char *name) +{ + return -1; +} diff --git a/src/boot.h b/src/boot.h index f1a428e..dd3cc49 100644 --- a/src/boot.h +++ b/src/boot.h @@ -35,14 +35,18 @@ struct ipl_s { // boot.c extern struct ipl_s IPL; void boot_setup(void); -void boot_add_bev(u16 seg, u16 bev, u16 desc); -void boot_add_bcv(u16 seg, u16 ip, u16 desc); +void boot_add_bev(u16 seg, u16 bev, u16 desc, int prio); +void boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio); struct drive_s; -void boot_add_floppy(struct drive_s *drive_g); -void boot_add_hd(struct drive_s *drive_g); -void boot_add_cd(struct drive_s *drive_g); -void boot_add_cbfs(void *data, const char *desc); +void boot_add_floppy(struct drive_s *drive_g, int prio); +void boot_add_hd(struct drive_s *drive_g, int prio); +void boot_add_cd(struct drive_s *drive_g, int prio); +void boot_add_cbfs(void *data, const char *desc, int prio);
void boot_prep(void); +int bootprio_find_pci_device(int bdf); +int bootprio_find_ata_device(int bdf, int chanid, int slave); +int bootprio_find_fdc_device(int bfd, int port, int fdid); +int bootprio_find_named_rom(const char *name);
#endif // __BOOT_H diff --git a/src/coreboot.c b/src/coreboot.c index dab0a54..503a6d2 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -608,7 +608,7 @@ register_cbfs_payload(void) if (!desc) break; snprintf(desc, MAXDESCSIZE, "Payload [%s]", &filename[4]); - boot_add_cbfs(file, desc); + boot_add_cbfs(file, desc, -1); } }
diff --git a/src/floppy.c b/src/floppy.c index 8986e39..c59b2fe 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -14,6 +14,9 @@ #include "pic.h" // eoi_pic1 #include "bregs.h" // struct bregs #include "boot.h" // boot_add_floppy +#include "pci.h" // pci_to_bdf +#include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA +
#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors #define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 @@ -117,7 +120,10 @@ addFloppy(int floppyid, int ftype, int driver) memcpy(&drive_g->lchs, &FloppyInfo[ftype].chs , sizeof(FloppyInfo[ftype].chs));
- boot_add_floppy(drive_g); + int bdf = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */ + int prio = bootprio_find_fdc_device(bdf, 0x3f0, floppyid); + + boot_add_floppy(drive_g, prio); return drive_g; }
diff --git a/src/optionroms.c b/src/optionroms.c index 2ac4325..87e645f 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -220,6 +220,16 @@ setRomSource(u64 *sources, struct rom_header *rom, u64 source) sources[((u32)rom - BUILD_ROM_START) / OPTION_ROM_ALIGN] = source; }
+static int +getRomPriority(u64 *sources, struct rom_header *rom) +{ + u64 source = sources[((u32)rom - BUILD_ROM_START) / OPTION_ROM_ALIGN]; + if (!source) + return -1; + if (source & RS_PCIROM) + return bootprio_find_pci_device(source); + return bootprio_find_named_rom(romfile_name(source)); +}
/**************************************************************** * Roms in CBFS @@ -408,21 +418,23 @@ optionrom_setup(void) pos += OPTION_ROM_ALIGN; continue; } + int prio = getRomPriority(sources, rom); pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN); struct pnp_data *pnp = get_pnp_rom(rom); if (! pnp) { // Legacy rom. - boot_add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0); + boot_add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0, prio); continue; } // PnP rom. if (pnp->bev) // Can boot system - add to IPL list. - boot_add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname); + boot_add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname, prio); else // Check for BCV (there may be multiple). while (pnp && pnp->bcv) { - boot_add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname); + boot_add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname, + prio); pnp = get_pnp_next(rom, pnp); } } diff --git a/src/usb-msc.c b/src/usb-msc.c index 378143e..2a6c31a 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -143,7 +143,7 @@ setup_drive_cdrom(struct disk_op_s *op) { op->drive_g->blksize = CDROM_SECTOR_SIZE; op->drive_g->sectors = (u64)-1; - boot_add_cd(op->drive_g); + boot_add_cd(op->drive_g, -1); return 0; }
@@ -171,7 +171,7 @@ setup_drive_hd(struct disk_op_s *op) setup_translation(op->drive_g);
// Register with bcv system. - boot_add_hd(op->drive_g); + boot_add_hd(op->drive_g, -1);
return 0; } diff --git a/src/virtio-blk.c b/src/virtio-blk.c index def8313..834523a 100644 --- a/src/virtio-blk.c +++ b/src/virtio-blk.c @@ -156,7 +156,7 @@ init_virtio_blk(u16 bdf) vdrive_g->drive.desc = desc;
setup_translation(&vdrive_g->drive); - boot_add_hd(&vdrive_g->drive); + boot_add_hd(&vdrive_g->drive, bootprio_find_pci_device(bdf));
vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
Add functions that find boot device path for pci/ata/floppy/rom devices.
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/boot.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 140 insertions(+), 4 deletions(-)
diff --git a/src/boot.c b/src/boot.c index e43d1a5..a670d3a 100644 --- a/src/boot.c +++ b/src/boot.c @@ -13,6 +13,7 @@ #include "boot.h" // struct ipl_s #include "cmos.h" // inb_cmos #include "paravirt.h" +#include "pci.h" //pci_bdf_to_*
struct ipl_s IPL;
@@ -493,22 +494,157 @@ handle_19(void) do_boot(0); }
-int bootprio_find_pci_device(int bdf) +/* + * function returns string representing firts device path element in 'dp' + * and puts pointer to the rest 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); + if (!node) { + warn_noalloc(); + return NULL; + } + 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 + 1, unit_address); +} + +static int match_next_node_address(const char *path, const char *addr, + const char **rest) +{ + char *node = dev_path_get_node(path, rest); + + if (!node) + return 0; + + int r = match_unit_address(node, addr); + free(node); + + return r; +} + +static int match_pci_node(const char *path, int bdf, const char **rest) +{ + char pci[7]; + int dev = pci_bdf_to_dev(bdf), fn = pci_bdf_to_fn(bdf); + + if (!fn) + snprintf(pci, sizeof(pci), "%x", dev); + else + snprintf(pci, sizeof(pci), "%x,%x", dev, fn); + + return match_next_node_address(path, pci, rest); +} + +#define FW_PCI_DOMAIN "/pci@i0cf8" + +static int find_pci_device(int bdf, int start_idx, const char **rest) +{ + int i; + + for (i = start_idx; i < IPL.fw_bootorder_count; i++) { + const char *path = IPL.fw_bootorder[i]; + + /* is pci domain? */ + if (memcmp(path, FW_PCI_DOMAIN, strlen(FW_PCI_DOMAIN))) + continue; + + if (match_pci_node(path + strlen(FW_PCI_DOMAIN), bdf, rest)) + return i; + } + return -1; }
+int bootprio_find_pci_device(int bdf) +{ + const char *rest; + + return find_pci_device(bdf, 0, &rest); +} + int bootprio_find_ata_device(int bdf, int chanid, int slave) { - return -1; + const char *rest; + int idx = 0; + + if (bdf == -1) + return -1; /* support only pci machine for now */ + + while((idx = find_pci_device(bdf, idx, &rest)) != -1) { + if (match_next_node_address(rest, chanid ? "1" : "0", &rest) && + match_next_node_address(rest, slave ? "1" : "0", &rest)) + break; + idx++; + } + + return idx; }
-int bootprio_find_fdc_device(int bfd, int port, int fdid) + +int bootprio_find_fdc_device(int bdf, int port, int fdid) { - return -1; + const char *rest; + int idx = 0; + char addr[5]; + + if (bdf == -1) + return -1; /* support only pci machine for now */ + + snprintf(addr, sizeof addr, "%04x", port); + + while((idx = find_pci_device(bdf, idx, &rest)) != -1) { + if (match_next_node_address(rest, addr, &rest) && + match_next_node_address(rest, fdid ? "1" : "0", &rest)) + break; + idx++; + } + + return idx; }
int bootprio_find_named_rom(const char *name) { + u8 i; + + for (i = 0; i < IPL.fw_bootorder_count; i++) { + const char *path = IPL.fw_bootorder[i]; + + /* is this rom file? */ + if (memcmp(path, "/rom@", strlen("/rom@"))) + continue; + + if (strcmp(path + strlen("/rom@"), name)) + return i; + } + return -1; }
On Mon, Dec 27, 2010 at 04:40:25PM +0200, Gleb Natapov wrote:
For each BAID/BCV/BEV lookup its boot priority in boot order file. If there is no entry for a device there assign it the lowest boot priority.
Signed-off-by: Gleb Natapov gleb@redhat.com
Thanks. I reworked this patch a bit and then committed it. I'm still looking through part 2 of the patch.
-Kevin