:p
atchew
Login
Non-standard logical geometries break under QEMU. A virtual disk which contains an operating system which depends on logical geometries (consistent values being reported from BIOS INT13 AH=08) will most likely break under QEMU/SeaBIOS if it has non-standard logical geometries - for example 56 SPT (sectors per track). No matter what QEMU will guess - SeaBIOS, for large enough disks - will use LBA translation, which will report 63 SPT instead. In addition we can not enforce SeaBIOS to rely on phyiscal geometries at all. A virtio-blk-pci virtual disk with 255 phyiscal heads can not report more than 16 physical heads when moved to an IDE controller, the ATA spec allows a maximum of 16 heads - this is an artifact of virtualization. By supplying the logical geometies directly we are able to support such "exotic" disks. We will use fw_cfg to do just that. Sam Eiderman (5): geometry: Read LCHS from fw_cfg boot: Reorder functions in boot.c geometry: Add boot_lchs_find_*() utility functions config: Add toggle for bootdevice information geometry: Apply LCHS values for boot devices src/Kconfig | 7 ++ src/block.c | 21 +++- src/block.h | 1 + src/boot.c | 272 ++++++++++++++++++++++++++++++++++++++++++--------- src/hw/ahci.c | 1 + src/hw/ata.c | 8 ++ src/hw/esp-scsi.c | 2 + src/hw/lsi-scsi.c | 2 + src/hw/megasas.c | 1 + src/hw/mpt-scsi.c | 2 + src/hw/pvscsi.c | 1 + src/hw/virtio-blk.c | 2 + src/hw/virtio-scsi.c | 2 + src/util.h | 6 ++ 14 files changed, 282 insertions(+), 46 deletions(-) -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Read boot device information from fw_cfg. Boot device information will contain logical geometry (LCHS) values, but it is implemented in a manner which allows extension. By receiving LCHS values directly from QEMU through fw_cfg we will be able to support logical geometries which can not be inferred by SeaBIOS itself. (For instance: A 8GB virtio-blk hard drive which was originally created as an IDE and must report LCHS of */32/63 for its operating system to function will always break under SeaBIOS since a LARGE/LBA translation will be used, causing the number of reported logical heads to be > 32.) The only LCHS paravirtual interface available at the moment is for IDE disks (rtc_read() in get_translation()) and it's limited to a maximum of 4 disks (this code existed in SeaBIOS's translation function before SCSI and VirtIO were even introduced). This is why we create a new interface which allows passing LCHS information per hdd. As mentioned, this interface may be easily extended to support more information per hdd. Boot device information is serialized in the following way: * struct_size (u32) * device path (sz string) * device information (struct_size) ... * device path (sz string) * device information (struct_size) Device path is a null terminated string in the "Open Firmware" device path format, the same path as used in bootorder. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/boot.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/boot.c b/src/boot.c index XXXXXXX..XXXXXXX 100644 --- a/src/boot.c +++ b/src/boot.c @@ -XXX,XX +XXX,XX @@ /**************************************************************** + * Boot device parameters + ****************************************************************/ + +typedef struct BootDeviceSerialized { + u32 lcyls; + u32 lheads; + u32 lsecs; +} PACKED BootDeviceSerialized; + +typedef struct BootDevice { + char *name; + u32 lcyls; + u32 lheads; + u32 lsecs; +} BootDevice; + +static BootDevice *BootDevices VARVERIFY32INIT; +static int BootDeviceCount; + +static void +loadBootDevices(void) +{ + BootDeviceCount = 0; + int fsize; + char *f = romfile_loadfile("bootdevices", &fsize); + if (!f) + return; + + if (fsize < sizeof(u32)) + return; + + u32 struct_size = *((u32 *)f); + if (struct_size < sizeof(BootDeviceSerialized)) + return; + + fsize -= sizeof(u32); + f += sizeof(u32); + + int i; + int str_found = 0; + + for (i = 0; i < fsize; i++) { + if (f[i] != '\0') + str_found = 1; + else if (f[i] == '\0' && str_found) { + str_found = 0; + i++; + if (i + struct_size > fsize) + break; + i += struct_size - 1; + BootDeviceCount++; + } else + break; + } + + BootDevices = malloc_tmphigh(BootDeviceCount * sizeof(BootDevice)); + if (!BootDevices) { + warn_noalloc(); + free(f); + BootDeviceCount = 0; + return; + } + + dprintf(1, "boot devices:\n"); + + BootDeviceSerialized *blk; + BootDevice *d; + + for (i = 0; i < BootDeviceCount; i++) { + d = &BootDevices[i]; + d->name = f; + f += strlen(f) + 1; + + blk = (BootDeviceSerialized *)f; + d->lcyls = blk->lcyls; + d->lheads = blk->lheads; + d->lsecs = blk->lsecs; + f += struct_size; + + dprintf(1, "%s: (%u, %u, %u)\n", + d->name, d->lcyls, d->lheads, d->lsecs); + } +} + + +/**************************************************************** * Boot priority ordering ****************************************************************/ @@ -XXX,XX +XXX,XX @@ boot_init(void) BootRetryTime = romfile_loadint("etc/boot-fail-wait", 60*1000); loadBootOrder(); + loadBootDevices(); } -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Currently glob_prefix() and build_pci_path() are under the "Boot priority ordering" section. Move them to a new "Helper search functions" section since we will reuse them in the next commit. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/boot.c | 94 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/src/boot.c b/src/boot.c index XXXXXXX..XXXXXXX 100644 --- a/src/boot.c +++ b/src/boot.c @@ -XXX,XX +XXX,XX @@ #include "util.h" // irqtimer_calc #include "tcgbios.h" // tpm_* +/**************************************************************** + * Helper search functions + ****************************************************************/ + +// See if 'str' starts with 'glob' - if glob contains an '*' character +// it will match any number of characters in str that aren't a '/' or +// the next glob character. +static char * +glob_prefix(const char *glob, const char *str) +{ + for (;;) { + if (!*glob && (!*str || *str == '/')) + return (char*)str; + if (*glob == '*') { + if (!*str || *str == '/' || *str == glob[1]) + glob++; + else + str++; + continue; + } + if (*glob != *str) + return NULL; + glob++; + str++; + } +} + +#define FW_PCI_DOMAIN "/pci@i0cf8" + +static char * +build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci) +{ + // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2 + char *p = buf; + if (pci->parent) { + p = build_pci_path(p, max, "pci-bridge", pci->parent); + } else { + p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN); + if (pci->rootbus) + p += snprintf(p, buf+max-p, ",%x", pci->rootbus); + } + + int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf); + p += snprintf(p, buf+max-p, "/%s@%x", devname, dev); + if (fn) + p += snprintf(p, buf+max-p, ",%x", fn); + return p; +} + /**************************************************************** * Boot device parameters @@ -XXX,XX +XXX,XX @@ loadBootOrder(void) } while (f); } -// See if 'str' starts with 'glob' - if glob contains an '*' character -// it will match any number of characters in str that aren't a '/' or -// the next glob character. -static char * -glob_prefix(const char *glob, const char *str) -{ - for (;;) { - if (!*glob && (!*str || *str == '/')) - return (char*)str; - if (*glob == '*') { - if (!*str || *str == '/' || *str == glob[1]) - glob++; - else - str++; - continue; - } - if (*glob != *str) - return NULL; - glob++; - str++; - } -} - // Search the bootorder list for the given glob pattern. static int find_prio(const char *glob) @@ -XXX,XX +XXX,XX @@ find_prio(const char *glob) return -1; } -#define FW_PCI_DOMAIN "/pci@i0cf8" - -static char * -build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci) -{ - // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2 - char *p = buf; - if (pci->parent) { - p = build_pci_path(p, max, "pci-bridge", pci->parent); - } else { - p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN); - if (pci->rootbus) - p += snprintf(p, buf+max-p, ",%x", pci->rootbus); - } - - int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf); - p += snprintf(p, buf+max-p, "/%s@%x", devname, dev); - if (fn) - p += snprintf(p, buf+max-p, ",%x", fn); - return p; -} - int bootprio_find_pci_device(struct pci_device *pci) { if (CONFIG_CSM) -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Adding the following utility functions: * boot_lchs_find_pci_device * boot_lchs_find_scsi_device * boot_lchs_find_ata_device These will be used to apply LCHS values received through fw_cfg. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/boot.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 6 +++++ 2 files changed, 88 insertions(+) diff --git a/src/boot.c b/src/boot.c index XXXXXXX..XXXXXXX 100644 --- a/src/boot.c +++ b/src/boot.c @@ -XXX,XX +XXX,XX @@ loadBootDevices(void) } } +// Search the bootdevices list for the given glob pattern. +static BootDevice * +bootdevice_find(const char *glob) +{ + dprintf(1, "Searching bootdevices for: %s\n", glob); + int i; + for (i = 0; i < BootDeviceCount; i++) + if (glob_prefix(glob, BootDevices[i].name)) + return &BootDevices[i]; + return NULL; +} + +static BootDevice * +bootdevice_find_pci_device(struct pci_device *pci) +{ + // Find pci device - for example: /pci@i0cf8/ethernet@5 + char desc[256]; + build_pci_path(desc, sizeof(desc), "*", pci); + return bootdevice_find(desc); +} + +static BootDevice * +bootdevice_find_scsi_device(struct pci_device *pci, int target, int lun) +{ + if (!pci) + // support only pci machine for now + return NULL; + // Find scsi drive - for example: /pci@i0cf8/scsi@5/channel@0/disk@1,0 + char desc[256], *p; + p = build_pci_path(desc, sizeof(desc), "*", pci); + snprintf(p, desc+sizeof(desc)-p, "/*@0/*@%x,%x", target, lun); + return bootdevice_find(desc); +} + +static BootDevice * +bootdevice_find_ata_device(struct pci_device *pci, int chanid, int slave) +{ + if (!pci) + // support only pci machine for now + return NULL; + // Find ata drive - for example: /pci@i0cf8/ide@1,1/drive@1/disk@0 + char desc[256], *p; + p = build_pci_path(desc, sizeof(desc), "*", pci); + snprintf(p, desc+sizeof(desc)-p, "/drive@%x/disk@%x", chanid, slave); + return bootdevice_find(desc); +} + +int boot_lchs_find_pci_device(struct pci_device *pci, struct chs_s *chs) +{ + BootDevice *b = bootdevice_find_pci_device(pci); + if (!b) + return -1; + chs->cylinder = (u16)b->lcyls; + chs->head = (u16)b->lheads; + chs->sector = (u16)b->lsecs; + return 0; +} + +int boot_lchs_find_scsi_device(struct pci_device *pci, int target, int lun, + struct chs_s *chs) +{ + BootDevice *b = bootdevice_find_scsi_device(pci, target, lun); + if (!b) + return -1; + chs->cylinder = (u16)b->lcyls; + chs->head = (u16)b->lheads; + chs->sector = (u16)b->lsecs; + return 0; +} + +int boot_lchs_find_ata_device(struct pci_device *pci, int chanid, int slave, + struct chs_s *chs) +{ + BootDevice *b = bootdevice_find_ata_device(pci, chanid, slave); + if (!b) + return -1; + chs->cylinder = (u16)b->lcyls; + chs->head = (u16)b->lheads; + chs->sector = (u16)b->lsecs; + return 0; +} + /**************************************************************** * Boot priority ordering diff --git a/src/util.h b/src/util.h index XXXXXXX..XXXXXXX 100644 --- a/src/util.h +++ b/src/util.h @@ -XXX,XX +XXX,XX @@ struct usbdevice_s; int bootprio_find_usb(struct usbdevice_s *usbdev, int lun); int get_keystroke_full(int msec); int get_keystroke(int msec); +struct chs_s; +int boot_lchs_find_pci_device(struct pci_device *pci, struct chs_s *chs); +int boot_lchs_find_scsi_device(struct pci_device *pci, int target, int lun, + struct chs_s *chs); +int boot_lchs_find_ata_device(struct pci_device *pci, int chanid, int slave, + struct chs_s *chs); // bootsplash.c void enable_vga_console(void); -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Add the "BOOTDEVICES" toggle to remove boot device information received through fw_cfg. We will use this toggle in QEMU to reduce the size of the 128k SeaBIOS rom, which is only used in old compat versions, where this boot device information does not exist. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/Kconfig | 7 +++++++ src/boot.c | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/src/Kconfig b/src/Kconfig index XXXXXXX..XXXXXXX 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -XXX,XX +XXX,XX @@ endchoice help Support controlling of the boot order via the fw_cfg/CBFS "bootorder" file. + config BOOTDEVICES + depends on BOOT + bool "Boot device information" + default y + help + Support boot device information via the fw_cfg/CBFS + "bootdevices" file. config COREBOOT_FLASH depends on COREBOOT diff --git a/src/boot.c b/src/boot.c index XXXXXXX..XXXXXXX 100644 --- a/src/boot.c +++ b/src/boot.c @@ -XXX,XX +XXX,XX @@ static int BootDeviceCount; static void loadBootDevices(void) { + if (!CONFIG_BOOTDEVICES) + return; + BootDeviceCount = 0; int fsize; char *f = romfile_loadfile("bootdevices", &fsize); @@ -XXX,XX +XXX,XX @@ bootdevice_find(const char *glob) static BootDevice * bootdevice_find_pci_device(struct pci_device *pci) { + if (!CONFIG_BOOTDEVICES) + return NULL; // Find pci device - for example: /pci@i0cf8/ethernet@5 char desc[256]; build_pci_path(desc, sizeof(desc), "*", pci); @@ -XXX,XX +XXX,XX @@ bootdevice_find_pci_device(struct pci_device *pci) static BootDevice * bootdevice_find_scsi_device(struct pci_device *pci, int target, int lun) { + if (!CONFIG_BOOTDEVICES) + return NULL; if (!pci) // support only pci machine for now return NULL; @@ -XXX,XX +XXX,XX @@ bootdevice_find_scsi_device(struct pci_device *pci, int target, int lun) static BootDevice * bootdevice_find_ata_device(struct pci_device *pci, int chanid, int slave) { + if (!CONFIG_BOOTDEVICES) + return NULL; if (!pci) // support only pci machine for now return NULL; -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Boot devices which use overriden LCHS values are: * ata * ahci * scsi * esp * lsi * megasas * mpt * pvscsi * virtio * virtio-blk We use these values in get_translation() and setup_translation() by introducing a new translation type: "TRANSLATION_MACHINE". We treat this translation as TRANSLATION_NONE in fill_ata_edd(), although this does not really matter since now the translation between physical and logical geometry does not exist. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/block.c | 21 ++++++++++++++++++++- src/block.h | 1 + src/hw/ahci.c | 1 + src/hw/ata.c | 8 ++++++++ src/hw/esp-scsi.c | 2 ++ src/hw/lsi-scsi.c | 2 ++ src/hw/megasas.c | 1 + src/hw/mpt-scsi.c | 2 ++ src/hw/pvscsi.c | 1 + src/hw/virtio-blk.c | 2 ++ src/hw/virtio-scsi.c | 2 ++ 11 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/block.c b/src/block.c index XXXXXXX..XXXXXXX 100644 --- a/src/block.c +++ b/src/block.c @@ -XXX,XX +XXX,XX @@ int create_bounce_buf(void) * Disk geometry translation ****************************************************************/ +static int +overriden_lchs_supplied(struct drive_s *drive) +{ + return drive->lchs.cylinder || drive->lchs.head || drive->lchs.sector; +} + static u8 get_translation(struct drive_s *drive) { + if (overriden_lchs_supplied(drive)) + return TRANSLATION_MACHINE; u8 type = drive->type; if (CONFIG_QEMU && type == DTYPE_ATA) { // Emulators pass in the translation info via nvram. @@ -XXX,XX +XXX,XX @@ setup_translation(struct drive_s *drive) break; } break; + case TRANSLATION_MACHINE: + desc = "overriden"; + cylinders = drive->lchs.cylinder; + heads = drive->lchs.head; + if (heads > 255) + heads = 255; + spt = drive->lchs.sector; + if (spt > 63) + spt = 63; + break; } // clip to 1024 cylinders in lchs if (cylinders > 1024) @@ -XXX,XX +XXX,XX @@ fill_ata_edd(struct segoff_s edd, struct drive_s *drive_gf) u16 options = 0; if (GET_GLOBALFLAT(drive_gf->type) == DTYPE_ATA) { u8 translation = GET_GLOBALFLAT(drive_gf->translation); - if (translation != TRANSLATION_NONE) { + if ((translation != TRANSLATION_NONE) && + (translation != TRANSLATION_MACHINE)) { options |= 1<<3; // CHS translation if (translation == TRANSLATION_LBA) options |= 1<<9; diff --git a/src/block.h b/src/block.h index XXXXXXX..XXXXXXX 100644 --- a/src/block.h +++ b/src/block.h @@ -XXX,XX +XXX,XX @@ struct drive_s { #define TRANSLATION_LBA 1 #define TRANSLATION_LARGE 2 #define TRANSLATION_RECHS 3 +#define TRANSLATION_MACHINE 4 #define EXTTYPE_FLOPPY 0 #define EXTTYPE_HD 1 diff --git a/src/hw/ahci.c b/src/hw/ahci.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/ahci.c +++ b/src/hw/ahci.c @@ -XXX,XX +XXX,XX @@ static int ahci_port_setup(struct ahci_port_s *port) , ata_extract_version(buffer)); port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0); } + boot_lchs_find_ata_device(ctrl->pci_tmp, pnr, 0, &(port->drive.lchs)); return 0; } diff --git a/src/hw/ata.c b/src/hw/ata.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/ata.c +++ b/src/hw/ata.c @@ -XXX,XX +XXX,XX @@ init_drive_atapi(struct atadrive_s *dummy, u16 *buffer) int prio = bootprio_find_ata_device(adrive->chan_gf->pci_tmp, adrive->chan_gf->chanid, adrive->slave); + boot_lchs_find_ata_device(adrive->chan_gf->pci_tmp, + adrive->chan_gf->chanid, + adrive->slave, + &(adrive->drive.lchs)); boot_add_cd(&adrive->drive, desc, prio); } @@ -XXX,XX +XXX,XX @@ init_drive_ata(struct atadrive_s *dummy, u16 *buffer) int prio = bootprio_find_ata_device(adrive->chan_gf->pci_tmp, adrive->chan_gf->chanid, adrive->slave); + boot_lchs_find_ata_device(adrive->chan_gf->pci_tmp, + adrive->chan_gf->chanid, + adrive->slave, + &(adrive->drive.lchs)); // Register with bcv system. boot_add_hd(&adrive->drive, desc, prio); diff --git a/src/hw/esp-scsi.c b/src/hw/esp-scsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/esp-scsi.c +++ b/src/hw/esp-scsi.c @@ -XXX,XX +XXX,XX @@ esp_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) char *name = znprintf(MAXDESCSIZE, "esp %pP %d:%d", llun->pci, llun->target, llun->lun); + boot_lchs_find_scsi_device(llun->pci, llun->target, llun->lun, + &(llun->drive.lchs)); int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); int ret = scsi_drive_setup(&llun->drive, name, prio); free(name); diff --git a/src/hw/lsi-scsi.c b/src/hw/lsi-scsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/lsi-scsi.c +++ b/src/hw/lsi-scsi.c @@ -XXX,XX +XXX,XX @@ lsi_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) lsi_scsi_init_lun(llun, tmpl_llun->pci, tmpl_llun->iobase, tmpl_llun->target, lun); + boot_lchs_find_scsi_device(llun->pci, llun->target, llun->lun, + &(llun->drive.lchs)); char *name = znprintf(MAXDESCSIZE, "lsi %pP %d:%d", llun->pci, llun->target, llun->lun); int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); diff --git a/src/hw/megasas.c b/src/hw/megasas.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/megasas.c +++ b/src/hw/megasas.c @@ -XXX,XX +XXX,XX @@ megasas_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) free(mlun); return -1; } + boot_lchs_find_scsi_device(pci, target, lun, &(mlun->drive.lchs)); name = znprintf(MAXDESCSIZE, "MegaRAID SAS (PCI %pP) LD %d:%d" , pci, target, lun); prio = bootprio_find_scsi_device(pci, target, lun); diff --git a/src/hw/mpt-scsi.c b/src/hw/mpt-scsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/mpt-scsi.c +++ b/src/hw/mpt-scsi.c @@ -XXX,XX +XXX,XX @@ mpt_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) mpt_scsi_init_lun(llun, tmpl_llun->pci, tmpl_llun->iobase, tmpl_llun->target, lun); + boot_lchs_find_scsi_device(llun->pci, llun->target, llun->lun, + &(llun->drive.lchs)); char *name = znprintf(MAXDESCSIZE, "mpt %pP %d:%d", llun->pci, llun->target, llun->lun); int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); diff --git a/src/hw/pvscsi.c b/src/hw/pvscsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/pvscsi.c +++ b/src/hw/pvscsi.c @@ -XXX,XX +XXX,XX @@ pvscsi_add_lun(struct pci_device *pci, void *iobase, plun->iobase = iobase; plun->ring_dsc = ring_dsc; + boot_lchs_find_scsi_device(pci, target, lun, &(plun->drive.lchs)); char *name = znprintf(MAXDESCSIZE, "pvscsi %pP %d:%d", pci, target, lun); int prio = bootprio_find_scsi_device(pci, target, lun); int ret = scsi_drive_setup(&plun->drive, name, prio); diff --git a/src/hw/virtio-blk.c b/src/hw/virtio-blk.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/virtio-blk.c +++ b/src/hw/virtio-blk.c @@ -XXX,XX +XXX,XX @@ init_virtio_blk(void *data) status |= VIRTIO_CONFIG_S_DRIVER_OK; vp_set_status(&vdrive->vp, status); + + boot_lchs_find_pci_device(pci, &vdrive->drive.lchs); return; fail: diff --git a/src/hw/virtio-scsi.c b/src/hw/virtio-scsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/virtio-scsi.c +++ b/src/hw/virtio-scsi.c @@ -XXX,XX +XXX,XX @@ virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) virtio_scsi_init_lun(vlun, tmpl_vlun->pci, tmpl_vlun->vp, tmpl_vlun->vq, tmpl_vlun->target, lun); + boot_lchs_find_scsi_device(vlun->pci, vlun->target, vlun->lun, + &(vlun->drive.lchs)); int prio = bootprio_find_scsi_device(vlun->pci, vlun->target, vlun->lun); int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio); if (ret) -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
v1: Non-standard logical geometries break under QEMU. A virtual disk which contains an operating system which depends on logical geometries (consistent values being reported from BIOS INT13 AH=08) will most likely break under QEMU/SeaBIOS if it has non-standard logical geometries - for example 56 SPT (sectors per track). No matter what QEMU will guess - SeaBIOS, for large enough disks - will use LBA translation, which will report 63 SPT instead. In addition we can not enforce SeaBIOS to rely on phyiscal geometries at all. A virtio-blk-pci virtual disk with 255 phyiscal heads can not report more than 16 physical heads when moved to an IDE controller, the ATA spec allows a maximum of 16 heads - this is an artifact of virtualization. By supplying the logical geometies directly we are able to support such "exotic" disks. We will use fw_cfg to do just that. v2: Rename bootdevices fw_cfg key to bios-geoemtry v3: Change fw_cfg interface from mixed binary/textual to textual only Squash commit "config: Add toggle for bootdevice information" Sam Eiderman (4): geometry: Read LCHS from fw_cfg boot: Reorder functions in boot.c geometry: Add boot_lchs_find_*() utility functions geometry: Apply LCHS values for boot devices src/Kconfig | 7 ++ src/block.c | 21 ++++- src/block.h | 1 + src/boot.c | 239 +++++++++++++++++++++++++++++++++++++++++---------- src/hw/ahci.c | 1 + src/hw/ata.c | 8 ++ src/hw/esp-scsi.c | 2 + src/hw/lsi-scsi.c | 2 + src/hw/megasas.c | 1 + src/hw/mpt-scsi.c | 2 + src/hw/pvscsi.c | 1 + src/hw/virtio-blk.c | 2 + src/hw/virtio-scsi.c | 2 + src/util.h | 6 ++ 14 files changed, 249 insertions(+), 46 deletions(-) -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Read bios geometry for boot devices from fw_cfg. By receiving LCHS values directly from QEMU through fw_cfg we will be able to support logical geometries which can not be inferred by SeaBIOS itself. (For instance: A 8GB virtio-blk hard drive which was originally created as an IDE and must report LCHS of */32/63 for its operating system to function will always break under SeaBIOS since a LARGE/LBA translation will be used, causing the number of reported logical heads to be > 32.) The only LCHS paravirtual interface available at the moment is for IDE disks (rtc_read() in get_translation()) and it's limited to a maximum of 4 disks (this code existed in SeaBIOS's translation function before SCSI and VirtIO were even introduced). This is why we create a new interface which allows passing LCHS information per hdd. Boot device information is serialized in the following way: * device_path lcyls lheads lsecs\n ... * device_path lcyls lheads lsecs\0 Device path is a null terminated string in the "Open Firmware" device path format, the same path as used in bootorder. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/boot.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/boot.c b/src/boot.c index XXXXXXX..XXXXXXX 100644 --- a/src/boot.c +++ b/src/boot.c @@ -XXX,XX +XXX,XX @@ /**************************************************************** + * Boot device logical geometry + ****************************************************************/ + +typedef struct BootDeviceLCHS { + char *name; + u32 lcyls; + u32 lheads; + u32 lsecs; +} BootDeviceLCHS; + +static BootDeviceLCHS *BiosGeometry VARVERIFY32INIT; +static int BiosGeometryCount; + +static char * +parse_u32(char *cur, u32 *n) +{ + u32 m = 0; + if (cur) { + while ('0' <= *cur && *cur <= '9') { + m = 10 * m + (*cur - '0'); + cur++; + } + if (*cur != '\0') + cur++; + } + *n = m; + return cur; +} + +static void +loadBiosGeometry(void) +{ + char *f = romfile_loadfile("bios-geometry", NULL); + if (!f) + return; + + int i = 0; + BiosGeometryCount = 1; + while (f[i]) { + if (f[i] == '\n') + BiosGeometryCount++; + i++; + } + BiosGeometry = malloc_tmphigh(BiosGeometryCount * sizeof(BootDeviceLCHS)); + if (!BiosGeometry) { + warn_noalloc(); + free(f); + BiosGeometryCount = 0; + return; + } + + dprintf(1, "bios geometry:\n"); + i = 0; + do { + BootDeviceLCHS *d = &BiosGeometry[i]; + d->name = f; + f = strchr(f, '\n'); + if (f) + *(f++) = '\0'; + char *chs_values = strchr(d->name, ' '); + if (chs_values) + *(chs_values++) = '\0'; + chs_values = parse_u32(chs_values, &d->lcyls); + chs_values = parse_u32(chs_values, &d->lheads); + chs_values = parse_u32(chs_values, &d->lsecs); + dprintf(1, "%s: (%u, %u, %u)\n", + d->name, d->lcyls, d->lheads, d->lsecs); + i++; + } while (f); +} + + +/**************************************************************** * Boot priority ordering ****************************************************************/ @@ -XXX,XX +XXX,XX @@ boot_init(void) BootRetryTime = romfile_loadint("etc/boot-fail-wait", 60*1000); loadBootOrder(); + loadBiosGeometry(); } -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Currently glob_prefix() and build_pci_path() are under the "Boot priority ordering" section. Move them to a new "Helper search functions" section since we will reuse them in the next commit. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/boot.c | 94 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/src/boot.c b/src/boot.c index XXXXXXX..XXXXXXX 100644 --- a/src/boot.c +++ b/src/boot.c @@ -XXX,XX +XXX,XX @@ #include "util.h" // irqtimer_calc #include "tcgbios.h" // tpm_* +/**************************************************************** + * Helper search functions + ****************************************************************/ + +// See if 'str' starts with 'glob' - if glob contains an '*' character +// it will match any number of characters in str that aren't a '/' or +// the next glob character. +static char * +glob_prefix(const char *glob, const char *str) +{ + for (;;) { + if (!*glob && (!*str || *str == '/')) + return (char*)str; + if (*glob == '*') { + if (!*str || *str == '/' || *str == glob[1]) + glob++; + else + str++; + continue; + } + if (*glob != *str) + return NULL; + glob++; + str++; + } +} + +#define FW_PCI_DOMAIN "/pci@i0cf8" + +static char * +build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci) +{ + // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2 + char *p = buf; + if (pci->parent) { + p = build_pci_path(p, max, "pci-bridge", pci->parent); + } else { + p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN); + if (pci->rootbus) + p += snprintf(p, buf+max-p, ",%x", pci->rootbus); + } + + int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf); + p += snprintf(p, buf+max-p, "/%s@%x", devname, dev); + if (fn) + p += snprintf(p, buf+max-p, ",%x", fn); + return p; +} + /**************************************************************** * Boot device logical geometry @@ -XXX,XX +XXX,XX @@ loadBootOrder(void) } while (f); } -// See if 'str' starts with 'glob' - if glob contains an '*' character -// it will match any number of characters in str that aren't a '/' or -// the next glob character. -static char * -glob_prefix(const char *glob, const char *str) -{ - for (;;) { - if (!*glob && (!*str || *str == '/')) - return (char*)str; - if (*glob == '*') { - if (!*str || *str == '/' || *str == glob[1]) - glob++; - else - str++; - continue; - } - if (*glob != *str) - return NULL; - glob++; - str++; - } -} - // Search the bootorder list for the given glob pattern. static int find_prio(const char *glob) @@ -XXX,XX +XXX,XX @@ find_prio(const char *glob) return -1; } -#define FW_PCI_DOMAIN "/pci@i0cf8" - -static char * -build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci) -{ - // Build the string path of a bdf - for example: /pci@i0cf8/isa@1,2 - char *p = buf; - if (pci->parent) { - p = build_pci_path(p, max, "pci-bridge", pci->parent); - } else { - p += snprintf(p, buf+max-p, "%s", FW_PCI_DOMAIN); - if (pci->rootbus) - p += snprintf(p, buf+max-p, ",%x", pci->rootbus); - } - - int dev = pci_bdf_to_dev(pci->bdf), fn = pci_bdf_to_fn(pci->bdf); - p += snprintf(p, buf+max-p, "/%s@%x", devname, dev); - if (fn) - p += snprintf(p, buf+max-p, ",%x", fn); - return p; -} - int bootprio_find_pci_device(struct pci_device *pci) { if (CONFIG_CSM) -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Adding the following utility functions: * boot_lchs_find_pci_device * boot_lchs_find_scsi_device * boot_lchs_find_ata_device These will be used to apply LCHS values received through fw_cfg. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/Kconfig | 7 ++++++ src/boot.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 6 ++++++ 3 files changed, 84 insertions(+) diff --git a/src/Kconfig b/src/Kconfig index XXXXXXX..XXXXXXX 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -XXX,XX +XXX,XX @@ endchoice help Support controlling of the boot order via the fw_cfg/CBFS "bootorder" file. + config BIOS_GEOMETRY + depends on BOOT + bool "Boot device bios geometry override" + default y + help + Support overriding bios (logical) geometry of boot devices via the + fw_cfg/CBFS "bios-geometry" file. config COREBOOT_FLASH depends on COREBOOT diff --git a/src/boot.c b/src/boot.c index XXXXXXX..XXXXXXX 100644 --- a/src/boot.c +++ b/src/boot.c @@ -XXX,XX +XXX,XX @@ parse_u32(char *cur, u32 *n) static void loadBiosGeometry(void) { + if (!CONFIG_BIOS_GEOMETRY) + return; char *f = romfile_loadfile("bios-geometry", NULL); if (!f) return; @@ -XXX,XX +XXX,XX @@ loadBiosGeometry(void) } while (f); } +// Search the bios-geometry list for the given glob pattern. +static BootDeviceLCHS * +boot_lchs_find(const char *glob) +{ + dprintf(1, "Searching bios-geometry for: %s\n", glob); + int i; + for (i = 0; i < BiosGeometryCount; i++) + if (glob_prefix(glob, BiosGeometry[i].name)) + return &BiosGeometry[i]; + return NULL; +} + +int boot_lchs_find_pci_device(struct pci_device *pci, struct chs_s *chs) +{ + if (!CONFIG_BIOS_GEOMETRY) + return -1; + char desc[256]; + build_pci_path(desc, sizeof(desc), "*", pci); + BootDeviceLCHS *b = boot_lchs_find(desc); + if (!b) + return -1; + chs->cylinder = (u16)b->lcyls; + chs->head = (u16)b->lheads; + chs->sector = (u16)b->lsecs; + return 0; +} + +int boot_lchs_find_scsi_device(struct pci_device *pci, int target, int lun, + struct chs_s *chs) +{ + if (!CONFIG_BIOS_GEOMETRY) + return -1; + if (!pci) + // support only pci machine for now + return -1; + // Find scsi drive - for example: /pci@i0cf8/scsi@5/channel@0/disk@1,0 + char desc[256], *p; + p = build_pci_path(desc, sizeof(desc), "*", pci); + snprintf(p, desc+sizeof(desc)-p, "/*@0/*@%x,%x", target, lun); + BootDeviceLCHS *b = boot_lchs_find(desc); + if (!b) + return -1; + chs->cylinder = (u16)b->lcyls; + chs->head = (u16)b->lheads; + chs->sector = (u16)b->lsecs; + return 0; +} + +int boot_lchs_find_ata_device(struct pci_device *pci, int chanid, int slave, + struct chs_s *chs) +{ + if (!CONFIG_BIOS_GEOMETRY) + return -1; + if (!pci) + // support only pci machine for now + return -1; + // Find ata drive - for example: /pci@i0cf8/ide@1,1/drive@1/disk@0 + char desc[256], *p; + p = build_pci_path(desc, sizeof(desc), "*", pci); + snprintf(p, desc+sizeof(desc)-p, "/drive@%x/disk@%x", chanid, slave); + BootDeviceLCHS *b = boot_lchs_find(desc); + if (!b) + return -1; + chs->cylinder = (u16)b->lcyls; + chs->head = (u16)b->lheads; + chs->sector = (u16)b->lsecs; + return 0; +} + /**************************************************************** * Boot priority ordering diff --git a/src/util.h b/src/util.h index XXXXXXX..XXXXXXX 100644 --- a/src/util.h +++ b/src/util.h @@ -XXX,XX +XXX,XX @@ struct usbdevice_s; int bootprio_find_usb(struct usbdevice_s *usbdev, int lun); int get_keystroke_full(int msec); int get_keystroke(int msec); +struct chs_s; +int boot_lchs_find_pci_device(struct pci_device *pci, struct chs_s *chs); +int boot_lchs_find_scsi_device(struct pci_device *pci, int target, int lun, + struct chs_s *chs); +int boot_lchs_find_ata_device(struct pci_device *pci, int chanid, int slave, + struct chs_s *chs); // bootsplash.c void enable_vga_console(void); -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org
Boot devices which use overriden LCHS values are: * ata * ahci * scsi * esp * lsi * megasas * mpt * pvscsi * virtio * virtio-blk We use these values in get_translation() and setup_translation() by introducing a new translation type: "TRANSLATION_MACHINE". We treat this translation as TRANSLATION_NONE in fill_ata_edd(), although this does not really matter since now the translation between physical and logical geometry does not exist. Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> Reviewed-by: Arbel Moshe <arbel.moshe@oracle.com> Signed-off-by: Sam Eiderman <shmuel.eiderman@oracle.com> --- src/block.c | 21 ++++++++++++++++++++- src/block.h | 1 + src/hw/ahci.c | 1 + src/hw/ata.c | 8 ++++++++ src/hw/esp-scsi.c | 2 ++ src/hw/lsi-scsi.c | 2 ++ src/hw/megasas.c | 1 + src/hw/mpt-scsi.c | 2 ++ src/hw/pvscsi.c | 1 + src/hw/virtio-blk.c | 2 ++ src/hw/virtio-scsi.c | 2 ++ 11 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/block.c b/src/block.c index XXXXXXX..XXXXXXX 100644 --- a/src/block.c +++ b/src/block.c @@ -XXX,XX +XXX,XX @@ int create_bounce_buf(void) * Disk geometry translation ****************************************************************/ +static int +overriden_lchs_supplied(struct drive_s *drive) +{ + return drive->lchs.cylinder || drive->lchs.head || drive->lchs.sector; +} + static u8 get_translation(struct drive_s *drive) { + if (overriden_lchs_supplied(drive)) + return TRANSLATION_MACHINE; u8 type = drive->type; if (CONFIG_QEMU && type == DTYPE_ATA) { // Emulators pass in the translation info via nvram. @@ -XXX,XX +XXX,XX @@ setup_translation(struct drive_s *drive) break; } break; + case TRANSLATION_MACHINE: + desc = "overriden"; + cylinders = drive->lchs.cylinder; + heads = drive->lchs.head; + if (heads > 255) + heads = 255; + spt = drive->lchs.sector; + if (spt > 63) + spt = 63; + break; } // clip to 1024 cylinders in lchs if (cylinders > 1024) @@ -XXX,XX +XXX,XX @@ fill_ata_edd(struct segoff_s edd, struct drive_s *drive_gf) u16 options = 0; if (GET_GLOBALFLAT(drive_gf->type) == DTYPE_ATA) { u8 translation = GET_GLOBALFLAT(drive_gf->translation); - if (translation != TRANSLATION_NONE) { + if ((translation != TRANSLATION_NONE) && + (translation != TRANSLATION_MACHINE)) { options |= 1<<3; // CHS translation if (translation == TRANSLATION_LBA) options |= 1<<9; diff --git a/src/block.h b/src/block.h index XXXXXXX..XXXXXXX 100644 --- a/src/block.h +++ b/src/block.h @@ -XXX,XX +XXX,XX @@ struct drive_s { #define TRANSLATION_LBA 1 #define TRANSLATION_LARGE 2 #define TRANSLATION_RECHS 3 +#define TRANSLATION_MACHINE 4 #define EXTTYPE_FLOPPY 0 #define EXTTYPE_HD 1 diff --git a/src/hw/ahci.c b/src/hw/ahci.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/ahci.c +++ b/src/hw/ahci.c @@ -XXX,XX +XXX,XX @@ static int ahci_port_setup(struct ahci_port_s *port) , ata_extract_version(buffer)); port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0); } + boot_lchs_find_ata_device(ctrl->pci_tmp, pnr, 0, &(port->drive.lchs)); return 0; } diff --git a/src/hw/ata.c b/src/hw/ata.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/ata.c +++ b/src/hw/ata.c @@ -XXX,XX +XXX,XX @@ init_drive_atapi(struct atadrive_s *dummy, u16 *buffer) int prio = bootprio_find_ata_device(adrive->chan_gf->pci_tmp, adrive->chan_gf->chanid, adrive->slave); + boot_lchs_find_ata_device(adrive->chan_gf->pci_tmp, + adrive->chan_gf->chanid, + adrive->slave, + &(adrive->drive.lchs)); boot_add_cd(&adrive->drive, desc, prio); } @@ -XXX,XX +XXX,XX @@ init_drive_ata(struct atadrive_s *dummy, u16 *buffer) int prio = bootprio_find_ata_device(adrive->chan_gf->pci_tmp, adrive->chan_gf->chanid, adrive->slave); + boot_lchs_find_ata_device(adrive->chan_gf->pci_tmp, + adrive->chan_gf->chanid, + adrive->slave, + &(adrive->drive.lchs)); // Register with bcv system. boot_add_hd(&adrive->drive, desc, prio); diff --git a/src/hw/esp-scsi.c b/src/hw/esp-scsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/esp-scsi.c +++ b/src/hw/esp-scsi.c @@ -XXX,XX +XXX,XX @@ esp_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) char *name = znprintf(MAXDESCSIZE, "esp %pP %d:%d", llun->pci, llun->target, llun->lun); + boot_lchs_find_scsi_device(llun->pci, llun->target, llun->lun, + &(llun->drive.lchs)); int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); int ret = scsi_drive_setup(&llun->drive, name, prio); free(name); diff --git a/src/hw/lsi-scsi.c b/src/hw/lsi-scsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/lsi-scsi.c +++ b/src/hw/lsi-scsi.c @@ -XXX,XX +XXX,XX @@ lsi_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) lsi_scsi_init_lun(llun, tmpl_llun->pci, tmpl_llun->iobase, tmpl_llun->target, lun); + boot_lchs_find_scsi_device(llun->pci, llun->target, llun->lun, + &(llun->drive.lchs)); char *name = znprintf(MAXDESCSIZE, "lsi %pP %d:%d", llun->pci, llun->target, llun->lun); int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); diff --git a/src/hw/megasas.c b/src/hw/megasas.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/megasas.c +++ b/src/hw/megasas.c @@ -XXX,XX +XXX,XX @@ megasas_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun) free(mlun); return -1; } + boot_lchs_find_scsi_device(pci, target, lun, &(mlun->drive.lchs)); name = znprintf(MAXDESCSIZE, "MegaRAID SAS (PCI %pP) LD %d:%d" , pci, target, lun); prio = bootprio_find_scsi_device(pci, target, lun); diff --git a/src/hw/mpt-scsi.c b/src/hw/mpt-scsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/mpt-scsi.c +++ b/src/hw/mpt-scsi.c @@ -XXX,XX +XXX,XX @@ mpt_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) mpt_scsi_init_lun(llun, tmpl_llun->pci, tmpl_llun->iobase, tmpl_llun->target, lun); + boot_lchs_find_scsi_device(llun->pci, llun->target, llun->lun, + &(llun->drive.lchs)); char *name = znprintf(MAXDESCSIZE, "mpt %pP %d:%d", llun->pci, llun->target, llun->lun); int prio = bootprio_find_scsi_device(llun->pci, llun->target, llun->lun); diff --git a/src/hw/pvscsi.c b/src/hw/pvscsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/pvscsi.c +++ b/src/hw/pvscsi.c @@ -XXX,XX +XXX,XX @@ pvscsi_add_lun(struct pci_device *pci, void *iobase, plun->iobase = iobase; plun->ring_dsc = ring_dsc; + boot_lchs_find_scsi_device(pci, target, lun, &(plun->drive.lchs)); char *name = znprintf(MAXDESCSIZE, "pvscsi %pP %d:%d", pci, target, lun); int prio = bootprio_find_scsi_device(pci, target, lun); int ret = scsi_drive_setup(&plun->drive, name, prio); diff --git a/src/hw/virtio-blk.c b/src/hw/virtio-blk.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/virtio-blk.c +++ b/src/hw/virtio-blk.c @@ -XXX,XX +XXX,XX @@ init_virtio_blk(void *data) status |= VIRTIO_CONFIG_S_DRIVER_OK; vp_set_status(&vdrive->vp, status); + + boot_lchs_find_pci_device(pci, &vdrive->drive.lchs); return; fail: diff --git a/src/hw/virtio-scsi.c b/src/hw/virtio-scsi.c index XXXXXXX..XXXXXXX 100644 --- a/src/hw/virtio-scsi.c +++ b/src/hw/virtio-scsi.c @@ -XXX,XX +XXX,XX @@ virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv) virtio_scsi_init_lun(vlun, tmpl_vlun->pci, tmpl_vlun->vp, tmpl_vlun->vq, tmpl_vlun->target, lun); + boot_lchs_find_scsi_device(vlun->pci, vlun->target, vlun->lun, + &(vlun->drive.lchs)); int prio = bootprio_find_scsi_device(vlun->pci, vlun->target, vlun->lun); int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio); if (ret) -- 2.13.3 _______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-leave@seabios.org