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 **/
31struct 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 */
190struct 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 */
292enum 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 **/
304static 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
321void lba_to_chs(const struct driveinfo *drive_info, const int lba,
322		unsigned int *cylinder, unsigned int *head,
323		unsigned int *sector);
324int get_drive_parameters(struct driveinfo *drive_info);
325
326#endif /* _GEOM_H */
327