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