mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[FREELDR]
- Simplify the implementation of the 'DiskGetBootPath' function; - Cache the retrived freeldr boot path (corresponding to a given 'FrldrBootDrive' number); - Introduce a 'DiskIsCdRomDrive' function to attempt to fix CORE-12692 . svn path=/trunk/; revision=73621
This commit is contained in:
parent
841f48d8f2
commit
ff5f825f59
3 changed files with 145 additions and 67 deletions
|
@ -17,6 +17,8 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
// #if defined(__i386__) || defined(_M_AMD64)
|
||||
|
||||
#include <freeldr.h>
|
||||
|
||||
#define NDEBUG
|
||||
|
@ -25,6 +27,7 @@
|
|||
DBG_DEFAULT_CHANNEL(DISK);
|
||||
|
||||
#include <pshpack2.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR PacketSize; // 00h - Size of packet (10h or 18h)
|
||||
|
@ -38,6 +41,38 @@ typedef struct
|
|||
// Commented since some earlier BIOSes refuse to work with
|
||||
// such extended structure
|
||||
} I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR PacketSize; // 00h - Size of packet in bytes (13h)
|
||||
UCHAR MediaType; // 01h - Boot media type (see #00282)
|
||||
UCHAR DriveNumber; /* 02h - Drive number:
|
||||
* 00h Floppy image
|
||||
* 80h Bootable hard disk
|
||||
* 81h-FFh Nonbootable or no emulation
|
||||
*/
|
||||
UCHAR Controller; // 03h - CD-ROM controller number
|
||||
ULONG LBAImage; // 04h - Logical Block Address of disk image to emulate
|
||||
USHORT DeviceSpec; /* 08h - Device specification (see also #00282)
|
||||
* (IDE) Bit 0:
|
||||
* Drive is slave instead of master
|
||||
* (SCSI) Bits 7-0:
|
||||
* LUN and PUN
|
||||
* Bits 15-8:
|
||||
* Bus number
|
||||
*/
|
||||
USHORT Buffer; // 0Ah - Segment of 3K buffer for caching CD-ROM reads
|
||||
USHORT LoadSeg; // 0Ch - Load segment for initial boot image.
|
||||
// If 0000h, load at segment 07C0h.
|
||||
USHORT SectorCount; // 0Eh - Number of 512-byte virtual sectors to load
|
||||
// (only valid for AH=4Ch).
|
||||
UCHAR CHSGeometry[3]; /* 10h - Low byte of cylinder count (for INT 13/AH=08h)
|
||||
* 11h - Sector count, high bits of cylinder count (for INT 13/AH=08h)
|
||||
* 12h - Head count (for INT 13/AH=08h)
|
||||
*/
|
||||
UCHAR Reserved;
|
||||
} I386_CDROM_SPEC_PACKET, *PI386_CDROM_SPEC_PACKET;
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
@ -540,6 +575,69 @@ PcDiskGetCacheableBlockCount(UCHAR DriveNumber)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static BOOLEAN
|
||||
FallbackDiskIsCdRomDrive(UCHAR DriveNumber)
|
||||
{
|
||||
MASTER_BOOT_RECORD MasterBootRecord;
|
||||
|
||||
TRACE("FallbackDiskIsCdRomDrive(0x%x)\n", DriveNumber);
|
||||
|
||||
/* CD-ROM drive numbers are always > 0x80 */
|
||||
if (DriveNumber <= 0x80)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* We suppose that a CD-ROM does not have a MBR
|
||||
* (not always true: example of the Hybrid USB-ISOs).
|
||||
*/
|
||||
return !DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord);
|
||||
}
|
||||
|
||||
BOOLEAN DiskIsCdRomDrive(UCHAR DriveNumber)
|
||||
{
|
||||
REGS RegsIn, RegsOut;
|
||||
PI386_CDROM_SPEC_PACKET Packet = (PI386_CDROM_SPEC_PACKET)(BIOSCALLBUFFER);
|
||||
|
||||
TRACE("DiskIsCdRomDrive(0x%x)\n", DriveNumber);
|
||||
|
||||
/* CD-ROM drive numbers are always > 0x80 */
|
||||
if (DriveNumber <= 0x80)
|
||||
return FALSE;
|
||||
|
||||
/* Setup disk address packet */
|
||||
RtlZeroMemory(Packet, sizeof(*Packet));
|
||||
Packet->PacketSize = sizeof(*Packet);
|
||||
|
||||
/*
|
||||
* BIOS Int 13h, function 4B01h - Bootable CD-ROM - Get Disk Emulation Status
|
||||
* AX = 4B01h
|
||||
* DL = drive number
|
||||
* DS:SI -> empty specification packet
|
||||
* Return:
|
||||
* CF clear if successful
|
||||
* CF set on error
|
||||
* AX = return codes
|
||||
* DS:SI specification packet filled
|
||||
*/
|
||||
RegsIn.w.ax = 0x4B01;
|
||||
RegsIn.b.dl = DriveNumber;
|
||||
RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> specification packet
|
||||
RegsIn.w.si = BIOSCALLBUFOFFSET;
|
||||
|
||||
Int386(0x13, &RegsIn, &RegsOut);
|
||||
|
||||
// return (INT386_SUCCESS(RegsOut) && (Packet->DriveNumber == DriveNumber));
|
||||
/*
|
||||
* If the simple test failed, try to use the fallback code,
|
||||
* but we can be on *very* thin ice.
|
||||
*/
|
||||
if (!INT386_SUCCESS(RegsOut) || (Packet->DriveNumber != DriveNumber))
|
||||
return FallbackDiskIsCdRomDrive(DriveNumber);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
PcDiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
|
||||
{
|
||||
|
@ -550,6 +648,17 @@ PcDiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
|
|||
// we were booting from network (and: PC --> PXE, etc...)
|
||||
// and if so, set the correct ARC path. But then this new
|
||||
// logic could be moved back to DiskGetBootPath...
|
||||
|
||||
if (*FrldrBootPath)
|
||||
{
|
||||
/* Copy back the buffer */
|
||||
if (Size < strlen(FrldrBootPath) + 1)
|
||||
return FALSE;
|
||||
strncpy(BootPath, FrldrBootPath, Size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// FIXME! FIXME! Do this in some drive recognition procedure!!!!
|
||||
if (PxeInit())
|
||||
{
|
||||
strcpy(BootPath, "net(0)");
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
DBG_DEFAULT_CHANNEL(DISK);
|
||||
|
||||
CHAR FrldrBootPath[MAX_PATH] = "";
|
||||
|
||||
static BOOLEAN bReportError = TRUE;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
@ -98,93 +100,55 @@ BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
|
||||
|
||||
extern BOOLEAN
|
||||
DiskIsCdRomDrive(UCHAR DriveNumber);
|
||||
|
||||
BOOLEAN DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
|
||||
{
|
||||
static char Path[] = "multi(0)disk(0)";
|
||||
char Device[4];
|
||||
MASTER_BOOT_RECORD MasterBootRecord;
|
||||
if (*FrldrBootPath)
|
||||
goto Done;
|
||||
|
||||
/* 0x49 is our magic ramdisk drive, so try to detect it first */
|
||||
if (FrldrBootDrive == 0x49)
|
||||
{
|
||||
/* This is the ramdisk. See ArmDiskGetBootPath too... */
|
||||
|
||||
PCCH RamDiskPath = "ramdisk(0)";
|
||||
|
||||
if (Size < sizeof(RamDiskPath))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strcpy(BootPath, RamDiskPath);
|
||||
// sprintf(FrldrBootPath, "ramdisk(%u)", 0);
|
||||
strcpy(FrldrBootPath, "ramdisk(0)");
|
||||
}
|
||||
else if (FrldrBootDrive < 0x80)
|
||||
{
|
||||
/* This is a floppy */
|
||||
|
||||
if (Size <= sizeof(Path) + 7 + sizeof(Device))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strcpy(BootPath, Path);
|
||||
|
||||
_itoa(FrldrBootDrive, Device, 10);
|
||||
strcat(BootPath, "fdisk(");
|
||||
strcat(BootPath, Device);
|
||||
strcat(BootPath, ")");
|
||||
sprintf(FrldrBootPath, "multi(0)disk(0)fdisk(%u)", FrldrBootDrive);
|
||||
}
|
||||
/* FIXME */
|
||||
else if (DiskReadBootRecord(FrldrBootDrive, 0, &MasterBootRecord))
|
||||
else if (DiskIsCdRomDrive(FrldrBootDrive))
|
||||
{
|
||||
/* This is a CD-ROM drive */
|
||||
sprintf(FrldrBootPath, "multi(0)disk(0)cdrom(%u)", FrldrBootDrive - 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG BootPartition;
|
||||
PARTITION_TABLE_ENTRY PartitionEntry;
|
||||
char Partition[4];
|
||||
|
||||
/* This is a hard disk */
|
||||
if (!DiskGetActivePartitionEntry(FrldrBootDrive, &PartitionEntry, &BootPartition))
|
||||
{
|
||||
DbgPrint("Invalid active partition information\n");
|
||||
ERR("Invalid active partition information\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FrldrBootPartition = BootPartition;
|
||||
|
||||
if (Size <= sizeof(Path) + 18 + sizeof(Device) + sizeof(Partition))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strcpy(BootPath, Path);
|
||||
|
||||
_itoa(FrldrBootDrive - 0x80, Device, 10);
|
||||
strcat(BootPath, "rdisk(");
|
||||
strcat(BootPath, Device);
|
||||
strcat(BootPath, ")");
|
||||
|
||||
_itoa(FrldrBootPartition, Partition, 10);
|
||||
strcat(BootPath, "partition(");
|
||||
strcat(BootPath, Partition);
|
||||
strcat(BootPath, ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a CD-ROM drive */
|
||||
|
||||
if (Size <= sizeof(Path) + 7 + sizeof(Device))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strcpy(BootPath, Path);
|
||||
|
||||
_itoa(FrldrBootDrive - 0x80, Device, 10);
|
||||
strcat(BootPath, "cdrom(");
|
||||
strcat(BootPath, Device);
|
||||
strcat(BootPath, ")");
|
||||
sprintf(FrldrBootPath, "multi(0)disk(0)rdisk(%u)partition(%lu)",
|
||||
FrldrBootDrive - 0x80, FrldrBootPartition);
|
||||
}
|
||||
|
||||
Done:
|
||||
/* Copy back the buffer */
|
||||
if (Size < strlen(FrldrBootPath) + 1)
|
||||
return FALSE;
|
||||
strncpy(BootPath, FrldrBootPath, Size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,16 +121,21 @@ VOID DiskStopFloppyMotor(VOID);
|
|||
// FreeLoader Disk Functions
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
VOID DiskReportError (BOOLEAN bError);
|
||||
VOID DiskReportError(BOOLEAN bError);
|
||||
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode);
|
||||
PCSTR DiskGetErrorCodeString(ULONG ErrorCode);
|
||||
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
|
||||
extern UCHAR FrldrBootDrive;
|
||||
extern ULONG FrldrBootPartition;
|
||||
extern PVOID DiskReadBuffer;
|
||||
extern SIZE_T DiskReadBufferSize;
|
||||
|
||||
BOOLEAN DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size);
|
||||
/* Platform-specific boot drive and partition numbers */
|
||||
extern UCHAR FrldrBootDrive;
|
||||
extern ULONG FrldrBootPartition;
|
||||
/* ARC path of the boot drive and partition */
|
||||
extern CHAR FrldrBootPath[MAX_PATH];
|
||||
|
||||
/* Buffer for disk reads */
|
||||
extern PVOID DiskReadBuffer;
|
||||
extern SIZE_T DiskReadBufferSize;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in a new issue