Gleb Natapov (9): Provide full EDD 3.0 info for virtio disk Add BAID for ahci cdrom. Add strchr() function. Read bootorder file into memory. Add romfile_name() function. Add functions for boot device path parsing. Create mapping between rom address and boot priority. Record boot priority for each BAID/BCV/BEV. Sort IPLs according to their boot priority.
src/ahci.c | 6 +- src/ata.c | 10 ++- src/boot.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++---- src/boot.h | 17 +++- src/disk.c | 126 +++++++++++++---------- src/floppy.c | 22 ++++- src/optionroms.c | 53 +++++++++- src/paravirt.c | 8 ++ src/paravirt.h | 6 + src/usb-msc.c | 2 +- src/util.c | 11 ++ src/util.h | 1 + src/virtio-blk.c | 2 +- 13 files changed, 471 insertions(+), 89 deletions(-)
Fill out entire EDD 3.0 structure for virtio disk. Currently only EDD 1.0 part is filled which is missing such important info as device path. Use SCSI device type since virtio is not defined by EDD spec and virtio disk pci device uses SCSI class.
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/disk.c | 126 ++++++++++++++++++++++++++++++++++------------------------- 1 files changed, 73 insertions(+), 53 deletions(-)
diff --git a/src/disk.c b/src/disk.c index 242c742..56c369a 100644 --- a/src/disk.c +++ b/src/disk.c @@ -544,64 +544,78 @@ disk_1348(struct bregs *regs, struct drive_s *drive_g) } SET_INT13DPT(regs, blksize, blksize);
- if (size < 30 || (type != DTYPE_ATA && type != DTYPE_ATAPI)) { + if (size < 30 || + (type != DTYPE_ATA && type != DTYPE_ATAPI && type != DTYPE_VIRTIO)) { disk_ret(regs, DISK_RET_SUCCESS); return; }
// EDD 2.x
- u16 ebda_seg = get_ebda_seg(); + int bdf; + u16 iobase1; + u64 device_path; SET_INT13DPT(regs, size, 30); + if (type == DTYPE_ATA || type == DTYPE_ATAPI) { + u16 ebda_seg = get_ebda_seg();
- SET_INT13DPT(regs, dpte_segment, ebda_seg); - SET_INT13DPT(regs, dpte_offset - , offsetof(struct extended_bios_data_area_s, dpte)); - - // Fill in dpte - struct atadrive_s *adrive_g = container_of( - drive_g, struct atadrive_s, drive); - struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); - u8 slave = GET_GLOBAL(adrive_g->slave); - u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); - u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); - u8 irq = GET_GLOBALFLAT(chan_gf->irq); - - u16 options = 0; - if (type == DTYPE_ATA) { - u8 translation = GET_GLOBAL(drive_g->translation); - if (translation != TRANSLATION_NONE) { - options |= 1<<3; // CHS translation - if (translation == TRANSLATION_LBA) - options |= 1<<9; - if (translation == TRANSLATION_RECHS) - options |= 3<<9; + SET_INT13DPT(regs, dpte_segment, ebda_seg); + SET_INT13DPT(regs, dpte_offset + , offsetof(struct extended_bios_data_area_s, dpte)); + + // Fill in dpte + struct atadrive_s *adrive_g = container_of( + drive_g, struct atadrive_s, drive); + struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf); + u8 slave = GET_GLOBAL(adrive_g->slave); + u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); + u8 irq = GET_GLOBALFLAT(chan_gf->irq); + iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); + bdf = GET_GLOBALFLAT(chan_gf->pci_bdf); + device_path = slave; + + u16 options = 0; + if (type == DTYPE_ATA) { + u8 translation = GET_GLOBAL(drive_g->translation); + if (translation != TRANSLATION_NONE) { + options |= 1<<3; // CHS translation + if (translation == TRANSLATION_LBA) + options |= 1<<9; + if (translation == TRANSLATION_RECHS) + options |= 3<<9; + } + } else { + // ATAPI + options |= 1<<5; // removable device + options |= 1<<6; // atapi device } + options |= 1<<4; // lba translation + if (CONFIG_ATA_PIO32) + options |= 1<<7; + + SET_EBDA2(ebda_seg, dpte.iobase1, iobase1); + SET_EBDA2(ebda_seg, dpte.iobase2, iobase2 + ATA_CB_DC); + SET_EBDA2(ebda_seg, dpte.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) + | ATA_CB_DH_LBA)); + SET_EBDA2(ebda_seg, dpte.unused, 0xcb); + SET_EBDA2(ebda_seg, dpte.irq, irq); + SET_EBDA2(ebda_seg, dpte.blkcount, 1); + SET_EBDA2(ebda_seg, dpte.dma, 0); + SET_EBDA2(ebda_seg, dpte.pio, 0); + SET_EBDA2(ebda_seg, dpte.options, options); + SET_EBDA2(ebda_seg, dpte.reserved, 0); + SET_EBDA2(ebda_seg, dpte.revision, 0x11); + + u8 sum = checksum_far( + ebda_seg, (void*)offsetof(struct extended_bios_data_area_s, dpte), 15); + SET_EBDA2(ebda_seg, dpte.checksum, -sum); } else { - // ATAPI - options |= 1<<5; // removable device - options |= 1<<6; // atapi device + SET_INT13DPT(regs, dpte_segment, 0); + SET_INT13DPT(regs, dpte_offset, 0); + bdf = GET_GLOBAL(drive_g->cntl_id); + device_path = 0; + iobase1 = 0; } - options |= 1<<4; // lba translation - if (CONFIG_ATA_PIO32) - options |= 1<<7; - - SET_EBDA2(ebda_seg, dpte.iobase1, iobase1); - SET_EBDA2(ebda_seg, dpte.iobase2, iobase2 + ATA_CB_DC); - SET_EBDA2(ebda_seg, dpte.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) - | ATA_CB_DH_LBA)); - SET_EBDA2(ebda_seg, dpte.unused, 0xcb); - SET_EBDA2(ebda_seg, dpte.irq, irq); - SET_EBDA2(ebda_seg, dpte.blkcount, 1); - SET_EBDA2(ebda_seg, dpte.dma, 0); - SET_EBDA2(ebda_seg, dpte.pio, 0); - SET_EBDA2(ebda_seg, dpte.options, options); - SET_EBDA2(ebda_seg, dpte.reserved, 0); - SET_EBDA2(ebda_seg, dpte.revision, 0x11); - - u8 sum = checksum_far( - ebda_seg, (void*)offsetof(struct extended_bios_data_area_s, dpte), 15); - SET_EBDA2(ebda_seg, dpte.checksum, -sum);
if (size < 66) { disk_ret(regs, DISK_RET_SUCCESS); @@ -614,7 +628,6 @@ disk_1348(struct bregs *regs, struct drive_s *drive_g) SET_INT13DPT(regs, reserved1, 0); SET_INT13DPT(regs, reserved2, 0);
- int bdf = GET_GLOBALFLAT(chan_gf->pci_bdf); if (bdf != -1) { SET_INT13DPT(regs, host_bus[0], 'P'); SET_INT13DPT(regs, host_bus[1], 'C'); @@ -634,16 +647,23 @@ disk_1348(struct bregs *regs, struct drive_s *drive_g) SET_INT13DPT(regs, iface_path, iobase1); }
- SET_INT13DPT(regs, iface_type[0], 'A'); - SET_INT13DPT(regs, iface_type[1], 'T'); - SET_INT13DPT(regs, iface_type[2], 'A'); - SET_INT13DPT(regs, iface_type[3], 0); + if (type != DTYPE_VIRTIO) { + SET_INT13DPT(regs, iface_type[0], 'A'); + SET_INT13DPT(regs, iface_type[1], 'T'); + SET_INT13DPT(regs, iface_type[2], 'A'); + SET_INT13DPT(regs, iface_type[3], 0); + } else { + SET_INT13DPT(regs, iface_type[0], 'S'); + SET_INT13DPT(regs, iface_type[1], 'C'); + SET_INT13DPT(regs, iface_type[2], 'S'); + SET_INT13DPT(regs, iface_type[3], 'I'); + } SET_INT13DPT(regs, iface_type[4], 0); SET_INT13DPT(regs, iface_type[5], 0); SET_INT13DPT(regs, iface_type[6], 0); SET_INT13DPT(regs, iface_type[7], 0);
- SET_INT13DPT(regs, device_path, slave); + SET_INT13DPT(regs, device_path, device_path);
SET_INT13DPT(regs, checksum , -checksum_far(regs->ds, (void*)(regs->si+30), 35));
On Thu, Dec 23, 2010 at 11:29:35AM +0200, Gleb Natapov wrote:
Fill out entire EDD 3.0 structure for virtio disk. Currently only EDD 1.0 part is filled which is missing such important info as device path. Use SCSI device type since virtio is not defined by EDD spec and virtio disk pci device uses SCSI class.
Signed-off-by: Gleb Natapov gleb@redhat.com
Thanks - I applied this.
BTW, at some point we'll have to break up disk_1348() into per-disk type handlers.
-Kevin
On Fri, Dec 24, 2010 at 10:42:50AM -0500, Kevin O'Connor wrote:
On Thu, Dec 23, 2010 at 11:29:35AM +0200, Gleb Natapov wrote:
Fill out entire EDD 3.0 structure for virtio disk. Currently only EDD 1.0 part is filled which is missing such important info as device path. Use SCSI device type since virtio is not defined by EDD spec and virtio disk pci device uses SCSI class.
Signed-off-by: Gleb Natapov gleb@redhat.com
Thanks - I applied this.
BTW, at some point we'll have to break up disk_1348() into per-disk type handlers.
Yes, and what about moving to EDD4.0?
-- Gleb.
On Sun, Dec 26, 2010 at 04:12:21PM +0200, Gleb Natapov wrote:
On Fri, Dec 24, 2010 at 10:42:50AM -0500, Kevin O'Connor wrote:
On Thu, Dec 23, 2010 at 11:29:35AM +0200, Gleb Natapov wrote:
Fill out entire EDD 3.0 structure for virtio disk. Currently only EDD 1.0 part is filled which is missing such important info as device path. Use SCSI device type since virtio is not defined by EDD spec and virtio disk pci device uses SCSI class.
Signed-off-by: Gleb Natapov gleb@redhat.com
Thanks - I applied this.
BTW, at some point we'll have to break up disk_1348() into per-disk type handlers.
Yes, and what about moving to EDD4.0?
Yes - that should be done as well.
-Kevin
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/ahci.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/src/ahci.c b/src/ahci.c index e2b2dbf..70c0f1c 100644 --- a/src/ahci.c +++ b/src/ahci.c @@ -395,8 +395,10 @@ ahci_port_init(struct ahci_ctrl_s *ctrl, u32 pnr) , (iscd ? "DVD/CD" : "Device"));
// fill cdidmap - if (iscd) + if (iscd) { map_cd_drive(&port->drive); + add_baid_cdrom(&port->drive); + } } dprintf(1, "%s\n", port->drive.desc);
On Thu, Dec 23, 2010 at 11:29:36AM +0200, Gleb Natapov wrote:
Signed-off-by: Gleb Natapov gleb@redhat.com
Thanks - I applied this.
-Kevin
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/util.c | 11 +++++++++++ src/util.h | 1 + 2 files changed, 12 insertions(+), 0 deletions(-)
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
On Thu, Dec 23, 2010 at 11:29:37AM +0200, Gleb Natapov wrote:
Signed-off-by: Gleb Natapov gleb@redhat.com
src/util.c | 11 +++++++++++ src/util.h | 1 + 2 files changed, 12 insertions(+), 0 deletions(-)
How about this instead?
-Kevin
--- a/src/util.c +++ b/src/util.c @@ -262,6 +262,15 @@ 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) +{ + for (; *s; s++) + if (*s == c) + return (char*)s; + return 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
On Fri, Dec 24, 2010 at 10:41:45AM -0500, Kevin O'Connor wrote:
On Thu, Dec 23, 2010 at 11:29:37AM +0200, Gleb Natapov wrote:
Signed-off-by: Gleb Natapov gleb@redhat.com
src/util.c | 11 +++++++++++ src/util.h | 1 + 2 files changed, 12 insertions(+), 0 deletions(-)
How about this instead?
OK. The result is the same :)
-Kevin
--- a/src/util.c +++ b/src/util.c @@ -262,6 +262,15 @@ 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) +{
- for (; *s; s++)
if (*s == c)
return (char*)s;
- return 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
-- Gleb.
Read bootorder file, parse it and put it into array for easy consumption.
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/boot.h | 2 ++ 2 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/src/boot.c b/src/boot.c index 9c94439..9c37023 100644 --- a/src/boot.c +++ b/src/boot.c @@ -67,6 +67,51 @@ 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. diff --git a/src/boot.h b/src/boot.h index f751d71..778aebd 100644 --- a/src/boot.h +++ b/src/boot.h @@ -20,6 +20,8 @@ struct ipl_s { int bevcount, bcvcount; u32 bootorder; int checkfloppysig; + char **fw_bootorder; + int fw_bootorder_count; };
#define IPL_TYPE_FLOPPY 0x01
On Thu, Dec 23, 2010 at 11:29:38AM +0200, Gleb Natapov wrote:
Read bootorder file, parse it and put it into array for easy consumption.
Signed-off-by: Gleb Natapov gleb@redhat.com
I applied this. I'd like to apply two patches on top of it as a cleanup.
I've also changed the code so that the bootorder file doesn't need to be null-terminated (seabios will tack on a trailing null itself).
-Kevin
romfile_name() return file name given file handler. Works for qemu and coreboot.
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/paravirt.c | 8 ++++++++ src/paravirt.h | 6 ++++++ 2 files changed, 14 insertions(+), 0 deletions(-)
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);
On Thu, Dec 23, 2010 at 11:29:39AM +0200, Gleb Natapov wrote:
romfile_name() return file name given file handler. Works for qemu and coreboot.
Signed-off-by: Gleb Natapov gleb@redhat.com
Thanks - I applied this.
-Kevin
Add functions that find boot device path for pci/ata/floppy/rom devices.
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/boot.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/boot.h | 5 ++ 2 files changed, 161 insertions(+), 0 deletions(-)
diff --git a/src/boot.c b/src/boot.c index 9c37023..aeacf08 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;
@@ -574,3 +575,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 778aebd..0dfb135 100644 --- a/src/boot.h +++ b/src/boot.h @@ -33,6 +33,7 @@ struct ipl_s { #define BCV_TYPE_EXTERNAL 0x80 #define BCV_TYPE_INTERNAL 0x02
+#define MAX_BOOT_PRIO 255
/**************************************************************** * Function defs @@ -48,5 +49,9 @@ void add_bcv_internal(struct drive_s *drive_g); void add_baid_cdrom(struct drive_s *drive_g);
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
At the time of bev/bcv initialization the device rom was loaded from is no longer know. Only memory address where rom resides is know at this point. This patch create mapping between boot priority and rom address at rom initialization time for use during bev/bcv init.
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/optionroms.c | 35 ++++++++++++++++++++++++++++++++--- 1 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..33f2a03 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -74,6 +74,23 @@ 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++; + } +}
/**************************************************************** * Helper functions @@ -248,8 +265,12 @@ run_file_roms(const char *prefix, int isvga) 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 +363,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; }
On Thu, Dec 23, 2010 at 11:29:41AM +0200, Gleb Natapov wrote:
At the time of bev/bcv initialization the device rom was loaded from is no longer know. Only memory address where rom resides is know at this point. This patch create mapping between boot priority and rom address at rom initialization time for use during bev/bcv init.
Signed-off-by: Gleb Natapov gleb@redhat.com
I find this patch confusing. How about the patch below instead?
-Kevin
diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..579fdd8 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -195,13 +195,17 @@ copy_rom(struct rom_header *rom) return (void*)RomEnd; }
+static u8 RomPriority[(BUILD_BIOS_ADDR - BUILD_ROM_START) / OPTION_ROM_ALIGN]; + // Run rom init code and note rom size. static int -init_optionrom(struct rom_header *rom, u16 bdf, int isvga) +init_optionrom(struct rom_header *rom, u16 bdf, int isvga, u8 prio) { if (! is_valid_rom(rom)) return -1;
+ RomPriority[((u32)rom - BUILD_ROM_START) / OPTION_ROM_ALIGN] = prio; + if (isvga || get_pnp_rom(rom)) // Only init vga and PnP roms here. callrom(rom, bdf); @@ -249,7 +253,7 @@ run_file_roms(const char *prefix, int isvga) break; int ret = romfile_copy(file, (void*)RomEnd, max_rom() - RomEnd); if (ret > 0) - init_optionrom((void*)RomEnd, 0, isvga); + init_optionrom((void*)RomEnd, 0, isvga, -1); } }
@@ -342,7 +346,7 @@ init_pcirom(u16 bdf, int isvga) if (! rom) // No ROM present. return -1; - return init_optionrom(rom, bdf, isvga); + return init_optionrom(rom, bdf, isvga, -1); }
@@ -364,7 +368,7 @@ optionrom_setup(void) // Option roms are already deployed on the system. u32 pos = RomEnd; while (pos < max_rom()) { - int ret = init_optionrom((void*)pos, 0, 0); + int ret = init_optionrom((void*)pos, 0, 0, -1); if (ret) pos += OPTION_ROM_ALIGN; else @@ -430,7 +434,7 @@ vga_setup(void)
if (CONFIG_OPTIONROMS_DEPLOYED) { // Option roms are already deployed on the system. - init_optionrom((void*)BUILD_ROM_START, 0, 1); + init_optionrom((void*)BUILD_ROM_START, 0, 1, -1); } else { // Clear option rom memory memset((void*)RomEnd, 0, _max_rom() - RomEnd);
On Fri, Dec 24, 2010 at 12:13:14PM -0500, Kevin O'Connor wrote:
On Thu, Dec 23, 2010 at 11:29:41AM +0200, Gleb Natapov wrote:
At the time of bev/bcv initialization the device rom was loaded from is no longer know. Only memory address where rom resides is know at this point. This patch create mapping between boot priority and rom address at rom initialization time for use during bev/bcv init.
Signed-off-by: Gleb Natapov gleb@redhat.com
I find this patch confusing. How about the patch below instead?
Yes, better indeed. Need to pass actual priority instead of -1.
-Kevin
diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..579fdd8 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -195,13 +195,17 @@ copy_rom(struct rom_header *rom) return (void*)RomEnd; }
+static u8 RomPriority[(BUILD_BIOS_ADDR - BUILD_ROM_START) / OPTION_ROM_ALIGN];
// Run rom init code and note rom size. static int -init_optionrom(struct rom_header *rom, u16 bdf, int isvga) +init_optionrom(struct rom_header *rom, u16 bdf, int isvga, u8 prio) { if (! is_valid_rom(rom)) return -1;
- RomPriority[((u32)rom - BUILD_ROM_START) / OPTION_ROM_ALIGN] = prio;
- if (isvga || get_pnp_rom(rom)) // Only init vga and PnP roms here. callrom(rom, bdf);
@@ -249,7 +253,7 @@ run_file_roms(const char *prefix, int isvga) break; int ret = romfile_copy(file, (void*)RomEnd, max_rom() - RomEnd); if (ret > 0)
init_optionrom((void*)RomEnd, 0, isvga);
}init_optionrom((void*)RomEnd, 0, isvga, -1);
}
@@ -342,7 +346,7 @@ init_pcirom(u16 bdf, int isvga) if (! rom) // No ROM present. return -1;
- return init_optionrom(rom, bdf, isvga);
- return init_optionrom(rom, bdf, isvga, -1);
}
@@ -364,7 +368,7 @@ optionrom_setup(void) // Option roms are already deployed on the system. u32 pos = RomEnd; while (pos < max_rom()) {
int ret = init_optionrom((void*)pos, 0, 0);
int ret = init_optionrom((void*)pos, 0, 0, -1); if (ret) pos += OPTION_ROM_ALIGN; else
@@ -430,7 +434,7 @@ vga_setup(void)
if (CONFIG_OPTIONROMS_DEPLOYED) { // Option roms are already deployed on the system.
init_optionrom((void*)BUILD_ROM_START, 0, 1);
} else { // Clear option rom memory memset((void*)RomEnd, 0, _max_rom() - RomEnd);init_optionrom((void*)BUILD_ROM_START, 0, 1, -1);
-- Gleb.
On Fri, Dec 24, 2010 at 12:13:14PM -0500, Kevin O'Connor wrote:
On Thu, Dec 23, 2010 at 11:29:41AM +0200, Gleb Natapov wrote:
At the time of bev/bcv initialization the device rom was loaded from is no longer know. Only memory address where rom resides is know at this point. This patch create mapping between boot priority and rom address at rom initialization time for use during bev/bcv init.
Signed-off-by: Gleb Natapov gleb@redhat.com
I find this patch confusing. How about the patch below instead?
Hrmm - instead of tracking the priority of each rom, lets track the source of each rom, and then calculate the priority when adding the bev/bcv. How about the attached instead? (It is admittedly more complex, but it gives me the ability to set priorities for each BCV.)
-Kevin
On Fri, Dec 24, 2010 at 01:33:20PM -0500, Kevin O'Connor wrote:
On Fri, Dec 24, 2010 at 12:13:14PM -0500, Kevin O'Connor wrote:
On Thu, Dec 23, 2010 at 11:29:41AM +0200, Gleb Natapov wrote:
At the time of bev/bcv initialization the device rom was loaded from is no longer know. Only memory address where rom resides is know at this point. This patch create mapping between boot priority and rom address at rom initialization time for use during bev/bcv init.
Signed-off-by: Gleb Natapov gleb@redhat.com
I find this patch confusing. How about the patch below instead?
Hrmm - instead of tracking the priority of each rom, lets track the source of each rom, and then calculate the priority when adding the bev/bcv. How about the attached instead? (It is admittedly more complex, but it gives me the ability to set priorities for each BCV.)
I am OK with this one too. The attached patch includes parts of patch 8 though (pass prio too add_bev/add_bcv functions).
-Kevin
commit 16ef4c87505b415d033b39722e5e829d13708f77 Author: Kevin O'Connor kevin@koconnor.net Date: Fri Dec 24 13:28:12 2010 -0500
Support qemu based romfile wrappers to be called out of order. If the file requested isn't the last file read, then reread the index to find the given file.
diff --git a/src/paravirt.c b/src/paravirt.c index 74d3743..dcb2798 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -338,26 +338,43 @@ u32 qemu_cfg_find_file(const char *name) return __cfg_next_prefix_file(name, strlen(name) + 1, 0); }
+static int +__qemu_cfg_set_file(u32 select) +{
- if (!qemu_cfg_present)
return -1;
- if (select == ntohs(LastFile.select))
return 0;
- u32 count;
- qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
- count = ntohl(count);
- u32 e;
- for (e = 0; e < count; e++) {
qemu_cfg_read((void*)&LastFile, sizeof(LastFile));
if (select == ntohs(LastFile.select))
return 0;
- }
- return -1;
+}
int qemu_cfg_size_file(u32 select) {
- if (select != ntohs(LastFile.select))
- if (__qemu_cfg_set_file(select)) return -1; return ntohl(LastFile.size);
}
const char* qemu_cfg_name_file(u32 select) {
- if (select != ntohs(LastFile.select))
- if (__qemu_cfg_set_file(select)) return NULL; return LastFile.name;
}
int qemu_cfg_read_file(u32 select, void *dst, u32 maxlen) {
- if (!qemu_cfg_present)
return -1;
- if (!select || select != ntohs(LastFile.select))
- if (!select || __qemu_cfg_set_file(select)) return -1; int len = qemu_cfg_size_file(select); if (len < 0 || len > maxlen)
diff --git a/src/boot.c b/src/boot.c index 5137345..9777bd6 100644 --- a/src/boot.c +++ b/src/boot.c @@ -21,6 +21,18 @@ struct ipl_s IPL;
- Boot setup
****************************************************************/
+int +bootprio_find_pci_device(int bdf, int instance) +{
- return -1;
+}
+int +bootprio_find_named_rom(const char *name, int instance) +{
- return -1;
+}
static void loadBootOrder(void) { @@ -113,7 +125,7 @@ boot_setup(void)
// 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; @@ -150,7 +162,7 @@ add_baid_cdrom(struct drive_s *drive_g)
// 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; diff --git a/src/boot.h b/src/boot.h index 778aebd..272c574 100644 --- a/src/boot.h +++ b/src/boot.h @@ -41,12 +41,14 @@ 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 boot_prep(void); +int bootprio_find_pci_device(int bdf, int instance); +int bootprio_find_named_rom(const char *name, int instance);
#endif // __BOOT_H diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..697b4ef 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -211,6 +211,26 @@ init_optionrom(struct rom_header *rom, u16 bdf, int isvga) return 0; }
+#define RS_PCIROM (1LL<<33)
+static void +setRomSource(u64 *sources, struct rom_header *rom, u64 source) +{
- if (sources)
sources[((u32)rom - BUILD_ROM_START) / OPTION_ROM_ALIGN] = source;
+}
+static u8 +getRomPriority(u64 *sources, struct rom_header *rom, int instance) +{
- 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, instance);
- return bootprio_find_named_rom(romfile_name(source), instance);
+}
/****************************************************************
- Roms in CBFS
@@ -240,16 +260,19 @@ lookup_hardcode(u32 vendev)
// Run all roms in a given CBFS directory. static void -run_file_roms(const char *prefix, int isvga) +run_file_roms(const char *prefix, int isvga, u64 *sources) { 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);
struct rom_header *rom = (void*)RomEnd;
int ret = romfile_copy(file, rom, max_rom() - RomEnd);
if (ret > 0) {
setRomSource(sources, rom, file);
init_optionrom(rom, 0, isvga);
}}
}
@@ -330,7 +353,7 @@ fail:
// Attempt to map and initialize the option rom on a given PCI device. static int -init_pcirom(u16 bdf, int isvga) +init_pcirom(u16 bdf, int isvga, u64 *sources) { u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID); dprintf(4, "Attempting to init PCI bdf %02x:%02x.%x (vd %04x:%04x)\n" @@ -342,6 +365,7 @@ init_pcirom(u16 bdf, int isvga) if (! rom) // No ROM present. return -1;
- setRomSource(sources, rom, RS_PCIROM | bdf); return init_optionrom(rom, bdf, isvga);
}
@@ -357,7 +381,8 @@ optionrom_setup(void) return;
dprintf(1, "Scan for option roms\n");
u64 sources[(BUILD_BIOS_ADDR - BUILD_ROM_START) / OPTION_ROM_ALIGN];
memset(sources, 0, sizeof(sources)); u32 post_vga = RomEnd;
if (CONFIG_OPTIONROMS_DEPLOYED) {
@@ -378,11 +403,11 @@ optionrom_setup(void) if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA || (CONFIG_ATA && v == PCI_CLASS_STORAGE_IDE)) continue;
init_pcirom(bdf, 0);
init_pcirom(bdf, 0, sources); } // Find and deploy CBFS roms not associated with a device.
run_file_roms("genroms/", 0);
run_file_roms("genroms/", 0, sources);
}
// All option roms found and deployed - now build BEV/BCV vectors.
@@ -394,21 +419,25 @@ optionrom_setup(void) pos += OPTION_ROM_ALIGN; continue; }
int instance = 0; 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
, getRomPriority(sources, rom, instance)); 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
, getRomPriority(sources, rom, instance)); 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
}, getRomPriority(sources, rom, instance++)); pnp = get_pnp_next(rom, pnp); }
@@ -438,10 +467,10 @@ vga_setup(void) // Find and deploy PCI VGA rom. int bdf = VGAbdf = pci_find_vga(); if (bdf >= 0)
init_pcirom(bdf, 1);
init_pcirom(bdf, 1, NULL); // Find and deploy CBFS vga-style roms not associated with a device.
run_file_roms("vgaroms/", 1);
run_file_roms("vgaroms/", 1, NULL);
}
if (RomEnd == BUILD_ROM_START) {
-- Gleb.
On Fri, Dec 24, 2010 at 08:41:21PM +0200, Gleb Natapov wrote:
On Fri, Dec 24, 2010 at 01:33:20PM -0500, Kevin O'Connor wrote:
On Fri, Dec 24, 2010 at 12:13:14PM -0500, Kevin O'Connor wrote:
On Thu, Dec 23, 2010 at 11:29:41AM +0200, Gleb Natapov wrote:
At the time of bev/bcv initialization the device rom was loaded from is no longer know. Only memory address where rom resides is know at this point. This patch create mapping between boot priority and rom address at rom initialization time for use during bev/bcv init.
Signed-off-by: Gleb Natapov gleb@redhat.com
I find this patch confusing. How about the patch below instead?
Hrmm - instead of tracking the priority of each rom, lets track the source of each rom, and then calculate the priority when adding the bev/bcv. How about the attached instead? (It is admittedly more complex, but it gives me the ability to set priorities for each BCV.)
I am OK with this one too. The attached patch includes parts of patch 8 though (pass prio too add_bev/add_bcv functions).
Yeah - it conflicts with your patch 5 as well. I'm going to commit the patch below (which should be more of a replacement for your patch 7).
-Kevin
commit bca3a878467d30e13a776243c5ca3e426dc847a0 Author: Kevin O'Connor kevin@koconnor.net Date: Fri Dec 24 14:42:42 2010 -0500
Track the source of each optionrom deployed.
It's useful to track where each optionrom in the system originated from when initializing bev/bcvs. So, keep a map of the rom address to its source.
diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..19672f7 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -211,6 +211,15 @@ init_optionrom(struct rom_header *rom, u16 bdf, int isvga) return 0; }
+#define RS_PCIROM (1LL<<33) + +static void +setRomSource(u64 *sources, struct rom_header *rom, u64 source) +{ + if (sources) + sources[((u32)rom - BUILD_ROM_START) / OPTION_ROM_ALIGN] = source; +} +
/**************************************************************** * Roms in CBFS @@ -240,16 +249,19 @@ lookup_hardcode(u32 vendev)
// Run all roms in a given CBFS directory. static void -run_file_roms(const char *prefix, int isvga) +run_file_roms(const char *prefix, int isvga, u64 *sources) { 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); + struct rom_header *rom = (void*)RomEnd; + int ret = romfile_copy(file, rom, max_rom() - RomEnd); + if (ret > 0) { + setRomSource(sources, rom, file); + init_optionrom(rom, 0, isvga); + } } }
@@ -330,7 +342,7 @@ fail:
// Attempt to map and initialize the option rom on a given PCI device. static int -init_pcirom(u16 bdf, int isvga) +init_pcirom(u16 bdf, int isvga, u64 *sources) { u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID); dprintf(4, "Attempting to init PCI bdf %02x:%02x.%x (vd %04x:%04x)\n" @@ -342,6 +354,7 @@ init_pcirom(u16 bdf, int isvga) if (! rom) // No ROM present. return -1; + setRomSource(sources, rom, RS_PCIROM | bdf); return init_optionrom(rom, bdf, isvga); }
@@ -357,7 +370,8 @@ optionrom_setup(void) return;
dprintf(1, "Scan for option roms\n"); - + u64 sources[(BUILD_BIOS_ADDR - BUILD_ROM_START) / OPTION_ROM_ALIGN]; + memset(sources, 0, sizeof(sources)); u32 post_vga = RomEnd;
if (CONFIG_OPTIONROMS_DEPLOYED) { @@ -378,11 +392,11 @@ optionrom_setup(void) if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA || (CONFIG_ATA && v == PCI_CLASS_STORAGE_IDE)) continue; - init_pcirom(bdf, 0); + init_pcirom(bdf, 0, sources); }
// Find and deploy CBFS roms not associated with a device. - run_file_roms("genroms/", 0); + run_file_roms("genroms/", 0, sources); }
// All option roms found and deployed - now build BEV/BCV vectors. @@ -438,10 +452,10 @@ vga_setup(void) // Find and deploy PCI VGA rom. int bdf = VGAbdf = pci_find_vga(); if (bdf >= 0) - init_pcirom(bdf, 1); + init_pcirom(bdf, 1, NULL);
// Find and deploy CBFS vga-style roms not associated with a device. - run_file_roms("vgaroms/", 1); + run_file_roms("vgaroms/", 1, NULL); }
if (RomEnd == BUILD_ROM_START) {
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 | 10 ++++++++-- src/boot.c | 18 ++++++++++++++---- src/boot.h | 10 ++++++---- src/floppy.c | 22 ++++++++++++++++++++-- src/optionroms.c | 18 +++++++++++++++--- src/usb-msc.c | 2 +- src/virtio-blk.c | 2 +- 8 files changed, 67 insertions(+), 19 deletions(-)
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 aeacf08..5c35555 100644 --- a/src/boot.c +++ b/src/boot.c @@ -117,7 +117,7 @@ boot_setup(void)
// 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; @@ -131,11 +131,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; @@ -150,11 +151,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; @@ -168,11 +176,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; @@ -200,6 +209,7 @@ add_bcv_internal(struct drive_s *drive_g) ie->type = BCV_TYPE_INTERNAL; ie->vector = (u32)drive_g; ie->description = ""; + ie->prio = prio; }
diff --git a/src/boot.h b/src/boot.h index 0dfb135..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 { @@ -42,11 +43,12 @@ 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); 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 33f2a03..56f4997 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -92,6 +92,17 @@ static void map_rom2prio(void *addr, u8 prio) } }
+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 MAX_BOOT_PRIO; +} + /**************************************************************** * Helper functions ****************************************************************/ @@ -423,21 +434,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/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/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));
On Thu, Dec 23, 2010 at 11:29:42AM +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
It's not clear what the floppy part of this patch does. Can you expand on that, or better yet, pull it out into its own patch?
The non-floppy parts look fine.
I think what the floppy stuff is doing is ordering the drives based on its priority, but that seems like it will conflict with the boot menu code which can also swap the floppy drives around. Maybe we can add floppies to the BCV list and have run_bcv() call map_floppy_drive()? That way we use the same prioritization code for hds and floppies.
Also, if you respin patch 8, my preference would be to have patch 8 come before patch 5 (with all the bootprio_XXX() functions stubbed out).
-Kevin
On Fri, Dec 24, 2010 at 02:59:52PM -0500, Kevin O'Connor wrote:
On Thu, Dec 23, 2010 at 11:29:42AM +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
It's not clear what the floppy part of this patch does. Can you expand on that, or better yet, pull it out into its own patch?
The non-floppy parts look fine.
I think what the floppy stuff is doing is ordering the drives based on its priority, but that seems like it will conflict with the boot menu code which can also swap the floppy drives around.
This is exactly what it does and it does not conflict with boot menu. If B has greater boot priority then A it will be shown first in boot menu and user will be able to override boot order.
Maybe we can add
floppies to the BCV list and have run_bcv() call map_floppy_drive()? That way we use the same prioritization code for hds and floppies.
It may work, but floppy is not a BCV, so IMHO it will be out of place there.
Also, if you respin patch 8, my preference would be to have patch 8 come before patch 5 (with all the bootprio_XXX() functions stubbed out).
OK.
-- Gleb.
Signed-off-by: Gleb Natapov gleb@redhat.com --- src/boot.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 63 insertions(+), 14 deletions(-)
diff --git a/src/boot.c b/src/boot.c index 5c35555..e754930 100644 --- a/src/boot.c +++ b/src/boot.c @@ -379,6 +379,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) @@ -390,24 +425,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; + } + } }