iPXE
int13.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <stdint.h>
27#include <stdlib.h>
28#include <string.h>
29#include <limits.h>
30#include <byteswap.h>
31#include <errno.h>
32#include <assert.h>
33#include <ipxe/blockdev.h>
34#include <ipxe/acpi.h>
35#include <ipxe/sanboot.h>
36#include <ipxe/device.h>
37#include <ipxe/pci.h>
38#include <ipxe/eltorito.h>
39#include <ipxe/memmap.h>
40#include <realmode.h>
41#include <bios.h>
42#include <biosint.h>
43#include <bootsector.h>
44#include <int13.h>
45
46/** @file
47 *
48 * INT 13 emulation
49 *
50 * This module provides a mechanism for exporting block devices via
51 * the BIOS INT 13 disk interrupt interface.
52 *
53 */
54
55/** INT 13 SAN device private data */
56struct int13_data {
57 /** BIOS natural drive number (0x00-0xff)
58 *
59 * This is the drive number that would have been assigned by
60 * 'naturally' appending the drive to the end of the BIOS
61 * drive list.
62 *
63 * If the emulated drive replaces a preexisting drive, this is
64 * the drive number that the preexisting drive gets remapped
65 * to.
66 */
67 unsigned int natural_drive;
68
69 /** Number of cylinders
70 *
71 * The cylinder number field in an INT 13 call is ten bits
72 * wide, giving a maximum of 1024 cylinders. Conventionally,
73 * when the 7.8GB limit of a CHS address is exceeded, it is
74 * the number of cylinders that is increased beyond the
75 * addressable limit.
76 */
77 unsigned int cylinders;
78 /** Number of heads
79 *
80 * The head number field in an INT 13 call is eight bits wide,
81 * giving a maximum of 256 heads. However, apparently all
82 * versions of MS-DOS up to and including Win95 fail with 256
83 * heads, so the maximum encountered in practice is 255.
84 */
85 unsigned int heads;
86 /** Number of sectors per track
87 *
88 * The sector number field in an INT 13 call is six bits wide,
89 * giving a maximum of 63 sectors, since sector numbering
90 * (unlike head and cylinder numbering) starts at 1, not 0.
91 */
92 unsigned int sectors_per_track;
93
94 /** Address of El Torito boot catalog (if any) */
95 unsigned int boot_catalog;
96 /** Status of last operation */
98};
99
100/** Vector for chaining to other INT 13 handlers */
101static struct segoff __text16 ( int13_vector );
102#define int13_vector __use_text16 ( int13_vector )
103
104/** Assembly wrapper */
105extern void int13_wrapper ( void );
106
107/** Dummy floppy disk parameter table */
109 /* 512 bytes per sector */
110 .bytes_per_sector = 0x02,
111 /* Highest sectors per track that we ever return */
112 .sectors_per_track = 48,
113};
114#define int13_fdd_params __use_data16 ( int13_fdd_params )
115
116/**
117 * Equipment word
118 *
119 * This is a cached copy of the BIOS Data Area equipment word at
120 * 40:10.
121 */
123
124/**
125 * Number of BIOS floppy disk drives
126 *
127 * This is derived from the equipment word. It is held in .text16 to
128 * allow for easy access by the INT 13,08 wrapper.
129 */
131#define num_fdds __use_text16 ( num_fdds )
132
133/**
134 * Number of BIOS hard disk drives
135 *
136 * This is a cached copy of the BIOS Data Area number of hard disk
137 * drives at 40:75. It is held in .text16 to allow for easy access by
138 * the INT 13,08 wrapper.
139 */
141#define num_drives __use_text16 ( num_drives )
142
143/**
144 * Calculate SAN device capacity (limited to 32 bits)
145 *
146 * @v sandev SAN device
147 * @ret blocks Number of blocks
148 */
149static inline uint32_t int13_capacity32 ( struct san_device *sandev ) {
150 uint64_t capacity = sandev_capacity ( sandev );
151 return ( ( capacity <= 0xffffffffUL ) ? capacity : 0xffffffff );
152}
153
154/**
155 * Test if SAN device is a floppy disk drive
156 *
157 * @v sandev SAN device
158 * @ret is_fdd SAN device is a floppy disk drive
159 */
160static inline int int13_is_fdd ( struct san_device *sandev ) {
161 return ( ! ( sandev->drive & 0x80 ) );
162}
163
164/**
165 * Parse El Torito parameters
166 *
167 * @v sandev SAN device
168 * @v scratch Scratch area for single-sector reads
169 * @ret rc Return status code
170 *
171 * Reads and parses El Torito parameters, if present.
172 */
173static int int13_parse_eltorito ( struct san_device *sandev, void *scratch ) {
174 struct int13_data *int13 = sandev->priv;
175 static const struct eltorito_descriptor_fixed boot_check = {
176 .type = ISO9660_TYPE_BOOT,
177 .id = ISO9660_ID,
178 .version = 1,
179 .system_id = "EL TORITO SPECIFICATION",
180 };
181 struct eltorito_descriptor *boot = scratch;
182 int rc;
183
184 /* Read boot record volume descriptor */
185 if ( ( rc = sandev_read ( sandev, ELTORITO_LBA, 1, boot ) ) != 0 ) {
186 DBGC ( sandev->drive, "INT13 drive %02x could not read El "
187 "Torito boot record volume descriptor: %s\n",
188 sandev->drive, strerror ( rc ) );
189 return rc;
190 }
191
192 /* Check for an El Torito boot catalog */
193 if ( memcmp ( boot, &boot_check, sizeof ( boot_check ) ) == 0 ) {
194 int13->boot_catalog = boot->sector;
195 DBGC ( sandev->drive, "INT13 drive %02x has an El Torito boot "
196 "catalog at LBA %08x\n", sandev->drive,
197 int13->boot_catalog );
198 } else {
199 DBGC ( sandev->drive, "INT13 drive %02x has no El Torito boot "
200 "catalog\n", sandev->drive );
201 }
202
203 return 0;
204}
205
206/**
207 * Guess INT 13 hard disk drive geometry
208 *
209 * @v sandev SAN device
210 * @v scratch Scratch area for single-sector reads
211 * @ret heads Guessed number of heads
212 * @ret sectors Guessed number of sectors per track
213 * @ret rc Return status code
214 *
215 * Guesses the drive geometry by inspecting the partition table.
216 */
217static int int13_guess_geometry_hdd ( struct san_device *sandev, void *scratch,
218 unsigned int *heads,
219 unsigned int *sectors ) {
220 struct master_boot_record *mbr = scratch;
221 struct partition_table_entry *partition;
222 unsigned int i;
223 unsigned int start_cylinder;
224 unsigned int start_head;
225 unsigned int start_sector;
226 unsigned int end_head;
227 unsigned int end_sector;
228 int rc;
229
230 /* Read partition table */
231 if ( ( rc = sandev_read ( sandev, 0, 1, mbr ) ) != 0 ) {
232 DBGC ( sandev->drive, "INT13 drive %02x could not read "
233 "partition table to guess geometry: %s\n",
234 sandev->drive, strerror ( rc ) );
235 return rc;
236 }
237 DBGC2 ( sandev->drive, "INT13 drive %02x has MBR:\n", sandev->drive );
238 DBGC2_HDA ( sandev->drive, 0, mbr, sizeof ( *mbr ) );
239 DBGC ( sandev->drive, "INT13 drive %02x has signature %08x\n",
240 sandev->drive, mbr->signature );
241
242 /* Scan through partition table and modify guesses for
243 * heads and sectors_per_track if we find any used
244 * partitions.
245 */
246 *heads = 0;
247 *sectors = 0;
248 for ( i = 0 ; i < 4 ; i++ ) {
249
250 /* Skip empty partitions */
251 partition = &mbr->partitions[i];
252 if ( ! partition->type )
253 continue;
254
255 /* If partition starts on cylinder 0 then we can
256 * unambiguously determine the number of sectors.
257 */
258 start_cylinder = PART_CYLINDER ( partition->chs_start );
259 start_head = PART_HEAD ( partition->chs_start );
260 start_sector = PART_SECTOR ( partition->chs_start );
261 if ( ( start_cylinder == 0 ) && ( start_head != 0 ) ) {
262 *sectors = ( ( partition->start + 1 - start_sector ) /
263 start_head );
264 DBGC ( sandev->drive, "INT13 drive %02x guessing "
265 "C/H/S xx/xx/%d based on partition %d\n",
266 sandev->drive, *sectors, ( i + 1 ) );
267 }
268
269 /* If partition ends on a higher head or sector number
270 * than our current guess, then increase the guess.
271 */
272 end_head = PART_HEAD ( partition->chs_end );
273 end_sector = PART_SECTOR ( partition->chs_end );
274 if ( ( end_head + 1 ) > *heads ) {
275 *heads = ( end_head + 1 );
276 DBGC ( sandev->drive, "INT13 drive %02x guessing "
277 "C/H/S xx/%d/xx based on partition %d\n",
278 sandev->drive, *heads, ( i + 1 ) );
279 }
280 if ( end_sector > *sectors ) {
281 *sectors = end_sector;
282 DBGC ( sandev->drive, "INT13 drive %02x guessing "
283 "C/H/S xx/xx/%d based on partition %d\n",
284 sandev->drive, *sectors, ( i + 1 ) );
285 }
286 }
287
288 /* Default guess is xx/255/63 */
289 if ( ! *heads )
290 *heads = 255;
291 if ( ! *sectors )
292 *sectors = 63;
293
294 return 0;
295}
296
297/** Recognised floppy disk geometries */
299 INT13_FDD_GEOMETRY ( 40, 1, 8 ),
300 INT13_FDD_GEOMETRY ( 40, 1, 9 ),
301 INT13_FDD_GEOMETRY ( 40, 2, 8 ),
302 INT13_FDD_GEOMETRY ( 40, 1, 9 ),
303 INT13_FDD_GEOMETRY ( 80, 2, 8 ),
304 INT13_FDD_GEOMETRY ( 80, 2, 9 ),
305 INT13_FDD_GEOMETRY ( 80, 2, 15 ),
306 INT13_FDD_GEOMETRY ( 80, 2, 18 ),
307 INT13_FDD_GEOMETRY ( 80, 2, 20 ),
308 INT13_FDD_GEOMETRY ( 80, 2, 21 ),
309 INT13_FDD_GEOMETRY ( 82, 2, 21 ),
310 INT13_FDD_GEOMETRY ( 83, 2, 21 ),
311 INT13_FDD_GEOMETRY ( 80, 2, 22 ),
312 INT13_FDD_GEOMETRY ( 80, 2, 23 ),
313 INT13_FDD_GEOMETRY ( 80, 2, 24 ),
314 INT13_FDD_GEOMETRY ( 80, 2, 36 ),
315 INT13_FDD_GEOMETRY ( 80, 2, 39 ),
316 INT13_FDD_GEOMETRY ( 80, 2, 40 ),
317 INT13_FDD_GEOMETRY ( 80, 2, 44 ),
318 INT13_FDD_GEOMETRY ( 80, 2, 48 ),
319};
320
321/**
322 * Guess INT 13 floppy disk drive geometry
323 *
324 * @v sandev SAN device
325 * @ret heads Guessed number of heads
326 * @ret sectors Guessed number of sectors per track
327 * @ret rc Return status code
328 *
329 * Guesses the drive geometry by inspecting the disk size.
330 */
331static int int13_guess_geometry_fdd ( struct san_device *sandev,
332 unsigned int *heads,
333 unsigned int *sectors ) {
334 unsigned int blocks = sandev_capacity ( sandev );
335 const struct int13_fdd_geometry *geometry;
336 unsigned int cylinders;
337 unsigned int i;
338
339 /* Look for a match against a known geometry */
340 for ( i = 0 ; i < ( sizeof ( int13_fdd_geometries ) /
341 sizeof ( int13_fdd_geometries[0] ) ) ; i++ ) {
342 geometry = &int13_fdd_geometries[i];
343 cylinders = INT13_FDD_CYLINDERS ( geometry );
344 *heads = INT13_FDD_HEADS ( geometry );
345 *sectors = INT13_FDD_SECTORS ( geometry );
346 if ( ( cylinders * (*heads) * (*sectors) ) == blocks ) {
347 DBGC ( sandev->drive, "INT13 drive %02x guessing "
348 "C/H/S %d/%d/%d based on size %dK\n",
349 sandev->drive, cylinders, *heads, *sectors,
350 ( blocks / 2 ) );
351 return 0;
352 }
353 }
354
355 /* Otherwise, assume a partial disk image in the most common
356 * format (1440K, 80/2/18).
357 */
358 *heads = 2;
359 *sectors = 18;
360 DBGC ( sandev->drive, "INT13 drive %02x guessing C/H/S xx/%d/%d "
361 "based on size %dK\n", sandev->drive, *heads, *sectors,
362 ( blocks / 2 ) );
363 return 0;
364}
365
366/**
367 * Guess INT 13 drive geometry
368 *
369 * @v sandev SAN device
370 * @v scratch Scratch area for single-sector reads
371 * @ret rc Return status code
372 */
373static int int13_guess_geometry ( struct san_device *sandev, void *scratch ) {
374 struct int13_data *int13 = sandev->priv;
375 unsigned int guessed_heads;
376 unsigned int guessed_sectors;
377 unsigned int blocks;
378 unsigned int blocks_per_cyl;
379 int rc;
380
381 /* Guess geometry according to drive type */
382 if ( int13_is_fdd ( sandev ) ) {
383 if ( ( rc = int13_guess_geometry_fdd ( sandev, &guessed_heads,
384 &guessed_sectors )) != 0)
385 return rc;
386 } else {
387 if ( ( rc = int13_guess_geometry_hdd ( sandev, scratch,
388 &guessed_heads,
389 &guessed_sectors )) != 0)
390 return rc;
391 }
392
393 /* Apply guesses if no geometry already specified */
394 if ( ! int13->heads )
395 int13->heads = guessed_heads;
396 if ( ! int13->sectors_per_track )
397 int13->sectors_per_track = guessed_sectors;
398 if ( ! int13->cylinders ) {
399 /* Avoid attempting a 64-bit divide on a 32-bit system */
400 blocks = int13_capacity32 ( sandev );
401 blocks_per_cyl = ( int13->heads * int13->sectors_per_track );
402 assert ( blocks_per_cyl != 0 );
403 int13->cylinders = ( blocks / blocks_per_cyl );
404 if ( int13->cylinders > 1024 )
405 int13->cylinders = 1024;
406 }
407
408 return 0;
409}
410
411/**
412 * Update BIOS drive count
413 */
414static void int13_sync_num_drives ( void ) {
415 struct san_device *sandev;
416 struct int13_data *int13;
417 uint8_t *counter;
418 uint8_t max_drive;
419 uint8_t required;
420
421 /* Get current drive counts */
424 num_fdds = ( ( equipment_word & 0x0001 ) ?
425 ( ( ( equipment_word >> 6 ) & 0x3 ) + 1 ) : 0 );
426
427 /* Ensure count is large enough to cover all of our SAN devices */
428 for_each_sandev ( sandev ) {
429 int13 = sandev->priv;
430 counter = ( int13_is_fdd ( sandev ) ? &num_fdds : &num_drives );
431 max_drive = sandev->drive;
432 if ( max_drive < int13->natural_drive )
433 max_drive = int13->natural_drive;
434 required = ( ( max_drive & 0x7f ) + 1 );
435 if ( *counter < required ) {
436 *counter = required;
437 DBGC ( sandev->drive, "INT13 drive %02x added to "
438 "drive count: %d HDDs, %d FDDs\n",
439 sandev->drive, num_drives, num_fdds );
440 }
441 }
442
443 /* Update current drive count */
444 equipment_word &= ~( ( 0x3 << 6 ) | 0x0001 );
445 if ( num_fdds ) {
446 equipment_word |= ( 0x0001 |
447 ( ( ( num_fdds - 1 ) & 0x3 ) << 6 ) );
448 }
451}
452
453/**
454 * Check number of drives
455 */
456static void int13_check_num_drives ( void ) {
457 uint16_t check_equipment_word;
458 uint8_t check_num_drives;
459
460 get_real ( check_equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
461 get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
462 if ( ( check_equipment_word != equipment_word ) ||
463 ( check_num_drives != num_drives ) ) {
465 }
466}
467
468/**
469 * INT 13, 00 - Reset disk system
470 *
471 * @v sandev SAN device
472 * @ret status Status code
473 */
474static int int13_reset ( struct san_device *sandev,
475 struct i386_all_regs *ix86 __unused ) {
476 int rc;
477
478 DBGC2 ( sandev->drive, "Reset drive\n" );
479
480 /* Reset SAN device */
481 if ( ( rc = sandev_reset ( sandev ) ) != 0 )
483
484 return 0;
485}
486
487/**
488 * INT 13, 01 - Get status of last operation
489 *
490 * @v sandev SAN device
491 * @ret status Status code
492 */
493static int int13_get_last_status ( struct san_device *sandev,
494 struct i386_all_regs *ix86 __unused ) {
495 struct int13_data *int13 = sandev->priv;
496
497 DBGC2 ( sandev->drive, "Get status of last operation\n" );
498 return int13->last_status;
499}
500
501/**
502 * Read / write sectors
503 *
504 * @v sandev SAN device
505 * @v al Number of sectors to read or write (must be nonzero)
506 * @v ch Low bits of cylinder number
507 * @v cl (bits 7:6) High bits of cylinder number
508 * @v cl (bits 5:0) Sector number
509 * @v dh Head number
510 * @v es:bx Data buffer
511 * @v sandev_rw SAN device read/write method
512 * @ret status Status code
513 * @ret al Number of sectors read or written
514 */
515static int int13_rw_sectors ( struct san_device *sandev,
516 struct i386_all_regs *ix86,
517 int ( * sandev_rw ) ( struct san_device *sandev,
519 unsigned int count,
520 void *buffer ) ) {
521 struct int13_data *int13 = sandev->priv;
522 unsigned int cylinder, head, sector;
523 unsigned long lba;
524 unsigned int count;
525 void *buffer;
526 int rc;
527
528 /* Validate blocksize */
529 if ( sandev_blksize ( sandev ) != INT13_BLKSIZE ) {
530 DBGC ( sandev->drive, "\nINT 13 drive %02x invalid blocksize "
531 "(%zd) for non-extended read/write\n",
532 sandev->drive, sandev_blksize ( sandev ) );
533 return -INT13_STATUS_INVALID;
534 }
535
536 /* Calculate parameters */
537 cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
538 head = ix86->regs.dh;
539 sector = ( ix86->regs.cl & 0x3f );
540 if ( ( cylinder >= int13->cylinders ) ||
541 ( head >= int13->heads ) ||
542 ( sector < 1 ) || ( sector > int13->sectors_per_track ) ) {
543 DBGC ( sandev->drive, "C/H/S %d/%d/%d out of range for "
544 "geometry %d/%d/%d\n", cylinder, head, sector,
545 int13->cylinders, int13->heads,
546 int13->sectors_per_track );
547 return -INT13_STATUS_INVALID;
548 }
549 lba = ( ( ( ( cylinder * int13->heads ) + head )
550 * int13->sectors_per_track ) + sector - 1 );
551 count = ix86->regs.al;
552 buffer = real_to_virt ( ix86->segs.es, ix86->regs.bx );
553
554 DBGC2 ( sandev->drive, "C/H/S %d/%d/%d = LBA %08lx <-> %04x:%04x "
555 "(count %d)\n", cylinder, head, sector, lba, ix86->segs.es,
556 ix86->regs.bx, count );
557
558 /* Read from / write to block device */
559 if ( ( rc = sandev_rw ( sandev, lba, count, buffer ) ) != 0 ){
560 DBGC ( sandev->drive, "INT13 drive %02x I/O failed: %s\n",
561 sandev->drive, strerror ( rc ) );
563 }
564
565 return 0;
566}
567
568/**
569 * INT 13, 02 - Read sectors
570 *
571 * @v sandev SAN device
572 * @v al Number of sectors to read (must be nonzero)
573 * @v ch Low bits of cylinder number
574 * @v cl (bits 7:6) High bits of cylinder number
575 * @v cl (bits 5:0) Sector number
576 * @v dh Head number
577 * @v es:bx Data buffer
578 * @ret status Status code
579 * @ret al Number of sectors read
580 */
581static int int13_read_sectors ( struct san_device *sandev,
582 struct i386_all_regs *ix86 ) {
583
584 DBGC2 ( sandev->drive, "Read: " );
585 return int13_rw_sectors ( sandev, ix86, sandev_read );
586}
587
588/**
589 * INT 13, 03 - Write sectors
590 *
591 * @v sandev SAN device
592 * @v al Number of sectors to write (must be nonzero)
593 * @v ch Low bits of cylinder number
594 * @v cl (bits 7:6) High bits of cylinder number
595 * @v cl (bits 5:0) Sector number
596 * @v dh Head number
597 * @v es:bx Data buffer
598 * @ret status Status code
599 * @ret al Number of sectors written
600 */
601static int int13_write_sectors ( struct san_device *sandev,
602 struct i386_all_regs *ix86 ) {
603
604 DBGC2 ( sandev->drive, "Write: " );
605 return int13_rw_sectors ( sandev, ix86, sandev_write );
606}
607
608/**
609 * INT 13, 08 - Get drive parameters
610 *
611 * @v sandev SAN device
612 * @ret status Status code
613 * @ret ch Low bits of maximum cylinder number
614 * @ret cl (bits 7:6) High bits of maximum cylinder number
615 * @ret cl (bits 5:0) Maximum sector number
616 * @ret dh Maximum head number
617 * @ret dl Number of drives
618 */
619static int int13_get_parameters ( struct san_device *sandev,
620 struct i386_all_regs *ix86 ) {
621 struct int13_data *int13 = sandev->priv;
622 unsigned int max_cylinder = int13->cylinders - 1;
623 unsigned int max_head = int13->heads - 1;
624 unsigned int max_sector = int13->sectors_per_track; /* sic */
625
626 DBGC2 ( sandev->drive, "Get drive parameters\n" );
627
628 /* Validate blocksize */
629 if ( sandev_blksize ( sandev ) != INT13_BLKSIZE ) {
630 DBGC ( sandev->drive, "\nINT 13 drive %02x invalid blocksize "
631 "(%zd) for non-extended parameters\n",
632 sandev->drive, sandev_blksize ( sandev ) );
633 return -INT13_STATUS_INVALID;
634 }
635
636 /* Common parameters */
637 ix86->regs.ch = ( max_cylinder & 0xff );
638 ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
639 ix86->regs.dh = max_head;
640 ix86->regs.dl = ( int13_is_fdd ( sandev ) ? num_fdds : num_drives );
641
642 /* Floppy-specific parameters */
643 if ( int13_is_fdd ( sandev ) ) {
645 ix86->segs.es = rm_ds;
647 }
648
649 return 0;
650}
651
652/**
653 * INT 13, 15 - Get disk type
654 *
655 * @v sandev SAN device
656 * @ret ah Type code
657 * @ret cx:dx Sector count
658 * @ret status Status code / disk type
659 */
660static int int13_get_disk_type ( struct san_device *sandev,
661 struct i386_all_regs *ix86 ) {
662 uint32_t blocks;
663
664 DBGC2 ( sandev->drive, "Get disk type\n" );
665
666 if ( int13_is_fdd ( sandev ) ) {
667 return INT13_DISK_TYPE_FDD;
668 } else {
669 blocks = int13_capacity32 ( sandev );
670 ix86->regs.cx = ( blocks >> 16 );
671 ix86->regs.dx = ( blocks & 0xffff );
672 return INT13_DISK_TYPE_HDD;
673 }
674}
675
676/**
677 * INT 13, 41 - Extensions installation check
678 *
679 * @v sandev SAN device
680 * @v bx 0x55aa
681 * @ret bx 0xaa55
682 * @ret cx Extensions API support bitmap
683 * @ret status Status code / API version
684 */
685static int int13_extension_check ( struct san_device *sandev,
686 struct i386_all_regs *ix86 ) {
687
688 if ( ( ix86->regs.bx == 0x55aa ) && ! int13_is_fdd ( sandev ) ) {
689 DBGC2 ( sandev->drive, "INT13 extensions check\n" );
690 ix86->regs.bx = 0xaa55;
691 ix86->regs.cx = ( INT13_EXTENSION_LINEAR |
695 } else {
696 return -INT13_STATUS_INVALID;
697 }
698}
699
700/**
701 * Extended read / write
702 *
703 * @v sandev SAN device
704 * @v ds:si Disk address packet
705 * @v sandev_rw SAN device read/write method
706 * @ret status Status code
707 */
708static int int13_extended_rw ( struct san_device *sandev,
709 struct i386_all_regs *ix86,
710 int ( * sandev_rw ) ( struct san_device *sandev,
712 unsigned int count,
713 void *buffer ) ) {
717 unsigned long count;
718 void *buffer;
719 int rc;
720
721 /* Extended reads are not allowed on floppy drives.
722 * ELTORITO.SYS seems to assume that we are really a CD-ROM if
723 * we support extended reads for a floppy drive.
724 */
725 if ( int13_is_fdd ( sandev ) )
726 return -INT13_STATUS_INVALID;
727
728 /* Get buffer size */
729 get_real ( bufsize, ix86->segs.ds,
730 ( ix86->regs.si + offsetof ( typeof ( addr ), bufsize ) ) );
731 if ( bufsize < offsetof ( typeof ( addr ), buffer_phys ) ) {
732 DBGC2 ( sandev->drive, "<invalid buffer size %#02x\n>\n",
733 bufsize );
734 return -INT13_STATUS_INVALID;
735 }
736
737 /* Read parameters from disk address structure */
738 memset ( &addr, 0, sizeof ( addr ) );
739 copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, bufsize );
740 lba = addr.lba;
741 DBGC2 ( sandev->drive, "LBA %08llx <-> ",
742 ( ( unsigned long long ) lba ) );
743 if ( ( addr.count == 0xff ) ||
744 ( ( addr.buffer.segment == 0xffff ) &&
745 ( addr.buffer.offset == 0xffff ) ) ) {
746 buffer = phys_to_virt ( addr.buffer_phys );
747 DBGC2 ( sandev->drive, "%08llx",
748 ( ( unsigned long long ) addr.buffer_phys ) );
749 } else {
750 buffer = real_to_virt ( addr.buffer.segment,
751 addr.buffer.offset );
752 DBGC2 ( sandev->drive, "%04x:%04x", addr.buffer.segment,
753 addr.buffer.offset );
754 }
755 if ( addr.count <= 0x7f ) {
756 count = addr.count;
757 } else if ( addr.count == 0xff ) {
758 count = addr.long_count;
759 } else {
760 DBGC2 ( sandev->drive, " <invalid count %#02x>\n", addr.count );
761 return -INT13_STATUS_INVALID;
762 }
763 DBGC2 ( sandev->drive, " (count %ld)\n", count );
764
765 /* Read from / write to block device */
766 if ( ( rc = sandev_rw ( sandev, lba, count, buffer ) ) != 0 ) {
767 DBGC ( sandev->drive, "INT13 drive %02x extended I/O failed: "
768 "%s\n", sandev->drive, strerror ( rc ) );
769 /* Record that no blocks were transferred successfully */
770 addr.count = 0;
771 put_real ( addr.count, ix86->segs.ds,
772 ( ix86->regs.si +
773 offsetof ( typeof ( addr ), count ) ) );
775 }
776
777 return 0;
778}
779
780/**
781 * INT 13, 42 - Extended read
782 *
783 * @v sandev SAN device
784 * @v ds:si Disk address packet
785 * @ret status Status code
786 */
787static int int13_extended_read ( struct san_device *sandev,
788 struct i386_all_regs *ix86 ) {
789
790 DBGC2 ( sandev->drive, "Extended read: " );
791 return int13_extended_rw ( sandev, ix86, sandev_read );
792}
793
794/**
795 * INT 13, 43 - Extended write
796 *
797 * @v sandev SAN device
798 * @v ds:si Disk address packet
799 * @ret status Status code
800 */
801static int int13_extended_write ( struct san_device *sandev,
802 struct i386_all_regs *ix86 ) {
803
804 DBGC2 ( sandev->drive, "Extended write: " );
805 return int13_extended_rw ( sandev, ix86, sandev_write );
806}
807
808/**
809 * INT 13, 44 - Verify sectors
810 *
811 * @v sandev SAN device
812 * @v ds:si Disk address packet
813 * @ret status Status code
814 */
815static int int13_extended_verify ( struct san_device *sandev,
816 struct i386_all_regs *ix86 ) {
819 unsigned long count;
820
821 /* Read parameters from disk address structure */
822 if ( DBG_EXTRA ) {
823 copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
824 sizeof ( addr ));
825 lba = addr.lba;
826 count = addr.count;
827 DBGC2 ( sandev->drive, "Verify: LBA %08llx (count %ld)\n",
828 ( ( unsigned long long ) lba ), count );
829 }
830
831 /* We have no mechanism for verifying sectors */
832 return -INT13_STATUS_INVALID;
833}
834
835/**
836 * INT 13, 44 - Extended seek
837 *
838 * @v sandev SAN device
839 * @v ds:si Disk address packet
840 * @ret status Status code
841 */
842static int int13_extended_seek ( struct san_device *sandev,
843 struct i386_all_regs *ix86 ) {
846 unsigned long count;
847
848 /* Read parameters from disk address structure */
849 if ( DBG_EXTRA ) {
850 copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
851 sizeof ( addr ));
852 lba = addr.lba;
853 count = addr.count;
854 DBGC2 ( sandev->drive, "Seek: LBA %08llx (count %ld)\n",
855 ( ( unsigned long long ) lba ), count );
856 }
857
858 /* Ignore and return success */
859 return 0;
860}
861
862/**
863 * Build device path information
864 *
865 * @v sandev SAN device
866 * @v dpi Device path information
867 * @ret rc Return status code
868 */
869static int int13_device_path_info ( struct san_device *sandev,
871 struct san_path *sanpath;
872 struct device *device;
873 struct device_description *desc;
874 unsigned int i;
875 uint8_t sum = 0;
876 int rc;
877
878 /* Reopen block device if necessary */
879 if ( sandev_needs_reopen ( sandev ) &&
880 ( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
881 return rc;
882 sanpath = sandev->active;
883 assert ( sanpath != NULL );
884
885 /* Get underlying hardware device */
886 device = identify_device ( &sanpath->block );
887 if ( ! device ) {
888 DBGC ( sandev->drive, "INT13 drive %02x cannot identify "
889 "hardware device\n", sandev->drive );
890 return -ENODEV;
891 }
892
893 /* Fill in bus type and interface path */
894 desc = &device->desc;
895 switch ( desc->bus_type ) {
896 case BUS_TYPE_PCI:
897 dpi->host_bus_type.type = EDD_BUS_TYPE_PCI;
898 dpi->interface_path.pci.bus = PCI_BUS ( desc->location );
899 dpi->interface_path.pci.slot = PCI_SLOT ( desc->location );
900 dpi->interface_path.pci.function = PCI_FUNC ( desc->location );
901 dpi->interface_path.pci.channel = 0xff; /* unused */
902 break;
903 default:
904 DBGC ( sandev->drive, "INT13 drive %02x unrecognised bus "
905 "type %d\n", sandev->drive, desc->bus_type );
906 return -ENOTSUP;
907 }
908
909 /* Get EDD block device description */
910 if ( ( rc = edd_describe ( &sanpath->block, &dpi->interface_type,
911 &dpi->device_path ) ) != 0 ) {
912 DBGC ( sandev->drive, "INT13 drive %02x cannot identify "
913 "block device: %s\n", sandev->drive, strerror ( rc ) );
914 return rc;
915 }
916
917 /* Fill in common fields and fix checksum */
919 dpi->len = sizeof ( *dpi );
920 for ( i = 0 ; i < sizeof ( *dpi ) ; i++ )
921 sum += *( ( ( uint8_t * ) dpi ) + i );
922 dpi->checksum -= sum;
923
924 return 0;
925}
926
927/**
928 * INT 13, 48 - Get extended parameters
929 *
930 * @v sandev SAN device
931 * @v ds:si Drive parameter table
932 * @ret status Status code
933 */
934static int int13_get_extended_parameters ( struct san_device *sandev,
935 struct i386_all_regs *ix86 ) {
936 struct int13_data *int13 = sandev->priv;
937 struct int13_disk_parameters params;
938 struct segoff address;
939 size_t len = sizeof ( params );
941 int rc;
942
943 /* Get buffer size */
944 get_real ( bufsize, ix86->segs.ds,
945 ( ix86->regs.si + offsetof ( typeof ( params ), bufsize )));
946
947 DBGC2 ( sandev->drive, "Get extended drive parameters to "
948 "%04x:%04x+%02x\n", ix86->segs.ds, ix86->regs.si, bufsize );
949
950 /* Build drive parameters */
951 memset ( &params, 0, sizeof ( params ) );
953 if ( ( int13->cylinders < 1024 ) &&
954 ( sandev_capacity ( sandev ) <= INT13_MAX_CHS_SECTORS ) ) {
955 params.flags |= INT13_FL_CHS_VALID;
956 }
957 params.cylinders = int13->cylinders;
958 params.heads = int13->heads;
959 params.sectors_per_track = int13->sectors_per_track;
960 params.sectors = sandev_capacity ( sandev );
961 params.sector_size = sandev_blksize ( sandev );
962 memset ( &params.dpte, 0xff, sizeof ( params.dpte ) );
963 if ( ( rc = int13_device_path_info ( sandev, &params.dpi ) ) != 0 ) {
964 DBGC ( sandev->drive, "INT13 drive %02x could not provide "
965 "device path information: %s\n",
966 sandev->drive, strerror ( rc ) );
967 len = offsetof ( typeof ( params ), dpi );
968 }
969
970 /* Calculate returned "buffer size" (which will be less than
971 * the length actually copied if device path information is
972 * present).
973 */
974 if ( bufsize < offsetof ( typeof ( params ), dpte ) )
975 return -INT13_STATUS_INVALID;
976 if ( bufsize < offsetof ( typeof ( params ), dpi ) ) {
977 params.bufsize = offsetof ( typeof ( params ), dpte );
978 } else {
979 params.bufsize = offsetof ( typeof ( params ), dpi );
980 }
981
982 DBGC ( sandev->drive, "INT 13 drive %02x described using extended "
983 "parameters:\n", sandev->drive );
984 address.segment = ix86->segs.ds;
985 address.offset = ix86->regs.si;
986 DBGC_HDA ( sandev->drive, address, &params, len );
987
988 /* Return drive parameters */
989 if ( len > bufsize )
990 len = bufsize;
991 copy_to_real ( ix86->segs.ds, ix86->regs.si, &params, len );
992
993 return 0;
994}
995
996/**
997 * INT 13, 4b - Get status or terminate CD-ROM emulation
998 *
999 * @v sandev SAN device
1000 * @v ds:si Specification packet
1001 * @ret status Status code
1002 */
1003static int int13_cdrom_status_terminate ( struct san_device *sandev,
1004 struct i386_all_regs *ix86 ) {
1005 struct int13_cdrom_specification specification;
1006
1007 DBGC2 ( sandev->drive, "Get CD-ROM emulation status to %04x:%04x%s\n",
1008 ix86->segs.ds, ix86->regs.si,
1009 ( ix86->regs.al ? "" : " and terminate" ) );
1010
1011 /* Fail if we are not a CD-ROM */
1012 if ( ! sandev->is_cdrom ) {
1013 DBGC ( sandev->drive, "INT13 drive %02x is not a CD-ROM\n",
1014 sandev->drive );
1015 return -INT13_STATUS_INVALID;
1016 }
1017
1018 /* Build specification packet */
1019 memset ( &specification, 0, sizeof ( specification ) );
1020 specification.size = sizeof ( specification );
1021 specification.drive = sandev->drive;
1022
1023 /* Return specification packet */
1024 copy_to_real ( ix86->segs.ds, ix86->regs.si, &specification,
1025 sizeof ( specification ) );
1026
1027 return 0;
1028}
1029
1030
1031/**
1032 * INT 13, 4d - Read CD-ROM boot catalog
1033 *
1034 * @v sandev SAN device
1035 * @v ds:si Command packet
1036 * @ret status Status code
1037 */
1038static int int13_cdrom_read_boot_catalog ( struct san_device *sandev,
1039 struct i386_all_regs *ix86 ) {
1040 struct int13_data *int13 = sandev->priv;
1042 unsigned int start;
1043 int rc;
1044
1045 /* Read parameters from command packet */
1046 copy_from_real ( &command, ix86->segs.ds, ix86->regs.si,
1047 sizeof ( command ) );
1048 DBGC2 ( sandev->drive, "Read CD-ROM boot catalog to %08x\n",
1049 command.buffer );
1050
1051 /* Fail if we have no boot catalog */
1052 if ( ! int13->boot_catalog ) {
1053 DBGC ( sandev->drive, "INT13 drive %02x has no boot catalog\n",
1054 sandev->drive );
1055 return -INT13_STATUS_INVALID;
1056 }
1057 start = ( int13->boot_catalog + command.start );
1058
1059 /* Read from boot catalog */
1060 if ( ( rc = sandev_read ( sandev, start, command.count,
1061 phys_to_virt ( command.buffer ) ) ) != 0 ) {
1062 DBGC ( sandev->drive, "INT13 drive %02x could not read boot "
1063 "catalog: %s\n", sandev->drive, strerror ( rc ) );
1065 }
1066
1067 return 0;
1068}
1069
1070/**
1071 * INT 13 handler
1072 *
1073 */
1074static __asmcall __used void int13 ( struct i386_all_regs *ix86 ) {
1075 int command = ix86->regs.ah;
1076 unsigned int bios_drive = ix86->regs.dl;
1077 struct san_device *sandev;
1078 struct int13_data *int13;
1079 int status;
1080
1081 /* Check BIOS hasn't killed off our drive */
1083
1084 for_each_sandev ( sandev ) {
1085
1086 int13 = sandev->priv;
1087 if ( bios_drive != sandev->drive ) {
1088 /* Remap any accesses to this drive's natural number */
1089 if ( bios_drive == int13->natural_drive ) {
1090 DBGC2 ( sandev->drive, "INT13,%02x (%02x) "
1091 "remapped to (%02x)\n", ix86->regs.ah,
1092 bios_drive, sandev->drive );
1093 ix86->regs.dl = sandev->drive;
1094 return;
1095 } else if ( ( ( bios_drive & 0x7f ) == 0x7f ) &&
1097 && sandev->is_cdrom ) {
1098 /* Catch non-drive-specific CD-ROM calls */
1099 } else {
1100 continue;
1101 }
1102 }
1103
1104 DBGC2 ( sandev->drive, "INT13,%02x (%02x): ",
1105 ix86->regs.ah, bios_drive );
1106
1107 switch ( command ) {
1108 case INT13_RESET:
1109 status = int13_reset ( sandev, ix86 );
1110 break;
1112 status = int13_get_last_status ( sandev, ix86 );
1113 break;
1114 case INT13_READ_SECTORS:
1115 status = int13_read_sectors ( sandev, ix86 );
1116 break;
1118 status = int13_write_sectors ( sandev, ix86 );
1119 break;
1121 status = int13_get_parameters ( sandev, ix86 );
1122 break;
1124 status = int13_get_disk_type ( sandev, ix86 );
1125 break;
1127 status = int13_extension_check ( sandev, ix86 );
1128 break;
1130 status = int13_extended_read ( sandev, ix86 );
1131 break;
1133 status = int13_extended_write ( sandev, ix86 );
1134 break;
1136 status = int13_extended_verify ( sandev, ix86 );
1137 break;
1139 status = int13_extended_seek ( sandev, ix86 );
1140 break;
1142 status = int13_get_extended_parameters ( sandev, ix86 );
1143 break;
1145 status = int13_cdrom_status_terminate ( sandev, ix86 );
1146 break;
1148 status = int13_cdrom_read_boot_catalog ( sandev, ix86 );
1149 break;
1150 default:
1151 DBGC2 ( sandev->drive, "*** Unrecognised INT13 ***\n" );
1153 break;
1154 }
1155
1156 /* Store status for INT 13,01 */
1157 int13->last_status = status;
1158
1159 /* Negative status indicates an error */
1160 if ( status < 0 ) {
1161 status = -status;
1162 DBGC ( sandev->drive, "INT13,%02x (%02x) failed with "
1163 "status %02x\n", ix86->regs.ah, sandev->drive,
1164 status );
1165 } else {
1166 ix86->flags &= ~CF;
1167 }
1168 ix86->regs.ah = status;
1169
1170 /* Set OF to indicate to wrapper not to chain this call */
1171 ix86->flags |= OF;
1172
1173 return;
1174 }
1175}
1176
1177/**
1178 * Hook INT 13 handler
1179 *
1180 */
1181static void int13_hook_vector ( void ) {
1182 /* Assembly wrapper to call int13(). int13() sets OF if we
1183 * should not chain to the previous handler. (The wrapper
1184 * clears CF and OF before calling int13()).
1185 */
1187 TEXT16_CODE ( "\nint13_wrapper:\n\t"
1188 /* Preserve %ax and %dx for future reference */
1189 "pushw %%bp\n\t"
1190 "movw %%sp, %%bp\n\t"
1191 "pushw %%ax\n\t"
1192 "pushw %%dx\n\t"
1193 /* Clear OF, set CF, call int13() */
1194 "orb $0, %%al\n\t"
1195 "stc\n\t"
1196 VIRT_CALL ( int13 )
1197 /* Chain if OF not set */
1198 "jo 1f\n\t"
1199 "pushfw\n\t"
1200 "lcall *%%cs:int13_vector\n\t"
1201 "\n1:\n\t"
1202 /* Overwrite flags for iret */
1203 "pushfw\n\t"
1204 "popw 6(%%bp)\n\t"
1205 /* Fix up %dl:
1206 *
1207 * INT 13,15 : do nothing if hard disk
1208 * INT 13,08 : load with number of drives
1209 * all others: restore original value
1210 */
1211 "cmpb $0x15, -1(%%bp)\n\t"
1212 "jne 2f\n\t"
1213 "testb $0x80, -4(%%bp)\n\t"
1214 "jnz 3f\n\t"
1215 "\n2:\n\t"
1216 "movb -4(%%bp), %%dl\n\t"
1217 "cmpb $0x08, -1(%%bp)\n\t"
1218 "jne 3f\n\t"
1219 "testb $0x80, %%dl\n\t"
1220 "movb %%cs:num_drives, %%dl\n\t"
1221 "jnz 3f\n\t"
1222 "movb %%cs:num_fdds, %%dl\n\t"
1223 /* Return */
1224 "\n3:\n\t"
1225 "movw %%bp, %%sp\n\t"
1226 "popw %%bp\n\t"
1227 "iret\n\t" ) : : );
1228
1230}
1231
1232/**
1233 * Unhook INT 13 handler
1234 */
1235static void int13_unhook_vector ( void ) {
1237 &int13_vector );
1238}
1239
1240/**
1241 * Hook INT 13 SAN device
1242 *
1243 * @v drive Drive number
1244 * @v uris List of URIs
1245 * @v count Number of URIs
1246 * @v flags Flags
1247 * @ret drive Drive number, or negative error
1248 *
1249 * Registers the drive with the INT 13 emulation subsystem, and hooks
1250 * the INT 13 interrupt vector (if not already hooked).
1251 */
1252static int int13_hook ( unsigned int drive, struct uri **uris,
1253 unsigned int count, unsigned int flags ) {
1254 struct san_device *sandev;
1255 struct int13_data *int13;
1256 unsigned int natural_drive;
1257 void *scratch;
1258 int need_hook = ( ! have_sandevs() );
1259 int rc;
1260
1261 /* Calculate natural drive number */
1263 natural_drive = ( ( drive & 0x80 ) ? ( num_drives | 0x80 ) : num_fdds );
1264
1265 /* Use natural drive number if directed to do so */
1266 if ( ( drive & 0x7f ) == 0x7f )
1268
1269 /* Allocate SAN device */
1270 sandev = alloc_sandev ( uris, count, sizeof ( *int13 ) );
1271 if ( ! sandev ) {
1272 rc = -ENOMEM;
1273 goto err_alloc;
1274 }
1275 int13 = sandev->priv;
1276 int13->natural_drive = natural_drive;
1277
1278 /* Register SAN device */
1279 if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
1280 DBGC ( drive, "INT13 drive %02x could not register: %s\n",
1281 drive, strerror ( rc ) );
1282 goto err_register;
1283 }
1284
1285 /* Allocate scratch area */
1286 scratch = malloc ( sandev_blksize ( sandev ) );
1287 if ( ! scratch )
1288 goto err_alloc_scratch;
1289
1290 /* Parse parameters, if present */
1291 if ( sandev->is_cdrom &&
1292 ( ( rc = int13_parse_eltorito ( sandev, scratch ) ) != 0 ) )
1293 goto err_parse_eltorito;
1294
1295 /* Give drive a default geometry, if applicable */
1296 if ( ( sandev_blksize ( sandev ) == INT13_BLKSIZE ) &&
1297 ( ( rc = int13_guess_geometry ( sandev, scratch ) ) != 0 ) )
1298 goto err_guess_geometry;
1299
1300 DBGC ( drive, "INT13 drive %02x (naturally %02x) registered with "
1301 "C/H/S geometry %d/%d/%d\n", drive, int13->natural_drive,
1302 int13->cylinders, int13->heads, int13->sectors_per_track );
1303
1304 /* Hook INT 13 vector if not already hooked */
1305 if ( need_hook ) {
1307 devices_get();
1308 }
1309
1310 /* Update BIOS drive count */
1312
1313 free ( scratch );
1314 return drive;
1315
1316 err_guess_geometry:
1317 err_parse_eltorito:
1318 free ( scratch );
1319 err_alloc_scratch:
1320 unregister_sandev ( sandev );
1321 err_register:
1322 sandev_put ( sandev );
1323 err_alloc:
1324 return rc;
1325}
1326
1327/**
1328 * Unhook INT 13 SAN device
1329 *
1330 * @v drive Drive number
1331 *
1332 * Unregisters the drive from the INT 13 emulation subsystem. If this
1333 * is the last SAN device, the INT 13 vector is unhooked (if
1334 * possible).
1335 */
1336static void int13_unhook ( unsigned int drive ) {
1337 struct san_device *sandev;
1338
1339 /* Find drive */
1340 sandev = sandev_find ( drive );
1341 if ( ! sandev ) {
1342 DBGC ( drive, "INT13 drive %02x is not a SAN drive\n", drive );
1343 return;
1344 }
1345
1346 /* Unregister SAN device */
1347 unregister_sandev ( sandev );
1348
1349 /* Should adjust BIOS drive count, but it's difficult
1350 * to do so reliably.
1351 */
1352
1353 DBGC ( drive, "INT13 drive %02x unregistered\n", drive );
1354
1355 /* Unhook INT 13 vector if no more drives */
1356 if ( ! have_sandevs() ) {
1357 devices_put();
1359 }
1360
1361 /* Drop reference to drive */
1362 sandev_put ( sandev );
1363}
1364
1365/**
1366 * Load and verify master boot record from INT 13 drive
1367 *
1368 * @v drive Drive number
1369 * @v address Boot code address to fill in
1370 * @ret rc Return status code
1371 */
1372static int int13_load_mbr ( unsigned int drive, struct segoff *address ) {
1374 int discard_b, discard_c, discard_d;
1376
1377 /* Use INT 13, 02 to read the MBR */
1378 address->segment = 0;
1379 address->offset = 0x7c00;
1380 __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
1381 "pushl %%ebx\n\t"
1382 "popw %%bx\n\t"
1383 "popw %%es\n\t"
1384 "stc\n\t"
1385 "sti\n\t"
1386 "int $0x13\n\t"
1387 "sti\n\t" /* BIOS bugs */
1388 "jc 1f\n\t"
1389 "xorw %%ax, %%ax\n\t"
1390 "\n1:\n\t"
1391 "popw %%es\n\t" )
1392 : "=a" ( status ), "=b" ( discard_b ),
1393 "=c" ( discard_c ), "=d" ( discard_d )
1394 : "a" ( 0x0201 ), "b" ( *address ),
1395 "c" ( 1 ), "d" ( drive ) );
1396 if ( status ) {
1397 DBGC ( drive, "INT13 drive %02x could not read MBR (status "
1398 "%04x)\n", drive, status );
1399 return -EIO;
1400 }
1401
1402 /* Check magic signature */
1403 get_real ( magic, address->segment,
1404 ( address->offset +
1405 offsetof ( struct master_boot_record, magic ) ) );
1406 if ( magic != INT13_MBR_MAGIC ) {
1407 DBGC ( drive, "INT13 drive %02x does not contain a valid MBR\n",
1408 drive );
1409 return -ENOEXEC;
1410 }
1411
1412 return 0;
1413}
1414
1415/** El Torito boot catalog command packet */
1417 .size = sizeof ( struct int13_cdrom_boot_catalog_command ),
1418 .count = 1,
1419 .buffer = 0x7c00,
1420 .start = 0,
1421};
1422#define eltorito_cmd __use_data16 ( eltorito_cmd )
1423
1424/** El Torito disk address packet */
1426#define eltorito_address __use_data16 ( eltorito_address )
1427
1428/**
1429 * Load and verify El Torito boot record from INT 13 drive
1430 *
1431 * @v drive Drive number
1432 * @v address Boot code address to fill in
1433 * @ret rc Return status code
1434 */
1435static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
1436 struct {
1437 struct eltorito_validation_entry valid;
1438 struct eltorito_boot_entry boot;
1439 } __attribute__ (( packed )) catalog;
1441
1442 /* Use INT 13, 4d to read the boot catalog */
1443 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
1444 "sti\n\t"
1445 "int $0x13\n\t"
1446 "sti\n\t" /* BIOS bugs */
1447 "jc 1f\n\t"
1448 "xorw %%ax, %%ax\n\t"
1449 "\n1:\n\t" )
1450 : "=a" ( status )
1451 : "a" ( 0x4d00 ), "d" ( drive ),
1452 "S" ( __from_data16 ( &eltorito_cmd ) ) );
1453 if ( status ) {
1454 DBGC ( drive, "INT13 drive %02x could not read El Torito boot "
1455 "catalog (status %04x)\n", drive, status );
1456 return -EIO;
1457 }
1458 memcpy ( &catalog, phys_to_virt ( eltorito_cmd.buffer ),
1459 sizeof ( catalog ) );
1460
1461 /* Sanity checks */
1462 if ( catalog.valid.platform_id != ELTORITO_PLATFORM_X86 ) {
1463 DBGC ( drive, "INT13 drive %02x El Torito specifies unknown "
1464 "platform %02x\n", drive, catalog.valid.platform_id );
1465 return -ENOEXEC;
1466 }
1467 if ( catalog.boot.indicator != ELTORITO_BOOTABLE ) {
1468 DBGC ( drive, "INT13 drive %02x El Torito is not bootable\n",
1469 drive );
1470 return -ENOEXEC;
1471 }
1472 if ( catalog.boot.media_type != ELTORITO_NO_EMULATION ) {
1473 DBGC ( drive, "INT13 drive %02x El Torito requires emulation "
1474 "type %02x\n", drive, catalog.boot.media_type );
1475 return -ENOTSUP;
1476 }
1477 DBGC ( drive, "INT13 drive %02x El Torito boot image at LBA %08x "
1478 "(count %d)\n", drive, catalog.boot.start, catalog.boot.length );
1479 address->segment = ( catalog.boot.load_segment ?
1480 catalog.boot.load_segment : 0x7c0 );
1481 address->offset = 0;
1482 DBGC ( drive, "INT13 drive %02x El Torito boot image loads at "
1483 "%04x:%04x\n", drive, address->segment, address->offset );
1484
1485 /* Use INT 13, 42 to read the boot image */
1486 eltorito_address.bufsize =
1488 eltorito_address.count = catalog.boot.length;
1489 eltorito_address.buffer = *address;
1490 eltorito_address.lba = catalog.boot.start;
1491 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
1492 "sti\n\t"
1493 "int $0x13\n\t"
1494 "sti\n\t" /* BIOS bugs */
1495 "jc 1f\n\t"
1496 "xorw %%ax, %%ax\n\t"
1497 "\n1:\n\t" )
1498 : "=a" ( status )
1499 : "a" ( 0x4200 ), "d" ( drive ),
1500 "S" ( __from_data16 ( &eltorito_address ) ) );
1501 if ( status ) {
1502 DBGC ( drive, "INT13 drive %02x could not read El Torito boot "
1503 "image (status %04x)\n", drive, status );
1504 return -EIO;
1505 }
1506
1507 return 0;
1508}
1509
1510/**
1511 * Attempt to boot from an INT 13 drive
1512 *
1513 * @v drive Drive number
1514 * @v config Boot configuration parameters
1515 * @ret rc Return status code
1516 *
1517 * This boots from the specified INT 13 drive by loading the Master
1518 * Boot Record to 0000:7c00 and jumping to it. INT 18 is hooked to
1519 * capture an attempt by the MBR to boot the next device. (This is
1520 * the closest thing to a return path from an MBR).
1521 *
1522 * Note that this function can never return success, by definition.
1523 */
1524static int int13_boot ( unsigned int drive,
1525 struct san_boot_config *config __unused ) {
1526 struct segoff address;
1527 int rc;
1528
1529 /* Look for a usable boot sector */
1530 if ( ( ( rc = int13_load_mbr ( drive, &address ) ) != 0 ) &&
1531 ( ( rc = int13_load_eltorito ( drive, &address ) ) != 0 ) )
1532 return rc;
1533
1534 /* Dump out memory map prior to boot, if memmap debugging is
1535 * enabled. Not required for program flow, but we have so
1536 * many problems that turn out to be memory-map related that
1537 * it's worth doing.
1538 */
1539 memmap_dump_all ( 1 );
1540
1541 /* Jump to boot sector */
1542 if ( ( rc = call_bootsector ( address.segment, address.offset,
1543 drive ) ) != 0 ) {
1544 DBGC ( drive, "INT13 drive %02x boot returned: %s\n",
1545 drive, strerror ( rc ) );
1546 return rc;
1547 }
1548
1549 return -ECANCELED; /* -EIMPOSSIBLE */
1550}
1551
1552/** Maximum size of boot firmware table(s) */
1553#define XBFTAB_SIZE 768
1554
1555/** Alignment of boot firmware table entries */
1556#define XBFTAB_ALIGN 16
1557
1558/** The boot firmware table(s) generated by iPXE */
1560 __attribute__ (( aligned ( XBFTAB_ALIGN ) ));
1561#define xbftab __use_data16 ( xbftab )
1562
1563/** Total used length of boot firmware tables */
1564static size_t xbftab_used;
1565
1566/**
1567 * Install ACPI table
1568 *
1569 * @v acpi ACPI description header
1570 * @ret rc Return status code
1571 */
1572static int int13_install ( struct acpi_header *acpi ) {
1573 struct segoff xbft_address;
1574 struct acpi_header *installed;
1575 size_t len;
1576
1577 /* Check length */
1578 len = acpi->length;
1579 if ( len > ( sizeof ( xbftab ) - xbftab_used ) ) {
1580 DBGC ( acpi, "INT13 out of space for %s table\n",
1581 acpi_name ( acpi->signature ) );
1582 return -ENOSPC;
1583 }
1584
1585 /* Install table */
1586 installed = ( ( ( void * ) xbftab ) + xbftab_used );
1587 memcpy ( installed, acpi, len );
1588 xbft_address.segment = rm_ds;
1589 xbft_address.offset = __from_data16 ( installed );
1590
1591 /* Fill in common parameters */
1592 strncpy ( installed->oem_id, "FENSYS",
1593 sizeof ( installed->oem_id ) );
1594 strncpy ( installed->oem_table_id, "iPXE",
1595 sizeof ( installed->oem_table_id ) );
1596
1597 /* Fix checksum */
1598 acpi_fix_checksum ( installed );
1599
1600 /* Update used length */
1601 xbftab_used = ( ( xbftab_used + len + XBFTAB_ALIGN - 1 ) &
1602 ~( XBFTAB_ALIGN - 1 ) );
1603
1604 DBGC ( acpi, "INT13 installed %s:\n",
1605 acpi_name ( installed->signature ) );
1606 DBGC_HDA ( acpi, xbft_address, installed, len );
1607 return 0;
1608}
1609
1610/**
1611 * Describe SAN devices for SAN-booted operating system
1612 *
1613 * @ret rc Return status code
1614 */
1615static int int13_describe ( void ) {
1616 int rc;
1617
1618 /* Clear tables */
1619 memset ( &xbftab, 0, sizeof ( xbftab ) );
1620 xbftab_used = 0;
1621
1622 /* Install ACPI tables */
1623 if ( ( rc = acpi_install ( int13_install ) ) != 0 ) {
1624 DBG ( "INT13 could not install ACPI tables: %s\n",
1625 strerror ( rc ) );
1626 return rc;
1627 }
1628
1629 return 0;
1630}
1631
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
int acpi_install(int(*install)(struct acpi_header *acpi))
Install ACPI tables.
Definition acpi.c:344
void acpi_fix_checksum(struct acpi_header *acpi)
Fix up ACPI table checksum.
Definition acpi.c:80
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define __asmcall
Declare a function with standard calling conventions.
Definition compiler.h:15
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
unsigned short uint16_t
Definition stdint.h:11
unsigned long intptr_t
Definition stdint.h:21
unsigned int uint32_t
Definition stdint.h:12
unsigned long long uint64_t
Definition stdint.h:13
unsigned char uint8_t
Definition stdint.h:10
long discard_c
Definition bigint.h:33
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define BDA_SEG
Definition bios.h:6
#define BDA_EQUIPMENT_WORD
Definition bios.h:8
#define BDA_NUM_DRIVES
Definition bios.h:19
void hook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Hook INT vector.
Definition biosint.c:25
int unhook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Unhook INT vector.
Definition biosint.c:70
Block devices.
int call_bootsector(unsigned int segment, unsigned int offset, unsigned int drive)
Jump to preloaded bootsector.
Definition bootsector.c:64
x86 bootsector image format
uint16_t magic
Magic signature.
Definition bzimage.h:1
struct device * identify_device(struct interface *intf)
Identify a device behind an interface.
Definition device.c:126
Device model.
#define BUS_TYPE_PCI
PCI bus type.
Definition device.h:44
static void devices_get(void)
Prevent devices from being removed on shutdown.
Definition device.h:165
static void devices_put(void)
Allow devices to be removed on shutdown.
Definition device.h:173
ring len
Length.
Definition dwmac.h:226
uint32_t addr
Buffer address.
Definition dwmac.h:9
int edd_describe(struct interface *intf, struct edd_interface_type *type, union edd_device_path *path)
Describe a disk device using EDD.
Definition edd.c:45
#define EDD_DEVICE_PATH_INFO_KEY
EDD device path information key.
Definition edd.h:185
#define EDD_BUS_TYPE_PCI
EDD PCI bus type.
Definition edd.h:28
static EFI_ACPI_TABLE_PROTOCOL * acpi
ACPI table protocol protocol.
Definition efi_block.c:67
El Torito bootable CD-ROM specification.
uint32_t sector
Boot catalog sector.
Definition eltorito.h:5
@ ELTORITO_PLATFORM_X86
Definition eltorito.h:64
@ ELTORITO_NO_EMULATION
No emulation.
Definition eltorito.h:100
#define ELTORITO_LBA
El Torito Boot Record Volume Descriptor block address.
Definition eltorito.h:39
#define ELTORITO_BOOTABLE
Boot indicator for a bootable ISO image.
Definition eltorito.h:95
uint8_t flags
Flags.
Definition ena.h:7
uint8_t status
Status.
Definition ena.h:5
uint64_t address
Base address.
Definition ena.h:13
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
Error codes.
#define __used
Declare a function as used.
Definition compiler.h:605
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC2(...)
Definition compiler.h:522
#define DBG_EXTRA
Definition compiler.h:319
#define DBGC2_HDA(...)
Definition compiler.h:523
#define DBGC(...)
Definition compiler.h:505
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define DBGC_HDA(...)
Definition compiler.h:506
#define INT13_EXTENSION_64BIT
64-bit extensions are present
Definition int13.h:181
#define INT13_EXTENSION_LINEAR
Extended disk access functions supported.
Definition int13.h:175
#define INT13_EXTENSION_EDD
EDD functions supported.
Definition int13.h:179
uint8_t bufsize
Size of the packet, in bytes.
Definition int13.h:1
uint8_t drive
Drive number.
Definition int13.h:214
uint32_t signature
Disk signature.
Definition int13.h:282
#define INT13_FDD_GEOMETRY(cylinders, heads, sectors)
Define a floppy disk geometry.
Definition int13.h:303
uint64_t sectors
Total number of sectors on drive.
Definition int13.h:122
#define PART_HEAD(chs)
Definition int13.h:257
#define PART_CYLINDER(chs)
Definition int13.h:259
uint32_t cylinders
Number of cylinders.
Definition int13.h:5
uint8_t drive
Drive number.
Definition int13.h:5
#define PART_SECTOR(chs)
Definition int13.h:258
uint32_t start
Linear start address.
Definition int13.h:272
#define INT13_MAX_CHS_SECTORS
Maximum number of sectors for which CHS geometry is allowed to be valid.
Definition int13.h:205
#define INT13_FDD_HEADS(geometry)
Get floppy disk number of heads.
Definition int13.h:313
#define INT13_FDD_CYLINDERS(geometry)
Get floppy disk number of cylinders.
Definition int13.h:310
uint16_t flags
Flags.
Definition int13.h:114
uint32_t start
Starting offset.
Definition netvsc.h:1
uint16_t bufsize
Size of this structure.
Definition int13.h:112
uint16_t sector_size
Bytes per sector.
Definition int13.h:124
#define INT13_MBR_MAGIC
MBR magic signature.
Definition int13.h:292
uint32_t sectors_per_track
Number of sectors per track.
Definition int13.h:120
struct segoff dpte
Device parameter table extension.
Definition int13.h:15
static unsigned int count
Number of entries.
Definition dwmac.h:220
struct partition_chs chs_end
C/H/S end address.
Definition int13.h:270
uint8_t head
Head number.
Definition int13.h:23
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition netvsc.h:5
uint8_t size
Size of packet in bytes.
Definition int13.h:210
uint8_t type
System indicator (partition type)
Definition int13.h:268
struct partition_chs chs_start
C/H/S start address.
Definition int13.h:266
uint64_t lba
Starting block number.
Definition int13.h:11
uint64_t sectors
Total number of sectors on drive.
Definition int13.h:11
#define INT13_FDD_SECTORS(geometry)
Get floppy disk number of sectors per track.
Definition int13.h:316
#define INT13_FDD_TYPE_1M44
1.44M
Definition int13.h:85
uint32_t heads
Number of heads.
Definition int13.h:7
uint64_t buffer_phys
Data buffer (EDD 3.0+ only)
Definition int13.h:13
struct edd_device_path_information dpi
Device path information.
Definition int13.h:128
struct segoff dpte
Device parameter table extension.
Definition int13.h:126
struct edd_device_path_information dpi
Device path information.
Definition int13.h:17
uint32_t heads
Number of heads.
Definition int13.h:118
uint32_t cylinders
Number of cylinders.
Definition int13.h:116
struct partition_table_entry partitions[4]
Partition table.
Definition int13.h:286
#define INT13_FL_CHS_VALID
CHS information is valid.
Definition int13.h:155
#define INT13_FL_DMA_TRANSPARENT
DMA boundary errors handled transparently.
Definition int13.h:153
#define INT13_EXTENDED_VERIFY
Verify sectors.
Definition int13.h:41
#define INT13_EXTENDED_WRITE
Extended write.
Definition int13.h:39
#define INT13_CDROM_READ_BOOT_CATALOG
Read CD-ROM boot catalog.
Definition int13.h:49
#define INT13_GET_PARAMETERS
Get drive parameters.
Definition int13.h:31
#define INT13_RESET
Reset disk system.
Definition int13.h:23
#define INT13_GET_LAST_STATUS
Get status of last operation.
Definition int13.h:25
#define INT13_WRITE_SECTORS
Write sectors.
Definition int13.h:29
#define INT13_EXTENDED_READ
Extended read.
Definition int13.h:37
#define INT13_GET_DISK_TYPE
Get disk type.
Definition int13.h:33
#define INT13_READ_SECTORS
Read sectors.
Definition int13.h:27
#define INT13_CDROM_STATUS_TERMINATE
Get CD-ROM status / terminate emulation.
Definition int13.h:47
#define INT13_GET_EXTENDED_PARAMETERS
Get extended drive parameters.
Definition int13.h:45
#define INT13_EXTENSION_CHECK
Extensions installation check.
Definition int13.h:35
#define INT13_EXTENDED_SEEK
Extended seek.
Definition int13.h:43
#define INT13_STATUS_READ_ERROR
Read error.
Definition int13.h:63
#define INT13_STATUS_INVALID
Invalid function or parameter.
Definition int13.h:61
#define INT13_STATUS_RESET_FAILED
Reset failed.
Definition int13.h:65
#define INT13_DISK_TYPE_FDD
Floppy without change-line support.
Definition int13.h:139
#define INT13_DISK_TYPE_HDD
Hard disk.
Definition int13.h:143
#define INT13_EXTENSION_VER_3_0
INT13 extensions version 3.0 (EDD-3.0)
Definition int13.h:197
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOSPC
No space left on device.
Definition errno.h:550
#define ENOEXEC
Exec format error.
Definition errno.h:520
#define ENOMEM
Not enough space.
Definition errno.h:535
#define EIO
Input/output error.
Definition errno.h:434
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ECANCELED
Operation canceled.
Definition errno.h:344
#define ENODEV
No such device.
Definition errno.h:510
#define __attribute__(x)
Definition compiler.h:10
ACPI data structures.
static const char * acpi_name(uint32_t signature)
Transcribe ACPI table signature (for debugging)
Definition acpi.h:207
System memory map.
static void memmap_dump_all(int hide)
Dump system memory map (for debugging)
Definition memmap.h:216
iPXE sanboot API
static size_t sandev_blksize(struct san_device *sandev)
Calculate SAN device block size.
Definition sanboot.h:236
static uint64_t sandev_capacity(struct san_device *sandev)
Calculate SAN device capacity.
Definition sanboot.h:246
static int sandev_needs_reopen(struct san_device *sandev)
Check if SAN device needs to be reopened.
Definition sanboot.h:256
static int have_sandevs(void)
There exist some SAN devices.
Definition sanboot.h:204
static void sandev_put(struct san_device *sandev)
Drop reference to SAN device.
Definition sanboot.h:226
void san_unhook(unsigned int drive)
Unhook SAN device.
int san_describe(void)
Describe SAN devices for SAN-booted operating system.
int san_hook(unsigned int drive, struct uri **uris, unsigned int count, unsigned int flags)
Hook SAN device.
#define for_each_sandev(sandev)
Iterate over all SAN devices.
Definition sanboot.h:197
int san_boot(unsigned int drive, struct san_boot_config *config)
Attempt to boot from a SAN device.
#define PROVIDE_SANBOOT(_subsys, _api_func, _func)
Provide a sanboot API implementation.
Definition sanboot.h:139
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
static int int13_cdrom_read_boot_catalog(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 4d - Read CD-ROM boot catalog.
Definition int13.c:1038
static int int13_read_sectors(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 02 - Read sectors.
Definition int13.c:581
static int int13_hook(unsigned int drive, struct uri **uris, unsigned int count, unsigned int flags)
Hook INT 13 SAN device.
Definition int13.c:1252
static void int13_unhook_vector(void)
Unhook INT 13 handler.
Definition int13.c:1235
#define xbftab
Definition int13.c:1561
static int int13_device_path_info(struct san_device *sandev, struct edd_device_path_information *dpi)
Build device path information.
Definition int13.c:869
static int int13_parse_eltorito(struct san_device *sandev, void *scratch)
Parse El Torito parameters.
Definition int13.c:173
static int int13_get_parameters(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 08 - Get drive parameters.
Definition int13.c:619
static int int13_extended_write(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 43 - Extended write.
Definition int13.c:801
static int int13_is_fdd(struct san_device *sandev)
Test if SAN device is a floppy disk drive.
Definition int13.c:160
static void int13_hook_vector(void)
Hook INT 13 handler.
Definition int13.c:1181
#define XBFTAB_SIZE
Maximum size of boot firmware table(s)
Definition int13.c:1553
#define num_drives
Definition int13.c:141
static void int13_sync_num_drives(void)
Update BIOS drive count.
Definition int13.c:414
static int int13_reset(struct san_device *sandev, struct i386_all_regs *ix86 __unused)
INT 13, 00 - Reset disk system.
Definition int13.c:474
static int int13_extended_rw(struct san_device *sandev, struct i386_all_regs *ix86, int(*sandev_rw)(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer))
Extended read / write.
Definition int13.c:708
static int int13_extended_verify(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 44 - Verify sectors.
Definition int13.c:815
static int int13_load_mbr(unsigned int drive, struct segoff *address)
Load and verify master boot record from INT 13 drive.
Definition int13.c:1372
static __asmcall __used void int13(struct i386_all_regs *ix86)
INT 13 handler.
Definition int13.c:1074
static int int13_load_eltorito(unsigned int drive, struct segoff *address)
Load and verify El Torito boot record from INT 13 drive.
Definition int13.c:1435
void int13_wrapper(void)
Assembly wrapper.
static void int13_check_num_drives(void)
Check number of drives.
Definition int13.c:456
static int int13_extended_seek(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 44 - Extended seek.
Definition int13.c:842
static int int13_guess_geometry_fdd(struct san_device *sandev, unsigned int *heads, unsigned int *sectors)
Guess INT 13 floppy disk drive geometry.
Definition int13.c:331
static uint16_t equipment_word
Equipment word.
Definition int13.c:122
#define eltorito_address
Definition int13.c:1426
static int int13_extended_read(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 42 - Extended read.
Definition int13.c:787
#define int13_fdd_params
Definition int13.c:114
static int int13_extension_check(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 41 - Extensions installation check.
Definition int13.c:685
static int int13_write_sectors(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 03 - Write sectors.
Definition int13.c:601
static int int13_guess_geometry_hdd(struct san_device *sandev, void *scratch, unsigned int *heads, unsigned int *sectors)
Guess INT 13 hard disk drive geometry.
Definition int13.c:217
static int int13_boot(unsigned int drive, struct san_boot_config *config __unused)
Attempt to boot from an INT 13 drive.
Definition int13.c:1524
static int int13_install(struct acpi_header *acpi)
Install ACPI table.
Definition int13.c:1572
#define int13_vector
Definition int13.c:102
static int int13_guess_geometry(struct san_device *sandev, void *scratch)
Guess INT 13 drive geometry.
Definition int13.c:373
static int int13_get_extended_parameters(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 48 - Get extended parameters.
Definition int13.c:934
static int int13_get_disk_type(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 15 - Get disk type.
Definition int13.c:660
static int int13_describe(void)
Describe SAN devices for SAN-booted operating system.
Definition int13.c:1615
static void int13_unhook(unsigned int drive)
Unhook INT 13 SAN device.
Definition int13.c:1336
static uint32_t int13_capacity32(struct san_device *sandev)
Calculate SAN device capacity (limited to 32 bits)
Definition int13.c:149
#define eltorito_cmd
Definition int13.c:1422
static int int13_get_last_status(struct san_device *sandev, struct i386_all_regs *ix86 __unused)
INT 13, 01 - Get status of last operation.
Definition int13.c:493
#define num_fdds
Definition int13.c:131
static size_t xbftab_used
Total used length of boot firmware tables.
Definition int13.c:1564
static const struct int13_fdd_geometry int13_fdd_geometries[]
Recognised floppy disk geometries.
Definition int13.c:298
static int int13_rw_sectors(struct san_device *sandev, struct i386_all_regs *ix86, int(*sandev_rw)(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer))
Read / write sectors.
Definition int13.c:515
#define XBFTAB_ALIGN
Alignment of boot firmware table entries.
Definition int13.c:1556
static int int13_cdrom_status_terminate(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 4b - Get status or terminate CD-ROM emulation.
Definition int13.c:1003
INT 13 emulation.
#define INT13_BLKSIZE
Block size for non-extended INT 13 calls.
Definition int13.h:72
#define ISO9660_TYPE_BOOT
ISO9660 Boot Volume Descriptor type.
Definition iso9660.h:40
#define ISO9660_ID
ISO9660 identifier.
Definition iso9660.h:43
#define rm_ds
Definition libkir.h:39
#define put_real
Definition libkir.h:150
#define __data16(variable)
Definition libkir.h:14
#define REAL_CODE(asm_code_str)
Definition libkir.h:226
#define __bss16(variable)
Definition libkir.h:16
#define TEXT16_CODE(asm_code_str)
Definition libkir.h:217
#define __text16(variable)
Definition libkir.h:18
#define copy_to_real
Definition libkir.h:78
#define __from_data16(pointer)
Definition libkir.h:22
#define copy_from_real
Definition libkir.h:79
#define __bss16_array(variable, array)
Definition libkir.h:17
#define get_real
Definition libkir.h:151
#define VIRT_CALL(function)
Call C function from real-mode code.
Definition librm.h:72
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
PCI bus.
#define PCI_FUNC(busdevfn)
Definition pci.h:286
#define PCI_BUS(busdevfn)
Definition pci.h:284
#define PCI_SLOT(busdevfn)
Definition pci.h:285
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition realmode.h:77
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define OF
Definition registers.h:186
#define CF
Definition registers.h:181
static int sandev_rw(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer, int(*block_rw)(struct interface *control, struct interface *data, uint64_t lba, unsigned int count, void *buffer, size_t len))
Read from or write to SAN device.
Definition sanboot.c:598
int sandev_read(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer)
Read from SAN device.
Definition sanboot.c:647
int sandev_reopen(struct san_device *sandev)
(Re)open SAN device
Definition sanboot.c:373
int register_sandev(struct san_device *sandev, unsigned int drive, unsigned int flags)
Register SAN device.
Definition sanboot.c:880
int sandev_write(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer)
Write to SAN device.
Definition sanboot.c:668
int sandev_reset(struct san_device *sandev)
Reset SAN device.
Definition sanboot.c:576
void unregister_sandev(struct san_device *sandev)
Unregister SAN device.
Definition sanboot.c:942
struct san_device * alloc_sandev(struct uri **uris, unsigned int count, size_t priv_size)
Allocate SAN device.
Definition sanboot.c:837
struct san_device * sandev_find(unsigned int drive)
Find SAN device by drive number.
Definition sanboot.c:92
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition string.c:361
An ACPI description header.
Definition acpi.h:180
uint32_t signature
ACPI signature (4 ASCII characters)
Definition acpi.h:182
char oem_id[6]
OEM identification.
Definition acpi.h:190
char oem_table_id[8]
OEM table identification.
Definition acpi.h:192
A command-line command.
Definition command.h:10
A hardware device description.
Definition device.h:20
A hardware device.
Definition device.h:77
struct device_description desc
Device description.
Definition device.h:83
EDD device path information.
Definition edd.h:163
A bootable entry in the El Torito Boot Catalog.
Definition eltorito.h:70
An El Torito Boot Record Volume Descriptor (fixed portion)
Definition eltorito.h:17
An El Torito Boot Record Volume Descriptor.
Definition eltorito.h:29
uint32_t sector
Boot catalog sector.
Definition eltorito.h:35
An El Torito Boot Catalog Validation Entry.
Definition eltorito.h:42
A full register dump.
Definition registers.h:174
uint32_t flags
Definition registers.h:177
struct i386_seg_regs segs
Definition registers.h:175
struct i386_regs regs
Definition registers.h:176
uint16_t bx
Definition registers.h:84
uint8_t cl
Definition registers.h:97
uint8_t ah
Definition registers.h:106
uint8_t ch
Definition registers.h:98
uint16_t si
Definition registers.h:68
uint8_t bl
Definition registers.h:81
uint16_t cx
Definition registers.h:100
uint8_t al
Definition registers.h:105
uint16_t di
Definition registers.h:64
uint8_t dh
Definition registers.h:90
uint8_t dl
Definition registers.h:89
uint16_t dx
Definition registers.h:92
uint16_t ds
Definition registers.h:141
uint16_t es
Definition registers.h:142
Bootable CD-ROM boot catalog command packet.
Definition int13.h:236
Bootable CD-ROM specification packet.
Definition int13.h:208
INT 13 SAN device private data.
Definition int13.c:56
unsigned int sectors_per_track
Number of sectors per track.
Definition int13.c:92
unsigned int cylinders
Number of cylinders.
Definition int13.c:77
unsigned int heads
Number of heads.
Definition int13.c:85
unsigned int natural_drive
BIOS natural drive number (0x00-0xff)
Definition int13.c:67
int last_status
Status of last operation.
Definition int13.c:97
unsigned int boot_catalog
Address of El Torito boot catalog (if any)
Definition int13.c:95
An INT 13 disk address packet.
Definition int13.h:88
INT 13 disk parameters.
Definition int13.h:110
A floppy disk geometry.
Definition int13.h:295
A floppy drive parameter table.
Definition int13.h:319
A Master Boot Record.
Definition int13.h:278
A partition table entry within the MBR.
Definition int13.h:262
SAN boot configuration parameters.
Definition sanboot.h:111
A SAN device.
Definition sanboot.h:59
void * priv
Driver private data.
Definition sanboot.h:90
struct san_path * active
Current active path.
Definition sanboot.h:95
unsigned int drive
Drive number.
Definition sanboot.h:66
int is_cdrom
Drive is a CD-ROM.
Definition sanboot.h:87
A SAN path.
Definition sanboot.h:37
struct interface block
Underlying block device interface.
Definition sanboot.h:48
uint16_t segment
Definition registers.h:193
uint16_t offset
Definition registers.h:192
A Uniform Resource Identifier.
Definition uri.h:65