qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface
@ 2019-06-26 12:38 Sam Eiderman
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 1/5] geometry: Read LCHS from fw_cfg Sam Eiderman
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Sam Eiderman @ 2019-06-26 12:38 UTC (permalink / raw)
  To: kwolf, qemu-block, qemu-devel, mreitz, seabios, kraxel, kevin
  Cc: liran.alon, shmuel.eiderman, karl.heubaum, arbel.moshe

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"

v4:

* Rename TRANSLATION_MACHINE to TRANSLATION_HOST
* Rename "overriden" translation name to "host-supplied"
* Rename overriden_lchs_supplied() to host_lchs_supplied()
* Move sectors and heads check to host_lchs_supplied()
* Reuse duplicate code in boot.c

Sam Eiderman (5):
  geometry: Read LCHS from fw_cfg
  boot: Reorder functions in boot.c
  boot: Build ata and scsi paths in function
  geometry: Add boot_lchs_find_*() utility functions
  geometry: Apply LCHS values for boot devices

 src/Kconfig          |   7 ++
 src/block.c          |  18 +++-
 src/block.h          |   1 +
 src/boot.c           | 273 +++++++++++++++++++++++++++++++++++++++++----------
 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, 272 insertions(+), 54 deletions(-)

-- 
2.13.3



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Qemu-devel] [SeaBIOS] [PATCH v4 1/5] geometry: Read LCHS from fw_cfg
  2019-06-26 12:38 [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Sam Eiderman
@ 2019-06-26 12:38 ` Sam Eiderman
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 2/5] boot: Reorder functions in boot.c Sam Eiderman
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sam Eiderman @ 2019-06-26 12:38 UTC (permalink / raw)
  To: kwolf, qemu-block, qemu-devel, mreitz, seabios, kraxel, kevin
  Cc: liran.alon, shmuel.eiderman, karl.heubaum, arbel.moshe

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 5acf94fe..a2cb167c 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -24,6 +24,79 @@
 
 
 /****************************************************************
+ * 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
  ****************************************************************/
 
@@ -288,6 +361,7 @@ boot_init(void)
     BootRetryTime = romfile_loadint("etc/boot-fail-wait", 60*1000);
 
     loadBootOrder();
+    loadBiosGeometry();
 }
 
 
-- 
2.13.3



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [SeaBIOS] [PATCH v4 2/5] boot: Reorder functions in boot.c
  2019-06-26 12:38 [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Sam Eiderman
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 1/5] geometry: Read LCHS from fw_cfg Sam Eiderman
@ 2019-06-26 12:38 ` Sam Eiderman
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 3/5] boot: Build ata and scsi paths in function Sam Eiderman
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sam Eiderman @ 2019-06-26 12:38 UTC (permalink / raw)
  To: kwolf, qemu-block, qemu-devel, mreitz, seabios, kraxel, kevin
  Cc: liran.alon, shmuel.eiderman, karl.heubaum, arbel.moshe

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 commits.

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 a2cb167c..70f639f4 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -22,6 +22,55 @@
 #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
@@ -141,29 +190,6 @@ 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)
@@ -176,28 +202,6 @@ 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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [SeaBIOS] [PATCH v4 3/5] boot: Build ata and scsi paths in function
  2019-06-26 12:38 [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Sam Eiderman
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 1/5] geometry: Read LCHS from fw_cfg Sam Eiderman
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 2/5] boot: Reorder functions in boot.c Sam Eiderman
@ 2019-06-26 12:38 ` Sam Eiderman
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 4/5] geometry: Add boot_lchs_find_*() utility functions Sam Eiderman
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sam Eiderman @ 2019-06-26 12:38 UTC (permalink / raw)
  To: kwolf, qemu-block, qemu-devel, mreitz, seabios, kraxel, kevin
  Cc: liran.alon, shmuel.eiderman, karl.heubaum, arbel.moshe

Introduce build_scsi_path() and build_ata_path().
We will reuse these functions 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 | 36 ++++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/src/boot.c b/src/boot.c
index 70f639f4..52e1c8e6 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -71,6 +71,30 @@ build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci)
     return p;
 }
 
+static char *
+build_scsi_path(char *buf, int max,
+                struct pci_device *pci, int target, int lun)
+{
+    // Build the string path of a scsi drive - for example:
+    // /pci@i0cf8/scsi@5/channel@0/disk@1,0
+    char *p;
+    p = build_pci_path(buf, max, "*", pci);
+    p += snprintf(p, buf+max-p, "/*@0/*@%x,%x", target, lun);
+    return p;
+}
+
+static char *
+build_ata_path(char *buf, int max,
+               struct pci_device *pci, int chanid, int slave)
+{
+    // Build the string path of an ata drive - for example:
+    // /pci@i0cf8/ide@1,1/drive@1/disk@0
+    char *p;
+    p = build_pci_path(buf, max, "*", pci);
+    p += snprintf(p, buf+max-p, "/drive@%x/disk@%x", chanid, slave);
+    return p;
+}
+
 
 /****************************************************************
  * Boot device logical geometry
@@ -221,10 +245,8 @@ int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun)
     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);
+    char desc[256];
+    build_scsi_path(desc, sizeof(desc), pci, target, lun);
     return find_prio(desc);
 }
 
@@ -237,10 +259,8 @@ int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave)
     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);
+    char desc[256];
+    build_ata_path(desc, sizeof(desc), pci, chanid, slave);
     return find_prio(desc);
 }
 
-- 
2.13.3



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [SeaBIOS] [PATCH v4 4/5] geometry: Add boot_lchs_find_*() utility functions
  2019-06-26 12:38 [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Sam Eiderman
                   ` (2 preceding siblings ...)
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 3/5] boot: Build ata and scsi paths in function Sam Eiderman
@ 2019-06-26 12:38 ` Sam Eiderman
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 5/5] geometry: Apply LCHS values for boot devices Sam Eiderman
  2019-07-01  7:44 ` [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Gerd Hoffmann
  5 siblings, 0 replies; 7+ messages in thread
From: Sam Eiderman @ 2019-06-26 12:38 UTC (permalink / raw)
  To: kwolf, qemu-block, qemu-devel, mreitz, seabios, kraxel, kevin
  Cc: liran.alon, shmuel.eiderman, karl.heubaum, arbel.moshe

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  | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util.h  |  6 ++++++
 3 files changed, 82 insertions(+)

diff --git a/src/Kconfig b/src/Kconfig
index 55a87cb7..6606ce4d 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -72,6 +72,13 @@ endchoice
         help
             Support controlling of the boot order via the fw_cfg/CBFS
             "bootorder" file.
+    config HOST_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 52e1c8e6..ea18194d 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -129,6 +129,8 @@ parse_u32(char *cur, u32 *n)
 static void
 loadBiosGeometry(void)
 {
+    if (!CONFIG_HOST_BIOS_GEOMETRY)
+        return;
     char *f = romfile_loadfile("bios-geometry", NULL);
     if (!f)
         return;
@@ -168,6 +170,73 @@ 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_HOST_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_HOST_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];
+    build_scsi_path(desc, sizeof(desc), pci, 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_HOST_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];
+    build_ata_path(desc, sizeof(desc), pci, 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 e2afc80c..b173fa88 100644
--- a/src/util.h
+++ b/src/util.h
@@ -38,6 +38,12 @@ 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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [SeaBIOS] [PATCH v4 5/5] geometry: Apply LCHS values for boot devices
  2019-06-26 12:38 [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Sam Eiderman
                   ` (3 preceding siblings ...)
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 4/5] geometry: Add boot_lchs_find_*() utility functions Sam Eiderman
@ 2019-06-26 12:38 ` Sam Eiderman
  2019-07-01  7:44 ` [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Gerd Hoffmann
  5 siblings, 0 replies; 7+ messages in thread
From: Sam Eiderman @ 2019-06-26 12:38 UTC (permalink / raw)
  To: kwolf, qemu-block, qemu-devel, mreitz, seabios, kraxel, kevin
  Cc: liran.alon, shmuel.eiderman, karl.heubaum, arbel.moshe

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_HOST".

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          | 18 +++++++++++++++++-
 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, 39 insertions(+), 1 deletion(-)

diff --git a/src/block.c b/src/block.c
index f73ec18c..1f600b85 100644
--- a/src/block.c
+++ b/src/block.c
@@ -69,9 +69,18 @@ int create_bounce_buf(void)
  * Disk geometry translation
  ****************************************************************/
 
+static int
+host_lchs_supplied(struct drive_s *drive)
+{
+    return (drive->lchs.head <= 255 &&
+            drive->lchs.sector > 0 && drive->lchs.sector <= 63);
+}
+
 static u8
 get_translation(struct drive_s *drive)
 {
+    if (host_lchs_supplied(drive))
+        return TRANSLATION_HOST;
     u8 type = drive->type;
     if (CONFIG_QEMU && type == DTYPE_ATA) {
         // Emulators pass in the translation info via nvram.
@@ -159,6 +168,12 @@ setup_translation(struct drive_s *drive)
                 break;
         }
         break;
+    case TRANSLATION_HOST:
+        desc = "host-supplied";
+        cylinders = drive->lchs.cylinder;
+        heads = drive->lchs.head;
+        spt = drive->lchs.sector;
+        break;
     }
     // clip to 1024 cylinders in lchs
     if (cylinders > 1024)
@@ -423,7 +438,8 @@ 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_HOST)) {
             options |= 1<<3; // CHS translation
             if (translation == TRANSLATION_LBA)
                 options |= 1<<9;
diff --git a/src/block.h b/src/block.h
index f64e8807..c1b8d734 100644
--- a/src/block.h
+++ b/src/block.h
@@ -90,6 +90,7 @@ struct drive_s {
 #define TRANSLATION_LBA   1
 #define TRANSLATION_LARGE 2
 #define TRANSLATION_RECHS 3
+#define TRANSLATION_HOST 4
 
 #define EXTTYPE_FLOPPY 0
 #define EXTTYPE_HD 1
diff --git a/src/hw/ahci.c b/src/hw/ahci.c
index 1746e7a1..97a072a1 100644
--- a/src/hw/ahci.c
+++ b/src/hw/ahci.c
@@ -593,6 +593,7 @@ 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 b6e073cf..f788ce71 100644
--- a/src/hw/ata.c
+++ b/src/hw/ata.c
@@ -755,6 +755,10 @@ 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);
     }
 
@@ -805,6 +809,10 @@ 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 ffd86d0f..cc25f227 100644
--- a/src/hw/esp-scsi.c
+++ b/src/hw/esp-scsi.c
@@ -181,6 +181,8 @@ 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 d5fc3e45..cbaa2acd 100644
--- a/src/hw/lsi-scsi.c
+++ b/src/hw/lsi-scsi.c
@@ -158,6 +158,8 @@ 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 d2675804..87b8beec 100644
--- a/src/hw/megasas.c
+++ b/src/hw/megasas.c
@@ -225,6 +225,7 @@ 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 1faede6a..570b2126 100644
--- a/src/hw/mpt-scsi.c
+++ b/src/hw/mpt-scsi.c
@@ -221,6 +221,8 @@ 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 9d7d68d8..3e5171ad 100644
--- a/src/hw/pvscsi.c
+++ b/src/hw/pvscsi.c
@@ -273,6 +273,7 @@ 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 88d7e54a..3e615b26 100644
--- a/src/hw/virtio-blk.c
+++ b/src/hw/virtio-blk.c
@@ -183,6 +183,8 @@ 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 a87cad88..e1e2f5d4 100644
--- a/src/hw/virtio-scsi.c
+++ b/src/hw/virtio-scsi.c
@@ -121,6 +121,8 @@ 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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface
  2019-06-26 12:38 [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Sam Eiderman
                   ` (4 preceding siblings ...)
  2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 5/5] geometry: Apply LCHS values for boot devices Sam Eiderman
@ 2019-07-01  7:44 ` Gerd Hoffmann
  5 siblings, 0 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2019-07-01  7:44 UTC (permalink / raw)
  To: Sam Eiderman
  Cc: kwolf, qemu-block, arbel.moshe, seabios, qemu-devel, mreitz,
	kevin, liran.alon, karl.heubaum

On Wed, Jun 26, 2019 at 03:38:11PM +0300, Sam Eiderman wrote:
> 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"
> 
> v4:
> 
> * Rename TRANSLATION_MACHINE to TRANSLATION_HOST
> * Rename "overriden" translation name to "host-supplied"
> * Rename overriden_lchs_supplied() to host_lchs_supplied()
> * Move sectors and heads check to host_lchs_supplied()
> * Reuse duplicate code in boot.c

Looks all sane to me.

Usual workflow is to have to qemu bits merged first, so we'll go wait
for that.

cheers,
  Gerd



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-07-01  7:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-26 12:38 [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Sam Eiderman
2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 1/5] geometry: Read LCHS from fw_cfg Sam Eiderman
2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 2/5] boot: Reorder functions in boot.c Sam Eiderman
2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 3/5] boot: Build ata and scsi paths in function Sam Eiderman
2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 4/5] geometry: Add boot_lchs_find_*() utility functions Sam Eiderman
2019-06-26 12:38 ` [Qemu-devel] [SeaBIOS] [PATCH v4 5/5] geometry: Apply LCHS values for boot devices Sam Eiderman
2019-07-01  7:44 ` [Qemu-devel] [SeaBIOS] [PATCH v4 0/5] Add Qemu to SeaBIOS LCHS interface Gerd Hoffmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).