aboutsummaryrefslogtreecommitdiff
path: root/src/boot.c
diff options
context:
space:
mode:
authorSam Eiderman <shmuel.eiderman@oracle.com>2019-06-26 15:38:12 +0300
committerGerd Hoffmann <kraxel@redhat.com>2019-11-18 14:58:37 +0100
commit9383ba748bcff20ed7b442230ecf064b530405af (patch)
tree7fabd96ed7b6ef0950c0d09ece4ecbcf95eaae74 /src/boot.c
parent695f176d3e70ef37b4456cb33f37820457725ae9 (diff)
downloadseabios-hppa-9383ba748bcff20ed7b442230ecf064b530405af.zip
seabios-hppa-9383ba748bcff20ed7b442230ecf064b530405af.tar.gz
seabios-hppa-9383ba748bcff20ed7b442230ecf064b530405af.tar.bz2
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>
Diffstat (limited to 'src/boot.c')
-rw-r--r--src/boot.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/boot.c b/src/boot.c
index b5535ce..70f639f 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -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();
}