Search code examples
x86bootbootloaderbioshard-drive

INT 13h effective sector size


I'm working on writing my own bootloader. I'm looking to leverage int 13h,02h to read sectors from the boot drive. I'm referencing https://en.wikipedia.org/wiki/INT_13H for documentation on this bios interrupt.

Most reference code I've found assumes the size of a sector to be exclusively 512 bytes, despite the fact that other sizes exist (non-standard sizes such as 520-byte sectors, and 4096-byte sectors). Some sources I've found seem to suggest that the BIOS will always emulate a sector as 512 bytes no matter the underlying size (LBA and sector size), and some appear to indicate that this is not the case (https://www.reddit.com/r/osdev/comments/ajfmtf/is_the_sector_size_for_bios_int_13h_ah2_always/), though no source I've found provides conclusive documentation supporting this fact.

I understand that I can use int 13h,48h to read information about the drive parameters, however I'm still not sure whether the "sector size" returned by this interrupt will be the one used, or whether the BIOS will automatically emulate 512-byte sectors. In addition to this, int 13h,48h is not guaranteed to be supported on every platform (I believe). The reference linked appears to suggest the latter: "Assume you want to read 16 sectors (= 2000h bytes)".

If possible, I'm looking for the following:

  1. Which sector size is actually used for drives with a non-standard sector size, and concrete documentation that supports this answer.
  2. If the non-standard size is in fact the one used, is there a way to determine this value without relying on int 13h,48h?

Solution

  • All the non extended BIOS disk services like Int 13h/AH=2h, Int 13h=AH=3h etc. are all assumed to be 512 byte sectors. There is translation done if the underlying media happens to use a larger disk sector size.

    Sector sizes will be a multiple of 512 bytes to be compatible with legacy BIOS. In the early days of the IBM-PC there were some drives that supported esoteric sector sizes but they required using different services provided by a BIOS to utilize or required accessing the drive directly (via IO ports etc). In effect you needed special hardware to use such devices or you need to write code written specifically for those devices.

    There are certain kinds of SCSI devices (including SAS SSDs) that use 520 byte sectors at the lowest level but you would usually need to wipe the drive and reformat it to use some standard sector size that is a multiple of 512 bytes to be understood by most software and OSes. This usually involves issuing SCSI commands to the drive directly. In Linux sg_format can be used to do this kind of low level operation. These kind of drives generally require specialized controllers as well.

    The extended BIOS disk services like Int 13h/AH=42h and Int 13h/AH=43h do not make any such assumption that a sector size is fixed at 512 bytes. On any kind of drive that supports extended disk BIOS services you can query the drive parameters to determine the disk sector size.

    If a drive is found to support extended BIOS disk services, you can determine the sector size when your bootloader is running. See the additional notes about how to check if a BIOS and the drive supports these extensions. If the BIOS and drive does support them then you can use Int 13h/AH=48h to query the disk sector size:

    IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS
    AH = 48h
    DL = drive (80h-FFh)
    DS:SI -> buffer for drive parameters (see #00273)
    
    Return:
    CF clear if successful
    AH = 00h
    DS:SI buffer filled
    CF set on error
    AH = error code
    

    [snip]

    Format of IBM/MS INT 13 Extensions drive parameters:
    
    Offset  Size    Description     (Table 00273)
    00h    WORD    (call) size of buffer
    (001Ah for v1.x, 001Eh for v2.x, 42h for v3.0)
    (ret) size of returned data
    02h    WORD    information flags (see #00274)
    04h    DWORD   number of physical cylinders on drive
    08h    DWORD   number of physical heads on drive
    0Ch    DWORD   number of physical sectors per track
    10h    QWORD   total number of sectors on drive
    **18h    WORD    bytes per sector**
    ---v2.0+ ---
    1Ah    DWORD   -> EDD configuration parameters (see #00278)
    FFFFh:FFFFh if not available
    ---v3.0 ---
    1Eh    WORD    signature BEDDh to indicate presence of Device Path info
    20h    BYTE    length of Device Path information, including signature and this
    byte (24h for v3.0)
    21h  3 BYTEs   reserved (0)
    24h  4 BYTEs   ASCIZ name of host bus ("ISA" or "PCI")
    28h  8 BYTEs   ASCIZ name of interface type
    "ATA"
    "ATAPI"
    "SCSI"
    "USB"
    "1394" IEEE 1394 (FireWire)
    "FIBRE" Fibre Channel
    30h  8 BYTEs   Interface Path (see #00275)
    38h  8 BYTEs   Device Path (see #00276)
    40h    BYTE    reserved (0)
    41h    BYTE    checksum of bytes 1Eh-40h (two's complement of sum, which makes
    the 8-bit sum of bytes 1Eh-41h equal 00h)
    

    Notice that the disk structure returned includes:

    10h    QWORD  total number of sectors on drive
    

    Additional Notes

    Int 13h/AH=48h and the other extended disk functions will likely be part of all modern systems that still support legacy BIOSes. Decades ago this may not have been the case. To determine if the BIOS actually supports extended disk BIOS services you can use Int 13/AH=41h/BX=55AAh:

    IBM/MS INT 13 Extensions - INSTALLATION CHECK
    AH = 41h
    BX = 55AAh
    DL = drive (80h-FFh)
    
    Return:
    CF set on error (extensions not supported)
    AH = 01h (invalid function)
    CF clear if successful
    BX = AA55h if installed
    AH = major version of extensions
    01h = 1.x
    20h = 2.0 / EDD-1.0
    21h = 2.1 / EDD-1.1
    30h = EDD-3.0
    AL = internal use
    CX = API subset support bitmap (see #00271)
    DH = extension version (v2.0+ ??? -- not present in 1.x)
    

    If you use this BIOS service and the value returned in BX = AA55h then the BIOS supports disk extensions. If it doesn't you have to fall back to using the non-extended disk functions using CHS addressing. If the BIOS does support extended disk services, it doesn't mean the disk you are checking actually supports it! Most floppy disks do not support extended BIOS disk services even though the BIOS itself does.

    That is why you need to also check the Carry Flag (CF) that is returned to see if the disk extensions are supported on the drive you are interested in. If they are not supported you would have to fall back to non-extended BIOS disk services using CHS addressing, otherwise you are free to use the extended disk BIOS services on the drive.

    Once you have determine a drive supports extended BIOS disk services then you can use Int 13h/AH=48h as discussed in the first section of this answer to determine the sector size.