Disk access using the BIOS (INT 13h): Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
Arto (talk | contribs)
m →‎Comments: Categorized the article.
m Fix lint errors: missing end tag of <b>
 
(16 intermediate revisions by 10 users not shown)
Line 1:
When the CPU is in Real Mode (before entering Protected Mode, or Long Mode), the BIOS is still operational. The BIOS provides a set of disk access routines using the INT 0x13 family of BIOS functions. Until an OSappropriate (ordriver bootloader) has a disk driveris loadedimplemented, these BIOS functions are the only way to access disks.
 
There are two basic INT0x13INT calls0x13 call families to use for ATA disk access. One uses Cylinder, Head, Sector addressing, and the other uses LBA addressing. There is a third command set to access ATAPI drives using the PACKET command set.
 
Note: These BIOS INT calls should completely preserve all the registers (except AX). However, some older versions of the Bochs/QemuQEMU BIOS destroyed the upper words16-bit values of some of the 32bit registers.
 
==CHS==
 
Remember that there are severe addressing limitations with CHS addressing. Typically only the first 8 GB of the media can be accessed, at most. Sometimes USB drives might be using floppy emulation, so the maximum accessable size becomes only 1.44M.
Reading or writing an ATA hard disk in Real Mode with CHS addressing is <i>precisely</i> the same as doing the same operation on a floppy drive. Also remember that there are severe addressing limitations with CHS addressing. Typically only the first 8GB of the media can be accessed, at most.
And when you read from USB (as floppy), 1440 Kb is the most.
 
===Converting LBA to CHS===
The addresses of interesting sectors on a disk are almost always calculated or stored as LBAs, but some drives (especially USBfloppies flashand USB drives doingwith floppy emulation) cannot use LBA addressing. So your code must translate the address, and use a CHS read call. This also applies if you are trying to read floppies and hard disks with the same code.
 
====Quick Explanation of the Algorithm====
Line 23 ⟶ 22:
*Cylinder = Temp / (Number of Heads)
 
'''Note: Always remember that Sectorsector is 1-based, and not 0-based ... this detail causes many problems.'''
 
====Getting Sectors/Track, Total Head values====
Line 33 ⟶ 32:
*AND the value returned in CL with 0x3f to get the "Sectors per Track".
 
Note: INT0x13INT 0x13 AH=8 does not seem to work well with floppy drives, or emulated floppy drives. It may be best to use default values in that case.
 
===Reading sectors with a CHS address===
Line 66 ⟶ 65:
 
 
To read or write, first you need to set up a "Disk Address Packet Structure" in memory, on a DWORDuint32_t (4 byte) boundary.
 
* Format of disk address packet:
<pre>
Offset Size Description
0 BYTE1 size of packet (16 bytes)
1 BYTE1 always 0
2 WORD2 number of sectors to transfer (max 127 on some BIOSes)
4 DWORD4 -> transfer buffer (16 bit segment:16 bit offset) (see note #1)
8 DWORD4 lower 32-bits of 48-bit starting LBA
12 DWORD4 used for upper part16-bits of 48-bit bitstarting LBAsLBA
</pre>
 
Notes:
 
(1) The 16 bit segment value ends up at an offset of 6 from the beginning of the structure (i.e., when declaring segment:offset as two separate word16-sizedbit fields, place the offset first and then follow with the segment because x86 is little-endian).
 
(2) If the disk drive itself does not support LBA addressing, the BIOS will automatically convert the LBA to a CHS address for you -- so this function still works.
 
(3) The transfer buffer should be WORD16-bit (2 byte) aligned.
 
 
Line 99 ⟶ 98:
 
To write to a disk, set AH = 0x43.
 
=== 64-bit Addressing Extensions ===
 
The BIOS Enhanced Disk Drives Services version 3.0 specifies the possibility of loading to flat 64-bit addresses. Then the format of disk address packet looks like:
<pre>
Offset Size Description
0 1 size of packet (24 bytes)
1 1 always 0
2 2 number of sectors to transfer (max 127 on some BIOSes)
4 4 transfer buffer (0xFFFF:0xFFFF)
8 4 lower 32-bits of starting 48-bit LBA
12 4 upper 32-bits of starting 48-bit LBA
16 4 lower 32-bits of load address
20 4 upper 32-bits of load address
</pre>
 
'''Warning''': 64-bit addressing extensions are not implemented by most BIOSes, therefore they are very unpractical. Even BIOSes of most virtual machine softwares don't implement them!
 
==x86 Examples==
 
* Reading 16 sectors from LBA #1 to physical address 0x7C00
<sourcesyntaxhighlight lang="asm">
DAPACK:
db 0x10
Line 118 ⟶ 134:
int 0x13
jc short .error
</syntaxhighlight>
</source>
 
==Supported Systems==
Line 124 ⟶ 140:
All systems support CHS addressing.
 
There exist some 486 systems that do not support LBA in any way. All known original Pentium and newer systems support Extended LBA in the BIOS.
 
==Comments==
 
One of the easiest ways to read or write a USB flash drive is to drop into Real or Unreal Mode, and use the INT 0x13 BIOS commands. However, the transfer must fit in the usable part of low memory (if in Real Mode), and you need to somehow know the proper drive number to use in DL.
 
BIOS can emulate USB flash drives as a floppy drive or as an hard disk. If the USB drive is emulated as a floppy drive, it is likely 0x00 or 0x01 and you can only use AH=0x02 and AH=0x03. If it's emulated as an hard disk, it is most likely 0x80 or 0x81 and you can '''also''' use AH=0x42 and AH=0x43.
 
[[Category:ATABIOS]]
[[Category:Disks]]
[[Category:X86]]