With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
qemu -drive file=nonbootable.iso,if=none,id=d1,media=cdrom -device ide-drive,drive=d1,bootindex=0 -drive file=rhel6.iso,if=none,id=d2,media=cdrom -device ide-drive,drive=d2,bootindex=80 -drive if=none,file=fda.img,id=fda -drive if=none,file=fdb.img,id=fdb -global isa-fdc.bootindexB=30 -global isa-fdc.bootindexA=40 -global isa-fdc.driveA=fda -global isa-fdc.driveB=fdb -netdev type=user,id=net1 -device virtio-pci-net,netdev=net1,bootindex=20 -netdev type=user,id=net2 -device e1000,netdev=net2,bootindex=10 -drive file=/home/gleb_local/debian-testing1.img,if=none,id=d3 -device virtio-blk-pci,multifunction=on,drive=d3,bootindex=100
Seabios tries to boot from nonbootable.iso (ata1-0) first, then from virtio-net nic, then from e1000 nic, then from floppy and finally from rhel6.iso (ata1-1) at which point boot succeeds.
Signed-off-by: Gleb Natapov gleb@redhat.com diff --git a/src/ahci.c b/src/ahci.c index ee404d4..1dcbec1 100644 --- a/src/ahci.c +++ b/src/ahci.c @@ -376,7 +376,7 @@ ahci_port_init(struct ahci_ctrl_s *ctrl, u32 pnr) // Setup disk geometry translation. setup_translation(&port->drive); // Register with bcv system. - add_bcv_internal(&port->drive); + add_bcv_internal(&port->drive, -1); } else { // found cdrom (atapi) port->drive.blksize = CDROM_SECTOR_SIZE; diff --git a/src/ata.c b/src/ata.c index bdec225..d4ba3e0 100644 --- a/src/ata.c +++ b/src/ata.c @@ -780,8 +780,11 @@ init_drive_atapi(struct atadrive_s *dummy, u16 *buffer)
// fill cdidmap if (iscd) { + int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_bdf, + adrive_g->chan_gf->chanid, + adrive_g->slave); map_cd_drive(&adrive_g->drive); - add_baid_cdrom(&adrive_g->drive); + add_baid_cdrom(&adrive_g->drive, prio); }
return adrive_g; @@ -831,8 +834,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. - add_bcv_internal(&adrive_g->drive); + add_bcv_internal(&adrive_g->drive, prio);
return adrive_g; } diff --git a/src/boot.c b/src/boot.c index 9c94439..39ab78f 100644 --- a/src/boot.c +++ b/src/boot.c @@ -13,10 +13,21 @@ #include "boot.h" // struct ipl_s #include "cmos.h" // inb_cmos #include "paravirt.h" +#include "pci.h" //pci_bdf_to_*
struct ipl_s IPL;
+static u8 get_boot_priority(int prio) +{ + static u8 index = 0; + + if (prio < 0) + return IPL.fw_bootorder_count + index++; + + return (u8)prio; +} + /**************************************************************** * IPL and BCV handlers ****************************************************************/ @@ -67,11 +78,56 @@ 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); + dprintf(3, "bootorder file found (len %d)\n", filesize); + + if (filesize == 0) + return; + + char *f = malloc_tmphigh(filesize); + + if (!f) { + warn_noalloc(); + 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) { + warn_noalloc(); + 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. void -add_bev(u16 seg, u16 bev, u16 desc) +add_bev(u16 seg, u16 bev, u16 desc, int prio) { if (! CONFIG_BOOT) return; @@ -85,11 +141,12 @@ add_bev(u16 seg, u16 bev, u16 desc) if (desc) d = MAKE_FLATPTR(seg, desc); ie->description = d; + ie->prio = get_boot_priority(prio); }
// Add a IPL entry for BAID cdrom. void -add_baid_cdrom(struct drive_s *drive_g) +add_baid_cdrom(struct drive_s *drive_g, int prio) { if (! CONFIG_CDROM_BOOT) return; @@ -104,11 +161,18 @@ add_baid_cdrom(struct drive_s *drive_g) ie->type = IPL_TYPE_CDROM; ie->vector = (u32)drive_g; ie->description = "DVD/CD"; + ie->prio = get_boot_priority(prio); +} + +void set_floppy_baid_prio(int prio) +{ + struct ipl_entry_s *ie = &IPL.bev[0]; + ie->prio = get_boot_priority(prio); }
// Add a bcv entry for an expansion card harddrive or legacy option rom void -add_bcv(u16 seg, u16 ip, u16 desc) +add_bcv(u16 seg, u16 ip, u16 desc, int prio) { if (! CONFIG_BOOT) return; @@ -122,11 +186,12 @@ add_bcv(u16 seg, u16 ip, u16 desc) if (desc) d = MAKE_FLATPTR(seg, desc); ie->description = d; + ie->prio = get_boot_priority(prio); }
// Add a bcv entry for an internal harddrive void -add_bcv_internal(struct drive_s *drive_g) +add_bcv_internal(struct drive_s *drive_g, int prio) { if (! CONFIG_BOOT) return; @@ -154,6 +219,7 @@ add_bcv_internal(struct drive_s *drive_g) ie->type = BCV_TYPE_INTERNAL; ie->vector = (u32)drive_g; ie->description = ""; + ie->prio = get_boot_priority(prio); }
@@ -323,6 +389,40 @@ run_bcv(struct ipl_entry_s *ie) } }
+/* Bubble sort! Should be good enough for 8 elements */ +static void sort_ipls(struct ipl_entry_s *ipls, int iplscount) +{ + int stop; + if (iplscount == 0) + return; + + do { + int i; + stop = 1; + for (i = 0; i < iplscount - 1; i++) { + if (ipls[i].prio > ipls[i+1].prio) { + struct ipl_entry_s tmp; + tmp = ipls[i]; + ipls[i] = ipls[i+1]; + ipls[i+1] = tmp; + stop = 0; + } + } + } while (!stop); +} + +static void order_boot_devices(void) +{ + if (IPL.fw_bootorder_count == 0) + return; + + sort_ipls(IPL.bcv, IPL.bcvcount); + /* Hard disk IPL inherits priority of the bootanle bcv */ + IPL.bev[1].prio = IPL.bcv[0].prio; + sort_ipls(IPL.bev, IPL.bevcount); + IPL.bootorder = 0x87654321; +} + // Prepare for boot - show menu and run bcvs. void boot_prep(void) @@ -334,6 +434,8 @@ boot_prep(void)
// XXX - show available drives?
+ order_boot_devices(); + // Allow user to modify BCV/IPL order. interactive_bootmenu(); wait_threads(); @@ -529,3 +631,156 @@ 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 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) +{ + const char *rest; + int idx = -1; + + if (bdf == -1) + return -1; /* support only pci machine for now */ + + while((idx = find_pci_device(bdf, idx + 1, &rest)) >= 0) { + if (match_next_node_address(rest, chanid ? "1" : "0", &rest) && + match_next_node_address(rest, slave ? "1" : "0", &rest)) + break; + } + + return idx; +} + + +int bootprio_find_fdc_device(int bdf, int port, int fdid) +{ + const char *rest; + int idx = -1; + 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 + 1, &rest)) >= 0) { + if (match_next_node_address(rest, addr, &rest) && + match_next_node_address(rest, fdid ? "1" : "0", &rest)) + break; + } + + return idx; +} + +int bootprio_find_named_rom(const char *name) +{ + int 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; +} diff --git a/src/boot.h b/src/boot.h index f751d71..931d140 100644 --- a/src/boot.h +++ b/src/boot.h @@ -12,6 +12,7 @@ struct ipl_entry_s { u16 subchoice; u32 vector; const char *description; + u8 prio; };
struct ipl_s { @@ -20,6 +21,8 @@ struct ipl_s { int bevcount, bcvcount; u32 bootorder; int checkfloppysig; + char **fw_bootorder; + int fw_bootorder_count; };
#define IPL_TYPE_FLOPPY 0x01 @@ -39,12 +42,17 @@ struct ipl_s { // boot.c extern struct ipl_s IPL; void boot_setup(void); -void add_bev(u16 seg, u16 bev, u16 desc); -void add_bcv(u16 seg, u16 ip, u16 desc); +void add_bev(u16 seg, u16 bev, u16 desc, int prio); +void add_bcv(u16 seg, u16 ip, u16 desc, int prio); struct drive_s; -void add_bcv_internal(struct drive_s *drive_g); -void add_baid_cdrom(struct drive_s *drive_g); +void add_bcv_internal(struct drive_s *drive_g, int prio); +void add_baid_cdrom(struct drive_s *drive_g, int prio); +void set_floppy_baid_prio(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/config.h b/src/config.h index db3e578..0b575a9 100644 --- a/src/config.h +++ b/src/config.h @@ -16,9 +16,9 @@ #define CONFIG_COREBOOT 0
// Control how verbose debug output is. -#define CONFIG_DEBUG_LEVEL 1 +#define CONFIG_DEBUG_LEVEL 5 // Send debugging information to serial port -#define CONFIG_DEBUG_SERIAL 0 +#define CONFIG_DEBUG_SERIAL 1 // Screen writes are also sent to debug ports. #define CONFIG_SCREEN_AND_DEBUG 1
diff --git a/src/floppy.c b/src/floppy.c index 6491b96..d91ac24 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -13,6 +13,8 @@ #include "cmos.h" // inb_cmos #include "pic.h" // eoi_pic1 #include "bregs.h" // struct bregs +#include "pci.h" // pci_to_bdf +#include "boot.h" // bootprio_find_fdc_device
#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors #define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 @@ -131,10 +133,25 @@ floppy_setup(void) // XXX - disable floppies on coreboot for now. } else { u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); - if (type & 0xf0) + unsigned int prio0 = -1, prio1 = -1; + int bdf = pci_to_bdf(0, 1, 0); /* isa-to-pci bridge */ + + if (type & 0xf0) { addFloppy(0, type >> 4, DTYPE_FLOPPY); - if (type & 0x0f) + prio0 = bootprio_find_fdc_device(bdf, 0x3f0, 0); + } + if (type & 0x0f) { addFloppy(1, type & 0x0f, DTYPE_FLOPPY); + prio1 = bootprio_find_fdc_device(bdf, 0x3f0, 1); + } + if (prio1 < prio0) { + /* if B has lower boot priority swap it with A */ + struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0]; + Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][1]; + Drives.idmap[EXTTYPE_FLOPPY][1] = tmp; + set_floppy_baid_prio(prio1); + } else + set_floppy_baid_prio(prio0); }
outb(0x02, PORT_DMA1_MASK_REG); diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..4b2ae67 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -74,6 +74,34 @@ struct pnp_data { // The end of the last deployed rom. u32 RomEnd = BUILD_ROM_START;
+static struct rom_dev { + u32 addr; + int idx; +} rom2dev[92]; + +static int rom2dev_cnt; + +static void map_rom2dev(void *addr, int idx) +{ + if (rom2dev_cnt < ARRAY_SIZE(rom2dev)) { + rom2dev[rom2dev_cnt].addr = (u32)addr; + rom2dev[rom2dev_cnt].idx = idx; + dprintf(3, "pci rom at memory address %x has boot prio index %d\n", + rom2dev[rom2dev_cnt].addr, rom2dev[rom2dev_cnt].idx); + rom2dev_cnt++; + } +} + +static int rom2dev_idx(u32 addr) +{ + int i; + + for (i = 0; i < rom2dev_cnt; i++) + if (rom2dev[i].addr == addr) + return rom2dev[i].idx; + + return -1; +}
/**************************************************************** * Helper functions @@ -243,13 +271,18 @@ static void run_file_roms(const char *prefix, int isvga) { u32 file = 0; + for (;;) { file = romfile_findprefix(prefix, file); if (!file) break; int ret = romfile_copy(file, (void*)RomEnd, max_rom() - RomEnd); - if (ret > 0) - init_optionrom((void*)RomEnd, 0, isvga); + if (ret > 0) { + void *rom = (void*)RomEnd; + ret = init_optionrom(rom, 0, isvga); + if (!ret && is_valid_rom(rom)) + map_rom2dev(rom, bootprio_find_named_rom(romfile_name(file))); + } } }
@@ -342,7 +375,15 @@ 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; + + map_rom2dev(rom, bootprio_find_pci_device(bdf)); + + return r; }
@@ -394,21 +435,22 @@ optionrom_setup(void) pos += OPTION_ROM_ALIGN; continue; } + int devidx = rom2dev_idx(pos); pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN); struct pnp_data *pnp = get_pnp_rom(rom); if (! pnp) { // Legacy rom. - add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0); + add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0, devidx); continue; } // PnP rom. if (pnp->bev) // Can boot system - add to IPL list. - add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname); + add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname, devidx); else // Check for BCV (there may be multiple). while (pnp && pnp->bcv) { - add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname); + add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname, devidx); pnp = get_pnp_next(rom, pnp); } } diff --git a/src/paravirt.c b/src/paravirt.c index ca646d4..308c809 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -345,6 +345,14 @@ int qemu_cfg_size_file(u32 select) return ntohl(LastFile.size); }
+ +const char* qemu_cfg_name_file(u32 select) +{ + if (select != ntohs(LastFile.select)) + return NULL; + return LastFile.name; +} + int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen) { if (!qemu_cfg_present) diff --git a/src/paravirt.h b/src/paravirt.h index 7d4bc02..99c473b 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -71,6 +71,7 @@ struct e820_reservation { u32 qemu_cfg_next_prefix_file(const char *prefix, u32 prevselect); u32 qemu_cfg_find_file(const char *name); int qemu_cfg_size_file(u32 select); +const char* qemu_cfg_name_file(u32 select); int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen);
// Wrappers that select cbfs or qemu_cfg file interface. @@ -94,6 +95,11 @@ static inline int romfile_copy(u32 fileid, void *dst, u32 maxlen) { return cbfs_copyfile((void*)fileid, dst, maxlen); return qemu_cfg_read_file(fileid, dst, maxlen); } +static inline const char* romfile_name(u32 fileid) { + if (CONFIG_COREBOOT) + return cbfs_filename((void*)fileid); + return qemu_cfg_name_file(fileid); +}
u32 qemu_cfg_e820_entries(void); void* qemu_cfg_e820_load_next(void *addr); diff --git a/src/usb-msc.c b/src/usb-msc.c index 968cae3..f6253ca 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -168,7 +168,7 @@ setup_drive_hd(struct disk_op_s *op) setup_translation(op->drive_g);
// Register with bcv system. - add_bcv_internal(op->drive_g); + add_bcv_internal(op->drive_g, -1);
return 0; } diff --git a/src/util.c b/src/util.c index f9a7533..3892c3c 100644 --- a/src/util.c +++ b/src/util.c @@ -262,6 +262,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 diff --git a/src/util.h b/src/util.h index fa7b20f..f5b9446 100644 --- a/src/util.h +++ b/src/util.h @@ -209,6 +209,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 diff --git a/src/virtio-blk.c b/src/virtio-blk.c index 7a25826..3d2b7a6 100644 --- a/src/virtio-blk.c +++ b/src/virtio-blk.c @@ -153,7 +153,7 @@ init_virtio_blk(u16 bdf) vdrive_g->drive.pchs.spt = cfg.sectors;
setup_translation(&vdrive_g->drive); - add_bcv_internal(&vdrive_g->drive); + add_bcv_internal(&vdrive_g->drive, bootprio_find_pci_device(bdf));
snprintf(desc, MAXDESCSIZE, "Virtio disk PCI:%x:%x", pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); -- Gleb.
On Wed, Dec 08, 2010 at 02:00:50PM +0200, Gleb Natapov wrote:
With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
Hi Gleb.
I'm a bit behind right now, but I'll take a look this weekend.
-Kevin
On Thu, Dec 09, 2010 at 08:27:10PM -0500, Kevin O'Connor wrote:
On Wed, Dec 08, 2010 at 02:00:50PM +0200, Gleb Natapov wrote:
With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
Hi Gleb.
I'm a bit behind right now, but I'll take a look this weekend.
Have you had a chance to look at it? If not yet then here is updated version that fix one little bug with boot menu and choosing between multiple BCVs:
diff --git a/src/ahci.c b/src/ahci.c index e2b2dbf..bf9a1f0 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. - add_bcv_internal(&port->drive); + add_bcv_internal(&port->drive, -1); } else { // found cdrom (atapi) port->drive.blksize = CDROM_SECTOR_SIZE; diff --git a/src/ata.c b/src/ata.c index d971480..e45de50 100644 --- a/src/ata.c +++ b/src/ata.c @@ -783,8 +783,11 @@ init_drive_atapi(struct atadrive_s *dummy, u16 *buffer)
// fill cdidmap if (iscd) { + int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_bdf, + adrive_g->chan_gf->chanid, + adrive_g->slave); map_cd_drive(&adrive_g->drive); - add_baid_cdrom(&adrive_g->drive); + add_baid_cdrom(&adrive_g->drive, prio); }
return adrive_g; @@ -834,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. - add_bcv_internal(&adrive_g->drive); + add_bcv_internal(&adrive_g->drive, prio);
return adrive_g; } diff --git a/src/boot.c b/src/boot.c index 9c94439..7a320f7 100644 --- a/src/boot.c +++ b/src/boot.c @@ -13,10 +13,21 @@ #include "boot.h" // struct ipl_s #include "cmos.h" // inb_cmos #include "paravirt.h" +#include "pci.h" //pci_bdf_to_*
struct ipl_s IPL;
+static u8 get_boot_priority(int prio) +{ + static u8 index = 0; + + if (prio < 0) + return IPL.fw_bootorder_count + index++; + + return (u8)prio; +} + /**************************************************************** * IPL and BCV handlers ****************************************************************/ @@ -67,11 +78,56 @@ 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); + dprintf(3, "bootorder file found (len %d)\n", filesize); + + if (filesize == 0) + return; + + char *f = malloc_tmphigh(filesize); + + if (!f) { + warn_noalloc(); + 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) { + warn_noalloc(); + 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. void -add_bev(u16 seg, u16 bev, u16 desc) +add_bev(u16 seg, u16 bev, u16 desc, int prio) { if (! CONFIG_BOOT) return; @@ -85,11 +141,12 @@ add_bev(u16 seg, u16 bev, u16 desc) if (desc) d = MAKE_FLATPTR(seg, desc); ie->description = d; + ie->prio = get_boot_priority(prio); }
// Add a IPL entry for BAID cdrom. void -add_baid_cdrom(struct drive_s *drive_g) +add_baid_cdrom(struct drive_s *drive_g, int prio) { if (! CONFIG_CDROM_BOOT) return; @@ -104,11 +161,18 @@ add_baid_cdrom(struct drive_s *drive_g) ie->type = IPL_TYPE_CDROM; ie->vector = (u32)drive_g; ie->description = "DVD/CD"; + ie->prio = get_boot_priority(prio); +} + +void set_floppy_baid_prio(int prio) +{ + struct ipl_entry_s *ie = &IPL.bev[0]; + ie->prio = get_boot_priority(prio); }
// Add a bcv entry for an expansion card harddrive or legacy option rom void -add_bcv(u16 seg, u16 ip, u16 desc) +add_bcv(u16 seg, u16 ip, u16 desc, int prio) { if (! CONFIG_BOOT) return; @@ -122,11 +186,12 @@ add_bcv(u16 seg, u16 ip, u16 desc) if (desc) d = MAKE_FLATPTR(seg, desc); ie->description = d; + ie->prio = get_boot_priority(prio); }
// Add a bcv entry for an internal harddrive void -add_bcv_internal(struct drive_s *drive_g) +add_bcv_internal(struct drive_s *drive_g, int prio) { if (! CONFIG_BOOT) return; @@ -154,6 +219,7 @@ add_bcv_internal(struct drive_s *drive_g) ie->type = BCV_TYPE_INTERNAL; ie->vector = (u32)drive_g; ie->description = ""; + ie->prio = get_boot_priority(prio); }
@@ -323,6 +389,40 @@ run_bcv(struct ipl_entry_s *ie) } }
+/* Bubble sort! Should be good enough for 8 elements */ +static void sort_ipls(struct ipl_entry_s *ipls, int iplscount) +{ + int stop; + if (iplscount == 0) + return; + + do { + int i; + stop = 1; + for (i = 0; i < iplscount - 1; i++) { + if (ipls[i].prio > ipls[i+1].prio) { + struct ipl_entry_s tmp; + tmp = ipls[i]; + ipls[i] = ipls[i+1]; + ipls[i+1] = tmp; + stop = 0; + } + } + } while (!stop); +} + +static void order_boot_devices(void) +{ + if (IPL.fw_bootorder_count == 0) + return; + + sort_ipls(IPL.bcv, IPL.bcvcount); + /* Hard disk IPL inherits priority of the bootanle bcv */ + IPL.bev[1].prio = IPL.bcv[0].prio; + sort_ipls(IPL.bev, IPL.bevcount); + IPL.bootorder = 0x87654321; +} + // Prepare for boot - show menu and run bcvs. void boot_prep(void) @@ -334,24 +434,38 @@ boot_prep(void)
// XXX - show available drives?
+ order_boot_devices(); + // Allow user to modify BCV/IPL order. interactive_bootmenu(); wait_threads();
- // Setup floppy boot order - int override = IPL.bev[0].subchoice; - struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0]; - Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][override]; - Drives.idmap[EXTTYPE_FLOPPY][override] = tmp; - - // Run BCVs - override = IPL.bev[1].subchoice; - if (override < IPL.bcvcount) - run_bcv(&IPL.bcv[override]); - int i; - for (i=0; i<IPL.bcvcount; i++) - if (i != override) - run_bcv(&IPL.bcv[i]); + int j; + for (j = 0; j < IPL.bevcount; j++) { + int override; + switch (IPL.bev[j].type) { + case IPL_TYPE_FLOPPY: + // Setup floppy boot order + override = IPL.bev[j].subchoice; + struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0]; + Drives.idmap[EXTTYPE_FLOPPY][0] = + Drives.idmap[EXTTYPE_FLOPPY][override]; + Drives.idmap[EXTTYPE_FLOPPY][override] = tmp; + break; + case IPL_TYPE_HARDDISK: + // Run BCVs + override = IPL.bev[j].subchoice; + if (override < IPL.bcvcount) + run_bcv(&IPL.bcv[override]); + int i; + for (i=0; i<IPL.bcvcount; i++) + if (i != override) + run_bcv(&IPL.bcv[i]); + break; + default: + break; + } + } }
@@ -529,3 +643,156 @@ 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 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) +{ + const char *rest; + int idx = -1; + + if (bdf == -1) + return -1; /* support only pci machine for now */ + + while((idx = find_pci_device(bdf, idx + 1, &rest)) >= 0) { + if (match_next_node_address(rest, chanid ? "1" : "0", &rest) && + match_next_node_address(rest, slave ? "1" : "0", &rest)) + break; + } + + return idx; +} + + +int bootprio_find_fdc_device(int bdf, int port, int fdid) +{ + const char *rest; + int idx = -1; + 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 + 1, &rest)) >= 0) { + if (match_next_node_address(rest, addr, &rest) && + match_next_node_address(rest, fdid ? "1" : "0", &rest)) + break; + } + + return idx; +} + +int bootprio_find_named_rom(const char *name) +{ + int 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; +} diff --git a/src/boot.h b/src/boot.h index f751d71..931d140 100644 --- a/src/boot.h +++ b/src/boot.h @@ -12,6 +12,7 @@ struct ipl_entry_s { u16 subchoice; u32 vector; const char *description; + u8 prio; };
struct ipl_s { @@ -20,6 +21,8 @@ struct ipl_s { int bevcount, bcvcount; u32 bootorder; int checkfloppysig; + char **fw_bootorder; + int fw_bootorder_count; };
#define IPL_TYPE_FLOPPY 0x01 @@ -39,12 +42,17 @@ struct ipl_s { // boot.c extern struct ipl_s IPL; void boot_setup(void); -void add_bev(u16 seg, u16 bev, u16 desc); -void add_bcv(u16 seg, u16 ip, u16 desc); +void add_bev(u16 seg, u16 bev, u16 desc, int prio); +void add_bcv(u16 seg, u16 ip, u16 desc, int prio); struct drive_s; -void add_bcv_internal(struct drive_s *drive_g); -void add_baid_cdrom(struct drive_s *drive_g); +void add_bcv_internal(struct drive_s *drive_g, int prio); +void add_baid_cdrom(struct drive_s *drive_g, int prio); +void set_floppy_baid_prio(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/config.h b/src/config.h index db3e578..0b575a9 100644 --- a/src/config.h +++ b/src/config.h @@ -16,9 +16,9 @@ #define CONFIG_COREBOOT 0
// Control how verbose debug output is. -#define CONFIG_DEBUG_LEVEL 1 +#define CONFIG_DEBUG_LEVEL 5 // Send debugging information to serial port -#define CONFIG_DEBUG_SERIAL 0 +#define CONFIG_DEBUG_SERIAL 1 // Screen writes are also sent to debug ports. #define CONFIG_SCREEN_AND_DEBUG 1
diff --git a/src/floppy.c b/src/floppy.c index 6491b96..d91ac24 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -13,6 +13,8 @@ #include "cmos.h" // inb_cmos #include "pic.h" // eoi_pic1 #include "bregs.h" // struct bregs +#include "pci.h" // pci_to_bdf +#include "boot.h" // bootprio_find_fdc_device
#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors #define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 @@ -131,10 +133,25 @@ floppy_setup(void) // XXX - disable floppies on coreboot for now. } else { u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); - if (type & 0xf0) + unsigned int prio0 = -1, prio1 = -1; + int bdf = pci_to_bdf(0, 1, 0); /* isa-to-pci bridge */ + + if (type & 0xf0) { addFloppy(0, type >> 4, DTYPE_FLOPPY); - if (type & 0x0f) + prio0 = bootprio_find_fdc_device(bdf, 0x3f0, 0); + } + if (type & 0x0f) { addFloppy(1, type & 0x0f, DTYPE_FLOPPY); + prio1 = bootprio_find_fdc_device(bdf, 0x3f0, 1); + } + if (prio1 < prio0) { + /* if B has lower boot priority swap it with A */ + struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0]; + Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][1]; + Drives.idmap[EXTTYPE_FLOPPY][1] = tmp; + set_floppy_baid_prio(prio1); + } else + set_floppy_baid_prio(prio0); }
outb(0x02, PORT_DMA1_MASK_REG); diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..4b2ae67 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -74,6 +74,34 @@ struct pnp_data { // The end of the last deployed rom. u32 RomEnd = BUILD_ROM_START;
+static struct rom_dev { + u32 addr; + int idx; +} rom2dev[92]; + +static int rom2dev_cnt; + +static void map_rom2dev(void *addr, int idx) +{ + if (rom2dev_cnt < ARRAY_SIZE(rom2dev)) { + rom2dev[rom2dev_cnt].addr = (u32)addr; + rom2dev[rom2dev_cnt].idx = idx; + dprintf(3, "pci rom at memory address %x has boot prio index %d\n", + rom2dev[rom2dev_cnt].addr, rom2dev[rom2dev_cnt].idx); + rom2dev_cnt++; + } +} + +static int rom2dev_idx(u32 addr) +{ + int i; + + for (i = 0; i < rom2dev_cnt; i++) + if (rom2dev[i].addr == addr) + return rom2dev[i].idx; + + return -1; +}
/**************************************************************** * Helper functions @@ -243,13 +271,18 @@ static void run_file_roms(const char *prefix, int isvga) { u32 file = 0; + for (;;) { file = romfile_findprefix(prefix, file); if (!file) break; int ret = romfile_copy(file, (void*)RomEnd, max_rom() - RomEnd); - if (ret > 0) - init_optionrom((void*)RomEnd, 0, isvga); + if (ret > 0) { + void *rom = (void*)RomEnd; + ret = init_optionrom(rom, 0, isvga); + if (!ret && is_valid_rom(rom)) + map_rom2dev(rom, bootprio_find_named_rom(romfile_name(file))); + } } }
@@ -342,7 +375,15 @@ 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; + + map_rom2dev(rom, bootprio_find_pci_device(bdf)); + + return r; }
@@ -394,21 +435,22 @@ optionrom_setup(void) pos += OPTION_ROM_ALIGN; continue; } + int devidx = rom2dev_idx(pos); pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN); struct pnp_data *pnp = get_pnp_rom(rom); if (! pnp) { // Legacy rom. - add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0); + add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0, devidx); continue; } // PnP rom. if (pnp->bev) // Can boot system - add to IPL list. - add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname); + add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname, devidx); else // Check for BCV (there may be multiple). while (pnp && pnp->bcv) { - add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname); + add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname, devidx); pnp = get_pnp_next(rom, pnp); } } diff --git a/src/paravirt.c b/src/paravirt.c index ca646d4..308c809 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -345,6 +345,14 @@ int qemu_cfg_size_file(u32 select) return ntohl(LastFile.size); }
+ +const char* qemu_cfg_name_file(u32 select) +{ + if (select != ntohs(LastFile.select)) + return NULL; + return LastFile.name; +} + int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen) { if (!qemu_cfg_present) diff --git a/src/paravirt.h b/src/paravirt.h index 7d4bc02..99c473b 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -71,6 +71,7 @@ struct e820_reservation { u32 qemu_cfg_next_prefix_file(const char *prefix, u32 prevselect); u32 qemu_cfg_find_file(const char *name); int qemu_cfg_size_file(u32 select); +const char* qemu_cfg_name_file(u32 select); int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen);
// Wrappers that select cbfs or qemu_cfg file interface. @@ -94,6 +95,11 @@ static inline int romfile_copy(u32 fileid, void *dst, u32 maxlen) { return cbfs_copyfile((void*)fileid, dst, maxlen); return qemu_cfg_read_file(fileid, dst, maxlen); } +static inline const char* romfile_name(u32 fileid) { + if (CONFIG_COREBOOT) + return cbfs_filename((void*)fileid); + return qemu_cfg_name_file(fileid); +}
u32 qemu_cfg_e820_entries(void); void* qemu_cfg_e820_load_next(void *addr); diff --git a/src/usb-msc.c b/src/usb-msc.c index 080efdc..8b2f31b 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -171,7 +171,7 @@ setup_drive_hd(struct disk_op_s *op) setup_translation(op->drive_g);
// Register with bcv system. - add_bcv_internal(op->drive_g); + add_bcv_internal(op->drive_g, -1);
return 0; } diff --git a/src/util.c b/src/util.c index f9a7533..3892c3c 100644 --- a/src/util.c +++ b/src/util.c @@ -262,6 +262,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 diff --git a/src/util.h b/src/util.h index fa7b20f..f5b9446 100644 --- a/src/util.h +++ b/src/util.h @@ -209,6 +209,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 diff --git a/src/virtio-blk.c b/src/virtio-blk.c index 7a25826..3d2b7a6 100644 --- a/src/virtio-blk.c +++ b/src/virtio-blk.c @@ -153,7 +153,7 @@ init_virtio_blk(u16 bdf) vdrive_g->drive.pchs.spt = cfg.sectors;
setup_translation(&vdrive_g->drive); - add_bcv_internal(&vdrive_g->drive); + add_bcv_internal(&vdrive_g->drive, bootprio_find_pci_device(bdf));
snprintf(desc, MAXDESCSIZE, "Virtio disk PCI:%x:%x", pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); -- Gleb.
On Mon, Dec 13, 2010 at 03:12:51PM +0200, Gleb Natapov wrote:
On Thu, Dec 09, 2010 at 08:27:10PM -0500, Kevin O'Connor wrote:
On Wed, Dec 08, 2010 at 02:00:50PM +0200, Gleb Natapov wrote:
With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
Hi Gleb.
I'm a bit behind right now, but I'll take a look this weekend.
Have you had a chance to look at it? If not yet then here is updated version that fix one little bug with boot menu and choosing between multiple BCVs:
I did look at it, but didn't get a chance to reply. Here are my thoughts in brief:
* I'm okay with the general layout (read bootorder at start, note priority when adding each entry)
* The system seems to conflict with the sorting already done by add_bcv_internal() and add_ordered_drive() (which was added to handle threads adding drives in any order). The get_boot_priority() code you've added isn't right, because there's no guarentee that a drive will be added in a repeatable manor (you don't want a user without "bootorder" to see different drives being booted on different boots). Also, it's not clear how this mechanism works with the boot_sequence variable.
* The strchr and romfile_name changes are fine and can go in now. The "bootorder" reading code looks fine too.
* The ISA pci address is hardcoded (in floppy code), which isn't good.
* I'm still unhappy about the parsing code.
* I'd still like a way of designating an explicit rom (for coreboot only if necessary) - though I can add this on top.
These comments are on the previous patch.
-Kevin
On Mon, Dec 13, 2010 at 08:44:08AM -0500, Kevin O'Connor wrote:
On Mon, Dec 13, 2010 at 03:12:51PM +0200, Gleb Natapov wrote:
On Thu, Dec 09, 2010 at 08:27:10PM -0500, Kevin O'Connor wrote:
On Wed, Dec 08, 2010 at 02:00:50PM +0200, Gleb Natapov wrote:
With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
Hi Gleb.
I'm a bit behind right now, but I'll take a look this weekend.
Have you had a chance to look at it? If not yet then here is updated version that fix one little bug with boot menu and choosing between multiple BCVs:
I did look at it, but didn't get a chance to reply. Here are my thoughts in brief:
One other question - when a drive is listed in "bootorder", does your patch prioritize drive booting in the IPL in addition to the drive order in the BCV? I didn't see it, but I may have missed it.
-Kevin
On Mon, Dec 13, 2010 at 08:55:53AM -0500, Kevin O'Connor wrote:
On Mon, Dec 13, 2010 at 08:44:08AM -0500, Kevin O'Connor wrote:
On Mon, Dec 13, 2010 at 03:12:51PM +0200, Gleb Natapov wrote:
On Thu, Dec 09, 2010 at 08:27:10PM -0500, Kevin O'Connor wrote:
On Wed, Dec 08, 2010 at 02:00:50PM +0200, Gleb Natapov wrote:
With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
Hi Gleb.
I'm a bit behind right now, but I'll take a look this weekend.
Have you had a chance to look at it? If not yet then here is updated version that fix one little bug with boot menu and choosing between multiple BCVs:
I did look at it, but didn't get a chance to reply. Here are my thoughts in brief:
One other question - when a drive is listed in "bootorder", does your patch prioritize drive booting in the IPL in addition to the drive order in the BCV? I didn't see it, but I may have missed it.
Yes:
sort_ipls(IPL.bcv, IPL.bcvcount); /* Hard disk IPL inherits priority of the bootanle bcv */ IPL.bev[1].prio = IPL.bcv[0].prio; <--- here it is sort_ipls(IPL.bev, IPL.bevcount); IPL.bootorder = 0x87654321;
-- Gleb.
On Mon, Dec 13, 2010 at 08:44:08AM -0500, Kevin O'Connor wrote:
On Mon, Dec 13, 2010 at 03:12:51PM +0200, Gleb Natapov wrote:
On Thu, Dec 09, 2010 at 08:27:10PM -0500, Kevin O'Connor wrote:
On Wed, Dec 08, 2010 at 02:00:50PM +0200, Gleb Natapov wrote:
With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
Hi Gleb.
I'm a bit behind right now, but I'll take a look this weekend.
Have you had a chance to look at it? If not yet then here is updated version that fix one little bug with boot menu and choosing between multiple BCVs:
I did look at it, but didn't get a chance to reply. Here are my thoughts in brief:
I'm okay with the general layout (read bootorder at start, note priority when adding each entry)
The system seems to conflict with the sorting already done by add_bcv_internal() and add_ordered_drive() (which was added to handle threads adding drives in any order). The get_boot_priority() code you've added isn't right, because there's no guarentee that a drive will be added in a repeatable manor (you don't want a user without "bootorder" to see different drives being booted on different boots).
Good point. Will fix. Probably will require more invasive changes though.
Also, it's not clear how this mechanism works
with the boot_sequence variable.
IPLs are sorted by priority, IPL.bootorder is set to 0x87654321 (i.e try each IPL in order) and then boot_sequence is used just like before the patch.
The strchr and romfile_name changes are fine and can go in now. The "bootorder" reading code looks fine too.
The ISA pci address is hardcoded (in floppy code), which isn't good.
Was too lazy :) Need to search for it dynamically.
- I'm still unhappy about the parsing code.
Any specific comments that I can address?
- I'd still like a way of designating an explicit rom (for coreboot only if necessary) - though I can add this on top.
These comments are on the previous patch.
The last one just fixed a bug, so all of them still apply. Thanks.
-- Gleb.
On Mon, Dec 13, 2010 at 05:02:43PM +0200, Gleb Natapov wrote:
On Mon, Dec 13, 2010 at 08:44:08AM -0500, Kevin O'Connor wrote:
On Mon, Dec 13, 2010 at 03:12:51PM +0200, Gleb Natapov wrote:
On Thu, Dec 09, 2010 at 08:27:10PM -0500, Kevin O'Connor wrote:
On Wed, Dec 08, 2010 at 02:00:50PM +0200, Gleb Natapov wrote:
With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
Hi Gleb.
I'm a bit behind right now, but I'll take a look this weekend.
Have you had a chance to look at it? If not yet then here is updated version that fix one little bug with boot menu and choosing between multiple BCVs:
I did look at it, but didn't get a chance to reply. Here are my thoughts in brief:
I'm okay with the general layout (read bootorder at start, note priority when adding each entry)
The system seems to conflict with the sorting already done by add_bcv_internal() and add_ordered_drive() (which was added to handle threads adding drives in any order). The get_boot_priority() code you've added isn't right, because there's no guarentee that a drive will be added in a repeatable manor (you don't want a user without "bootorder" to see different drives being booted on different boots).
Good point. Will fix. Probably will require more invasive changes though.
It was easier to fix than I initially thought. All BCVs and BEVs that do not have corespondent device paths get the same lowest priority. During sorting they stay in the same order at the end.
I search for ISA bridge dynamically now using pci_find_class(PCI_CLASS_BRIDGE_ISA).
Signed-off-by: Gleb Natapov gleb@redhat.com diff --git a/src/ahci.c b/src/ahci.c index 70c0f1c..a209c86 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. - add_bcv_internal(&port->drive); + add_bcv_internal(&port->drive, MAX_BOOT_PRIO); } 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) { map_cd_drive(&port->drive); - add_baid_cdrom(&port->drive); + add_baid_cdrom(&port->drive, MAX_BOOT_PRIO); } } dprintf(1, "%s\n", port->drive.desc); diff --git a/src/ata.c b/src/ata.c index d971480..e45de50 100644 --- a/src/ata.c +++ b/src/ata.c @@ -783,8 +783,11 @@ init_drive_atapi(struct atadrive_s *dummy, u16 *buffer)
// fill cdidmap if (iscd) { + int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_bdf, + adrive_g->chan_gf->chanid, + adrive_g->slave); map_cd_drive(&adrive_g->drive); - add_baid_cdrom(&adrive_g->drive); + add_baid_cdrom(&adrive_g->drive, prio); }
return adrive_g; @@ -834,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. - add_bcv_internal(&adrive_g->drive); + add_bcv_internal(&adrive_g->drive, prio);
return adrive_g; } diff --git a/src/boot.c b/src/boot.c index 9c94439..157f666 100644 --- a/src/boot.c +++ b/src/boot.c @@ -13,10 +13,12 @@ #include "boot.h" // struct ipl_s #include "cmos.h" // inb_cmos #include "paravirt.h" +#include "pci.h" //pci_bdf_to_*
struct ipl_s IPL;
+ /**************************************************************** * IPL and BCV handlers ****************************************************************/ @@ -67,11 +69,56 @@ 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); + dprintf(3, "bootorder file found (len %d)\n", filesize); + + if (filesize == 0) + return; + + char *f = malloc_tmphigh(filesize); + + if (!f) { + warn_noalloc(); + 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) { + warn_noalloc(); + 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. void -add_bev(u16 seg, u16 bev, u16 desc) +add_bev(u16 seg, u16 bev, u16 desc, u8 prio) { if (! CONFIG_BOOT) return; @@ -85,11 +132,12 @@ add_bev(u16 seg, u16 bev, u16 desc) if (desc) d = MAKE_FLATPTR(seg, desc); ie->description = d; + ie->prio = prio; }
// Add a IPL entry for BAID cdrom. void -add_baid_cdrom(struct drive_s *drive_g) +add_baid_cdrom(struct drive_s *drive_g, u8 prio) { if (! CONFIG_CDROM_BOOT) return; @@ -104,11 +152,18 @@ add_baid_cdrom(struct drive_s *drive_g) ie->type = IPL_TYPE_CDROM; ie->vector = (u32)drive_g; ie->description = "DVD/CD"; + ie->prio = prio; +} + +void set_floppy_baid_prio(u8 prio) +{ + struct ipl_entry_s *ie = &IPL.bev[0]; + ie->prio = prio; }
// Add a bcv entry for an expansion card harddrive or legacy option rom void -add_bcv(u16 seg, u16 ip, u16 desc) +add_bcv(u16 seg, u16 ip, u16 desc, u8 prio) { if (! CONFIG_BOOT) return; @@ -122,11 +177,12 @@ add_bcv(u16 seg, u16 ip, u16 desc) if (desc) d = MAKE_FLATPTR(seg, desc); ie->description = d; + ie->prio = prio; }
// Add a bcv entry for an internal harddrive void -add_bcv_internal(struct drive_s *drive_g) +add_bcv_internal(struct drive_s *drive_g, u8 prio) { if (! CONFIG_BOOT) return; @@ -154,6 +210,7 @@ add_bcv_internal(struct drive_s *drive_g) ie->type = BCV_TYPE_INTERNAL; ie->vector = (u32)drive_g; ie->description = ""; + ie->prio = prio; }
@@ -323,6 +380,41 @@ run_bcv(struct ipl_entry_s *ie) } }
+/* Bubble sort! Should be good enough for 8 elements */ +static void sort_ipls(struct ipl_entry_s *ipls, int iplscount) +{ + int stop; + + if (iplscount == 0) + return; + + do { + int i; + stop = 1; + for (i = 0; i < iplscount - 1; i++) { + if (ipls[i].prio > ipls[i+1].prio) { + struct ipl_entry_s tmp; + tmp = ipls[i]; + ipls[i] = ipls[i+1]; + ipls[i+1] = tmp; + stop = 0; + } + } + } while (!stop); +} + +static void order_boot_devices(void) +{ + if (IPL.fw_bootorder_count == 0) + return; + + sort_ipls(IPL.bcv, IPL.bcvcount); + /* Hard disk IPL inherits priority of the bootable bcv */ + IPL.bev[1].prio = IPL.bcv[0].prio; + sort_ipls(IPL.bev, IPL.bevcount); + IPL.bootorder = 0x87654321; +} + // Prepare for boot - show menu and run bcvs. void boot_prep(void) @@ -334,24 +426,38 @@ boot_prep(void)
// XXX - show available drives?
+ order_boot_devices(); + // Allow user to modify BCV/IPL order. interactive_bootmenu(); wait_threads();
- // Setup floppy boot order - int override = IPL.bev[0].subchoice; - struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0]; - Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][override]; - Drives.idmap[EXTTYPE_FLOPPY][override] = tmp; - - // Run BCVs - override = IPL.bev[1].subchoice; - if (override < IPL.bcvcount) - run_bcv(&IPL.bcv[override]); - int i; - for (i=0; i<IPL.bcvcount; i++) - if (i != override) - run_bcv(&IPL.bcv[i]); + int j; + for (j = 0; j < IPL.bevcount; j++) { + int override; + switch (IPL.bev[j].type) { + case IPL_TYPE_FLOPPY: + // Setup floppy boot order + override = IPL.bev[j].subchoice; + struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0]; + Drives.idmap[EXTTYPE_FLOPPY][0] = + Drives.idmap[EXTTYPE_FLOPPY][override]; + Drives.idmap[EXTTYPE_FLOPPY][override] = tmp; + break; + case IPL_TYPE_HARDDISK: + // Run BCVs + override = IPL.bev[j].subchoice; + if (override < IPL.bcvcount) + run_bcv(&IPL.bcv[override]); + int i; + for (i=0; i<IPL.bcvcount; i++) + if (i != override) + run_bcv(&IPL.bcv[i]); + break; + default: + break; + } + } }
@@ -529,3 +635,158 @@ 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 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 u8 find_pci_device(int bdf, u8 start_idx, const char **rest) +{ + u8 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 MAX_BOOT_PRIO; +} + +u8 bootprio_find_pci_device(int bdf) +{ + const char *rest; + + return find_pci_device(bdf, 0, &rest); +} + +u8 bootprio_find_ata_device(int bdf, int chanid, int slave) +{ + const char *rest; + u8 idx = 0; + + if (bdf == -1) + return MAX_BOOT_PRIO; /* support only pci machine for now */ + + while((idx = find_pci_device(bdf, idx, &rest)) != MAX_BOOT_PRIO) { + if (match_next_node_address(rest, chanid ? "1" : "0", &rest) && + match_next_node_address(rest, slave ? "1" : "0", &rest)) + break; + idx++; + } + + return idx; +} + + +u8 bootprio_find_fdc_device(int bdf, int port, int fdid) +{ + const char *rest; + u8 idx = 0; + char addr[5]; + + if (bdf == -1) + return MAX_BOOT_PRIO; /* support only pci machine for now */ + + snprintf(addr, sizeof addr, "%04x", port); + + while((idx = find_pci_device(bdf, idx, &rest)) != MAX_BOOT_PRIO) { + if (match_next_node_address(rest, addr, &rest) && + match_next_node_address(rest, fdid ? "1" : "0", &rest)) + break; + idx++; + } + + return idx; +} + +u8 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 MAX_BOOT_PRIO; +} diff --git a/src/boot.h b/src/boot.h index f751d71..5a4c6ea 100644 --- a/src/boot.h +++ b/src/boot.h @@ -12,6 +12,7 @@ struct ipl_entry_s { u16 subchoice; u32 vector; const char *description; + u8 prio; };
struct ipl_s { @@ -20,6 +21,8 @@ struct ipl_s { int bevcount, bcvcount; u32 bootorder; int checkfloppysig; + char **fw_bootorder; + int fw_bootorder_count; };
#define IPL_TYPE_FLOPPY 0x01 @@ -31,6 +34,7 @@ struct ipl_s { #define BCV_TYPE_EXTERNAL 0x80 #define BCV_TYPE_INTERNAL 0x02
+#define MAX_BOOT_PRIO 255
/**************************************************************** * Function defs @@ -39,12 +43,17 @@ struct ipl_s { // boot.c extern struct ipl_s IPL; void boot_setup(void); -void add_bev(u16 seg, u16 bev, u16 desc); -void add_bcv(u16 seg, u16 ip, u16 desc); +void add_bev(u16 seg, u16 bev, u16 desc, u8 prio); +void add_bcv(u16 seg, u16 ip, u16 desc, u8 prio); struct drive_s; -void add_bcv_internal(struct drive_s *drive_g); -void add_baid_cdrom(struct drive_s *drive_g); +void add_bcv_internal(struct drive_s *drive_g, u8 prio); +void add_baid_cdrom(struct drive_s *drive_g, u8 prio); +void set_floppy_baid_prio(u8 prio);
void boot_prep(void); +u8 bootprio_find_pci_device(int bdf); +u8 bootprio_find_ata_device(int bdf, int chanid, int slave); +u8 bootprio_find_fdc_device(int bfd, int port, int fdid); +u8 bootprio_find_named_rom(const char *name);
#endif // __BOOT_H diff --git a/src/config.h b/src/config.h index db3e578..0b575a9 100644 --- a/src/config.h +++ b/src/config.h @@ -16,9 +16,9 @@ #define CONFIG_COREBOOT 0
// Control how verbose debug output is. -#define CONFIG_DEBUG_LEVEL 1 +#define CONFIG_DEBUG_LEVEL 5 // Send debugging information to serial port -#define CONFIG_DEBUG_SERIAL 0 +#define CONFIG_DEBUG_SERIAL 1 // Screen writes are also sent to debug ports. #define CONFIG_SCREEN_AND_DEBUG 1
diff --git a/src/floppy.c b/src/floppy.c index 6491b96..7dd3083 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -13,6 +13,9 @@ #include "cmos.h" // inb_cmos #include "pic.h" // eoi_pic1 #include "bregs.h" // struct bregs +#include "pci.h" // pci_to_bdf +#include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA +#include "boot.h" // bootprio_find_fdc_device
#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors #define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 @@ -131,10 +134,25 @@ floppy_setup(void) // XXX - disable floppies on coreboot for now. } else { u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); - if (type & 0xf0) + unsigned int prio0 = -1, prio1 = -1; + int bdf = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */ + + if (type & 0xf0) { addFloppy(0, type >> 4, DTYPE_FLOPPY); - if (type & 0x0f) + prio0 = bootprio_find_fdc_device(bdf, 0x3f0, 0); + } + if (type & 0x0f) { addFloppy(1, type & 0x0f, DTYPE_FLOPPY); + prio1 = bootprio_find_fdc_device(bdf, 0x3f0, 1); + } + if (prio1 < prio0) { + /* if B has lower boot priority swap it with A */ + struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0]; + Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][1]; + Drives.idmap[EXTTYPE_FLOPPY][1] = tmp; + set_floppy_baid_prio(prio1); + } else + set_floppy_baid_prio(prio0); }
outb(0x02, PORT_DMA1_MASK_REG); diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..0fd9aed 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -74,6 +74,34 @@ struct pnp_data { // The end of the last deployed rom. u32 RomEnd = BUILD_ROM_START;
+static struct rom_dev { + u32 addr; + u8 prio; +} rom2prio[92]; + +static int rom2prio_cnt; + +static void map_rom2prio(void *addr, u8 prio) +{ + if (rom2prio_cnt < ARRAY_SIZE(rom2prio)) { + rom2prio[rom2prio_cnt].addr = (u32)addr; + rom2prio[rom2prio_cnt].prio = prio; + dprintf(3, "pci rom at memory address %x has boot prio %d\n", + rom2prio[rom2prio_cnt].addr, rom2prio[rom2prio_cnt].prio); + rom2prio_cnt++; + } +} + +static u8 rom2prio_get(u32 addr) +{ + int i; + + for (i = 0; i < rom2prio_cnt; i++) + if (rom2prio[i].addr == addr) + return rom2prio[i].prio; + + return -1; +}
/**************************************************************** * Helper functions @@ -243,13 +271,18 @@ static void run_file_roms(const char *prefix, int isvga) { u32 file = 0; + for (;;) { file = romfile_findprefix(prefix, file); if (!file) break; int ret = romfile_copy(file, (void*)RomEnd, max_rom() - RomEnd); - if (ret > 0) - init_optionrom((void*)RomEnd, 0, isvga); + if (ret > 0) { + void *rom = (void*)RomEnd; + ret = init_optionrom(rom, 0, isvga); + if (!ret && is_valid_rom(rom)) + map_rom2prio(rom, bootprio_find_named_rom(romfile_name(file))); + } } }
@@ -342,7 +375,15 @@ 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; + + map_rom2prio(rom, bootprio_find_pci_device(bdf)); + + return r; }
@@ -394,21 +435,22 @@ optionrom_setup(void) pos += OPTION_ROM_ALIGN; continue; } + u8 romprio = rom2prio_get(pos); pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN); struct pnp_data *pnp = get_pnp_rom(rom); if (! pnp) { // Legacy rom. - add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0); + add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0, romprio); continue; } // PnP rom. if (pnp->bev) // Can boot system - add to IPL list. - add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname); + add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname, romprio); else // Check for BCV (there may be multiple). while (pnp && pnp->bcv) { - add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname); + add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname, romprio); pnp = get_pnp_next(rom, pnp); } } diff --git a/src/paravirt.c b/src/paravirt.c index ca646d4..308c809 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -345,6 +345,14 @@ int qemu_cfg_size_file(u32 select) return ntohl(LastFile.size); }
+ +const char* qemu_cfg_name_file(u32 select) +{ + if (select != ntohs(LastFile.select)) + return NULL; + return LastFile.name; +} + int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen) { if (!qemu_cfg_present) diff --git a/src/paravirt.h b/src/paravirt.h index 7d4bc02..99c473b 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -71,6 +71,7 @@ struct e820_reservation { u32 qemu_cfg_next_prefix_file(const char *prefix, u32 prevselect); u32 qemu_cfg_find_file(const char *name); int qemu_cfg_size_file(u32 select); +const char* qemu_cfg_name_file(u32 select); int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen);
// Wrappers that select cbfs or qemu_cfg file interface. @@ -94,6 +95,11 @@ static inline int romfile_copy(u32 fileid, void *dst, u32 maxlen) { return cbfs_copyfile((void*)fileid, dst, maxlen); return qemu_cfg_read_file(fileid, dst, maxlen); } +static inline const char* romfile_name(u32 fileid) { + if (CONFIG_COREBOOT) + return cbfs_filename((void*)fileid); + return qemu_cfg_name_file(fileid); +}
u32 qemu_cfg_e820_entries(void); void* qemu_cfg_e820_load_next(void *addr); diff --git a/src/usb-msc.c b/src/usb-msc.c index 080efdc..c3ffe0b 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -171,7 +171,7 @@ setup_drive_hd(struct disk_op_s *op) setup_translation(op->drive_g);
// Register with bcv system. - add_bcv_internal(op->drive_g); + add_bcv_internal(op->drive_g, MAX_BOOT_PRIO);
return 0; } diff --git a/src/util.c b/src/util.c index f9a7533..3892c3c 100644 --- a/src/util.c +++ b/src/util.c @@ -262,6 +262,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 diff --git a/src/util.h b/src/util.h index fa7b20f..f5b9446 100644 --- a/src/util.h +++ b/src/util.h @@ -209,6 +209,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 diff --git a/src/virtio-blk.c b/src/virtio-blk.c index 7a25826..3d2b7a6 100644 --- a/src/virtio-blk.c +++ b/src/virtio-blk.c @@ -153,7 +153,7 @@ init_virtio_blk(u16 bdf) vdrive_g->drive.pchs.spt = cfg.sectors;
setup_translation(&vdrive_g->drive); - add_bcv_internal(&vdrive_g->drive); + add_bcv_internal(&vdrive_g->drive, bootprio_find_pci_device(bdf));
snprintf(desc, MAXDESCSIZE, "Virtio disk PCI:%x:%x", pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)); -- Gleb.
Kevin, any additional comments about this patch?
On Tue, Dec 14, 2010 at 11:42:36AM +0200, Gleb Natapov wrote:
On Mon, Dec 13, 2010 at 05:02:43PM +0200, Gleb Natapov wrote:
On Mon, Dec 13, 2010 at 08:44:08AM -0500, Kevin O'Connor wrote:
On Mon, Dec 13, 2010 at 03:12:51PM +0200, Gleb Natapov wrote:
On Thu, Dec 09, 2010 at 08:27:10PM -0500, Kevin O'Connor wrote:
On Wed, Dec 08, 2010 at 02:00:50PM +0200, Gleb Natapov wrote:
With patch below (goes on top of bev per CD patch) I can specify boot order from qemu command line between several NICs, CDROMs, floppy and disk. With qemu command like this:
Hi Gleb.
I'm a bit behind right now, but I'll take a look this weekend.
Have you had a chance to look at it? If not yet then here is updated version that fix one little bug with boot menu and choosing between multiple BCVs:
I did look at it, but didn't get a chance to reply. Here are my thoughts in brief:
I'm okay with the general layout (read bootorder at start, note priority when adding each entry)
The system seems to conflict with the sorting already done by add_bcv_internal() and add_ordered_drive() (which was added to handle threads adding drives in any order). The get_boot_priority() code you've added isn't right, because there's no guarentee that a drive will be added in a repeatable manor (you don't want a user without "bootorder" to see different drives being booted on different boots).
Good point. Will fix. Probably will require more invasive changes though.
It was easier to fix than I initially thought. All BCVs and BEVs that do not have corespondent device paths get the same lowest priority. During sorting they stay in the same order at the end.
I search for ISA bridge dynamically now using pci_find_class(PCI_CLASS_BRIDGE_ISA).
Signed-off-by: Gleb Natapov gleb@redhat.com diff --git a/src/ahci.c b/src/ahci.c index 70c0f1c..a209c86 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.
add_bcv_internal(&port->drive);
} else { // found cdrom (atapi) port->drive.blksize = CDROM_SECTOR_SIZE;add_bcv_internal(&port->drive, MAX_BOOT_PRIO);
@@ -397,7 +397,7 @@ ahci_port_init(struct ahci_ctrl_s *ctrl, u32 pnr) // fill cdidmap if (iscd) { map_cd_drive(&port->drive);
add_baid_cdrom(&port->drive);
} } dprintf(1, "%s\n", port->drive.desc);add_baid_cdrom(&port->drive, MAX_BOOT_PRIO);
diff --git a/src/ata.c b/src/ata.c index d971480..e45de50 100644 --- a/src/ata.c +++ b/src/ata.c @@ -783,8 +783,11 @@ init_drive_atapi(struct atadrive_s *dummy, u16 *buffer)
// fill cdidmap if (iscd) {
int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_bdf,
adrive_g->chan_gf->chanid,
adrive_g->slave); map_cd_drive(&adrive_g->drive);
add_baid_cdrom(&adrive_g->drive);
add_baid_cdrom(&adrive_g->drive, prio);
}
return adrive_g;
@@ -834,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,
// Register with bcv system.adrive_g->slave);
- add_bcv_internal(&adrive_g->drive);
add_bcv_internal(&adrive_g->drive, prio);
return adrive_g;
} diff --git a/src/boot.c b/src/boot.c index 9c94439..157f666 100644 --- a/src/boot.c +++ b/src/boot.c @@ -13,10 +13,12 @@ #include "boot.h" // struct ipl_s #include "cmos.h" // inb_cmos #include "paravirt.h" +#include "pci.h" //pci_bdf_to_*
struct ipl_s IPL;
/****************************************************************
- IPL and BCV handlers
****************************************************************/ @@ -67,11 +69,56 @@ 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);
- dprintf(3, "bootorder file found (len %d)\n", filesize);
- if (filesize == 0)
return;
- char *f = malloc_tmphigh(filesize);
- if (!f) {
warn_noalloc();
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) {
warn_noalloc();
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. void -add_bev(u16 seg, u16 bev, u16 desc) +add_bev(u16 seg, u16 bev, u16 desc, u8 prio) { if (! CONFIG_BOOT) return; @@ -85,11 +132,12 @@ add_bev(u16 seg, u16 bev, u16 desc) if (desc) d = MAKE_FLATPTR(seg, desc); ie->description = d;
- ie->prio = prio;
}
// Add a IPL entry for BAID cdrom. void -add_baid_cdrom(struct drive_s *drive_g) +add_baid_cdrom(struct drive_s *drive_g, u8 prio) { if (! CONFIG_CDROM_BOOT) return; @@ -104,11 +152,18 @@ add_baid_cdrom(struct drive_s *drive_g) ie->type = IPL_TYPE_CDROM; ie->vector = (u32)drive_g; ie->description = "DVD/CD";
- ie->prio = prio;
+}
+void set_floppy_baid_prio(u8 prio) +{
- struct ipl_entry_s *ie = &IPL.bev[0];
- ie->prio = prio;
}
// Add a bcv entry for an expansion card harddrive or legacy option rom void -add_bcv(u16 seg, u16 ip, u16 desc) +add_bcv(u16 seg, u16 ip, u16 desc, u8 prio) { if (! CONFIG_BOOT) return; @@ -122,11 +177,12 @@ add_bcv(u16 seg, u16 ip, u16 desc) if (desc) d = MAKE_FLATPTR(seg, desc); ie->description = d;
- ie->prio = prio;
}
// Add a bcv entry for an internal harddrive void -add_bcv_internal(struct drive_s *drive_g) +add_bcv_internal(struct drive_s *drive_g, u8 prio) { if (! CONFIG_BOOT) return; @@ -154,6 +210,7 @@ add_bcv_internal(struct drive_s *drive_g) ie->type = BCV_TYPE_INTERNAL; ie->vector = (u32)drive_g; ie->description = "";
- ie->prio = prio;
}
@@ -323,6 +380,41 @@ run_bcv(struct ipl_entry_s *ie) } }
+/* Bubble sort! Should be good enough for 8 elements */ +static void sort_ipls(struct ipl_entry_s *ipls, int iplscount) +{
- int stop;
- if (iplscount == 0)
return;
- do {
int i;
stop = 1;
for (i = 0; i < iplscount - 1; i++) {
if (ipls[i].prio > ipls[i+1].prio) {
struct ipl_entry_s tmp;
tmp = ipls[i];
ipls[i] = ipls[i+1];
ipls[i+1] = tmp;
stop = 0;
}
}
- } while (!stop);
+}
+static void order_boot_devices(void) +{
- if (IPL.fw_bootorder_count == 0)
return;
- sort_ipls(IPL.bcv, IPL.bcvcount);
- /* Hard disk IPL inherits priority of the bootable bcv */
- IPL.bev[1].prio = IPL.bcv[0].prio;
- sort_ipls(IPL.bev, IPL.bevcount);
- IPL.bootorder = 0x87654321;
+}
// Prepare for boot - show menu and run bcvs. void boot_prep(void) @@ -334,24 +426,38 @@ boot_prep(void)
// XXX - show available drives?
- order_boot_devices();
- // Allow user to modify BCV/IPL order. interactive_bootmenu(); wait_threads();
- // Setup floppy boot order
- int override = IPL.bev[0].subchoice;
- struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0];
- Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][override];
- Drives.idmap[EXTTYPE_FLOPPY][override] = tmp;
- // Run BCVs
- override = IPL.bev[1].subchoice;
- if (override < IPL.bcvcount)
run_bcv(&IPL.bcv[override]);
- int i;
- for (i=0; i<IPL.bcvcount; i++)
if (i != override)
run_bcv(&IPL.bcv[i]);
- int j;
- for (j = 0; j < IPL.bevcount; j++) {
int override;
switch (IPL.bev[j].type) {
case IPL_TYPE_FLOPPY:
// Setup floppy boot order
override = IPL.bev[j].subchoice;
struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0];
Drives.idmap[EXTTYPE_FLOPPY][0] =
Drives.idmap[EXTTYPE_FLOPPY][override];
Drives.idmap[EXTTYPE_FLOPPY][override] = tmp;
break;
case IPL_TYPE_HARDDISK:
// Run BCVs
override = IPL.bev[j].subchoice;
if (override < IPL.bcvcount)
run_bcv(&IPL.bcv[override]);
int i;
for (i=0; i<IPL.bcvcount; i++)
if (i != override)
run_bcv(&IPL.bcv[i]);
break;
default:
break;
}
- }
}
@@ -529,3 +635,158 @@ 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 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 u8 find_pci_device(int bdf, u8 start_idx, const char **rest) +{
- u8 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 MAX_BOOT_PRIO;
+}
+u8 bootprio_find_pci_device(int bdf) +{
- const char *rest;
- return find_pci_device(bdf, 0, &rest);
+}
+u8 bootprio_find_ata_device(int bdf, int chanid, int slave) +{
- const char *rest;
- u8 idx = 0;
- if (bdf == -1)
return MAX_BOOT_PRIO; /* support only pci machine for now */
- while((idx = find_pci_device(bdf, idx, &rest)) != MAX_BOOT_PRIO) {
if (match_next_node_address(rest, chanid ? "1" : "0", &rest) &&
match_next_node_address(rest, slave ? "1" : "0", &rest))
break;
idx++;
- }
- return idx;
+}
+u8 bootprio_find_fdc_device(int bdf, int port, int fdid) +{
- const char *rest;
- u8 idx = 0;
- char addr[5];
- if (bdf == -1)
return MAX_BOOT_PRIO; /* support only pci machine for now */
- snprintf(addr, sizeof addr, "%04x", port);
- while((idx = find_pci_device(bdf, idx, &rest)) != MAX_BOOT_PRIO) {
if (match_next_node_address(rest, addr, &rest) &&
match_next_node_address(rest, fdid ? "1" : "0", &rest))
break;
idx++;
- }
- return idx;
+}
+u8 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 MAX_BOOT_PRIO;
+} diff --git a/src/boot.h b/src/boot.h index f751d71..5a4c6ea 100644 --- a/src/boot.h +++ b/src/boot.h @@ -12,6 +12,7 @@ struct ipl_entry_s { u16 subchoice; u32 vector; const char *description;
- u8 prio;
};
struct ipl_s { @@ -20,6 +21,8 @@ struct ipl_s { int bevcount, bcvcount; u32 bootorder; int checkfloppysig;
- char **fw_bootorder;
- int fw_bootorder_count;
};
#define IPL_TYPE_FLOPPY 0x01 @@ -31,6 +34,7 @@ struct ipl_s { #define BCV_TYPE_EXTERNAL 0x80 #define BCV_TYPE_INTERNAL 0x02
+#define MAX_BOOT_PRIO 255
/****************************************************************
- Function defs
@@ -39,12 +43,17 @@ struct ipl_s { // boot.c extern struct ipl_s IPL; void boot_setup(void); -void add_bev(u16 seg, u16 bev, u16 desc); -void add_bcv(u16 seg, u16 ip, u16 desc); +void add_bev(u16 seg, u16 bev, u16 desc, u8 prio); +void add_bcv(u16 seg, u16 ip, u16 desc, u8 prio); struct drive_s; -void add_bcv_internal(struct drive_s *drive_g); -void add_baid_cdrom(struct drive_s *drive_g); +void add_bcv_internal(struct drive_s *drive_g, u8 prio); +void add_baid_cdrom(struct drive_s *drive_g, u8 prio); +void set_floppy_baid_prio(u8 prio);
void boot_prep(void); +u8 bootprio_find_pci_device(int bdf); +u8 bootprio_find_ata_device(int bdf, int chanid, int slave); +u8 bootprio_find_fdc_device(int bfd, int port, int fdid); +u8 bootprio_find_named_rom(const char *name);
#endif // __BOOT_H diff --git a/src/config.h b/src/config.h index db3e578..0b575a9 100644 --- a/src/config.h +++ b/src/config.h @@ -16,9 +16,9 @@ #define CONFIG_COREBOOT 0
// Control how verbose debug output is. -#define CONFIG_DEBUG_LEVEL 1 +#define CONFIG_DEBUG_LEVEL 5 // Send debugging information to serial port -#define CONFIG_DEBUG_SERIAL 0 +#define CONFIG_DEBUG_SERIAL 1 // Screen writes are also sent to debug ports. #define CONFIG_SCREEN_AND_DEBUG 1
diff --git a/src/floppy.c b/src/floppy.c index 6491b96..7dd3083 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -13,6 +13,9 @@ #include "cmos.h" // inb_cmos #include "pic.h" // eoi_pic1 #include "bregs.h" // struct bregs +#include "pci.h" // pci_to_bdf +#include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA +#include "boot.h" // bootprio_find_fdc_device
#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors #define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 @@ -131,10 +134,25 @@ floppy_setup(void) // XXX - disable floppies on coreboot for now. } else { u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE);
if (type & 0xf0)
unsigned int prio0 = -1, prio1 = -1;
int bdf = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */
if (type & 0xf0) { addFloppy(0, type >> 4, DTYPE_FLOPPY);
if (type & 0x0f)
prio0 = bootprio_find_fdc_device(bdf, 0x3f0, 0);
}
if (type & 0x0f) { addFloppy(1, type & 0x0f, DTYPE_FLOPPY);
prio1 = bootprio_find_fdc_device(bdf, 0x3f0, 1);
}
if (prio1 < prio0) {
/* if B has lower boot priority swap it with A */
struct drive_s *tmp = Drives.idmap[EXTTYPE_FLOPPY][0];
Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][1];
Drives.idmap[EXTTYPE_FLOPPY][1] = tmp;
set_floppy_baid_prio(prio1);
} else
set_floppy_baid_prio(prio0);
}
outb(0x02, PORT_DMA1_MASK_REG);
diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..0fd9aed 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -74,6 +74,34 @@ struct pnp_data { // The end of the last deployed rom. u32 RomEnd = BUILD_ROM_START;
+static struct rom_dev {
- u32 addr;
- u8 prio;
+} rom2prio[92];
+static int rom2prio_cnt;
+static void map_rom2prio(void *addr, u8 prio) +{
- if (rom2prio_cnt < ARRAY_SIZE(rom2prio)) {
rom2prio[rom2prio_cnt].addr = (u32)addr;
rom2prio[rom2prio_cnt].prio = prio;
dprintf(3, "pci rom at memory address %x has boot prio %d\n",
rom2prio[rom2prio_cnt].addr, rom2prio[rom2prio_cnt].prio);
rom2prio_cnt++;
- }
+}
+static u8 rom2prio_get(u32 addr) +{
- int i;
- for (i = 0; i < rom2prio_cnt; i++)
if (rom2prio[i].addr == addr)
return rom2prio[i].prio;
- return -1;
+}
/****************************************************************
- Helper functions
@@ -243,13 +271,18 @@ static void run_file_roms(const char *prefix, int isvga) { u32 file = 0;
- for (;;) { file = romfile_findprefix(prefix, file); if (!file) break; int ret = romfile_copy(file, (void*)RomEnd, max_rom() - RomEnd);
if (ret > 0)
init_optionrom((void*)RomEnd, 0, isvga);
if (ret > 0) {
void *rom = (void*)RomEnd;
ret = init_optionrom(rom, 0, isvga);
if (!ret && is_valid_rom(rom))
map_rom2prio(rom, bootprio_find_named_rom(romfile_name(file)));
}}
}
@@ -342,7 +375,15 @@ 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;
- map_rom2prio(rom, bootprio_find_pci_device(bdf));
- return r;
}
@@ -394,21 +435,22 @@ optionrom_setup(void) pos += OPTION_ROM_ALIGN; continue; }
u8 romprio = rom2prio_get(pos); pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN); struct pnp_data *pnp = get_pnp_rom(rom); if (! pnp) { // Legacy rom.
add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0);
add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0, romprio); continue; } // PnP rom. if (pnp->bev) // Can boot system - add to IPL list.
add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname);
add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname, romprio); else // Check for BCV (there may be multiple). while (pnp && pnp->bcv) {
add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname);
}add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname, romprio); pnp = get_pnp_next(rom, pnp); }
diff --git a/src/paravirt.c b/src/paravirt.c index ca646d4..308c809 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -345,6 +345,14 @@ int qemu_cfg_size_file(u32 select) return ntohl(LastFile.size); }
+const char* qemu_cfg_name_file(u32 select) +{
- if (select != ntohs(LastFile.select))
return NULL;
- return LastFile.name;
+}
int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen) { if (!qemu_cfg_present) diff --git a/src/paravirt.h b/src/paravirt.h index 7d4bc02..99c473b 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -71,6 +71,7 @@ struct e820_reservation { u32 qemu_cfg_next_prefix_file(const char *prefix, u32 prevselect); u32 qemu_cfg_find_file(const char *name); int qemu_cfg_size_file(u32 select); +const char* qemu_cfg_name_file(u32 select); int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen);
// Wrappers that select cbfs or qemu_cfg file interface. @@ -94,6 +95,11 @@ static inline int romfile_copy(u32 fileid, void *dst, u32 maxlen) { return cbfs_copyfile((void*)fileid, dst, maxlen); return qemu_cfg_read_file(fileid, dst, maxlen); } +static inline const char* romfile_name(u32 fileid) {
- if (CONFIG_COREBOOT)
return cbfs_filename((void*)fileid);
- return qemu_cfg_name_file(fileid);
+}
u32 qemu_cfg_e820_entries(void); void* qemu_cfg_e820_load_next(void *addr); diff --git a/src/usb-msc.c b/src/usb-msc.c index 080efdc..c3ffe0b 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -171,7 +171,7 @@ setup_drive_hd(struct disk_op_s *op) setup_translation(op->drive_g);
// Register with bcv system.
- add_bcv_internal(op->drive_g);
add_bcv_internal(op->drive_g, MAX_BOOT_PRIO);
return 0;
} diff --git a/src/util.c b/src/util.c index f9a7533..3892c3c 100644 --- a/src/util.c +++ b/src/util.c @@ -262,6 +262,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
diff --git a/src/util.h b/src/util.h index fa7b20f..f5b9446 100644 --- a/src/util.h +++ b/src/util.h @@ -209,6 +209,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 diff --git a/src/virtio-blk.c b/src/virtio-blk.c index 7a25826..3d2b7a6 100644 --- a/src/virtio-blk.c +++ b/src/virtio-blk.c @@ -153,7 +153,7 @@ init_virtio_blk(u16 bdf) vdrive_g->drive.pchs.spt = cfg.sectors;
setup_translation(&vdrive_g->drive);
- add_bcv_internal(&vdrive_g->drive);
add_bcv_internal(&vdrive_g->drive, bootprio_find_pci_device(bdf));
snprintf(desc, MAXDESCSIZE, "Virtio disk PCI:%x:%x", pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
-- Gleb.
SeaBIOS mailing list SeaBIOS@seabios.org http://www.seabios.org/mailman/listinfo/seabios
-- Gleb.
On Tue, Dec 21, 2010 at 08:55:25AM +0200, Gleb Natapov wrote:
Kevin, any additional comments about this patch?
Hi Gleb,
I haven't had a chance to look through your recent changes.
If you break up the patch, I think we can commit most parts now.
-Kevin
On Wed, Dec 22, 2010 at 08:22:29AM -0500, Kevin O'Connor wrote:
On Tue, Dec 21, 2010 at 08:55:25AM +0200, Gleb Natapov wrote:
Kevin, any additional comments about this patch?
Hi Gleb,
I haven't had a chance to look through your recent changes.
If you break up the patch, I think we can commit most parts now.
Will do. Thanks!
-- Gleb.