jart / blink

tiniest x86-64-linux emulator
ISC License
6.96k stars 222 forks source link

Try to auto-detect boot disk geometry, in bare metal mode #74

Closed tkchia closed 1 year ago

tkchia commented 1 year ago

This patch is extracted & modified from Gregory Haerr's blink16 patches for ELKS OS emulation (https://github.com/ghaerr/blink16/commit/df6d5ef767e8 & (edit) https://github.com/ghaerr/blink16/commit/4c1e505225c4)

ghaerr commented 1 year ago

Hello @tkchia,

I just found that we have one additional problem in OnDiskServiceGetParms which should be fixed in this PR also. That is, %dh should return the max head number, not the maximum heads. See my fix 4c1e505225c4c412195bd320c46e3cddcf8b0813 Line 2618 for details.

Thank you!

tkchia commented 1 year ago

@ghaerr : Thanks! I have forced-pushed the fix.

@jart, @ghaerr : For the hard disk geometry, I decided to take a (second) look at QEMU's block device code. It looks like QEMU defaults to using a geometry with 16 heads per cylinder, rather than 255 (if other detection methods fail). So I am now thinking that perhaps Blinkenlights should do the same — I have pushed this change.

Thank you!

ghaerr commented 1 year ago

@tkchia: Have you determined more exactly why QEMU is limiting heads to 16? For Blink, reducing max heads from 255 to 16 won't change any internal arithmetic, but will reduce the allowable size of a passed .img file from 8G to 512Mb. It seems that the max heads is only really relevant in our case for the returned %dh value in OnDiskServiceGetParams. Are we aware of which programs might not be able to accept a head count > 15?

[EDIT: Interestingly, this article on CHS (under 'Heads') discusses a bug in MSDOS up to and including v7.10 where heads=256 doesn't work. They seem to indicate that heads=255 (which would be max head number of 254) does work, which means we might be safe at diskheads=255, rather than just 16. However, the article goes on to discuss that the ATA controller had a limit of 16 heads. So perhaps QEMU's emulation of ATA might be the reason for the much-decreased head count. IMO, we might be better off with a larger limit of 8G .img format than worry about ATA compatibility, until ATA is actually emulated by Blink, if ever.]

Thank you!

tkchia commented 1 year ago

Hello @ghaerr,

The main problem I am encountering with using a "non-standard" head count, is that existing hard disk images with MBRs which work under QEMU, no longer work under Blinkenlights — at least not without some serious fiddling.

The MBR code usually reads the disk via the CHS values recorded in the partition table, and the CHS values assume whatever disk geometry was in effect when the partition table was created.

(E.g. there is the FD13LITE.img (https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/distributions/1.3/official/) FreeDOS USB "Lite" installer.)

I suppose it might be useful in some cases to emulate a "logical" CHS geometry with more than 16 heads per cylinder, but this probably needs to be done a bit more carefully. (Alternatively, on the guest side, a boot sector can use the "extended read" BIOS call (int 0x13, ah = 0x42) to address up to 2 TiB of sectors via LBA.)

Thank you!

ghaerr commented 1 year ago

Hello @tkchia,

existing hard disk images with MBRs which work under QEMU, no longer work under Blinkenlights — at least not without some serious fiddling.

In that case, I fully agree!

suppose it might be useful in some cases to emulate a "logical" CHS geometry with more than 16 heads per cylinder

Given that we're automatically setting CHS based on image size, another idea might be to use 16 heads if image size <= 512Mb, and 255 heads otherwise. This would allow for all images constrained by the 16 heads limit to work, while also allowing for larger image sizes (which I imagine would not be concerned with any 16 heads limit due to their size and likely more modern creation date). [EDIT: This method could have a problem however if the image were in fact an MBR with multiple partitions with the total image size exceeding 512Mb. So I suppose it is a bit complicated; perhaps that can be dealt with when one actually has an image larger than 512MB requiring emulation by Blink].

Thank you!

tkchia commented 1 year ago

Hello @ghaerr,

[EDIT: This method could have a problem however if the image were in fact an MBR with multiple partitions with the total image size exceeding 512Mb. So I suppose it is a bit complicated; perhaps that can be dealt with when one actually has an image larger than 512MB requiring emulation by Blink].

Indeed.

Apparently the solution adopted by QEMU — see https://github.com/qemu/qemu/blob/fd8a68ad6823d33bedeba20a22857867a1c3890e/hw/block/hd-geometry.c — is to parse the partition table, and use that to try to guess the correct "logical" CHS geometry originally in effect.

I am seriously considering if Blink should also do something similar. :eyes:

Thank you!