| 
				
			 | 
			
			
				
				@@ -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; 
			 |