• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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  **/
chs_to_lba(const struct driveinfo * drive_info,const unsigned int cylinder,const unsigned int head,const unsigned int sector)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