mirror of
https://github.com/reactos/reactos.git
synced 2025-02-25 01:39:30 +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.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// #if defined(__i386__) || defined(_M_AMD64)
|
||||||
|
|
||||||
#include <freeldr.h>
|
#include <freeldr.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
@ -25,6 +27,7 @@
|
||||||
DBG_DEFAULT_CHANNEL(DISK);
|
DBG_DEFAULT_CHANNEL(DISK);
|
||||||
|
|
||||||
#include <pshpack2.h>
|
#include <pshpack2.h>
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UCHAR PacketSize; // 00h - Size of packet (10h or 18h)
|
UCHAR PacketSize; // 00h - Size of packet (10h or 18h)
|
||||||
|
@ -38,6 +41,38 @@ typedef struct
|
||||||
// Commented since some earlier BIOSes refuse to work with
|
// Commented since some earlier BIOSes refuse to work with
|
||||||
// such extended structure
|
// such extended structure
|
||||||
} I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET;
|
} 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>
|
#include <poppack.h>
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* 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
|
BOOLEAN
|
||||||
PcDiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
|
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...)
|
// we were booting from network (and: PC --> PXE, etc...)
|
||||||
// and if so, set the correct ARC path. But then this new
|
// and if so, set the correct ARC path. But then this new
|
||||||
// logic could be moved back to DiskGetBootPath...
|
// 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())
|
if (PxeInit())
|
||||||
{
|
{
|
||||||
strcpy(BootPath, "net(0)");
|
strcpy(BootPath, "net(0)");
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
DBG_DEFAULT_CHANNEL(DISK);
|
DBG_DEFAULT_CHANNEL(DISK);
|
||||||
|
|
||||||
|
CHAR FrldrBootPath[MAX_PATH] = "";
|
||||||
|
|
||||||
static BOOLEAN bReportError = TRUE;
|
static BOOLEAN bReportError = TRUE;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
@ -98,93 +100,55 @@ BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber)
|
||||||
return TRUE;
|
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)";
|
if (*FrldrBootPath)
|
||||||
char Device[4];
|
goto Done;
|
||||||
MASTER_BOOT_RECORD MasterBootRecord;
|
|
||||||
|
|
||||||
/* 0x49 is our magic ramdisk drive, so try to detect it first */
|
/* 0x49 is our magic ramdisk drive, so try to detect it first */
|
||||||
if (FrldrBootDrive == 0x49)
|
if (FrldrBootDrive == 0x49)
|
||||||
{
|
{
|
||||||
/* This is the ramdisk. See ArmDiskGetBootPath too... */
|
/* This is the ramdisk. See ArmDiskGetBootPath too... */
|
||||||
|
// sprintf(FrldrBootPath, "ramdisk(%u)", 0);
|
||||||
PCCH RamDiskPath = "ramdisk(0)";
|
strcpy(FrldrBootPath, "ramdisk(0)");
|
||||||
|
|
||||||
if (Size < sizeof(RamDiskPath))
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(BootPath, RamDiskPath);
|
|
||||||
}
|
}
|
||||||
else if (FrldrBootDrive < 0x80)
|
else if (FrldrBootDrive < 0x80)
|
||||||
{
|
{
|
||||||
/* This is a floppy */
|
/* This is a floppy */
|
||||||
|
sprintf(FrldrBootPath, "multi(0)disk(0)fdisk(%u)", FrldrBootDrive);
|
||||||
if (Size <= sizeof(Path) + 7 + sizeof(Device))
|
}
|
||||||
|
else if (DiskIsCdRomDrive(FrldrBootDrive))
|
||||||
{
|
{
|
||||||
return FALSE;
|
/* This is a CD-ROM drive */
|
||||||
|
sprintf(FrldrBootPath, "multi(0)disk(0)cdrom(%u)", FrldrBootDrive - 0x80);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
strcpy(BootPath, Path);
|
|
||||||
|
|
||||||
_itoa(FrldrBootDrive, Device, 10);
|
|
||||||
strcat(BootPath, "fdisk(");
|
|
||||||
strcat(BootPath, Device);
|
|
||||||
strcat(BootPath, ")");
|
|
||||||
}
|
|
||||||
/* FIXME */
|
|
||||||
else if (DiskReadBootRecord(FrldrBootDrive, 0, &MasterBootRecord))
|
|
||||||
{
|
{
|
||||||
ULONG BootPartition;
|
ULONG BootPartition;
|
||||||
PARTITION_TABLE_ENTRY PartitionEntry;
|
PARTITION_TABLE_ENTRY PartitionEntry;
|
||||||
char Partition[4];
|
|
||||||
|
|
||||||
/* This is a hard disk */
|
/* This is a hard disk */
|
||||||
if (!DiskGetActivePartitionEntry(FrldrBootDrive, &PartitionEntry, &BootPartition))
|
if (!DiskGetActivePartitionEntry(FrldrBootDrive, &PartitionEntry, &BootPartition))
|
||||||
{
|
{
|
||||||
DbgPrint("Invalid active partition information\n");
|
ERR("Invalid active partition information\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrldrBootPartition = BootPartition;
|
FrldrBootPartition = BootPartition;
|
||||||
|
|
||||||
if (Size <= sizeof(Path) + 18 + sizeof(Device) + sizeof(Partition))
|
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;
|
return FALSE;
|
||||||
}
|
strncpy(BootPath, FrldrBootPath, Size);
|
||||||
|
|
||||||
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, ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,12 +125,17 @@ VOID DiskReportError (BOOLEAN bError);
|
||||||
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode);
|
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode);
|
||||||
PCSTR DiskGetErrorCodeString(ULONG ErrorCode);
|
PCSTR DiskGetErrorCodeString(ULONG ErrorCode);
|
||||||
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
|
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);
|
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