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->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  */
217 static 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, virt_to_user ( 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 */
298 static const struct int13_fdd_geometry int13_fdd_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  */
331 static 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  */
373 static 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  */
414 static 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  */
456 static 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  */
474 static 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  */
493 static 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  */
515 static int int13_rw_sectors ( struct san_device *sandev,
516  struct i386_all_regs *ix86,
517  int ( * sandev_rw ) ( struct san_device *sandev,
518  uint64_t lba,
519  unsigned int count,
520  userptr_t buffer ) ) {
521  struct int13_data *int13 = sandev->priv;
522  unsigned int cylinder, head, sector;
523  unsigned long lba;
524  unsigned int count;
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_user ( 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 ) );
562  return -INT13_STATUS_READ_ERROR;
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  */
581 static 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  */
601 static 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  */
619 static 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 ) ) {
644  ix86->regs.bl = INT13_FDD_TYPE_1M44;
645  ix86->segs.es = rm_ds;
646  ix86->regs.di = __from_data16 ( &int13_fdd_params );
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  */
660 static int int13_get_disk_type ( struct san_device *sandev,
661  struct i386_all_regs *ix86 ) {
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  */
685 static 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  */
708 static int int13_extended_rw ( struct san_device *sandev,
709  struct i386_all_regs *ix86,
710  int ( * sandev_rw ) ( struct san_device *sandev,
711  uint64_t lba,
712  unsigned int count,
713  userptr_t buffer ) ) {
714  struct int13_disk_address addr;
716  uint64_t lba;
717  unsigned long count;
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_user ( addr.buffer_phys );
747  DBGC2 ( sandev->drive, "%08llx",
748  ( ( unsigned long long ) addr.buffer_phys ) );
749  } else {
750  buffer = real_to_user ( 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 ) ) );
774  return -INT13_STATUS_READ_ERROR;
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  */
787 static 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  */
801 static 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  */
815 static int int13_extended_verify ( struct san_device *sandev,
816  struct i386_all_regs *ix86 ) {
817  struct int13_disk_address addr;
818  uint64_t lba;
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  */
842 static int int13_extended_seek ( struct san_device *sandev,
843  struct i386_all_regs *ix86 ) {
844  struct int13_disk_address addr;
845  uint64_t lba;
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  */
869 static int int13_device_path_info ( struct san_device *sandev,
870  struct edd_device_path_information *dpi ) {
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:
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  */
934 static 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  */
1003 static 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  */
1038 static 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_user ( command.buffer ) ) ) != 0 ) {
1062  DBGC ( sandev->drive, "INT13 drive %02x could not read boot "
1063  "catalog: %s\n", sandev->drive, strerror ( rc ) );
1064  return -INT13_STATUS_READ_ERROR;
1065  }
1066 
1067  return 0;
1068 }
1069 
1070 /**
1071  * INT 13 handler
1072  *
1073  */
1074 static __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;
1111  case INT13_GET_LAST_STATUS:
1112  status = int13_get_last_status ( sandev, ix86 );
1113  break;
1114  case INT13_READ_SECTORS:
1115  status = int13_read_sectors ( sandev, ix86 );
1116  break;
1117  case INT13_WRITE_SECTORS:
1118  status = int13_write_sectors ( sandev, ix86 );
1119  break;
1120  case INT13_GET_PARAMETERS:
1121  status = int13_get_parameters ( sandev, ix86 );
1122  break;
1123  case INT13_GET_DISK_TYPE:
1124  status = int13_get_disk_type ( sandev, ix86 );
1125  break;
1126  case INT13_EXTENSION_CHECK:
1127  status = int13_extension_check ( sandev, ix86 );
1128  break;
1129  case INT13_EXTENDED_READ:
1130  status = int13_extended_read ( sandev, ix86 );
1131  break;
1132  case INT13_EXTENDED_WRITE:
1133  status = int13_extended_write ( sandev, ix86 );
1134  break;
1135  case INT13_EXTENDED_VERIFY:
1136  status = int13_extended_verify ( sandev, ix86 );
1137  break;
1138  case INT13_EXTENDED_SEEK:
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  */
1181 static 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  */
1235 static 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  */
1252 static 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 )
1267  drive = natural_drive;
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  */
1336 static 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  */
1372 static int int13_load_mbr ( unsigned int drive, struct segoff *address ) {
1373  uint16_t status;
1374  int discard_b, discard_c, discard_d;
1375  uint16_t magic;
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 */
1425 static struct int13_disk_address __bss16 ( eltorito_address );
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  */
1435 static 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;
1440  uint16_t status;
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  copy_from_user ( &catalog, phys_to_user ( eltorito_cmd.buffer ), 0,
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  */
1524 static int int13_boot ( unsigned int drive,
1525  struct san_boot_config *config __unused ) {
1526  struct memory_map memmap;
1527  struct segoff address;
1528  int rc;
1529 
1530  /* Look for a usable boot sector */
1531  if ( ( ( rc = int13_load_mbr ( drive, &address ) ) != 0 ) &&
1532  ( ( rc = int13_load_eltorito ( drive, &address ) ) != 0 ) )
1533  return rc;
1534 
1535  /* Dump out memory map prior to boot, if memmap debugging is
1536  * enabled. Not required for program flow, but we have so
1537  * many problems that turn out to be memory-map related that
1538  * it's worth doing.
1539  */
1540  get_memmap ( &memmap );
1541 
1542  /* Jump to boot sector */
1543  if ( ( rc = call_bootsector ( address.segment, address.offset,
1544  drive ) ) != 0 ) {
1545  DBGC ( drive, "INT13 drive %02x boot returned: %s\n",
1546  drive, strerror ( rc ) );
1547  return rc;
1548  }
1549 
1550  return -ECANCELED; /* -EIMPOSSIBLE */
1551 }
1552 
1553 /** Maximum size of boot firmware table(s) */
1554 #define XBFTAB_SIZE 768
1555 
1556 /** Alignment of boot firmware table entries */
1557 #define XBFTAB_ALIGN 16
1558 
1559 /** The boot firmware table(s) generated by iPXE */
1561  __attribute__ (( aligned ( XBFTAB_ALIGN ) ));
1562 #define xbftab __use_data16 ( xbftab )
1563 
1564 /** Total used length of boot firmware tables */
1565 static size_t xbftab_used;
1566 
1567 /**
1568  * Install ACPI table
1569  *
1570  * @v acpi ACPI description header
1571  * @ret rc Return status code
1572  */
1573 static int int13_install ( struct acpi_header *acpi ) {
1574  struct segoff xbft_address;
1575  struct acpi_header *installed;
1576  size_t len;
1577 
1578  /* Check length */
1579  len = acpi->length;
1580  if ( len > ( sizeof ( xbftab ) - xbftab_used ) ) {
1581  DBGC ( acpi, "INT13 out of space for %s table\n",
1582  acpi_name ( acpi->signature ) );
1583  return -ENOSPC;
1584  }
1585 
1586  /* Install table */
1587  installed = ( ( ( void * ) xbftab ) + xbftab_used );
1588  memcpy ( installed, acpi, len );
1589  xbft_address.segment = rm_ds;
1590  xbft_address.offset = __from_data16 ( installed );
1591 
1592  /* Fill in common parameters */
1593  strncpy ( installed->oem_id, "FENSYS",
1594  sizeof ( installed->oem_id ) );
1595  strncpy ( installed->oem_table_id, "iPXE",
1596  sizeof ( installed->oem_table_id ) );
1597 
1598  /* Fix checksum */
1599  acpi_fix_checksum ( installed );
1600 
1601  /* Update used length */
1602  xbftab_used = ( ( xbftab_used + len + XBFTAB_ALIGN - 1 ) &
1603  ~( XBFTAB_ALIGN - 1 ) );
1604 
1605  DBGC ( acpi, "INT13 installed %s:\n",
1606  acpi_name ( installed->signature ) );
1607  DBGC_HDA ( acpi, xbft_address, installed, len );
1608  return 0;
1609 }
1610 
1611 /**
1612  * Describe SAN devices for SAN-booted operating system
1613  *
1614  * @ret rc Return status code
1615  */
1616 static int int13_describe ( void ) {
1617  int rc;
1618 
1619  /* Clear tables */
1620  memset ( &xbftab, 0, sizeof ( xbftab ) );
1621  xbftab_used = 0;
1622 
1623  /* Install ACPI tables */
1624  if ( ( rc = acpi_install ( int13_install ) ) != 0 ) {
1625  DBG ( "INT13 could not install ACPI tables: %s\n",
1626  strerror ( rc ) );
1627  return rc;
1628  }
1629 
1630  return 0;
1631 }
1632 
1633 PROVIDE_SANBOOT ( pcbios, san_hook, int13_hook );
1635 PROVIDE_SANBOOT ( pcbios, san_boot, int13_boot );
#define PCI_FUNC(busdevfn)
Definition: pci.h:281
static int int13_extended_seek(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 44 - Extended seek.
Definition: int13.c:842
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:279
int sandev_reset(struct san_device *sandev)
Reset SAN device.
Definition: sanboot.c:574
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
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:175
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:1573
uint32_t signature
ACPI signature (4 ASCII characters)
Definition: acpi.h:165
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:1435
#define XBFTAB_SIZE
Maximum size of boot firmware table(s)
Definition: int13.c:1554
static __asmcall __used void int13(struct i386_all_regs *ix86)
INT 13 handler.
Definition: int13.c:1074
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:1336
#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:596
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:493
#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:619
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:939
#define get_real
Definition: libkir.h:151
int san_boot(unsigned int drive, struct san_boot_config *config)
Attempt to boot from a SAN device.
uint64_t desc
Microcode descriptor list physical address.
Definition: ucode.h:12
static int int13_extended_write(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 43 - Extended write.
Definition: int13.c:801
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:47
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:225
static int int13_device_path_info(struct san_device *sandev, struct edd_device_path_information *dpi)
Build device path information.
Definition: int13.c:869
#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:255
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:331
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:815
static void int13_hook_vector(void)
Hook INT 13 handler.
Definition: int13.c:1181
#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.
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:414
#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:456
#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:203
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:347
#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:298
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:660
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:15
char oem_id[6]
OEM identification.
Definition: acpi.h:173
#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 __used
Declare a function as used.
Definition: compiler.h:605
#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:1372
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:36
#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:65
unsigned int drive
Drive number.
Definition: sanboot.h:65
SAN boot configuration parameters.
Definition: sanboot.h:110
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:877
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:245
#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:85
#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:1616
static void int13_unhook_vector(void)
Unhook INT 13 handler.
Definition: int13.c:1235
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:515
static int int13_read_sectors(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 02 - Read sectors.
Definition: int13.c:581
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:336
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:217
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_extended_read(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 42 - Extended read.
Definition: int13.c:787
int is_cdrom
Drive is a CD-ROM.
Definition: sanboot.h:86
static size_t xbftab_used
Total used length of boot firmware tables.
Definition: int13.c:1565
#define num_fdds
Definition: int13.c:130
uint8_t ah
Definition: registers.h:106
#define PCI_SLOT(busdevfn)
Definition: pci.h:280
PCI bus.
#define copy_to_real
Definition: libkir.h:78
#define eltorito_address
Definition: int13.c:1426
#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:645
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
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:1003
void int13_wrapper(void)
Assembly wrapper.
#define XBFTAB_ALIGN
Alignment of boot firmware table entries.
Definition: int13.c:1557
uint16_t ds
Definition: registers.h:141
#define ENODEV
No such device.
Definition: errno.h:509
A SAN device.
Definition: sanboot.h:58
#define eltorito_cmd
Definition: int13.c:1422
u32 addr
Definition: sky2.h:8
unsigned char uint8_t
Definition: stdint.h:10
#define BDA_NUM_DRIVES
Definition: bios.h:19
#define for_each_sandev(sandev)
Iterate over all SAN devices.
Definition: sanboot.h:196
struct partition_chs chs_start
C/H/S start address.
Definition: int13.h:266
__asm__ __volatile__("\n1:\n\t" "movb -1(%3,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %4, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c), "+m"(*value) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
#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:601
#define BDA_EQUIPMENT_WORD
Definition: bios.h:8
An ACPI description header.
Definition: acpi.h:163
#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:474
#define INT13_CDROM_STATUS_TERMINATE
Get CD-ROM status / terminate emulation.
Definition: int13.h:47
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.
#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
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:90
#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:1252
void * priv
Driver private data.
Definition: sanboot.h:89
#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:190
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:235
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:708
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
Device model.
A Uniform Resource Identifier.
Definition: uri.h:64
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:32
#define xbftab
Definition: int13.c:1562
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:94
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition: acpi.c:45
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
static int int13_extension_check(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 41 - Extensions installation check.
Definition: int13.c:685
#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:114
#define REAL_CODE(asm_code_str)
Definition: libkir.h:226
int sandev_reopen(struct san_device *sandev)
(Re)open SAN device
Definition: sanboot.c:371
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
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:665
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:834
static int int13_guess_geometry(struct san_device *sandev, void *scratch)
Guess INT 13 drive geometry.
Definition: int13.c:373
#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