BIOS INT 0x13 partial reads
-
zerodivision
- Posts: 14
- Joined: Tue Sep 16, 2025 10:25 am
BIOS INT 0x13 partial reads
Hello everyone!
I've been wondering whether it's necessary, practical or even possible to reliably handle partial reads with BIOS INT 0x13 functions AH=0x02 and AH=0x42.
According to the Ralph Brown Interrupt List (RBIL), if an error occurs (CF set), the number of sectors successfully transferred is stored in AL for function AH=0x02 and in the Disk Address Packet (DAP) for function AH=0x42. However, the BIOS interfaces have never been standardized and the various BIOS implementations tend to be buggy, often in the most unexpected ways. As such, I expect the reliability of the returned sector count to be questionable, especially in case it's not used by mainstream OSes and bootloaders.
Given that I have setup several virtual machines with real BIOS ROMs in PCem, I tried to conduct some tests to determine how various BIOS implementations handle partial reads. Specifically, I tried various reads that start near the end of the last head of the last cylinder and extend beyond the end of the disk (known CHS geometry: 243, 16, 63; tried CHS start values: 242, 15, <63), expecting the BIOS to return a partial read (CF set and AL containing a short sector count). However, all BIOSes that I tested in PCem returned a successful read. In constrast, QEMU returned a short read with AL set as expected. So I still haven't been able to determine how do BIOSes handle short reads.
As for the necessity of handling short reads, there are several conditions that can cause a partial read. Most of them are probably non-recoverable / non-resumable (e.g. bad sectors), but some probably allow for resuming from the next sector after the cut-off (e.g. possibly request exceeding track boundary or timing issues). That said, I already split read requests to track boundaries for CHS and at between 120 and 127 sectors for LBA (due to alignment for 512e devices).
So to recap, even I adhere to the most strict limits imposed by BIOS implementations, is it still necessary to handle short reads and is it possible to do it reliably? Alternatively, does anyone have any ideas how to induce a partial read in an emulated environment?
Thanks in advance!
I've been wondering whether it's necessary, practical or even possible to reliably handle partial reads with BIOS INT 0x13 functions AH=0x02 and AH=0x42.
According to the Ralph Brown Interrupt List (RBIL), if an error occurs (CF set), the number of sectors successfully transferred is stored in AL for function AH=0x02 and in the Disk Address Packet (DAP) for function AH=0x42. However, the BIOS interfaces have never been standardized and the various BIOS implementations tend to be buggy, often in the most unexpected ways. As such, I expect the reliability of the returned sector count to be questionable, especially in case it's not used by mainstream OSes and bootloaders.
Given that I have setup several virtual machines with real BIOS ROMs in PCem, I tried to conduct some tests to determine how various BIOS implementations handle partial reads. Specifically, I tried various reads that start near the end of the last head of the last cylinder and extend beyond the end of the disk (known CHS geometry: 243, 16, 63; tried CHS start values: 242, 15, <63), expecting the BIOS to return a partial read (CF set and AL containing a short sector count). However, all BIOSes that I tested in PCem returned a successful read. In constrast, QEMU returned a short read with AL set as expected. So I still haven't been able to determine how do BIOSes handle short reads.
As for the necessity of handling short reads, there are several conditions that can cause a partial read. Most of them are probably non-recoverable / non-resumable (e.g. bad sectors), but some probably allow for resuming from the next sector after the cut-off (e.g. possibly request exceeding track boundary or timing issues). That said, I already split read requests to track boundaries for CHS and at between 120 and 127 sectors for LBA (due to alignment for 512e devices).
So to recap, even I adhere to the most strict limits imposed by BIOS implementations, is it still necessary to handle short reads and is it possible to do it reliably? Alternatively, does anyone have any ideas how to induce a partial read in an emulated environment?
Thanks in advance!
Re: BIOS INT 0x13 partial reads
Given that, unless it is a floppy, the BIOS has already retried as many times as could possibly matter, and that most uses of BIOS functions are in the bootloader, and there the only success is complete success, it is probably not sensible to retry on error. For problems of this nature I would always just wait for the first time I actually get a bug report about this. Otherwise just do the simplest thing you can get away with.
Carpe diem!
Re: BIOS INT 0x13 partial reads
Hi,
Also, if you don't mind, since you already have the test suite, will you please try the BIOS from https://github.com/fysnet/i440fx, namely i440fx.bin. I would love to see the results.
Ben
- https://www.fysnet.net/osdesign_book_series.htm
Rather than it being QEMU that passed, it will be the BIOS it uses that passes, SeaBIOS. Try SeaBIOS in you PCem tests and you should get the same results as when in QEMU. Since you have QEMU installed, look in the 'qemu\share' folder and you will find 'bios.bin' (as well as 'bios-25k.bin' and a few others). Try the 'bios.bin' with your PCem test suite and see what the results are.zerodivision wrote: ↑Sat Sep 20, 2025 7:59 amGiven that I have setup several virtual machines with real BIOS ROMs in PCem, I tried to conduct some tests to determine how various BIOS implementations handle partial reads. ... However, all BIOSes that I tested in PCem returned a successful read. In constrast, QEMU returned a short read with AL set as expected.
Also, if you don't mind, since you already have the test suite, will you please try the BIOS from https://github.com/fysnet/i440fx, namely i440fx.bin. I would love to see the results.
Ben
- https://www.fysnet.net/osdesign_book_series.htm
-
zerodivision
- Posts: 14
- Joined: Tue Sep 16, 2025 10:25 am
Re: BIOS INT 0x13 partial reads
Thank you for your answers!
Despite that, I'd still like to determine the possibility and/or practicality of a more robust solution that handles partial reads. First of all, it would be consistent with my own code that can actually return less sectors that requested. Besides, better robustness may allow the code to work reliably with a wider range of hardware, under the condition of course that handling partial reads is itself reliable in the first place. Furthermore, one of the reasons I got into OS development is to experiment with different and possibly better ways to implement various aspects of an OS. And lastly, this is a topic that doesn't appear to have many if any definitive resources and as such it would be interesting to further research it. I'll be sure to document any relevant findings.
However, this begs the following question: if the partial reads weren't due to the fact that I was attempting to read past the end of the disk but happened for other reasons as part of normal disk access patterns, would these specific BIOSes possibly report the partial reads as successful complete reads? This could be determined by somehow inducing a partial read. In the worst case, the PCem source code would have to be modified to introduce (recoverable) disk errors.
I agree that the assumption that "the only success is complete success" works for the vast majority of cases. That has been my experience as well and in fact I actually expect that most bootloaders don't specifically handle partial reads and instead treat them as errors.nullplan wrote:Given that, unless it is a floppy, the BIOS has already retried as many times as could possibly matter, and that most uses of BIOS functions are in the bootloader, and there the only success is complete success, it is probably not sensible to retry on error. For problems of this nature I would always just wait for the first time I actually get a bug report about this. Otherwise just do the simplest thing you can get away with.
Despite that, I'd still like to determine the possibility and/or practicality of a more robust solution that handles partial reads. First of all, it would be consistent with my own code that can actually return less sectors that requested. Besides, better robustness may allow the code to work reliably with a wider range of hardware, under the condition of course that handling partial reads is itself reliable in the first place. Furthermore, one of the reasons I got into OS development is to experiment with different and possibly better ways to implement various aspects of an OS. And lastly, this is a topic that doesn't appear to have many if any definitive resources and as such it would be interesting to further research it. I'll be sure to document any relevant findings.
That misses the point, which is to test as many different BIOS implementations as possible. Even testing reads that extend beyond the end of the disk isn't a point in itself, as I was only trying to induce a partial read in order to observe how do BIOSes handle that case, but I evidently failed at that because the tested BIOSes reported a complete read.BenLunt wrote:Try SeaBIOS in you PCem tests and you should get the same results as when in QEMU.
However, this begs the following question: if the partial reads weren't due to the fact that I was attempting to read past the end of the disk but happened for other reasons as part of normal disk access patterns, would these specific BIOSes possibly report the partial reads as successful complete reads? This could be determined by somehow inducing a partial read. In the worst case, the PCem source code would have to be modified to introduce (recoverable) disk errors.
Unfortunately, PCem expects specific filenames for the BIOS ROMs for each supported machine. I guess that the closest machine that would match your BIOS is the Intel VS440FX, which expects several BIOS ROM files of varying sizes. It's not obvious to me which files should I replace with which parts of your BIOS file. Otherwise, I'd gladly test your BIOS with PCem.BenLunt wrote:Also, if you don't mind, since you already have the test suite, will you please try the BIOS from https://github.com/fysnet/i440fx, namely i440fx.bin. I would love to see the results.
-
Octocontrabass
- Member

- Posts: 6248
- Joined: Mon Mar 25, 2013 7:01 pm
Re: BIOS INT 0x13 partial reads
What's practical depends on what you're doing. For example, in a bootloader it's not practical to read more than one sector at a time, so there's no need to worry about partial reads in the first place.zerodivision wrote: ↑Sat Sep 20, 2025 7:59 amI've been wondering whether it's necessary, practical or even possible to reliably handle partial reads with BIOS INT 0x13 functions AH=0x02 and AH=0x42.
They actually have been. (Oh, and you don't have to buy this standard if you can find one of the drafts that were available to the public.) But since you brought up standards, I figured I'd do some research, and it turns out IBM's PS/2 documentation says partial reads are only reported for floppy disks. So, uh, I guess that answers your question?zerodivision wrote: ↑Sat Sep 20, 2025 7:59 amHowever, the BIOS interfaces have never been standardized
The original PC/AT reserved a couple of cylinders for diagnostics. If PCem (or its BIOS) also reserves some cylinders, you can successfully read past the end of the normal data area into the reserved cylinders.zerodivision wrote: ↑Sat Sep 20, 2025 7:59 amHowever, all BIOSes that I tested in PCem returned a successful read.
How are you finding the correct alignment?
-
zerodivision
- Posts: 14
- Joined: Tue Sep 16, 2025 10:25 am
Re: BIOS INT 0x13 partial reads
Reading sector-by-sector is inefficient, even though a lot of the inefficiency is mitigated through the presence of disk buffers.Octocontrabass wrote:What's practical depends on what you're doing. For example, in a bootloader it's not practical to read more than one sector at a time, so there's no need to worry about partial reads in the first place.
I stand corrected, when it comes to INT 0x13. It's not that these services have never been standardized, but they were still standardized after several non-standardized BIOS implementations have existed. Any BIOS that doesn't support INT 0x13 extensions and only supports legacy CHS functions (I consider that case too, that's why I've even talked about INT 0x13 AH=0x02) by definition doesn't implement the standard, since it was the Enhanced Disk Drive specification that added the LBA functions.Octocontrabass wrote:They actually have been.zerodivision wrote:However, the BIOS interfaces have never been standardized
When it comes to other services implemented by the BIOS, most of them indeed have never been standardized. But since the topic in question is INT 0x13, I'm done nitpicking.
That doesn't answer the question, because most OS developers reading this topic including me aren't writing an OS for the IBM PS/2. However, the Enhanced Disk Drive specification indeed answers the question (emphasis mine):Octocontrabass wrote:But since you brought up standards, I figured I'd do some research, and it turns out IBM's PS/2 documentation says partial reads are only reported for floppy disks. So, uh, I guess that answers your question?
Which means that it can't be reliably determined that AL has been set to the number of sectors transferred and even if AL is set it can't be reliably determined which parts of the transfer have actually succeeded. Thus, for all practical purposes, the best strategy is to treat all errors including partial reads as errors and to assume that AL as well as whatever data previously residing in the designated buffer is undefined/destroyed regardless of success or error.EDD-3 wrote:When there is a partial data transfer, there is no reliable indication of what part of the data was successfully transferred. Some systems use DMA to return the data in an out-of-order fashion. This function does not have a mechanism to report what data is valid in the case of a partial transfer. In some conventional systems when a partial transfer occurs, AL contains the number of sectors transferred.
If you don't mind, I can add this bit of information to the relevant article(s) on the wiki.
I figured it. For the OS proper, I create a disk image of size 120M, which makes PCem assign by default the CHS geometry: 243, 16, 63. For the testing code, in order to make sure I have no "partial cylinder" at the end of the disk, I make a disk image of exactly 243 * 16 * 63 sectors. Indeed, INT 0x13 AH=0x08 returns a maximum cylinder index of 241, that is cylinder 242 is reserved. The QEMU BIOS returns the same geometry. However, the testing code requests to read from the end of the reserved cylinder 242, so the read should still extend beyond the end of the disk. The QEMU BIOS correctly returns a partial read, but all PCem BIOSes return a successful read.Octocontrabass wrote:The original PC/AT reserved a couple of cylinders for diagnostics. If PCem (or its BIOS) also reserves some cylinders, you can successfully read past the end of the normal data area into the reserved cylinders.
This really got me thinking. So I looked at the PCem source code and it looks like the code implementing the emulated IDE controller doesn't properly handle the case of a read extending past the end of the disk. The function doing the actual read from the disk image file will return 1 if sectors transferred are fewer than the requested ones, but this return value is ignored by code implementing the IDE controller. Modifying the PCem code to abort such requests causes the reads to fail, so my testing code was correct for its purpose.
In reality, what would an IDE controller return when a read extending beyond the end of the disk is attempted? I might later try to incorporate that logic into PCem.
Shouldn't every 8th 512-byte logical sector (i.e. LBA % 8 == 0) be aligned to the start of a 4096-byte physical sector?Octocontrabass wrote:How are you finding the correct alignment?
Last edited by zerodivision on Tue Sep 23, 2025 9:40 am, edited 2 times in total.
Re: BIOS INT 0x13 partial reads
If you are worrying about the efficiency of disk reads in a boot loader then you have your priorities all wrong. It’s a one-off process, so how long it takes is unimportant. Better to make the process accurate (and workable) rather than quick.[/Reading sector-by-sector is inefficient, even though a lot of the inefficiency is mitigated through the presence of disk buffers.
-
zerodivision
- Posts: 14
- Joined: Tue Sep 16, 2025 10:25 am
Re: BIOS INT 0x13 partial reads
Obviously correctness is the top priority. I have already ensured the correctness of multisector disk reads, save for the case of a partial read, which is probably unlikely to happen for normal disk access patterns. But if a recoverable partial read happens, then probably a recoverable error could also happen when reading sector-by-sector. If one intends to retry a failed read operation when reading sector-by-sector, one can also retry the operation when doing multisector reads. If one doesn't intend to retry a failed read operation when reading sector-by-sector, going the "easy" way and reading sector-by-sector probably wouldn't result in better reliability anyway.iansjack wrote:If you are worrying about the efficiency of disk reads in a boot loader then you have your priorities all wrong. It’s a one-off process, so how long it takes is unimportant. Better to make the process accurate (and workable) rather than quick.
However, even though handling partial reads has been already determined to be impossible to do reliably without retrying the entire operation, I still intend to conduct some additional tests, purely for documentation purposes.
Re: BIOS INT 0x13 partial reads
Isn't that exactly the point? Did you test SeaBIOS with PCem? If so, did it perform as expected? If you didn't try, then you aren't testing with as many different BIOS implementations as possible.zerodivision wrote: ↑Sat Sep 20, 2025 2:26 pmThat misses the point, which is to test as many different BIOS implementations as possible.BenLunt wrote:Try SeaBIOS in you PCem tests and you should get the same results as when in QEMU.
Last time I checked, a filename can be renamed. Does PCem emulate the Intel x86 32-bit machine? My BIOS is for the i440FX, as it is aptly named. Only one file with one location with one size works just fine. Does PCem separate the BIOS ROM with the Video ROM or does it expect it to be combined?zerodivision wrote: ↑Sat Sep 20, 2025 2:26 pmUnfortunately, PCem expects specific filenames for the BIOS ROMs for each supported machine. I guess that the closest machine that would match your BIOS is the Intel VS440FX, which expects several BIOS ROM files of varying sizes. It's not obvious to me which files should I replace with which parts of your BIOS file. Otherwise, I'd gladly test your BIOS with PCem.BenLunt wrote:Also, if you don't mind, since you already have the test suite, will you please try the BIOS from https://github.com/fysnet/i440fx, namely i440fx.bin. I would love to see the results.
I guess I am missing something here. You state you are trying to test as many BIOS implementations as possible to see what they return on partial reads. This means the emulator should have nothing to do with it. The BIOS is responsible for returning the success or failure of the read, not the emulator's disk access routines.
Looking at the list of ROMs you mentioned, the IBMPCjr ROM is a single 64k file, where mine is 128k. The Tandy was an x86 and has a single ROM file. It also looks like a majority of those you listed are 16-bit only. Why are we worried about such outdated BIOS implementations?
Edit:
To make sure I understand what you are trying to do here, you are trying to see what the BIOS returns when a read is requested that would cross a cylinder boundary, where that cylinder could be the last cylinder, or otherwise fail. Yes?
A BIOS, upon a request to read an arbitrary number of sectors from an arbitrary location is permitted to read those sectors anyway it wishes. For example, if the request is to read 20 sectors, where as the 15th sector would now cross a cylinder boundary, the BIOS is permitted to read a single sector at a time, stopping at the failed sector. Therefore, knowing exactly how many sectors were successfully read, placing this value in AL and returning.
With the example above, though it may violate the specs, that same BIOS is permitted to step over the cylinder boundary and continue reading a single sector at a time, returning full success.
The BIOS is not required to try to read the requested number of sectors all at once. For example, it is permitted to read a full track at once, transferring only the requested amount, if that amount is less than the number of sectors per track.
When a call to the BIOS is done, the caller can only assume, on success, the buffer specified will be filled with read data. It cannot assume that any number of invalid sectors were tried. The BIOS is even permitted to fail the whole request if it sees that the request is invalid.
Anyway, I was just curious to see if my BIOS passed or failed you tests. I would be interested in seeing your test suite as well.
Thank you,
Ben
-
zerodivision
- Posts: 14
- Joined: Tue Sep 16, 2025 10:25 am
Re: BIOS INT 0x13 partial reads
Thank you very much for your detailed answer!
After modifying PCem so that the IDE controller aborts such read requests, the BIOSes started returning a failure. Then I modified PCem so that the IDE controller sets an error status. I've tried various flag combinations because I don't know what would a real IDE controller set in this case. Of course, I'd be grateful for any suggestions. Whatever flags I set, apparently no BIOS knows how many sectors have been read before the end of the disk is reached. For a request of 24 sectors starting at 9 sectors before the end of the disk, no BIOS returns AL = 9, but that's maybe caused by the IDE controller not setting the correct flags. Most BIOSes return AL = 0, two return AL = 24 (the initially requested count), and one returns AL = 88 (seemingly completely unrelated). The conclusion is that, whatever the correctness or not of the IDE controller in this specific case, AL cannot be relied upon to contain the number of successfully read sectors.
However, the aforementioned reliance of the BIOS on the specific behavior of the emulated IDE controller means that it wouldn't be actually pointless to test SeaBIOS or your BIOS with PCem as opposed to just with QEMU. I had initially assumed that PCem didn't have this bug. Only after replying to you yesterday and going away from my computer for the night it occured to me that a PCem bug is a likely reason for the strange behavior of the tested BIOSes reporting successful reads past the end of the disk, especially because it affects all of them and not just one or two.
That said, the majority of my testing machines in PCem have 386 and 486 CPUs. For emulating later systems I use QEMU. I also possess several real machines too, but they aren't as old.
First of all, PCem expects for each emulated machine that all of its specific BIOS ROM files are present, and several emulated hardware components also need to have dedicated expansion ROM files. In other words, it's not possible out-of-the-box to emulate a generic or custom machine with a custom BIOS ROM image. What is possible is to try to modify the PCem source code and define a new machine that uses your BIOS and similarly another one that uses SeaBIOS.BenLunt wrote:Does PCem separate the BIOS ROM with the Video ROM or does it expect it to be combined?
The emulator's disk access routines still determine what does the BIOS see as a result of a disk read. I found out that the PCem emulated IDE controller doesn't set an error status if there is a request that extends beyond the end of the disk (a PCem bug, probably). As such, the BIOS doesn't know there should be an error and instead returns a successful read.BenLunt wrote:I guess I am missing something here. You state you are trying to test as many BIOS implementations as possible to see what they return on partial reads. This means the emulator should have nothing to do with it. The BIOS is responsible for returning the success or failure of the read, not the emulator's disk access routines.
After modifying PCem so that the IDE controller aborts such read requests, the BIOSes started returning a failure. Then I modified PCem so that the IDE controller sets an error status. I've tried various flag combinations because I don't know what would a real IDE controller set in this case. Of course, I'd be grateful for any suggestions. Whatever flags I set, apparently no BIOS knows how many sectors have been read before the end of the disk is reached. For a request of 24 sectors starting at 9 sectors before the end of the disk, no BIOS returns AL = 9, but that's maybe caused by the IDE controller not setting the correct flags. Most BIOSes return AL = 0, two return AL = 24 (the initially requested count), and one returns AL = 88 (seemingly completely unrelated). The conclusion is that, whatever the correctness or not of the IDE controller in this specific case, AL cannot be relied upon to contain the number of successfully read sectors.
However, the aforementioned reliance of the BIOS on the specific behavior of the emulated IDE controller means that it wouldn't be actually pointless to test SeaBIOS or your BIOS with PCem as opposed to just with QEMU. I had initially assumed that PCem didn't have this bug. Only after replying to you yesterday and going away from my computer for the night it occured to me that a PCem bug is a likely reason for the strange behavior of the tested BIOSes reporting successful reads past the end of the disk, especially because it affects all of them and not just one or two.
Again, it depends how is a specific emulated machine defined in the PCem source code. That's how it is, if I was the author of PCem, I'd probably make it much more flexible.BenLunt wrote:Looking at the list of ROMs you mentioned, the IBMPCjr ROM is a single 64k file, where is mine is 128k. The Tandy was an x86 and has a single ROM file.
I don't expect my OS to run on a 16-bit machine, at least not beyond the point where I detect the CPU and expect the presence of at least a 386. But I still want it to gracefully error out at this exact point, instead of crashing on an invalid instruction before that.BenLunt wrote:It also looks like a majority of those you listed are 16-bit only. Why are we worried about such outdated BIOS implementations?
That said, the majority of my testing machines in PCem have 386 and 486 CPUs. For emulating later systems I use QEMU. I also possess several real machines too, but they aren't as old.
I'd like to see that too, but it's probably too much of an effort to define a custom machine in the PCem source code and I haven't succeeded to make it display anything in QEMU ("Guest hasn't initialized the display (yet)"). I guess I might be missing an option to specify the VGA ROM. Again, I'd appreciate any suggestions.BenLunt wrote:Anyway, I was just curious to see if my BIOS passed or failed you tests.
Exactly, but regardless of the cause for the partial read.BenLunt wrote:To make sure I understand what you are trying to do here, you are trying to see what the BIOS returns when a read is requested that would cross a cylinder boundary, where that cylinder could be the last cylinder, or otherwise fail. Yes?
Do you mean that it can split the initial requests into smaller ones before the returning all requested sectors to the caller, or that it can return to the caller less sectors than requested without it actually being an error? If it's the latter, unfortunately, neither the Enhanced Disk Drive specification nor the aforementioned tests guarantee that AL is set to sectors successfully read, or even that sectors successfully transferred refer to the sectors from the beginning of the request so that it could be resumed from the sector where it failed.BenLunt wrote:The BIOS is not required to try to read the requested number of sectors all at once.
I understand this and I'm not trying to do that. The 9 sectors in the aforementioned test wouldn't be invalid, apart from belonging to the last reserved cylinder.BenLunt wrote:It cannot assume that any number of invalid sectors were tried.
-
Octocontrabass
- Member

- Posts: 6248
- Joined: Mon Mar 25, 2013 7:01 pm
Re: BIOS INT 0x13 partial reads
But you are writing an OS for a PS/2-compatible. (Well, mostly-PS/2-compatible. It's complicated.) All those non-standardized BIOS implementations were copying the behavior of IBM's BIOSes, so you only need to look at IBM's documentation to know how IBM-compatible BIOSes were expected to behave.zerodivision wrote: ↑Sun Sep 21, 2025 3:59 amThat doesn't answer the question, because most OS developers reading this topic including me aren't writing an OS for the IBM PS/2.
An IDE controller will return whatever the IDE drive attached to it returns. Unlike MFM/RLL/ESDI, an IDE "controller" doesn't control the drives at all - it just connects them to the rest of the PC.zerodivision wrote: ↑Sun Sep 21, 2025 3:59 amIn reality, what would an IDE controller return when a read extending beyond the end of the disk is attempted?
An IDE drive will do whatever it likes. Some will allow the read, either because the total addressable sectors doesn't evenly divide into the reported CHS geometry, or because they're based on ESDI designs that included diagnostic cylinders. Some will allow part of the read, then abort the command once the address increments past the end of the disk. Some will abort the command immediately because reading past the end of the disk doesn't make sense.
Some 512e drives intentionally misalign the start of the logical-to-physical mapping so that physical sectors will line up nicely with clusters in filesystems created by older versions of Windows.zerodivision wrote: ↑Sun Sep 21, 2025 3:59 amShouldn't every 8th 512-byte logical sector (i.e. LBA % 8 == 0) be aligned to the start of a 4096-byte physical sector?
Re: BIOS INT 0x13 partial reads
[As far as the BIOS is concerned, if it knows the geometry of the disk, and referring to previous comments,] Technically, this is correct behavior. Technically, there was no error reading from the disk. The BIOS saw that there were no more sectors available, stopped the process, and returned to the caller. This is why, even though the carry flag may be clear indicating a successful transfer, you still have to check the AL register to see that it matches the requested number of sectors. [As for PCem not giving an error, as you state, yes, that is probably an error in PCem. When I wrote this, I had so many thoughts in my head, and then re-read your comment above and my comments now don't match the quote above. Sorry :-)]zerodivision wrote: ↑Sun Sep 21, 2025 3:02 pm I found out that the PCem emulated IDE controller doesn't set an error status if there is a request that extends beyond the end of the disk (a PCem bug, probably). As such, the BIOS doesn't know there should be an error and instead returns a successful read.
I would still like to see your test suite. Is it simply a bootable disk image? If so, can you post it somewhere?zerodivision wrote: ↑Sun Sep 21, 2025 3:02 pm For a request of 24 sectors starting at 9 sectors before the end of the media, no BIOS returns AL = 9, but that's maybe caused by the IDE controller not setting the correct flags. Most BIOSes return AL = 0, two return AL = 24 (the initially requested count), and one returns AL = 88 (seemingly completely unrelated).
The BIOS is permitted to attempt to fill the request anyway it feels necessary. For example, if the request is for 10 sectors, the BIOS is permitted to read any arbitrary number of sectors per request to the hardware until the 10 sectors have been read. Then the BIOS can return to the caller, a value of 10 in the AL register, and the requested buffer filled. Another example is that the BIOS can determine that all 10 sectors requested reside on a single track and it can read the whole track at once, then extract the specified sectors out of that read track. The BIOS is permitted to attempt to read the requested sectors however if feels necessary, as long as the request is fulfilled.zerodivision wrote: ↑Sun Sep 21, 2025 3:02 pmDo you mean that it can split the initial requests into smaller ones before the returning all requested sectors to the caller, or that it can return to the caller less sectors than requested without it actually being an error? If it's the latter, unfortunately, neither the Enhanced Disk Drive specification nor the aforementioned tests guarantee that AL is set to sectors successfully read, or even that sectors successfully transferred refer to the sectors from the beginning of the request so that it could be resumed from the sector where it failed.BenLunt wrote:The BIOS is not required to try to read the requested number of sectors all at once.
Now let's say that the request is for 20 sectors, 10 sectors from the end of the media. The BIOS is permitted to read the last 10 sectors, placing the read data into the requested buffer, and then stop, returning to the caller. Technically, there was no error reading from the disk. All available sectors were read. Therefore, the carry flag can be cleared and indicate a successful read. However, the AL register will indicate that only 10 sectors were read, not the 20 requested.
So even though the return shows success, you still have to check the AL register. In the above example, since it didn't read all 20 sectors, if it was to return failure, there would be no reason for the AL register to indicate how many was actually read.
The IBM PS/2 Documentation Octocontrabass pointed to in a previous post states:
Code: Select all
On Return:
CF = 1 - Status is non 0
= 0 - Status is 0
(AL) - Number of sectors actually transferredTherefore, in my opinion, attempting to read 20 sectors from the LBA of the last 10 sectors, as long as those last 10 sectors were successfully read, the BIOS must return carry clear, indicating a successful transfer, but AL will indicate that only 10 were actually read. This is a perfectly normal result, which probably defeats all of your tests above.
Ben
-
Octocontrabass
- Member

- Posts: 6248
- Joined: Mon Mar 25, 2013 7:01 pm
Re: BIOS INT 0x13 partial reads
The section you're quoting only applies to floppy disks! For hard disks, there is no return value in AL.
This scenario is impossible. If the BIOS has decided that the request is invalid, it must return carry set, because an invalid request is an error.BenLunt wrote: ↑Mon Sep 22, 2025 10:24 amTherefore, in my opinion, attempting to read 20 sectors from the LBA of the last 10 sectors, as long as those last 10 sectors were successfully read, the BIOS must return carry clear, indicating a successful transfer, but AL will indicate that only 10 were actually read.
Re: BIOS INT 0x13 partial reads
And as stated, my opinion differs. I think what is more important to this conversation is what existing BIOS implementations do, not what our opinion is for future implementations. :-)Octocontrabass wrote: ↑Mon Sep 22, 2025 11:23 amThis scenario is impossible. If the BIOS has decided that the request is invalid, it must return carry set, because an invalid request is an error.BenLunt wrote: ↑Mon Sep 22, 2025 10:24 amTherefore, in my opinion, attempting to read 20 sectors from the LBA of the last 10 sectors, as long as those last 10 sectors were successfully read, the BIOS must return carry clear, indicating a successful transfer, but AL will indicate that only 10 were actually read.
-
zerodivision
- Posts: 14
- Joined: Tue Sep 16, 2025 10:25 am
Re: BIOS INT 0x13 partial reads
I know you're way more knowledgeable and experienced than me, but please allow me here to state that I consider this a somewhat arbitrary assumption. The IBM was the de facto standard and other BIOSes were indeed copying it, but no BIOS behaves in the exact same way as any of the original IBM BIOSes or any other IBM-compatible one for that matter. Some may have some features added (e.g. defining partial reads not only for floppies but also for hard disks), some may have been written taking into account newer hardware that breaks the old assumptions (e.g. some BIOSes update AL to sectors transferred, for older BIOSes it was presumably so that the read could be resumed from where it stopped, but the more recent EDD specification explicitly mentions that these sectors aren't necessarily at the beginning of the request due to out-of-order DMA completion so that the read can't be resumed anymore), and finally some differences may have been caused by misinterpretations of the IBM documentation or even bugs.Octocontrabass wrote:But you are writing an OS for a PS/2-compatible. (Well, mostly-PS/2-compatible. It's complicated.) All those non-standardized BIOS implementations were copying the behavior of IBM's BIOSes, so you only need to look at IBM's documentation to know how IBM-compatible BIOSes were expected to behave.
Consider INT 0x15 AX=0xE820, which is supposed to return the minimum of the size of a memory map entry and size requested. I've read on this forum about BIOSes that would return the full 24 bytes of an entry when 20 bytes were requested. I've also came across a BIOS (tested in PCem) that would return the 20 bytes of the first entry and 4 bytes of the second one when requesting 24 bytes.
Then the simplest way is to simply abort the command immediately, that is what I changed to initially.Octocontrabass wrote:An IDE drive will do whatever it likes. Some will allow the read, either because the total addressable sectors doesn't evenly divide into the reported CHS geometry, or because they're based on ESDI designs that included diagnostic cylinders. Some will allow part of the read, then abort the command once the address increments past the end of the disk. Some will abort the command immediately because reading past the end of the disk doesn't make sense.
Combining with the information provided by BenLunt, this leads me to believe that SeaBIOS (which returns the expected partial read) splits the read into smaller ones (it's a little hard to navigate the source), but the BIOSes tested in PCem request the full read at once and see the entirety of it failed (or succeeded, before the changes). Either way, we have already established that partial reads can't be reliably resumed given the returned information, so any further findings about what do BIOSes return for partial reads would only have documentation value.
You mentioned that partial reads are only defined for floppies in PS/2 compatibles. The common advice when it comes to floppies is to retry the read at least three times before giving up, but I've encountered no such advice for hard disks, optical drives or USB flash drives. So now the question is, should all read errors on these devices be considered fatal and not retry any failed read operation?
That's interesting. So now two more questions arise.Octocontrabass wrote:Some 512e drives intentionally misalign the start of the logical-to-physical mapping so that physical sectors will line up nicely with clusters in filesystems created by older versions of Windows.
First, most modern partitioning software, in order to not try to detect the characteristics of the disk or ask the user to specify them, will by default create partitions aligned to 1M. Besides, almost all modern filesystem formatters will create 4K filesystem blocks aligned to 4K. For drives that misalign the start of the logical-to-physical mapping, wouldn't both partitions and filesystem blocks be misaligned?
Second, is there a reliable way to determine the correct alignment for a disk?
BenLunt wrote:you still have to check the AL register to see that it matches the requested number of sectors.
AL is unreliable for both success and error. Actually, the RBIL states that AL is set to sectors transferred only at error for some BIOSes, implying that these BIOSes won't set AL at success. According to the EDD specification as well as in practice, as shown from my tests, some BIOSes won't set AL even at error.BenLunt wrote:the carry flag can be cleared and indicate a successful read. However, the AL register will indicate that only 10 sectors were read, not the 20 requested.
I'd rather not to, because it's somewhat of a mess (also testing other stuff). The part that matters is that I create a disk image of 243*16*63 sectors, then I attempt to read 24 sectors starting from cylinder 242, head 15 and sector 55.BenLunt wrote:I would still like to see your test suite. Is it simply a bootable disk image? If so, can you post it somewhere?
I also tried to define a custom machine in PCem to use with either SeaBIOS or your BIOS, but I haven't succeeded in that. I have based my definitions and initialization function on those for the Intel VS440FX machine, except for reading the BIOS in a continuous 128K chunk. When I run the machine, only a black screen appears (with both SeaBIOS and your BIOS). Does your BIOS support the configuration of the Intel VS440FX machine as defined in at_vs440fx_init()?
Last edited by zerodivision on Tue Sep 23, 2025 9:42 am, edited 1 time in total.