1#ifndef INT13_H
2#define INT13_H
3
4/** @file
5 *
6 * INT 13 emulation
7 *
8 */
9
10FILE_LICENCE ( GPL2_OR_LATER );
11
12#include <stdint.h>
13#include <gpxe/list.h>
14#include <realmode.h>
15
16struct block_device;
17
18/**
19 * @defgroup int13ops INT 13 operation codes
20 * @{
21 */
22
23/** Reset disk system */
24#define INT13_RESET			0x00
25/** Get status of last operation */
26#define INT13_GET_LAST_STATUS		0x01
27/** Read sectors */
28#define INT13_READ_SECTORS		0x02
29/** Write sectors */
30#define INT13_WRITE_SECTORS		0x03
31/** Get drive parameters */
32#define INT13_GET_PARAMETERS		0x08
33/** Get disk type */
34#define INT13_GET_DISK_TYPE		0x15
35/** Extensions installation check */
36#define INT13_EXTENSION_CHECK		0x41
37/** Extended read */
38#define INT13_EXTENDED_READ		0x42
39/** Extended write */
40#define INT13_EXTENDED_WRITE		0x43
41/** Get extended drive parameters */
42#define INT13_GET_EXTENDED_PARAMETERS	0x48
43/** Get CD-ROM status / terminate emulation */
44#define INT13_CDROM_STATUS_TERMINATE	0x4b
45
46/** @} */
47
48/**
49 * @defgroup int13status INT 13 status codes
50 * @{
51 */
52
53/** Operation completed successfully */
54#define INT13_STATUS_SUCCESS		0x00
55/** Invalid function or parameter */
56#define INT13_STATUS_INVALID		0x01
57/** Read error */
58#define INT13_STATUS_READ_ERROR		0x04
59/** Write error */
60#define INT13_STATUS_WRITE_ERROR	0xcc
61
62/** @} */
63
64/** Block size for non-extended INT 13 calls */
65#define INT13_BLKSIZE 512
66
67/** An INT 13 emulated drive */
68struct int13_drive {
69	/** List of all registered drives */
70	struct list_head list;
71
72	/** Underlying block device */
73	struct block_device *blockdev;
74
75	/** BIOS in-use drive number (0x80-0xff) */
76	unsigned int drive;
77	/** BIOS natural drive number (0x80-0xff)
78	 *
79	 * This is the drive number that would have been assigned by
80	 * 'naturally' appending the drive to the end of the BIOS
81	 * drive list.
82	 *
83	 * If the emulated drive replaces a preexisting drive, this is
84	 * the drive number that the preexisting drive gets remapped
85	 * to.
86	 */
87	unsigned int natural_drive;
88
89	/** Number of cylinders
90	 *
91	 * The cylinder number field in an INT 13 call is ten bits
92	 * wide, giving a maximum of 1024 cylinders.  Conventionally,
93	 * when the 7.8GB limit of a CHS address is exceeded, it is
94	 * the number of cylinders that is increased beyond the
95	 * addressable limit.
96	 */
97	unsigned int cylinders;
98	/** Number of heads
99	 *
100	 * The head number field in an INT 13 call is eight bits wide,
101	 * giving a maximum of 256 heads.  However, apparently all
102	 * versions of MS-DOS up to and including Win95 fail with 256
103	 * heads, so the maximum encountered in practice is 255.
104	 */
105	unsigned int heads;
106	/** Number of sectors per track
107	 *
108	 * The sector number field in an INT 13 call is six bits wide,
109	 * giving a maximum of 63 sectors, since sector numbering
110	 * (unlike head and cylinder numbering) starts at 1, not 0.
111	 */
112	unsigned int sectors_per_track;
113
114	/** Status of last operation */
115	int last_status;
116};
117
118/** An INT 13 disk address packet */
119struct int13_disk_address {
120	/** Size of the packet, in bytes */
121	uint8_t bufsize;
122	/** Reserved, must be zero */
123	uint8_t reserved;
124	/** Block count */
125	uint16_t count;
126	/** Data buffer */
127	struct segoff buffer;
128	/** Starting block number */
129	uint64_t lba;
130	/** Data buffer (EDD-3.0 only) */
131	uint64_t buffer_phys;
132} __attribute__ (( packed ));
133
134/** INT 13 disk parameters */
135struct int13_disk_parameters {
136	/** Size of this structure */
137	uint16_t bufsize;
138	/** Flags */
139	uint16_t flags;
140	/** Number of cylinders */
141	uint32_t cylinders;
142	/** Number of heads */
143	uint32_t heads;
144	/** Number of sectors per track */
145	uint32_t sectors_per_track;
146	/** Total number of sectors on drive */
147	uint64_t sectors;
148	/** Bytes per sector */
149	uint16_t sector_size;
150
151} __attribute__ (( packed ));
152
153/**
154 * @defgroup int13types INT 13 disk types
155 * @{
156 */
157
158/** No such drive */
159#define INT13_DISK_TYPE_NONE	0x00
160/** Floppy without change-line support */
161#define INT13_DISK_TYPE_FDD	0x01
162/** Floppy with change-line support */
163#define INT13_DISK_TYPE_FDD_CL	0x02
164/** Hard disk */
165#define INT13_DISK_TYPE_HDD	0x03
166
167/** @} */
168
169/**
170 * @defgroup int13flags INT 13 disk parameter flags
171 * @{
172 */
173
174/** DMA boundary errors handled transparently */
175#define INT13_FL_DMA_TRANSPARENT 0x01
176/** CHS information is valid */
177#define INT13_FL_CHS_VALID	 0x02
178/** Removable drive */
179#define INT13_FL_REMOVABLE	 0x04
180/** Write with verify supported */
181#define INT13_FL_VERIFIABLE	 0x08
182/** Has change-line supported (valid only for removable drives) */
183#define INT13_FL_CHANGE_LINE	 0x10
184/** Drive can be locked (valid only for removable drives) */
185#define INT13_FL_LOCKABLE	 0x20
186/** CHS is max possible, not current media (valid only for removable drives) */
187#define INT13_FL_CHS_MAX	 0x40
188
189/** @} */
190
191/**
192 * @defgroup int13exts INT 13 extension flags
193 * @{
194 */
195
196/** Extended disk access functions supported */
197#define INT13_EXTENSION_LINEAR		0x01
198/** Removable drive functions supported */
199#define INT13_EXTENSION_REMOVABLE	0x02
200/** EDD functions supported */
201#define INT13_EXTENSION_EDD		0x04
202
203/** @} */
204
205/**
206 * @defgroup int13vers INT 13 extension versions
207 * @{
208 */
209
210/** INT13 extensions version 1.x */
211#define INT13_EXTENSION_VER_1_X		0x01
212/** INT13 extensions version 2.0 (EDD-1.0) */
213#define INT13_EXTENSION_VER_2_0		0x20
214/** INT13 extensions version 2.1 (EDD-1.1) */
215#define INT13_EXTENSION_VER_2_1		0x21
216/** INT13 extensions version 3.0 (EDD-3.0) */
217#define INT13_EXTENSION_VER_3_0		0x30
218
219/** @} */
220
221/** Bootable CD-ROM specification packet */
222struct int13_cdrom_specification {
223	/** Size of packet in bytes */
224	uint8_t size;
225	/** Boot media type */
226	uint8_t media_type;
227	/** Drive number */
228	uint8_t drive;
229	/** CD-ROM controller number */
230	uint8_t controller;
231	/** LBA of disk image to emulate */
232	uint32_t lba;
233	/** Device specification */
234	uint16_t device;
235	/** Segment of 3K buffer for caching CD-ROM reads */
236	uint16_t cache_segment;
237	/** Load segment for initial boot image */
238	uint16_t load_segment;
239	/** Number of 512-byte sectors to load */
240	uint16_t load_sectors;
241	/** Low 8 bits of cylinder number */
242	uint8_t cyl;
243	/** Sector number, plus high 2 bits of cylinder number */
244	uint8_t cyl_sector;
245	/** Head number */
246	uint8_t head;
247} __attribute__ (( packed ));
248
249/** A C/H/S address within a partition table entry */
250struct partition_chs {
251	/** Head number */
252	uint8_t head;
253	/** Sector number, plus high 2 bits of cylinder number */
254	uint8_t cyl_sector;
255	/** Low 8 bits of cylinder number */
256	uint8_t cyl;
257} __attribute__ (( packed ));
258
259#define PART_HEAD(chs) ( (chs).head )
260#define PART_SECTOR(chs) ( (chs).cyl_sector & 0x3f )
261#define PART_CYLINDER(chs) ( (chs).cyl | ( ( (chs).cyl_sector & 0xc0 ) << 2 ) )
262
263/** A partition table entry within the MBR */
264struct partition_table_entry {
265	/** Bootable flag */
266	uint8_t bootable;
267	/** C/H/S start address */
268	struct partition_chs chs_start;
269	/** System indicator (partition type) */
270	uint8_t type;
271	/** C/H/S end address */
272	struct partition_chs chs_end;
273	/** Linear start address */
274	uint32_t start;
275	/** Linear length */
276	uint32_t length;
277} __attribute__ (( packed ));
278
279/** A Master Boot Record */
280struct master_boot_record {
281	uint8_t pad[446];
282	/** Partition table */
283	struct partition_table_entry partitions[4];
284	/** 0x55aa MBR signature */
285	uint16_t signature;
286} __attribute__ (( packed ));
287
288extern void register_int13_drive ( struct int13_drive *drive );
289extern void unregister_int13_drive ( struct int13_drive *drive );
290extern int int13_boot ( unsigned int drive );
291
292#endif /* INT13_H */
293