Appendix A - CHS mapping

Existing operating systems use a Cylinder-Head-Sector (CHS) mapping for "talking" to hard disk drives via INT 13h. These CHS values limit the maximum number of blocks on a disk to 1024 * 255 * 63 which is slightly less than eight Gigabytes. To overcome this, new operating systems have defined new partition table system type values. These values will be used for partition entries whose limits exceed the CHS mapping capabilities.

The two new system types are 0Eh for primary partitions and 0Fh for extended partitions meeting the criteria above. These entries will have CHS values of 0Fh and will use the LBA starting field (offset 08h in the partition entry) and the Length field (offset 0Ch) to describe the partition. Access to these partitions will be by the INT 13h extensions as defined by Microsoft. The following routine is pseudo-code for detecting an existing partition and calculating geometry using this information.

Partition table entry format

Offset

Description

Variable

00h

Boot indicator

01h

Start Head

StartHead

02h

Start Sector/Cylinder

StartSector

03h

Start Cylinder (low 8 bits)

StartCylinder

04h

System type

SystemType

05h

Ending Head

EndHead

06h

Ending Sector/Cylinder

EndSector

07h

Ending Cylinder (low 8 bits)

EndCylinder

08h

Starting sector

StartingSector

0Ch

Number of sectors in partition

NumSectors


Some other variables

Description

Sectors
Heads
Cylinders
CHS

capacity

Sector value for CHS result
Head value for CHS result
Cylinder value for CHS result
Short for StartHead, StartSector, and StartCylinder

Value returned from SCSI read capacity



void  GetCHS( void )
{
    ulong  logical_end;
    ushort Sectors;
    ushort Heads;
    ushort Cylinders;


For each drive
    Read Boot sector
    Validate Sector Signature (55AAh)
    Find Partition with largest logical start cylinder
        If no partitions found
            Use your own geometry routine
            exit

    if ((CHS == FF) || (SystemType == 0x0E) || (SystemType == 0x0F))
    {
        /* No Geometry is needed, use INT 13h Extensions */
        exit;
    }
    else 
    {
        Sectors = EndSector;
        Heads = EndHead + 1;
        logical_end = (EndCylinder * Heads * Sectors) +
                      (EndHead * Sectors) + Sectors;

        if (logical_end != StartingSector + NumSectors)
        {
            /* use your own geometry routine */
            exit;
        }

        Cylinders = capacity / (Heads * Sectors);
    }

    /* Now use the calculated Cylinders, Sectors, and Heads values. */
}