Home | History | Annotate | Download | only in disk
      1 /* ----------------------------------------------------------------------- *
      2  *
      3  *   Copyright 2009 Pierre-Alexandre Meyer
      4  *
      5  *   Some parts borrowed from chain.c32:
      6  *
      7  *   Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
      8  *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
      9  *
     10  *   Some parts borrowed from Linux:
     11  *
     12  *   Copyright (C) 2002, 2003, 2004 Dell Inc.
     13  *   by Matt Domsch <Matt_Domsch (at) dell.com>
     14  *
     15  *   This file is part of Syslinux, and is made available under
     16  *   the terms of the GNU General Public License version 2.
     17  *
     18  * ----------------------------------------------------------------------- */
     19 
     20 #ifndef _GEOM_H_
     21 #define _GEOM_H_
     22 
     23 #include <stdint.h>
     24 
     25 /**
     26  * INT 13 Extensions
     27  *
     28  * Note: if the size is less than 30 on call, the final DWORD will not be
     29  *       returned by a v2.x implementation; similarly for the Device Path info
     30  **/
     31 struct edd_device_parameters {
     32     uint16_t len;		/* size of returned data */
     33 	/**
     34 	 * Bitfields for IBM/MS INT 13 Extensions information flags:
     35 	 * Bit(s)    Description    (Table 00274)
     36 	 * 0    DMA boundary errors handled transparently
     37 	 * 1    cylinder/head/sectors-per-track information is valid
     38 	 * 2    removable drive
     39 	 * 3    write with verify supported
     40 	 * 4    drive has change-line support (required if drive >= 80h is removable)
     41 	 * 5    drive can be locked (required if drive >= 80h is removable)
     42 	 * 6    CHS information set to maximum supported values, not current media
     43 	 * 15-7    reserved (0)
     44 	 **/
     45     uint16_t info;		/* information flags */
     46     uint32_t cylinders;		/* number of physical cylinders on drive */
     47     uint32_t heads;		/* number of physical heads on drive */
     48     uint32_t sectors_per_track;	/* number of physical sectors per track */
     49     uint64_t sectors;		/* total number of sectors on drive */
     50     uint16_t bytes_per_sector;	/* bytes per sector */
     51     /* --- v2.0+ --- */
     52     uint32_t dpte_pointer;	/* EDD configuration parameters, FFFFh:FFFFh if not available */
     53     /* --- v3.0 --- */
     54     uint16_t device_path_information;	/* signature BEDDh to indicate presence of Device Path info */
     55     uint8_t device_path_length;	/* length of Device Path information, including signature and this byte (24h for v3.0) */
     56     uint8_t device_path_reserved;	/* reserved (0) */
     57     uint16_t device_path_reserved_2;	/* reserved (0) */
     58     uint8_t host_bus_type[4];	/* ASCIZ name of host bus ("ISA" or "PCI") */
     59     uint8_t interface_type[8];	/* ASCIZ name of interface type
     60 				 *         "ATA"
     61 				 *         "ATAPI"
     62 				 *         "SCSI"
     63 				 *         "USB"
     64 				 *         "1394" IEEE 1394 (FireWire)
     65 				 *         "FIBRE" Fibre Channel
     66 				 */
     67 	/**
     68 	 * Format of EDD v3.0 Interface Path:
     69 	 * Offset    Size    Description    (Table 00275)
     70 	 * ---ISA---
     71 	 * 00h    WORD    16-bit base address
     72 	 * 02h 6 BYTEs    reserved (0)
     73 	 * ---PCI---
     74 	 * 00h    BYTE    PCI bus number
     75 	 * 01h    BYTE    PCI device number
     76 	 * 02h    BYTE    PCI function number
     77 	 * 03h 5 BYTEs    reserved (0)
     78 	 **/
     79     union {
     80 	struct {
     81 	    uint16_t base_address;
     82 	    uint16_t reserved1;
     83 	    uint32_t reserved2;
     84 	} __attribute__ ((packed)) isa;
     85 	struct {
     86 	    uint8_t bus;
     87 	    uint8_t slot;
     88 	    uint8_t function;
     89 	    uint8_t channel;
     90 	    uint32_t reserved;
     91 	} __attribute__ ((packed)) pci;
     92 	/* pcix is same as pci */
     93 	struct {
     94 	    uint64_t reserved;
     95 	} __attribute__ ((packed)) ibnd;
     96 	struct {
     97 	    uint64_t reserved;
     98 	} __attribute__ ((packed)) xprs;
     99 	struct {
    100 	    uint64_t reserved;
    101 	} __attribute__ ((packed)) htpt;
    102 	struct {
    103 	    uint64_t reserved;
    104 	} __attribute__ ((packed)) unknown;
    105     } interface_path;
    106 	/**
    107 	 * Format of EDD v3.0 Device Path:
    108 	 * Offset    Size    Description    (Table 00276)
    109 	 * ---ATA---
    110 	 * 00h    BYTE    flag: 00h = master, 01h = slave
    111 	 * 01h 7 BYTEs    reserved (0)
    112 	 * ---ATAPI---
    113 	 * 00h    BYTE    flag: 00h = master, 01h = slave
    114 	 * 01h    BYTE    logical unit number
    115 	 * 02h 6 BYTEs    reserved (0)
    116 	 * ---SCSI---
    117 	 * 00h    BYTE    logical unit number
    118 	 * 01h 7 BYTEs    reserved (0)
    119 	 * ---USB---
    120 	 * 00h    BYTE    to be determined
    121 	 * 01h 7 BYTEs    reserved (0)
    122 	 * ---IEEE1394---
    123 	 * 00h    QWORD    64-bit FireWire General Unique Identifier (GUID)
    124 	 * ---FibreChannel---
    125 	 * 00h    QWORD    Word Wide Number (WWN)
    126 	 **/
    127     union {
    128 	struct {
    129 	    uint8_t device;
    130 	    uint8_t reserved1;
    131 	    uint16_t reserved2;
    132 	    uint32_t reserved3;
    133 	    uint64_t reserved4;
    134 	} __attribute__ ((packed)) ata;
    135 	struct {
    136 	    uint8_t device;
    137 	    uint8_t lun;
    138 	    uint8_t reserved1;
    139 	    uint8_t reserved2;
    140 	    uint32_t reserved3;
    141 	    uint64_t reserved4;
    142 	} __attribute__ ((packed)) atapi;
    143 	struct {
    144 	    uint16_t id;
    145 	    uint64_t lun;
    146 	    uint16_t reserved1;
    147 	    uint32_t reserved2;
    148 	} __attribute__ ((packed)) scsi;
    149 	struct {
    150 	    uint64_t serial_number;
    151 	    uint64_t reserved;
    152 	} __attribute__ ((packed)) usb;
    153 	struct {
    154 	    uint64_t eui;
    155 	    uint64_t reserved;
    156 	} __attribute__ ((packed)) i1394;
    157 	struct {
    158 	    uint64_t wwid;
    159 	    uint64_t lun;
    160 	} __attribute__ ((packed)) fibre;
    161 	struct {
    162 	    uint64_t identity_tag;
    163 	    uint64_t reserved;
    164 	} __attribute__ ((packed)) i2o;
    165 	struct {
    166 	    uint32_t array_number;
    167 	    uint32_t reserved1;
    168 	    uint64_t reserved2;
    169 	} __attribute__ ((packed)) raid;
    170 	struct {
    171 	    uint8_t device;
    172 	    uint8_t reserved1;
    173 	    uint16_t reserved2;
    174 	    uint32_t reserved3;
    175 	    uint64_t reserved4;
    176 	} __attribute__ ((packed)) sata;
    177 	struct {
    178 	    uint64_t reserved1;
    179 	    uint64_t reserved2;
    180 	} __attribute__ ((packed)) unknown;
    181     } device_path;
    182     uint8_t reserved;		/* reserved (0) */
    183     uint8_t checksum;		/* checksum of bytes 1Eh-40h (two's complement of sum, which makes
    184 				 * the 8-bit sum of bytes 1Eh-41h equal 00h) */
    185 } __attribute__ ((packed));
    186 
    187 /*
    188  * Disk parameters
    189  */
    190 struct driveinfo {
    191     int disk;			/* Disk port (0x80 - 0xff) */
    192     /* Legacy C/H/S */
    193     int cbios;			/* CHS geometry is valid */
    194     int legacy_max_head;
    195     int legacy_max_cylinder;
    196     int legacy_sectors_per_track;
    197     int legacy_max_drive;
    198     int legacy_type;		/* Drive type (AT/PS2 floppies only) */
    199     /* EDD support */
    200     int ebios;			/* EBIOS supported on this disk */
    201     int edd_version;		/* EBIOS major version */
    202     int edd_functionality_subset;
    203     struct edd_device_parameters edd_params;	/* EDD parameters */
    204 };
    205 
    206 /**
    207  * Format of Phoenix Enhanced Disk Drive Spec translated drive parameter table:
    208  * Offset    Size    Description    (Table 00277)
    209  * 00h    WORD    number of cylinders
    210  * 02h    BYTE    number of heads
    211  * 03h    BYTE    A0h (signature indicating translated table)
    212  * 04h    BYTE    number of physical sectors per track
    213  * 05h    WORD    starting write precompensation cylinder number
    214  * 07h    BYTE    reserved
    215  * 08h    BYTE    control byte (see #03198 at INT 41"DISK 0")
    216  * 09h    WORD    number of physical cylinders
    217  * 0Bh    BYTE    number of physical heads
    218  * 0Ch    WORD    cylinder number of landing zone
    219  * 0Eh    BYTE    number of logical sectors per track
    220  * 0Fh    BYTE    checksum
    221  * Program: the Phoenix Enhanced Disk Drive Specification is an addition to the
    222  *     IBM/MS INT 13 extensions
    223  *
    224  * Format of Phoenix Enhanced Disk Drive Spec Fixed Disk Parameter Table:
    225  * Offset    Size    Description    (Table 00278)
    226  * 00h    WORD    physical I/O port base address
    227  * 02h    WORD    disk-drive control port address
    228  * 04h    BYTE    drive flags (see #00279)
    229  * 05h    BYTE    proprietary information
    230  *         bits 7-4 reserved (0)
    231  *         bits 3-0: Phoenix proprietary (used by BIOS)
    232  * 06h    BYTE    IRQ for drive (bits 3-0; bits 7-4 reserved and must be 0)
    233  * 07h    BYTE    sector count for multi-sector transfers
    234  * 08h    BYTE    DMA control
    235  *         bits 7-4: DMA type (0-2) as per ATA-2 specification
    236  *         bits 3-0: DMA channel
    237  * 09h    BYTE    programmed I/O control
    238  *         bits 7-4: reserved (0)
    239  *         bits 3-0: PIO type (1-4) as per ATA-2 specification
    240  * 0Ah    WORD    drive options (see #00280)
    241  * 0Ch 2 BYTEs    reserved (0)
    242  * 0Eh    BYTE    extension revision level (high nybble=major, low nybble=minor)
    243  *         (currently 10h for v1.0 and 11h for v1.1-3.0)
    244  * 0Fh    BYTE    2's complement checksum of bytes 00h-0Eh
    245  *         8-bit sum of all bytes 00h-0Fh should equal 00h
    246  * SeeAlso: #00277
    247  *
    248  * Bitfields for Phoenix Enhanced Disk Drive Spec drive flags:
    249  * Bit(s)    Description    (Table 00279)
    250  * 7    reserved (1)
    251  * 6    LBA enabled
    252  * 5    reserved (1)
    253  * 4    drive is slave
    254  * 3-0    reserved (0)
    255  * SeeAlso: #00278,#00280
    256  *
    257  * Bitfields for Phoenix Enhanced Disk Drive Spec drive options:
    258  * Bit(s)    Description    (Table 00280)
    259  * 0    fast PIO enabled
    260  * 1    fast DMA access enabled
    261  * 2    block PIO (multi-sector transfers) enabled
    262  * 3    CHS translation enabled
    263  * 4    LBA translation enabled
    264  * 5    removable media
    265  * 6    ATAPI device (CD-ROM)
    266  * 7    32-bit transfer mode
    267  * ---v1.1+ ---
    268  * 8    ATAPI device uses DRQ to signal readiness for packet command
    269  *     (must be 0 if bit 6 is 0)
    270  * 10-9    translation type (must be 00 if bit 3 is 0)
    271  *     00 Phoenix bit-shifting translation
    272  *     01 LBA-assisted translation
    273  *     10 reserved
    274  *     11 proprietary translation
    275  * ---v3.0---
    276  * 11    Ultra DMA access enabled
    277  * 15-12    reserved
    278  **/
    279 
    280 /*
    281  * Values for diskette drive type:
    282  *     01h    360K
    283  *     02h    1.2M
    284  *     03h    720K
    285  *     04h    1.44M
    286  *     05h    ???
    287  *            reportedly an obscure drive type shipped on some IBM machines,
    288  *            2.88M on some machines (at least AMI 486 BIOS)
    289  *     06h    2.88M
    290  *     10h    ATAPI Removable Media Device
    291  */
    292 enum diskette_drive_types {
    293     DISKETTE_360K = 1,
    294     DISKETTE_1_2M = 2,
    295     DISKETTE_720K = 3,
    296     DISKETTE_1_44M = 4,
    297     DISKETTE_2_88M = 6,
    298     DISKETTE_ATAPI = 10,
    299 };
    300 
    301 /**
    302  * chs_to_lba - compute lba value from cylinder, head and sector number
    303  **/
    304 static inline int chs_to_lba(const struct driveinfo *drive_info,
    305 			     const unsigned int cylinder,
    306 			     const unsigned int head, const unsigned int sector)
    307 {
    308     /* Use EDD, if valid */
    309     if (drive_info->edd_params.sectors_per_track > 0 &&
    310 	drive_info->edd_params.heads > 0)
    311 	return (sector - 1) +
    312 	    (head * drive_info->edd_params.sectors_per_track) +
    313 	    (cylinder * (drive_info->edd_params.heads) *
    314 	     drive_info->edd_params.sectors_per_track);
    315     else if (drive_info->cbios)
    316 	return (sector - 1) + (head * drive_info->legacy_sectors_per_track) +
    317 	    (cylinder * (drive_info->legacy_max_head + 1) *
    318 	     drive_info->legacy_sectors_per_track);
    319 }
    320 
    321 void lba_to_chs(const struct driveinfo *drive_info, const int lba,
    322 		unsigned int *cylinder, unsigned int *head,
    323 		unsigned int *sector);
    324 int get_drive_parameters(struct driveinfo *drive_info);
    325 
    326 #endif /* _GEOM_H */
    327