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