Skip to content

Commit a0c4273

Browse files
committed
[FREELDR] Improve DiskGetExtendedDriveParameters()
- Move BIOS-specific `EXTENDED_GEOMETRY` structure to pcdisk.c - Zero out the transfer buffer for INT 13h, function 48h before invocation. This ensures that any random data is removed and that some broken BIOSes behave better. - Use a more suitable type for the pointer to the transfer buffer, so that we can use more human-manageable member names in TRACEs instead of magic buffer offsets.
1 parent 1375320 commit a0c4273

File tree

2 files changed

+53
-49
lines changed

2 files changed

+53
-49
lines changed

boot/freeldr/freeldr/arch/i386/pc/pcdisk.c

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ DBG_DEFAULT_CHANNEL(DISK);
2727
/* Enable this line if you want to support multi-drive caching (increases FreeLdr size!) */
2828
// #define CACHE_MULTI_DRIVES
2929

30-
#include <pshpack2.h>
30+
#include <pshpack1.h>
3131

3232
typedef struct
3333
{
@@ -74,6 +74,22 @@ typedef struct
7474
UCHAR Reserved;
7575
} I386_CDROM_SPEC_PACKET, *PI386_CDROM_SPEC_PACKET;
7676

77+
/*
78+
* Extended disk geometry (Int13 / AH=48h)
79+
* See also ntdddisk.h DISK_EX_INT13_INFO
80+
*/
81+
typedef struct _EXTENDED_GEOMETRY
82+
{
83+
USHORT Size;
84+
USHORT Flags;
85+
ULONG Cylinders;
86+
ULONG Heads;
87+
ULONG SectorsPerTrack;
88+
ULONGLONG Sectors;
89+
USHORT BytesPerSector;
90+
ULONG PDPTE;
91+
} EXTENDED_GEOMETRY, *PEXTENDED_GEOMETRY;
92+
7793
#include <poppack.h>
7894

7995
typedef struct _PC_DISK_DRIVE
@@ -295,21 +311,27 @@ DiskInt13ExtensionsSupported(IN UCHAR DriveNumber)
295311

296312
static BOOLEAN
297313
DiskGetExtendedDriveParameters(
298-
IN UCHAR DriveNumber,
299-
IN PPC_DISK_DRIVE DiskDrive,
300-
OUT PVOID Buffer,
301-
IN USHORT BufferSize)
314+
_In_ UCHAR DriveNumber,
315+
_In_ PPC_DISK_DRIVE DiskDrive,
316+
_Out_ PVOID Buffer,
317+
_In_ USHORT BufferSize)
302318
{
319+
PEXTENDED_GEOMETRY Ptr = (PEXTENDED_GEOMETRY)BIOSCALLBUFFER;
303320
REGS RegsIn, RegsOut;
304-
PUSHORT Ptr = (PUSHORT)(BIOSCALLBUFFER);
305321

306322
TRACE("DiskGetExtendedDriveParameters(0x%x)\n", DriveNumber);
307323

308-
if (!DiskDrive->Int13ExtensionsSupported)
324+
if (!DiskDrive->Int13ExtensionsSupported || (BufferSize < sizeof(*Ptr)))
309325
return FALSE;
310326

311-
/* Initialize transfer buffer */
312-
*Ptr = BufferSize;
327+
/*
328+
* Initialize the transfer buffer.
329+
* NOTE: Zeroing out the buffer also helps avoiding the bug where Dell
330+
* machines using PhoenixBIOS 4.0 Release 6.0 fail to correctly handle
331+
* this function if Ptr->Flags is not 0 on entry.
332+
*/
333+
RtlZeroMemory(Ptr, sizeof(*Ptr)); // BufferSize;
334+
Ptr->Size = BufferSize;
313335

314336
/*
315337
* BIOS Int 13h, function 48h - Get drive parameters
@@ -325,7 +347,7 @@ DiskGetExtendedDriveParameters(
325347
*/
326348
RegsIn.b.ah = 0x48;
327349
RegsIn.b.dl = DriveNumber;
328-
RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
350+
RegsIn.x.ds = BIOSCALLBUFSEGMENT;
329351
RegsIn.w.si = BIOSCALLBUFOFFSET;
330352

331353
/* Get drive parameters */
@@ -336,22 +358,25 @@ DiskGetExtendedDriveParameters(
336358
RtlCopyMemory(Buffer, Ptr, BufferSize);
337359

338360
#if DBG
339-
TRACE("Size of buffer: 0x%x\n", Ptr[0]);
340-
TRACE("Information flags: 0x%x\n", Ptr[1]);
341-
TRACE("Number of physical cylinders on drive: %u\n", *(PULONG)&Ptr[2]);
342-
TRACE("Number of physical heads on drive: %u\n", *(PULONG)&Ptr[4]);
343-
TRACE("Number of physical sectors per track: %u\n", *(PULONG)&Ptr[6]);
344-
TRACE("Total number of sectors on drive: %I64u\n", *(PULONGLONG)&Ptr[8]);
345-
TRACE("Bytes per sector: %u\n", Ptr[12]);
346-
if (Ptr[0] >= 0x1e)
361+
TRACE("Size of buffer: 0x%x\n", Ptr->Size);
362+
TRACE("Information flags: 0x%x\n", Ptr->Flags);
363+
TRACE("Number of physical cylinders on drive: %u\n", Ptr->Cylinders);
364+
TRACE("Number of physical heads on drive: %u\n", Ptr->Heads);
365+
TRACE("Number of physical sectors per track: %u\n", Ptr->SectorsPerTrack);
366+
TRACE("Total number of sectors on drive: %I64u\n", Ptr->Sectors);
367+
TRACE("Bytes per sector: %u\n", Ptr->BytesPerSector);
368+
if (Ptr->Size >= 0x1E)
347369
{
348-
// Ptr[13]: offset, Ptr[14]: segment
349-
TRACE("EDD configuration parameters (DPTE): %x:%x\n", Ptr[14], Ptr[13]);
370+
// LOWORD(Ptr->PDPTE): offset, HIWORD(Ptr->PDPTE): segment
371+
USHORT Off = (USHORT)(Ptr->PDPTE & 0xFFFF); // ((PUSHORT)&Ptr->PDPTE)[0];
372+
USHORT Seg = (USHORT)((Ptr->PDPTE >> 16) & 0xFFFF); // ((PUSHORT)&Ptr->PDPTE)[1];
373+
TRACE("EDD configuration parameters (DPTE): %x:%x\n", Seg, Off);
374+
350375
/* The DPTE pointer is valid if it's != FFFF:FFFF (per the Enhanced Disk
351376
* Drive Specification), but also, when it's != 0000:0000 (broken BIOSes) */
352-
if (!(Ptr[13] == 0xFFFF && Ptr[14] == 0xFFFF) && !(Ptr[13] == 0 && Ptr[14] == 0))
377+
if (Ptr->PDPTE != 0xFFFFFFFF && Ptr->PDPTE != 0)
353378
{
354-
PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[14] << 4) + Ptr[13]);
379+
PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Seg << 4) + Off);
355380
TRACE("SpecPtr: 0x%x\n", SpecPtr);
356381
TRACE("Physical I/O port base address: 0x%x\n", *(PUSHORT)&SpecPtr[0]);
357382
TRACE("Disk-drive control port address: 0x%x\n", *(PUSHORT)&SpecPtr[2]);
@@ -364,9 +389,9 @@ DiskGetExtendedDriveParameters(
364389
TRACE("Drive options: 0x%x\n", *(PUSHORT)&SpecPtr[10]);
365390
}
366391
}
367-
if (Ptr[0] >= 0x42)
392+
if (Ptr->Size >= 0x42)
368393
{
369-
TRACE("Signature: 0x%x\n", Ptr[15]);
394+
TRACE("Signature: 0x%x\n", ((PUSHORT)Ptr)[15]);
370395
}
371396
#endif // DBG
372397

@@ -383,16 +408,11 @@ InitDriveGeometry(
383408
ULONG Cylinders;
384409

385410
/* Get the extended geometry first */
386-
DiskDrive->ExtGeometry.Size = sizeof(DiskDrive->ExtGeometry);
411+
RtlZeroMemory(&DiskDrive->ExtGeometry, sizeof(DiskDrive->ExtGeometry));
387412
Success = DiskGetExtendedDriveParameters(DriveNumber, DiskDrive,
388413
&DiskDrive->ExtGeometry,
389-
DiskDrive->ExtGeometry.Size);
390-
if (!Success)
391-
{
392-
/* Failed, zero it out */
393-
RtlZeroMemory(&DiskDrive->ExtGeometry, sizeof(DiskDrive->ExtGeometry));
394-
}
395-
else
414+
sizeof(DiskDrive->ExtGeometry));
415+
if (Success)
396416
{
397417
TRACE("DiskGetExtendedDriveParameters(0x%x) returned:\n"
398418
"Cylinders : 0x%x\n"
@@ -575,9 +595,9 @@ PcDiskReadLogicalSectorsLBA(
575595
IN ULONG SectorCount,
576596
OUT PVOID Buffer)
577597
{
598+
PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)BIOSCALLBUFFER;
578599
REGS RegsIn, RegsOut;
579600
ULONG RetryCount;
580-
PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER);
581601

582602
/* Setup disk address packet */
583603
RtlZeroMemory(Packet, sizeof(*Packet));

boot/freeldr/freeldr/include/disk.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,6 @@ typedef struct _GEOMETRY
3333

3434
#include <pshpack1.h>
3535

36-
/*
37-
* Extended disk geometry (Int13 / AH=48h)
38-
* See also ntdddisk.h DISK_EX_INT13_INFO
39-
*/
40-
typedef struct _EXTENDED_GEOMETRY
41-
{
42-
USHORT Size;
43-
USHORT Flags;
44-
ULONG Cylinders;
45-
ULONG Heads;
46-
ULONG SectorsPerTrack;
47-
ULONGLONG Sectors;
48-
USHORT BytesPerSector;
49-
ULONG PDPTE;
50-
} EXTENDED_GEOMETRY, *PEXTENDED_GEOMETRY;
51-
5236
/*
5337
* Define the structure of a partition table entry
5438
*/

0 commit comments

Comments
 (0)