|  | @@ -91,6 +91,13 @@ struct int13_drive {
 | 
		
	
		
			
			| 91 | 91 |  
 | 
		
	
		
			
			| 92 | 92 |  	/** Block device capacity */
 | 
		
	
		
			
			| 93 | 93 |  	struct block_device_capacity capacity;
 | 
		
	
		
			
			|  | 94 | +	/** INT 13 emulated blocksize shift
 | 
		
	
		
			
			|  | 95 | +	 *
 | 
		
	
		
			
			|  | 96 | +	 * To allow for emulation of CD-ROM access, this represents
 | 
		
	
		
			
			|  | 97 | +	 * the left-shift required to translate from INT 13 blocks to
 | 
		
	
		
			
			|  | 98 | +	 * underlying blocks.
 | 
		
	
		
			
			|  | 99 | +	 */
 | 
		
	
		
			
			|  | 100 | +	unsigned int blksize_shift;
 | 
		
	
		
			
			| 94 | 101 |  
 | 
		
	
		
			
			| 95 | 102 |  	/** Number of cylinders
 | 
		
	
		
			
			| 96 | 103 |  	 *
 | 
		
	
	
		
			
			|  | @@ -117,6 +124,9 @@ struct int13_drive {
 | 
		
	
		
			
			| 117 | 124 |  	 */
 | 
		
	
		
			
			| 118 | 125 |  	unsigned int sectors_per_track;
 | 
		
	
		
			
			| 119 | 126 |  
 | 
		
	
		
			
			|  | 127 | +	/** Address of El Torito boot catalog (if any) */
 | 
		
	
		
			
			|  | 128 | +	unsigned int boot_catalog;
 | 
		
	
		
			
			|  | 129 | +
 | 
		
	
		
			
			| 120 | 130 |  	/** Underlying device status, if in error */
 | 
		
	
		
			
			| 121 | 131 |  	int block_rc;
 | 
		
	
		
			
			| 122 | 132 |  	/** Status of last operation */
 | 
		
	
	
		
			
			|  | @@ -142,6 +152,37 @@ static LIST_HEAD ( int13s );
 | 
		
	
		
			
			| 142 | 152 |   */
 | 
		
	
		
			
			| 143 | 153 |  static uint8_t num_drives;
 | 
		
	
		
			
			| 144 | 154 |  
 | 
		
	
		
			
			|  | 155 | +/**
 | 
		
	
		
			
			|  | 156 | + * Calculate INT 13 drive sector size
 | 
		
	
		
			
			|  | 157 | + *
 | 
		
	
		
			
			|  | 158 | + * @v int13		Emulated drive
 | 
		
	
		
			
			|  | 159 | + * @ret blksize		Sector size
 | 
		
	
		
			
			|  | 160 | + */
 | 
		
	
		
			
			|  | 161 | +static inline unsigned int int13_blksize ( struct int13_drive *int13 ) {
 | 
		
	
		
			
			|  | 162 | +	return ( int13->capacity.blksize << int13->blksize_shift );
 | 
		
	
		
			
			|  | 163 | +}
 | 
		
	
		
			
			|  | 164 | +
 | 
		
	
		
			
			|  | 165 | +/**
 | 
		
	
		
			
			|  | 166 | + * Calculate INT 13 drive capacity
 | 
		
	
		
			
			|  | 167 | + *
 | 
		
	
		
			
			|  | 168 | + * @v int13		Emulated drive
 | 
		
	
		
			
			|  | 169 | + * @ret blocks		Number of blocks
 | 
		
	
		
			
			|  | 170 | + */
 | 
		
	
		
			
			|  | 171 | +static inline uint64_t int13_capacity ( struct int13_drive *int13 ) {
 | 
		
	
		
			
			|  | 172 | +	return ( int13->capacity.blocks >> int13->blksize_shift );
 | 
		
	
		
			
			|  | 173 | +}
 | 
		
	
		
			
			|  | 174 | +
 | 
		
	
		
			
			|  | 175 | +/**
 | 
		
	
		
			
			|  | 176 | + * Calculate INT 13 drive capacity (limited to 32 bits)
 | 
		
	
		
			
			|  | 177 | + *
 | 
		
	
		
			
			|  | 178 | + * @v int13		Emulated drive
 | 
		
	
		
			
			|  | 179 | + * @ret blocks		Number of blocks
 | 
		
	
		
			
			|  | 180 | + */
 | 
		
	
		
			
			|  | 181 | +static inline uint32_t int13_capacity32 ( struct int13_drive *int13 ) {
 | 
		
	
		
			
			|  | 182 | +	uint64_t capacity = int13_capacity ( int13 );
 | 
		
	
		
			
			|  | 183 | +	return ( ( capacity <= 0xffffffffUL ) ? capacity : 0xffffffff );
 | 
		
	
		
			
			|  | 184 | +}
 | 
		
	
		
			
			|  | 185 | +
 | 
		
	
		
			
			| 145 | 186 |  /** An INT 13 command */
 | 
		
	
		
			
			| 146 | 187 |  struct int13_command {
 | 
		
	
		
			
			| 147 | 188 |  	/** Status */
 | 
		
	
	
		
			
			|  | @@ -319,6 +360,10 @@ static int int13_rw ( struct int13_drive *int13, uint64_t lba,
 | 
		
	
		
			
			| 319 | 360 |  	size_t frag_len;
 | 
		
	
		
			
			| 320 | 361 |  	int rc;
 | 
		
	
		
			
			| 321 | 362 |  
 | 
		
	
		
			
			|  | 363 | +	/* Translate to underlying blocksize */
 | 
		
	
		
			
			|  | 364 | +	lba <<= int13->blksize_shift;
 | 
		
	
		
			
			|  | 365 | +	count <<= int13->blksize_shift;
 | 
		
	
		
			
			|  | 366 | +
 | 
		
	
		
			
			| 322 | 367 |  	while ( count ) {
 | 
		
	
		
			
			| 323 | 368 |  
 | 
		
	
		
			
			| 324 | 369 |  		/* Determine fragment length */
 | 
		
	
	
		
			
			|  | @@ -370,30 +415,111 @@ static int int13_read_capacity ( struct int13_drive *int13 ) {
 | 
		
	
		
			
			| 370 | 415 |  	return 0;
 | 
		
	
		
			
			| 371 | 416 |  }
 | 
		
	
		
			
			| 372 | 417 |  
 | 
		
	
		
			
			|  | 418 | +/**
 | 
		
	
		
			
			|  | 419 | + * Parse ISO9660 parameters
 | 
		
	
		
			
			|  | 420 | + *
 | 
		
	
		
			
			|  | 421 | + * @v int13		Emulated drive
 | 
		
	
		
			
			|  | 422 | + * @v scratch		Scratch area for single-sector reads
 | 
		
	
		
			
			|  | 423 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 424 | + *
 | 
		
	
		
			
			|  | 425 | + * Reads and parses ISO9660 parameters, if present.
 | 
		
	
		
			
			|  | 426 | + */
 | 
		
	
		
			
			|  | 427 | +static int int13_parse_iso9660 ( struct int13_drive *int13, void *scratch ) {
 | 
		
	
		
			
			|  | 428 | +	static const struct iso9660_primary_descriptor_fixed primary_check = {
 | 
		
	
		
			
			|  | 429 | +		.type = ISO9660_TYPE_PRIMARY,
 | 
		
	
		
			
			|  | 430 | +		.id = ISO9660_ID,
 | 
		
	
		
			
			|  | 431 | +	};
 | 
		
	
		
			
			|  | 432 | +	struct iso9660_primary_descriptor *primary = scratch;
 | 
		
	
		
			
			|  | 433 | +	static const struct eltorito_descriptor_fixed boot_check = {
 | 
		
	
		
			
			|  | 434 | +		.type = ISO9660_TYPE_BOOT,
 | 
		
	
		
			
			|  | 435 | +		.id = ISO9660_ID,
 | 
		
	
		
			
			|  | 436 | +		.version = 1,
 | 
		
	
		
			
			|  | 437 | +		.system_id = "EL TORITO SPECIFICATION",
 | 
		
	
		
			
			|  | 438 | +	};
 | 
		
	
		
			
			|  | 439 | +	struct eltorito_descriptor *boot = scratch;
 | 
		
	
		
			
			|  | 440 | +	unsigned int blksize;
 | 
		
	
		
			
			|  | 441 | +	unsigned int blksize_shift;
 | 
		
	
		
			
			|  | 442 | +	int rc;
 | 
		
	
		
			
			|  | 443 | +
 | 
		
	
		
			
			|  | 444 | +	/* Calculate required blocksize shift */
 | 
		
	
		
			
			|  | 445 | +	blksize = int13_blksize ( int13 );
 | 
		
	
		
			
			|  | 446 | +	blksize_shift = 0;
 | 
		
	
		
			
			|  | 447 | +	while ( blksize < ISO9660_BLKSIZE ) {
 | 
		
	
		
			
			|  | 448 | +		blksize <<= 1;
 | 
		
	
		
			
			|  | 449 | +		blksize_shift++;
 | 
		
	
		
			
			|  | 450 | +	}
 | 
		
	
		
			
			|  | 451 | +	if ( blksize > ISO9660_BLKSIZE ) {
 | 
		
	
		
			
			|  | 452 | +		/* Do nothing if the blksize is invalid for CD-ROM access */
 | 
		
	
		
			
			|  | 453 | +		return 0;
 | 
		
	
		
			
			|  | 454 | +	}
 | 
		
	
		
			
			|  | 455 | +
 | 
		
	
		
			
			|  | 456 | +	/* Read primary volume descriptor */
 | 
		
	
		
			
			|  | 457 | +	if ( ( rc = int13_rw ( int13,
 | 
		
	
		
			
			|  | 458 | +			       ( ISO9660_PRIMARY_LBA << blksize_shift ), 1,
 | 
		
	
		
			
			|  | 459 | +			       virt_to_user ( primary ), block_read ) ) != 0 ){
 | 
		
	
		
			
			|  | 460 | +		DBGC ( int13, "INT13 drive %02x could not read ISO9660 "
 | 
		
	
		
			
			|  | 461 | +		       "primary volume descriptor: %s\n",
 | 
		
	
		
			
			|  | 462 | +		       int13->drive, strerror ( rc ) );
 | 
		
	
		
			
			|  | 463 | +		return rc;
 | 
		
	
		
			
			|  | 464 | +	}
 | 
		
	
		
			
			|  | 465 | +
 | 
		
	
		
			
			|  | 466 | +	/* Do nothing unless this is an ISO image */
 | 
		
	
		
			
			|  | 467 | +	if ( memcmp ( primary, &primary_check, sizeof ( primary_check ) ) != 0 )
 | 
		
	
		
			
			|  | 468 | +		return 0;
 | 
		
	
		
			
			|  | 469 | +	DBGC ( int13, "INT13 drive %02x contains an ISO9660 filesystem; "
 | 
		
	
		
			
			|  | 470 | +	       "treating as CD-ROM\n", int13->drive );
 | 
		
	
		
			
			|  | 471 | +
 | 
		
	
		
			
			|  | 472 | +	/* Read boot record volume descriptor */
 | 
		
	
		
			
			|  | 473 | +	if ( ( rc = int13_rw ( int13,
 | 
		
	
		
			
			|  | 474 | +			       ( ELTORITO_LBA << blksize_shift ), 1,
 | 
		
	
		
			
			|  | 475 | +			       virt_to_user ( boot ), block_read ) ) != 0 ) {
 | 
		
	
		
			
			|  | 476 | +		DBGC ( int13, "INT13 drive %02x could not read El Torito boot "
 | 
		
	
		
			
			|  | 477 | +		       "record volume descriptor: %s\n",
 | 
		
	
		
			
			|  | 478 | +		       int13->drive, strerror ( rc ) );
 | 
		
	
		
			
			|  | 479 | +		return rc;
 | 
		
	
		
			
			|  | 480 | +	}
 | 
		
	
		
			
			|  | 481 | +
 | 
		
	
		
			
			|  | 482 | +	/* Check for an El Torito boot catalog */
 | 
		
	
		
			
			|  | 483 | +	if ( memcmp ( boot, &boot_check, sizeof ( boot_check ) ) == 0 ) {
 | 
		
	
		
			
			|  | 484 | +		int13->boot_catalog = boot->sector;
 | 
		
	
		
			
			|  | 485 | +		DBGC ( int13, "INT13 drive %02x has an El Torito boot catalog "
 | 
		
	
		
			
			|  | 486 | +		       "at LBA %08x\n", int13->drive, int13->boot_catalog );
 | 
		
	
		
			
			|  | 487 | +	} else {
 | 
		
	
		
			
			|  | 488 | +		DBGC ( int13, "INT13 drive %02x has no El Torito boot "
 | 
		
	
		
			
			|  | 489 | +		       "catalog\n", int13->drive );
 | 
		
	
		
			
			|  | 490 | +	}
 | 
		
	
		
			
			|  | 491 | +
 | 
		
	
		
			
			|  | 492 | +	/* Configure drive for no-emulation CD-ROM access */
 | 
		
	
		
			
			|  | 493 | +	int13->blksize_shift += blksize_shift;
 | 
		
	
		
			
			|  | 494 | +
 | 
		
	
		
			
			|  | 495 | +	return 0;
 | 
		
	
		
			
			|  | 496 | +}
 | 
		
	
		
			
			|  | 497 | +
 | 
		
	
		
			
			| 373 | 498 |  /**
 | 
		
	
		
			
			| 374 | 499 |   * Guess INT 13 drive geometry
 | 
		
	
		
			
			| 375 | 500 |   *
 | 
		
	
		
			
			| 376 | 501 |   * @v int13		Emulated drive
 | 
		
	
		
			
			|  | 502 | + * @v scratch		Scratch area for single-sector reads
 | 
		
	
		
			
			| 377 | 503 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 378 | 504 |   *
 | 
		
	
		
			
			| 379 | 505 |   * Guesses the drive geometry by inspecting the partition table.
 | 
		
	
		
			
			| 380 | 506 |   */
 | 
		
	
		
			
			| 381 |  | -static int int13_guess_geometry ( struct int13_drive *int13 ) {
 | 
		
	
		
			
			| 382 |  | -	struct master_boot_record mbr;
 | 
		
	
		
			
			|  | 507 | +static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) {
 | 
		
	
		
			
			|  | 508 | +	struct master_boot_record *mbr = scratch;
 | 
		
	
		
			
			| 383 | 509 |  	struct partition_table_entry *partition;
 | 
		
	
		
			
			| 384 | 510 |  	unsigned int guessed_heads = 255;
 | 
		
	
		
			
			| 385 | 511 |  	unsigned int guessed_sectors_per_track = 63;
 | 
		
	
		
			
			| 386 |  | -	unsigned long blocks;
 | 
		
	
		
			
			| 387 |  | -	unsigned long blocks_per_cyl;
 | 
		
	
		
			
			|  | 512 | +	unsigned int blocks;
 | 
		
	
		
			
			|  | 513 | +	unsigned int blocks_per_cyl;
 | 
		
	
		
			
			| 388 | 514 |  	unsigned int i;
 | 
		
	
		
			
			| 389 | 515 |  	int rc;
 | 
		
	
		
			
			| 390 | 516 |  
 | 
		
	
		
			
			| 391 | 517 |  	/* Don't even try when the blksize is invalid for C/H/S access */
 | 
		
	
		
			
			| 392 |  | -	if ( int13->capacity.blksize != INT13_BLKSIZE )
 | 
		
	
		
			
			|  | 518 | +	if ( int13_blksize ( int13 ) != INT13_BLKSIZE )
 | 
		
	
		
			
			| 393 | 519 |  		return 0;
 | 
		
	
		
			
			| 394 | 520 |  
 | 
		
	
		
			
			| 395 | 521 |  	/* Read partition table */
 | 
		
	
		
			
			| 396 |  | -	if ( ( rc = int13_rw ( int13, 0, 1, virt_to_user ( &mbr ),
 | 
		
	
		
			
			|  | 522 | +	if ( ( rc = int13_rw ( int13, 0, 1, virt_to_user ( mbr ),
 | 
		
	
		
			
			| 397 | 523 |  			       block_read ) ) != 0 ) {
 | 
		
	
		
			
			| 398 | 524 |  		DBGC ( int13, "INT13 drive %02x could not read partition "
 | 
		
	
		
			
			| 399 | 525 |  		       "table to guess geometry: %s\n",
 | 
		
	
	
		
			
			|  | @@ -401,15 +527,15 @@ static int int13_guess_geometry ( struct int13_drive *int13 ) {
 | 
		
	
		
			
			| 401 | 527 |  		return rc;
 | 
		
	
		
			
			| 402 | 528 |  	}
 | 
		
	
		
			
			| 403 | 529 |  	DBGC2 ( int13, "INT13 drive %02x has MBR:\n", int13->drive );
 | 
		
	
		
			
			| 404 |  | -	DBGC2_HDA ( int13, 0, &mbr, sizeof ( mbr ) );
 | 
		
	
		
			
			|  | 530 | +	DBGC2_HDA ( int13, 0, mbr, sizeof ( *mbr ) );
 | 
		
	
		
			
			| 405 | 531 |  	DBGC ( int13, "INT13 drive %02x has signature %08x\n",
 | 
		
	
		
			
			| 406 |  | -	       int13->drive, mbr.signature );
 | 
		
	
		
			
			|  | 532 | +	       int13->drive, mbr->signature );
 | 
		
	
		
			
			| 407 | 533 |  
 | 
		
	
		
			
			| 408 | 534 |  	/* Scan through partition table and modify guesses for heads
 | 
		
	
		
			
			| 409 | 535 |  	 * and sectors_per_track if we find any used partitions.
 | 
		
	
		
			
			| 410 | 536 |  	 */
 | 
		
	
		
			
			| 411 | 537 |  	for ( i = 0 ; i < 4 ; i++ ) {
 | 
		
	
		
			
			| 412 |  | -		partition = &mbr.partitions[i];
 | 
		
	
		
			
			|  | 538 | +		partition = &mbr->partitions[i];
 | 
		
	
		
			
			| 413 | 539 |  		if ( ! partition->type )
 | 
		
	
		
			
			| 414 | 540 |  			continue;
 | 
		
	
		
			
			| 415 | 541 |  		guessed_heads = ( PART_HEAD ( partition->chs_end ) + 1 );
 | 
		
	
	
		
			
			|  | @@ -426,8 +552,7 @@ static int int13_guess_geometry ( struct int13_drive *int13 ) {
 | 
		
	
		
			
			| 426 | 552 |  		int13->sectors_per_track = guessed_sectors_per_track;
 | 
		
	
		
			
			| 427 | 553 |  	if ( ! int13->cylinders ) {
 | 
		
	
		
			
			| 428 | 554 |  		/* Avoid attempting a 64-bit divide on a 32-bit system */
 | 
		
	
		
			
			| 429 |  | -		blocks = ( ( int13->capacity.blocks <= ULONG_MAX ) ?
 | 
		
	
		
			
			| 430 |  | -			   int13->capacity.blocks : ULONG_MAX );
 | 
		
	
		
			
			|  | 555 | +		blocks = int13_capacity32 ( int13 );
 | 
		
	
		
			
			| 431 | 556 |  		blocks_per_cyl = ( int13->heads * int13->sectors_per_track );
 | 
		
	
		
			
			| 432 | 557 |  		assert ( blocks_per_cyl != 0 );
 | 
		
	
		
			
			| 433 | 558 |  		int13->cylinders = ( blocks / blocks_per_cyl );
 | 
		
	
	
		
			
			|  | @@ -535,10 +660,10 @@ static int int13_rw_sectors ( struct int13_drive *int13,
 | 
		
	
		
			
			| 535 | 660 |  	int rc;
 | 
		
	
		
			
			| 536 | 661 |  
 | 
		
	
		
			
			| 537 | 662 |  	/* Validate blocksize */
 | 
		
	
		
			
			| 538 |  | -	if ( int13->capacity.blksize != INT13_BLKSIZE ) {
 | 
		
	
		
			
			|  | 663 | +	if ( int13_blksize ( int13 ) != INT13_BLKSIZE ) {
 | 
		
	
		
			
			| 539 | 664 |  		DBGC ( int13, "\nINT 13 drive %02x invalid blocksize (%zd) "
 | 
		
	
		
			
			| 540 | 665 |  		       "for non-extended read/write\n",
 | 
		
	
		
			
			| 541 |  | -		       int13->drive, int13->capacity.blksize );
 | 
		
	
		
			
			|  | 666 | +		       int13->drive, int13_blksize ( int13 ) );
 | 
		
	
		
			
			| 542 | 667 |  		return -INT13_STATUS_INVALID;
 | 
		
	
		
			
			| 543 | 668 |  	}
 | 
		
	
		
			
			| 544 | 669 |  	
 | 
		
	
	
		
			
			|  | @@ -625,6 +750,14 @@ static int int13_get_parameters ( struct int13_drive *int13,
 | 
		
	
		
			
			| 625 | 750 |  
 | 
		
	
		
			
			| 626 | 751 |  	DBGC2 ( int13, "Get drive parameters\n" );
 | 
		
	
		
			
			| 627 | 752 |  
 | 
		
	
		
			
			|  | 753 | +	/* Validate blocksize */
 | 
		
	
		
			
			|  | 754 | +	if ( int13_blksize ( int13 ) != INT13_BLKSIZE ) {
 | 
		
	
		
			
			|  | 755 | +		DBGC ( int13, "\nINT 13 drive %02x invalid blocksize (%zd) "
 | 
		
	
		
			
			|  | 756 | +		       "for non-extended parameters\n",
 | 
		
	
		
			
			|  | 757 | +		       int13->drive, int13_blksize ( int13 ) );
 | 
		
	
		
			
			|  | 758 | +		return -INT13_STATUS_INVALID;
 | 
		
	
		
			
			|  | 759 | +	}
 | 
		
	
		
			
			|  | 760 | +
 | 
		
	
		
			
			| 628 | 761 |  	ix86->regs.ch = ( max_cylinder & 0xff );
 | 
		
	
		
			
			| 629 | 762 |  	ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
 | 
		
	
		
			
			| 630 | 763 |  	ix86->regs.dh = max_head;
 | 
		
	
	
		
			
			|  | @@ -645,8 +778,7 @@ static int int13_get_disk_type ( struct int13_drive *int13,
 | 
		
	
		
			
			| 645 | 778 |  	uint32_t blocks;
 | 
		
	
		
			
			| 646 | 779 |  
 | 
		
	
		
			
			| 647 | 780 |  	DBGC2 ( int13, "Get disk type\n" );
 | 
		
	
		
			
			| 648 |  | -	blocks = ( ( int13->capacity.blocks <= 0xffffffffUL ) ?
 | 
		
	
		
			
			| 649 |  | -		   int13->capacity.blocks : 0xffffffffUL );
 | 
		
	
		
			
			|  | 781 | +	blocks = int13_capacity32 ( int13 );
 | 
		
	
		
			
			| 650 | 782 |  	ix86->regs.cx = ( blocks >> 16 );
 | 
		
	
		
			
			| 651 | 783 |  	ix86->regs.dx = ( blocks & 0xffff );
 | 
		
	
		
			
			| 652 | 784 |  	return INT13_DISK_TYPE_HDD;
 | 
		
	
	
		
			
			|  | @@ -916,14 +1048,14 @@ static int int13_get_extended_parameters ( struct int13_drive *int13,
 | 
		
	
		
			
			| 916 | 1048 |  	memset ( ¶ms, 0, sizeof ( params ) );
 | 
		
	
		
			
			| 917 | 1049 |  	params.flags = INT13_FL_DMA_TRANSPARENT;
 | 
		
	
		
			
			| 918 | 1050 |  	if ( ( int13->cylinders < 1024 ) &&
 | 
		
	
		
			
			| 919 |  | -	     ( int13->capacity.blocks <= INT13_MAX_CHS_SECTORS ) ) {
 | 
		
	
		
			
			|  | 1051 | +	     ( int13_capacity ( int13 ) <= INT13_MAX_CHS_SECTORS ) ) {
 | 
		
	
		
			
			| 920 | 1052 |  		params.flags |= INT13_FL_CHS_VALID;
 | 
		
	
		
			
			| 921 | 1053 |  	}
 | 
		
	
		
			
			| 922 | 1054 |  	params.cylinders = int13->cylinders;
 | 
		
	
		
			
			| 923 | 1055 |  	params.heads = int13->heads;
 | 
		
	
		
			
			| 924 | 1056 |  	params.sectors_per_track = int13->sectors_per_track;
 | 
		
	
		
			
			| 925 |  | -	params.sectors = int13->capacity.blocks;
 | 
		
	
		
			
			| 926 |  | -	params.sector_size = int13->capacity.blksize;
 | 
		
	
		
			
			|  | 1057 | +	params.sectors = int13_capacity ( int13 );
 | 
		
	
		
			
			|  | 1058 | +	params.sector_size = int13_blksize ( int13 );
 | 
		
	
		
			
			| 927 | 1059 |  	memset ( ¶ms.dpte, 0xff, sizeof ( params.dpte ) );
 | 
		
	
		
			
			| 928 | 1060 |  	if ( ( rc = int13_device_path_info ( int13, ¶ms.dpi ) ) != 0 ) {
 | 
		
	
		
			
			| 929 | 1061 |  		DBGC ( int13, "INT13 drive %02x could not provide device "
 | 
		
	
	
		
			
			|  | @@ -958,6 +1090,41 @@ static int int13_get_extended_parameters ( struct int13_drive *int13,
 | 
		
	
		
			
			| 958 | 1090 |  	return 0;
 | 
		
	
		
			
			| 959 | 1091 |  }
 | 
		
	
		
			
			| 960 | 1092 |  
 | 
		
	
		
			
			|  | 1093 | +/**
 | 
		
	
		
			
			|  | 1094 | + * INT 13, 4d - Read CD-ROM boot catalog
 | 
		
	
		
			
			|  | 1095 | + *
 | 
		
	
		
			
			|  | 1096 | + * @v int13		Emulated drive
 | 
		
	
		
			
			|  | 1097 | + * @v ds:si		Command packet
 | 
		
	
		
			
			|  | 1098 | + * @ret status		Status code
 | 
		
	
		
			
			|  | 1099 | + */
 | 
		
	
		
			
			|  | 1100 | +static int int13_cdrom_read_boot_catalog ( struct int13_drive *int13,
 | 
		
	
		
			
			|  | 1101 | +					   struct i386_all_regs *ix86 ) {
 | 
		
	
		
			
			|  | 1102 | +	struct int13_cdrom_boot_catalog_command command;
 | 
		
	
		
			
			|  | 1103 | +	int rc;
 | 
		
	
		
			
			|  | 1104 | +
 | 
		
	
		
			
			|  | 1105 | +	/* Fail if we have no boot catalog */
 | 
		
	
		
			
			|  | 1106 | +	if ( ! int13->boot_catalog ) {
 | 
		
	
		
			
			|  | 1107 | +		DBGC ( int13, "INT13 drive %02x has no boot catalog\n",
 | 
		
	
		
			
			|  | 1108 | +		       int13->drive );
 | 
		
	
		
			
			|  | 1109 | +		return -INT13_STATUS_INVALID;
 | 
		
	
		
			
			|  | 1110 | +	}
 | 
		
	
		
			
			|  | 1111 | +
 | 
		
	
		
			
			|  | 1112 | +	/* Read parameters from command packet */
 | 
		
	
		
			
			|  | 1113 | +	copy_from_real ( &command, ix86->segs.ds, ix86->regs.si,
 | 
		
	
		
			
			|  | 1114 | +			 sizeof ( command ) );
 | 
		
	
		
			
			|  | 1115 | +
 | 
		
	
		
			
			|  | 1116 | +	/* Read from boot catalog */
 | 
		
	
		
			
			|  | 1117 | +	if ( ( rc = int13_rw ( int13, ( int13->boot_catalog + command.start ),
 | 
		
	
		
			
			|  | 1118 | +			       command.count, phys_to_user ( command.buffer ),
 | 
		
	
		
			
			|  | 1119 | +			       block_read ) ) != 0 ) {
 | 
		
	
		
			
			|  | 1120 | +		DBGC ( int13, "INT13 drive %02x could not read boot catalog: "
 | 
		
	
		
			
			|  | 1121 | +		       "%s\n", int13->drive, strerror ( rc ) );
 | 
		
	
		
			
			|  | 1122 | +		return -INT13_STATUS_READ_ERROR;
 | 
		
	
		
			
			|  | 1123 | +	}
 | 
		
	
		
			
			|  | 1124 | +
 | 
		
	
		
			
			|  | 1125 | +	return 0;
 | 
		
	
		
			
			|  | 1126 | +}
 | 
		
	
		
			
			|  | 1127 | +
 | 
		
	
		
			
			| 961 | 1128 |  /**
 | 
		
	
		
			
			| 962 | 1129 |   * INT 13 handler
 | 
		
	
		
			
			| 963 | 1130 |   *
 | 
		
	
	
		
			
			|  | @@ -1025,6 +1192,9 @@ static __asmcall void int13 ( struct i386_all_regs *ix86 ) {
 | 
		
	
		
			
			| 1025 | 1192 |  		case INT13_GET_EXTENDED_PARAMETERS:
 | 
		
	
		
			
			| 1026 | 1193 |  			status = int13_get_extended_parameters ( int13, ix86 );
 | 
		
	
		
			
			| 1027 | 1194 |  			break;
 | 
		
	
		
			
			|  | 1195 | +		case INT13_CDROM_READ_BOOT_CATALOG:
 | 
		
	
		
			
			|  | 1196 | +			status = int13_cdrom_read_boot_catalog ( int13, ix86 );
 | 
		
	
		
			
			|  | 1197 | +			break;
 | 
		
	
		
			
			| 1028 | 1198 |  		default:
 | 
		
	
		
			
			| 1029 | 1199 |  			DBGC2 ( int13, "*** Unrecognised INT13 ***\n" );
 | 
		
	
		
			
			| 1030 | 1200 |  			status = -INT13_STATUS_INVALID;
 | 
		
	
	
		
			
			|  | @@ -1174,6 +1344,7 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
 | 
		
	
		
			
			| 1174 | 1344 |  	struct int13_drive *int13;
 | 
		
	
		
			
			| 1175 | 1345 |  	uint8_t num_drives;
 | 
		
	
		
			
			| 1176 | 1346 |  	unsigned int natural_drive;
 | 
		
	
		
			
			|  | 1347 | +	void *scratch;
 | 
		
	
		
			
			| 1177 | 1348 |  	int rc;
 | 
		
	
		
			
			| 1178 | 1349 |  
 | 
		
	
		
			
			| 1179 | 1350 |  	/* Calculate natural drive number */
 | 
		
	
	
		
			
			|  | @@ -1206,10 +1377,19 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
 | 
		
	
		
			
			| 1206 | 1377 |  
 | 
		
	
		
			
			| 1207 | 1378 |  	/* Read device capacity */
 | 
		
	
		
			
			| 1208 | 1379 |  	if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
 | 
		
	
		
			
			| 1209 |  | -		return rc;
 | 
		
	
		
			
			|  | 1380 | +		goto err_read_capacity;
 | 
		
	
		
			
			|  | 1381 | +
 | 
		
	
		
			
			|  | 1382 | +	/* Allocate scratch area */
 | 
		
	
		
			
			|  | 1383 | +	scratch = malloc ( int13_blksize ( int13 ) );
 | 
		
	
		
			
			|  | 1384 | +	if ( ! scratch )
 | 
		
	
		
			
			|  | 1385 | +		goto err_alloc_scratch;
 | 
		
	
		
			
			|  | 1386 | +
 | 
		
	
		
			
			|  | 1387 | +	/* Parse parameters, if present */
 | 
		
	
		
			
			|  | 1388 | +	if ( ( rc = int13_parse_iso9660 ( int13, scratch ) ) != 0 )
 | 
		
	
		
			
			|  | 1389 | +		goto err_parse_iso9660;
 | 
		
	
		
			
			| 1210 | 1390 |  
 | 
		
	
		
			
			| 1211 | 1391 |  	/* Give drive a default geometry */
 | 
		
	
		
			
			| 1212 |  | -	if ( ( rc = int13_guess_geometry ( int13 ) ) != 0 )
 | 
		
	
		
			
			|  | 1392 | +	if ( ( rc = int13_guess_geometry ( int13, scratch ) ) != 0 )
 | 
		
	
		
			
			| 1213 | 1393 |  		goto err_guess_geometry;
 | 
		
	
		
			
			| 1214 | 1394 |  
 | 
		
	
		
			
			| 1215 | 1395 |  	DBGC ( int13, "INT13 drive %02x (naturally %02x) registered with C/H/S "
 | 
		
	
	
		
			
			|  | @@ -1228,9 +1408,14 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
 | 
		
	
		
			
			| 1228 | 1408 |  	/* Update BIOS drive count */
 | 
		
	
		
			
			| 1229 | 1409 |  	int13_set_num_drives();
 | 
		
	
		
			
			| 1230 | 1410 |  
 | 
		
	
		
			
			|  | 1411 | +	free ( scratch );
 | 
		
	
		
			
			| 1231 | 1412 |  	return 0;
 | 
		
	
		
			
			| 1232 | 1413 |  
 | 
		
	
		
			
			| 1233 | 1414 |   err_guess_geometry:
 | 
		
	
		
			
			|  | 1415 | + err_parse_iso9660:
 | 
		
	
		
			
			|  | 1416 | +	free ( scratch );
 | 
		
	
		
			
			|  | 1417 | + err_alloc_scratch:
 | 
		
	
		
			
			|  | 1418 | + err_read_capacity:
 | 
		
	
		
			
			| 1234 | 1419 |   err_reopen_block:
 | 
		
	
		
			
			| 1235 | 1420 |  	intf_shutdown ( &int13->block, rc );
 | 
		
	
		
			
			| 1236 | 1421 |  	ref_put ( &int13->refcnt );
 | 
		
	
	
		
			
			|  | @@ -1297,53 +1482,172 @@ static void int13_unhook ( unsigned int drive ) {
 | 
		
	
		
			
			| 1297 | 1482 |  }
 | 
		
	
		
			
			| 1298 | 1483 |  
 | 
		
	
		
			
			| 1299 | 1484 |  /**
 | 
		
	
		
			
			| 1300 |  | - * Attempt to boot from an INT 13 drive
 | 
		
	
		
			
			|  | 1485 | + * Load and verify master boot record from INT 13 drive
 | 
		
	
		
			
			| 1301 | 1486 |   *
 | 
		
	
		
			
			| 1302 | 1487 |   * @v drive		Drive number
 | 
		
	
		
			
			|  | 1488 | + * @v address		Boot code address to fill in
 | 
		
	
		
			
			| 1303 | 1489 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 1304 |  | - *
 | 
		
	
		
			
			| 1305 |  | - * This boots from the specified INT 13 drive by loading the Master
 | 
		
	
		
			
			| 1306 |  | - * Boot Record to 0000:7c00 and jumping to it.  INT 18 is hooked to
 | 
		
	
		
			
			| 1307 |  | - * capture an attempt by the MBR to boot the next device.  (This is
 | 
		
	
		
			
			| 1308 |  | - * the closest thing to a return path from an MBR).
 | 
		
	
		
			
			| 1309 |  | - *
 | 
		
	
		
			
			| 1310 |  | - * Note that this function can never return success, by definition.
 | 
		
	
		
			
			| 1311 | 1490 |   */
 | 
		
	
		
			
			| 1312 |  | -static int int13_boot ( unsigned int drive ) {
 | 
		
	
		
			
			| 1313 |  | -	struct memory_map memmap;
 | 
		
	
		
			
			| 1314 |  | -	int status, signature;
 | 
		
	
		
			
			| 1315 |  | -	int discard_c, discard_d;
 | 
		
	
		
			
			| 1316 |  | -	int rc;
 | 
		
	
		
			
			| 1317 |  | -
 | 
		
	
		
			
			| 1318 |  | -	DBG ( "INT13 drive %02x booting\n", drive );
 | 
		
	
		
			
			| 1319 |  | -
 | 
		
	
		
			
			| 1320 |  | -	/* Use INT 13 to read the boot sector */
 | 
		
	
		
			
			|  | 1491 | +static int int13_load_mbr ( unsigned int drive, struct segoff *address ) {
 | 
		
	
		
			
			|  | 1492 | +	uint8_t status;
 | 
		
	
		
			
			|  | 1493 | +	int discard_b, discard_c, discard_d;
 | 
		
	
		
			
			|  | 1494 | +	uint16_t magic;
 | 
		
	
		
			
			|  | 1495 | +
 | 
		
	
		
			
			|  | 1496 | +	/* Use INT 13, 02 to read the MBR */
 | 
		
	
		
			
			|  | 1497 | +	address->segment = 0;
 | 
		
	
		
			
			|  | 1498 | +	address->offset = 0x7c00;
 | 
		
	
		
			
			| 1321 | 1499 |  	__asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
 | 
		
	
		
			
			| 1322 |  | -					   "pushw $0\n\t"
 | 
		
	
		
			
			|  | 1500 | +					   "pushl %%ebx\n\t"
 | 
		
	
		
			
			|  | 1501 | +					   "popw %%bx\n\t"
 | 
		
	
		
			
			| 1323 | 1502 |  					   "popw %%es\n\t"
 | 
		
	
		
			
			| 1324 | 1503 |  					   "stc\n\t"
 | 
		
	
		
			
			| 1325 | 1504 |  					   "sti\n\t"
 | 
		
	
		
			
			| 1326 | 1505 |  					   "int $0x13\n\t"
 | 
		
	
		
			
			| 1327 | 1506 |  					   "sti\n\t" /* BIOS bugs */
 | 
		
	
		
			
			| 1328 | 1507 |  					   "jc 1f\n\t"
 | 
		
	
		
			
			| 1329 |  | -					   "xorl %%eax, %%eax\n\t"
 | 
		
	
		
			
			|  | 1508 | +					   "xorw %%ax, %%ax\n\t"
 | 
		
	
		
			
			| 1330 | 1509 |  					   "\n1:\n\t"
 | 
		
	
		
			
			| 1331 |  | -					   "movzwl %%es:0x7dfe, %%ebx\n\t"
 | 
		
	
		
			
			| 1332 | 1510 |  					   "popw %%es\n\t" )
 | 
		
	
		
			
			| 1333 |  | -			       : "=a" ( status ), "=b" ( signature ),
 | 
		
	
		
			
			|  | 1511 | +			       : "=a" ( status ), "=b" ( discard_b ),
 | 
		
	
		
			
			| 1334 | 1512 |  				 "=c" ( discard_c ), "=d" ( discard_d )
 | 
		
	
		
			
			| 1335 |  | -			       : "a" ( 0x0201 ), "b" ( 0x7c00 ),
 | 
		
	
		
			
			|  | 1513 | +			       : "a" ( 0x0201 ), "b" ( *address ),
 | 
		
	
		
			
			| 1336 | 1514 |  				 "c" ( 1 ), "d" ( drive ) );
 | 
		
	
		
			
			| 1337 |  | -	if ( status )
 | 
		
	
		
			
			|  | 1515 | +	if ( status ) {
 | 
		
	
		
			
			|  | 1516 | +		DBG ( "INT13 drive %02x could not read MBR (status %02x)\n",
 | 
		
	
		
			
			|  | 1517 | +		      drive, status );
 | 
		
	
		
			
			| 1338 | 1518 |  		return -EIO;
 | 
		
	
		
			
			|  | 1519 | +	}
 | 
		
	
		
			
			| 1339 | 1520 |  
 | 
		
	
		
			
			| 1340 |  | -	/* Check signature is correct */
 | 
		
	
		
			
			| 1341 |  | -	if ( signature != be16_to_cpu ( 0x55aa ) ) {
 | 
		
	
		
			
			| 1342 |  | -		DBG ( "INT13 drive %02x invalid disk signature %#04x (should "
 | 
		
	
		
			
			| 1343 |  | -		      "be 0x55aa)\n", drive, cpu_to_be16 ( signature ) );
 | 
		
	
		
			
			|  | 1521 | +	/* Check magic signature */
 | 
		
	
		
			
			|  | 1522 | +	get_real ( magic, address->segment,
 | 
		
	
		
			
			|  | 1523 | +		   ( address->offset +
 | 
		
	
		
			
			|  | 1524 | +		     offsetof ( struct master_boot_record, magic ) ) );
 | 
		
	
		
			
			|  | 1525 | +	if ( magic != INT13_MBR_MAGIC ) {
 | 
		
	
		
			
			|  | 1526 | +		DBG ( "INT13 drive %02x does not contain a valid MBR\n",
 | 
		
	
		
			
			|  | 1527 | +		      drive );
 | 
		
	
		
			
			| 1344 | 1528 |  		return -ENOEXEC;
 | 
		
	
		
			
			| 1345 | 1529 |  	}
 | 
		
	
		
			
			| 1346 | 1530 |  
 | 
		
	
		
			
			|  | 1531 | +	return 0;
 | 
		
	
		
			
			|  | 1532 | +}
 | 
		
	
		
			
			|  | 1533 | +
 | 
		
	
		
			
			|  | 1534 | +/** El Torito boot catalog command packet */
 | 
		
	
		
			
			|  | 1535 | +static struct int13_cdrom_boot_catalog_command __data16 ( eltorito_cmd ) = {
 | 
		
	
		
			
			|  | 1536 | +	.size = sizeof ( struct int13_cdrom_boot_catalog_command ),
 | 
		
	
		
			
			|  | 1537 | +	.count = 1,
 | 
		
	
		
			
			|  | 1538 | +	.buffer = 0x7c00,
 | 
		
	
		
			
			|  | 1539 | +	.start = 0,
 | 
		
	
		
			
			|  | 1540 | +};
 | 
		
	
		
			
			|  | 1541 | +#define eltorito_cmd __use_data16 ( eltorito_cmd )
 | 
		
	
		
			
			|  | 1542 | +
 | 
		
	
		
			
			|  | 1543 | +/** El Torito disk address packet */
 | 
		
	
		
			
			|  | 1544 | +static struct int13_disk_address __bss16 ( eltorito_address );
 | 
		
	
		
			
			|  | 1545 | +#define eltorito_address __use_data16 ( eltorito_address )
 | 
		
	
		
			
			|  | 1546 | +
 | 
		
	
		
			
			|  | 1547 | +/**
 | 
		
	
		
			
			|  | 1548 | + * Load and verify El Torito boot record from INT 13 drive
 | 
		
	
		
			
			|  | 1549 | + *
 | 
		
	
		
			
			|  | 1550 | + * @v drive		Drive number
 | 
		
	
		
			
			|  | 1551 | + * @v address		Boot code address to fill in
 | 
		
	
		
			
			|  | 1552 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 1553 | + */
 | 
		
	
		
			
			|  | 1554 | +static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
 | 
		
	
		
			
			|  | 1555 | +	struct {
 | 
		
	
		
			
			|  | 1556 | +		struct eltorito_validation_entry valid;
 | 
		
	
		
			
			|  | 1557 | +		struct eltorito_boot_entry boot;
 | 
		
	
		
			
			|  | 1558 | +	} __attribute__ (( packed )) catalog;
 | 
		
	
		
			
			|  | 1559 | +	uint8_t status;
 | 
		
	
		
			
			|  | 1560 | +
 | 
		
	
		
			
			|  | 1561 | +	/* Use INT 13, 4d to read the boot catalog */
 | 
		
	
		
			
			|  | 1562 | +	__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
 | 
		
	
		
			
			|  | 1563 | +					   "sti\n\t"
 | 
		
	
		
			
			|  | 1564 | +					   "int $0x13\n\t"
 | 
		
	
		
			
			|  | 1565 | +					   "sti\n\t" /* BIOS bugs */
 | 
		
	
		
			
			|  | 1566 | +					   "jc 1f\n\t"
 | 
		
	
		
			
			|  | 1567 | +					   "xorw %%ax, %%ax\n\t"
 | 
		
	
		
			
			|  | 1568 | +					   "\n1:\n\t" )
 | 
		
	
		
			
			|  | 1569 | +			       : "=a" ( status )
 | 
		
	
		
			
			|  | 1570 | +			       : "a" ( 0x4d00 ), "d" ( drive ),
 | 
		
	
		
			
			|  | 1571 | +				 "S" ( __from_data16 ( &eltorito_cmd ) ) );
 | 
		
	
		
			
			|  | 1572 | +	if ( status ) {
 | 
		
	
		
			
			|  | 1573 | +		DBG ( "INT13 drive %02x could not read El Torito boot catalog "
 | 
		
	
		
			
			|  | 1574 | +		      "(status %02x)\n", drive, status );
 | 
		
	
		
			
			|  | 1575 | +		return -EIO;
 | 
		
	
		
			
			|  | 1576 | +	}
 | 
		
	
		
			
			|  | 1577 | +	copy_from_user ( &catalog, phys_to_user ( eltorito_cmd.buffer ), 0,
 | 
		
	
		
			
			|  | 1578 | +			 sizeof ( catalog ) );
 | 
		
	
		
			
			|  | 1579 | +
 | 
		
	
		
			
			|  | 1580 | +	/* Sanity checks */
 | 
		
	
		
			
			|  | 1581 | +	if ( catalog.valid.platform_id != ELTORITO_PLATFORM_X86 ) {
 | 
		
	
		
			
			|  | 1582 | +		DBG ( "INT13 drive %02x El Torito specifies unknown platform "
 | 
		
	
		
			
			|  | 1583 | +		      "%02x\n", drive, catalog.valid.platform_id );
 | 
		
	
		
			
			|  | 1584 | +		return -ENOEXEC;
 | 
		
	
		
			
			|  | 1585 | +	}
 | 
		
	
		
			
			|  | 1586 | +	if ( catalog.boot.indicator != ELTORITO_BOOTABLE ) {
 | 
		
	
		
			
			|  | 1587 | +		DBG ( "INT13 drive %02x El Torito is not bootable\n", drive );
 | 
		
	
		
			
			|  | 1588 | +		return -ENOEXEC;
 | 
		
	
		
			
			|  | 1589 | +	}
 | 
		
	
		
			
			|  | 1590 | +	if ( catalog.boot.media_type != ELTORITO_NO_EMULATION ) {
 | 
		
	
		
			
			|  | 1591 | +		DBG ( "INT13 drive %02x El Torito requires emulation "
 | 
		
	
		
			
			|  | 1592 | +		       "type %02x\n", drive, catalog.boot.media_type );
 | 
		
	
		
			
			|  | 1593 | +		return -ENOTSUP;
 | 
		
	
		
			
			|  | 1594 | +	}
 | 
		
	
		
			
			|  | 1595 | +	DBG ( "INT13 drive %02x El Torito boot image at LBA %08x (count %d)\n",
 | 
		
	
		
			
			|  | 1596 | +	      drive, catalog.boot.start, catalog.boot.length );
 | 
		
	
		
			
			|  | 1597 | +	address->segment = ( catalog.boot.load_segment ?
 | 
		
	
		
			
			|  | 1598 | +			     catalog.boot.load_segment : 0x7c0 );
 | 
		
	
		
			
			|  | 1599 | +	address->offset = 0;
 | 
		
	
		
			
			|  | 1600 | +	DBG ( "INT13 drive %02x El Torito boot image loads at %04x:%04x\n",
 | 
		
	
		
			
			|  | 1601 | +	      drive, address->segment, address->offset );
 | 
		
	
		
			
			|  | 1602 | +
 | 
		
	
		
			
			|  | 1603 | +	/* Use INT 13, 42 to read the boot image */
 | 
		
	
		
			
			|  | 1604 | +	eltorito_address.bufsize =
 | 
		
	
		
			
			|  | 1605 | +		offsetof ( typeof ( eltorito_address ), buffer_phys );
 | 
		
	
		
			
			|  | 1606 | +	eltorito_address.count = catalog.boot.length;
 | 
		
	
		
			
			|  | 1607 | +	eltorito_address.buffer = *address;
 | 
		
	
		
			
			|  | 1608 | +	eltorito_address.lba = catalog.boot.start;
 | 
		
	
		
			
			|  | 1609 | +	__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
 | 
		
	
		
			
			|  | 1610 | +					   "sti\n\t"
 | 
		
	
		
			
			|  | 1611 | +					   "int $0x13\n\t"
 | 
		
	
		
			
			|  | 1612 | +					   "sti\n\t" /* BIOS bugs */
 | 
		
	
		
			
			|  | 1613 | +					   "jc 1f\n\t"
 | 
		
	
		
			
			|  | 1614 | +					   "xorw %%ax, %%ax\n\t"
 | 
		
	
		
			
			|  | 1615 | +					   "\n1:\n\t" )
 | 
		
	
		
			
			|  | 1616 | +			       : "=a" ( status )
 | 
		
	
		
			
			|  | 1617 | +			       : "a" ( 0x4200 ), "d" ( drive ),
 | 
		
	
		
			
			|  | 1618 | +				 "S" ( __from_data16 ( &eltorito_address ) ) );
 | 
		
	
		
			
			|  | 1619 | +	if ( status ) {
 | 
		
	
		
			
			|  | 1620 | +		DBG ( "INT13 drive %02x could not read El Torito boot image "
 | 
		
	
		
			
			|  | 1621 | +		      "(status %02x)\n", drive, status );
 | 
		
	
		
			
			|  | 1622 | +		return -EIO;
 | 
		
	
		
			
			|  | 1623 | +	}
 | 
		
	
		
			
			|  | 1624 | +
 | 
		
	
		
			
			|  | 1625 | +	return 0;
 | 
		
	
		
			
			|  | 1626 | +}
 | 
		
	
		
			
			|  | 1627 | +
 | 
		
	
		
			
			|  | 1628 | +/**
 | 
		
	
		
			
			|  | 1629 | + * Attempt to boot from an INT 13 drive
 | 
		
	
		
			
			|  | 1630 | + *
 | 
		
	
		
			
			|  | 1631 | + * @v drive		Drive number
 | 
		
	
		
			
			|  | 1632 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 1633 | + *
 | 
		
	
		
			
			|  | 1634 | + * This boots from the specified INT 13 drive by loading the Master
 | 
		
	
		
			
			|  | 1635 | + * Boot Record to 0000:7c00 and jumping to it.  INT 18 is hooked to
 | 
		
	
		
			
			|  | 1636 | + * capture an attempt by the MBR to boot the next device.  (This is
 | 
		
	
		
			
			|  | 1637 | + * the closest thing to a return path from an MBR).
 | 
		
	
		
			
			|  | 1638 | + *
 | 
		
	
		
			
			|  | 1639 | + * Note that this function can never return success, by definition.
 | 
		
	
		
			
			|  | 1640 | + */
 | 
		
	
		
			
			|  | 1641 | +static int int13_boot ( unsigned int drive ) {
 | 
		
	
		
			
			|  | 1642 | +	struct memory_map memmap;
 | 
		
	
		
			
			|  | 1643 | +	struct segoff address;
 | 
		
	
		
			
			|  | 1644 | +	int rc;
 | 
		
	
		
			
			|  | 1645 | +
 | 
		
	
		
			
			|  | 1646 | +	/* Look for a usable boot sector */
 | 
		
	
		
			
			|  | 1647 | +	if ( ( ( rc = int13_load_mbr ( drive, &address ) ) != 0 ) &&
 | 
		
	
		
			
			|  | 1648 | +	     ( ( rc = int13_load_eltorito ( drive, &address ) ) != 0 ) )
 | 
		
	
		
			
			|  | 1649 | +		return rc;
 | 
		
	
		
			
			|  | 1650 | +
 | 
		
	
		
			
			| 1347 | 1651 |  	/* Dump out memory map prior to boot, if memmap debugging is
 | 
		
	
		
			
			| 1348 | 1652 |  	 * enabled.  Not required for program flow, but we have so
 | 
		
	
		
			
			| 1349 | 1653 |  	 * many problems that turn out to be memory-map related that
 | 
		
	
	
		
			
			|  | @@ -1352,7 +1656,8 @@ static int int13_boot ( unsigned int drive ) {
 | 
		
	
		
			
			| 1352 | 1656 |  	get_memmap ( &memmap );
 | 
		
	
		
			
			| 1353 | 1657 |  
 | 
		
	
		
			
			| 1354 | 1658 |  	/* Jump to boot sector */
 | 
		
	
		
			
			| 1355 |  | -	if ( ( rc = call_bootsector ( 0x0, 0x7c00, drive ) ) != 0 ) {
 | 
		
	
		
			
			|  | 1659 | +	if ( ( rc = call_bootsector ( address.segment, address.offset,
 | 
		
	
		
			
			|  | 1660 | +				      drive ) ) != 0 ) {
 | 
		
	
		
			
			| 1356 | 1661 |  		DBG ( "INT13 drive %02x boot returned: %s\n",
 | 
		
	
		
			
			| 1357 | 1662 |  		      drive, strerror ( rc ) );
 | 
		
	
		
			
			| 1358 | 1663 |  		return rc;
 |