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>
This commit is contained in:
parent
695f176d3e
commit
9383ba748b
74
src/boot.c
74
src/boot.c
|
@ -72,6 +72,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();
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue