mirror of
https://github.com/xcat2/xNBA.git
synced 2024-12-14 15:21:32 +00:00
Added geometry-guessing code based on the partition table
This commit is contained in:
parent
21bc2015f2
commit
0566ab2a2f
@ -201,6 +201,45 @@ struct int13_disk_parameters {
|
||||
|
||||
/** @} */
|
||||
|
||||
/** A C/H/S address within a partition table entry */
|
||||
struct partition_chs {
|
||||
/** Head number */
|
||||
uint8_t head;
|
||||
/** Sector number, plus high 2 bits of cylinder number */
|
||||
uint8_t cyl_sector;
|
||||
/** Low 8 bits of cylinder number */
|
||||
uint8_t cyl;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
#define PART_HEAD(chs) ( (chs).head )
|
||||
#define PART_SECTOR(chs) ( (chs).cyl_sector & 0x3f )
|
||||
#define PART_CYLINDER(chs) ( (chs).cyl | ( ( (chs).cyl_sector & 0xc0 ) << 2 ) )
|
||||
|
||||
/** A partition table entry within the MBR */
|
||||
struct partition_table_entry {
|
||||
/** Bootable flag */
|
||||
uint8_t bootable;
|
||||
/** C/H/S start address */
|
||||
struct partition_chs chs_start;
|
||||
/** System indicator (partition type) */
|
||||
uint8_t type;
|
||||
/** C/H/S end address */
|
||||
struct partition_chs chs_end;
|
||||
/** Linear start address */
|
||||
uint32_t start;
|
||||
/** Linear length */
|
||||
uint32_t length;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A Master Boot Record */
|
||||
struct master_boot_record {
|
||||
uint8_t pad[446];
|
||||
/** Partition table */
|
||||
struct partition_table_entry partitions[4];
|
||||
/** 0x55aa MBR signature */
|
||||
uint16_t signature;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
extern void register_int13_drive ( struct int13_drive *drive );
|
||||
extern void unregister_int13_drive ( struct int13_drive *drive );
|
||||
extern int int13_boot ( unsigned int drive );
|
||||
|
@ -437,6 +437,60 @@ static void unhook_int13 ( void ) {
|
||||
&int13_vector );
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess INT 13 drive geometry
|
||||
*
|
||||
* @v drive Emulated drive
|
||||
*
|
||||
* Guesses the drive geometry by inspecting the partition table.
|
||||
*/
|
||||
static void guess_int13_geometry ( struct int13_drive *drive ) {
|
||||
struct master_boot_record mbr;
|
||||
struct partition_table_entry *partition;
|
||||
unsigned int guessed_heads = 255;
|
||||
unsigned int guessed_sectors_per_track = 63;
|
||||
unsigned long blocks;
|
||||
unsigned long blocks_per_cyl;
|
||||
unsigned int i;
|
||||
|
||||
/* Scan through partition table and modify guesses for heads
|
||||
* and sectors_per_track if we find any used partitions.
|
||||
*/
|
||||
if ( drive->blockdev->read ( drive->blockdev, 0, 1,
|
||||
virt_to_user ( &mbr ) ) == 0 ) {
|
||||
for ( i = 0 ; i < 4 ; i++ ) {
|
||||
partition = &mbr.partitions[i];
|
||||
if ( ! partition->type )
|
||||
continue;
|
||||
guessed_heads =
|
||||
( PART_HEAD ( partition->chs_end ) + 1 );
|
||||
guessed_sectors_per_track =
|
||||
PART_SECTOR ( partition->chs_end );
|
||||
DBG ( "Guessing C/H/S xx/%d/%d based on partition "
|
||||
"%d\n", guessed_heads,
|
||||
guessed_sectors_per_track, ( i + 1 ) );
|
||||
}
|
||||
} else {
|
||||
DBG ( "Could not read partition table to guess geometry\n" );
|
||||
}
|
||||
|
||||
/* Apply guesses if no geometry already specified */
|
||||
if ( ! drive->heads )
|
||||
drive->heads = guessed_heads;
|
||||
if ( ! drive->sectors_per_track )
|
||||
drive->sectors_per_track = guessed_sectors_per_track;
|
||||
if ( ! drive->cylinders ) {
|
||||
/* Avoid attempting a 64-bit divide on a 32-bit system */
|
||||
blocks = ( ( drive->blockdev->blocks <= ULONG_MAX ) ?
|
||||
drive->blockdev->blocks : ULONG_MAX );
|
||||
blocks_per_cyl = ( drive->heads * drive->sectors_per_track );
|
||||
assert ( blocks_per_cyl != 0 );
|
||||
drive->cylinders = ( blocks / blocks_per_cyl );
|
||||
if ( drive->cylinders > 1024 )
|
||||
drive->cylinders = 1024;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register INT 13 emulated drive
|
||||
*
|
||||
@ -450,22 +504,9 @@ static void unhook_int13 ( void ) {
|
||||
*/
|
||||
void register_int13_drive ( struct int13_drive *drive ) {
|
||||
uint8_t num_drives;
|
||||
unsigned long blocks;
|
||||
unsigned long blocks_per_cyl;
|
||||
|
||||
/* Give drive a default geometry if none specified */
|
||||
if ( ! drive->heads )
|
||||
drive->heads = 255;
|
||||
if ( ! drive->sectors_per_track )
|
||||
drive->sectors_per_track = 63;
|
||||
if ( ! drive->cylinders ) {
|
||||
/* Avoid attempting a 64-bit divide on a 32-bit system */
|
||||
blocks = ( ( drive->blockdev->blocks <= ULONG_MAX ) ?
|
||||
drive->blockdev->blocks : ULONG_MAX );
|
||||
blocks_per_cyl = ( drive->heads * drive->sectors_per_track );
|
||||
assert ( blocks_per_cyl != 0 );
|
||||
drive->cylinders = ( blocks / blocks_per_cyl );
|
||||
}
|
||||
guess_int13_geometry ( drive );
|
||||
|
||||
/* Assign drive number if none specified, update BIOS drive count */
|
||||
get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
|
||||
|
Loading…
Reference in New Issue
Block a user