diff options
author | Sam Eiderman <shmuel.eiderman@oracle.com> | 2019-06-26 15:38:12 +0300 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2019-11-18 14:58:37 +0100 |
commit | 9383ba748bcff20ed7b442230ecf064b530405af (patch) | |
tree | 7fabd96ed7b6ef0950c0d09ece4ecbcf95eaae74 | |
parent | 695f176d3e70ef37b4456cb33f37820457725ae9 (diff) | |
download | seabios-9383ba748bcff20ed7b442230ecf064b530405af.tar.gz |
geometry: Read LCHS from fw_cfg
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>
Message-Id: <20190626123816.8907-2-shmuel.eiderman@oracle.com>
-rw-r--r-- | src/boot.c | 74 |
1 files changed, 74 insertions, 0 deletions
@@ -73,6 +73,79 @@ build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci) /**************************************************************** + * 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 ****************************************************************/ @@ -292,6 +365,7 @@ boot_init(void) BootRetryTime = romfile_loadint("etc/boot-fail-wait", 60*1000); loadBootOrder(); + loadBiosGeometry(); } |