From ff5f825f597a159ffeacb2ef341bf8559596ba1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 29 Jan 2017 15:43:12 +0000 Subject: [PATCH] [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 --- .../boot/freeldr/freeldr/arch/i386/pcdisk.c | 109 ++++++++++++++++++ reactos/boot/freeldr/freeldr/disk/disk.c | 88 +++++--------- reactos/boot/freeldr/freeldr/include/disk.h | 15 ++- 3 files changed, 145 insertions(+), 67 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/arch/i386/pcdisk.c b/reactos/boot/freeldr/freeldr/arch/i386/pcdisk.c index fd85af705fe..be051df775f 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/pcdisk.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/pcdisk.c @@ -17,6 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +// #if defined(__i386__) || defined(_M_AMD64) + #include #define NDEBUG @@ -25,6 +27,7 @@ DBG_DEFAULT_CHANNEL(DISK); #include + 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 /* 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)"); diff --git a/reactos/boot/freeldr/freeldr/disk/disk.c b/reactos/boot/freeldr/freeldr/disk/disk.c index 68218cfd018..accf8d51f15 100644 --- a/reactos/boot/freeldr/freeldr/disk/disk.c +++ b/reactos/boot/freeldr/freeldr/disk/disk.c @@ -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; } diff --git a/reactos/boot/freeldr/freeldr/include/disk.h b/reactos/boot/freeldr/freeldr/include/disk.h index b2e492cd504..a701ad26c15 100644 --- a/reactos/boot/freeldr/freeldr/include/disk.h +++ b/reactos/boot/freeldr/freeldr/include/disk.h @@ -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; ///////////////////////////////////////////////////////////////////////////////////////