I noticed that SeaBIOS fails to boot from virtio disk smaller than 512K. The attempt to access a disk fails at basic_access(). (cylinder >= nlc || head >= nlh || sector > nlspt) is true because nlc is zero. The problem seams to be in how SeaBIOS calculates lchs from pchs in get_translation(). Both QEMU and SeaBIOS fake disk geometry from real disk size, but it seams that they do it differently and when they disagree part of the disk may not be readable.
What would be the best way to fix that?
-- Gleb.
On Wed, Jun 13, 2012 at 04:51:04PM +0300, Gleb Natapov wrote:
I noticed that SeaBIOS fails to boot from virtio disk smaller than 512K. The attempt to access a disk fails at basic_access(). (cylinder >= nlc || head >= nlh || sector > nlspt) is true because nlc is zero. The problem seams to be in how SeaBIOS calculates lchs from pchs in get_translation(). Both QEMU and SeaBIOS fake disk geometry from real disk size, but it seams that they do it differently and when they disagree part of the disk may not be readable.
The LBA translation code comes from the original Bochs BIOS code. Looking at this now, I think it's not rounding properly and thus causing some sectors to get truncated.
What would be the best way to fix that?
If there's a better way to calculate a logical CHS then I'm open to fixing it in SeaBIOS.
-Kevin
Am 14.06.2012 02:52, schrieb Kevin O'Connor:
On Wed, Jun 13, 2012 at 04:51:04PM +0300, Gleb Natapov wrote:
I noticed that SeaBIOS fails to boot from virtio disk smaller than 512K. The attempt to access a disk fails at basic_access(). (cylinder >= nlc || head >= nlh || sector > nlspt) is true because nlc is zero. The problem seams to be in how SeaBIOS calculates lchs from pchs in get_translation(). Both QEMU and SeaBIOS fake disk geometry from real disk size, but it seams that they do it differently and when they disagree part of the disk may not be readable.
The LBA translation code comes from the original Bochs BIOS code. Looking at this now, I think it's not rounding properly and thus causing some sectors to get truncated.
This is probably the crucial point: What is "proper" rounding in this context? Leaving aside the choice of concrete CHS values, you'll always have to choose whether to round up or round down.
If you round down (which happens today in SeaBIOS and in most cases in qemu), you make part of the image inaccessible. Usually only a problem when you have something in /boot very close to the end of the image and the bootloader can't read it. It gets problematic with small images where everything is close to the end, and in Gleb's extreme case even the MBR isn't accessible any more.
If you round up (which qemu does in this case as for some unknown reason it always assumes a minimum of 2 cylinders), you pretend that the disk is larger than the image really is and part of the virtual disk only produces read/write errors. This is the only alternative implementation I can see, and it's not a clear winner for me.
What would be the best way to fix that?
If there's a better way to calculate a logical CHS then I'm open to fixing it in SeaBIOS.
Maybe sometimes it would be possible to get an exact match with different values for heads and spt, but in the general case I think rounding is inevitable and then the only choice that is left is in which direction you round.
Kevin
On Thu, Jun 14, 2012 at 10:12:23AM +0200, Kevin Wolf wrote:
Am 14.06.2012 02:52, schrieb Kevin O'Connor:
On Wed, Jun 13, 2012 at 04:51:04PM +0300, Gleb Natapov wrote:
I noticed that SeaBIOS fails to boot from virtio disk smaller than 512K. The attempt to access a disk fails at basic_access(). (cylinder >= nlc || head >= nlh || sector > nlspt) is true because nlc is zero. The problem seams to be in how SeaBIOS calculates lchs from pchs in get_translation(). Both QEMU and SeaBIOS fake disk geometry from real disk size, but it seams that they do it differently and when they disagree part of the disk may not be readable.
The LBA translation code comes from the original Bochs BIOS code. Looking at this now, I think it's not rounding properly and thus causing some sectors to get truncated.
This is probably the crucial point: What is "proper" rounding in this context? Leaving aside the choice of concrete CHS values, you'll always have to choose whether to round up or round down.
If you round down (which happens today in SeaBIOS and in most cases in qemu), you make part of the image inaccessible. Usually only a problem when you have something in /boot very close to the end of the image and the bootloader can't read it. It gets problematic with small images where everything is close to the end, and in Gleb's extreme case even the MBR isn't accessible any more.
Agreed. Not a great choice.
If you round up (which qemu does in this case as for some unknown reason it always assumes a minimum of 2 cylinders), you pretend that the disk is larger than the image really is and part of the virtual disk only produces read/write errors. This is the only alternative implementation I can see, and it's not a clear winner for me.
Maybe there is wisdom in setting a minimum of 2 cylinders. That way the really tiny disks are still functional.
-Kevin
Am 15.06.2012 14:42, schrieb Kevin O'Connor:
On Thu, Jun 14, 2012 at 10:12:23AM +0200, Kevin Wolf wrote:
If you round up (which qemu does in this case as for some unknown reason it always assumes a minimum of 2 cylinders), you pretend that the disk is larger than the image really is and part of the virtual disk only produces read/write errors. This is the only alternative implementation I can see, and it's not a clear winner for me.
Maybe there is wisdom in setting a minimum of 2 cylinders. That way the really tiny disks are still functional.
Yes, I can understand this reasoning and while it's still not fully functional it should be enough to get something booted and then the OS has a chance to ignore the whole geometry issues.
On the other hand, which OS with a virtio driver fits on a < 1 MB disk? One of the more likely OSes for such an image is DOS, and it will certainly fail when part of the pretended disk is neither writeable nor readable. Of course, with a 0 cylinder disk it wouldn't work much better, so we don't break much (1 cylinder disks maybe...), but I also doubt if we gain anything.
Kevin