[FREELDR] Addendum / actual fix for ef76709b

According to the Advanced RISC Computing Specification v1.2, for partitions,
StartingAddress and EndingAddress are the start and end positions of the
partition in terms of byte offsets from the start of the disk.
CurrentAddress is the current offset into (i.e. relative to) the partition.

Fix also the FAT filesystem in accordance.

- FIXME fix: Retrieve the size of the disk in number of sectors in DiskOpen().
- Add extra validity checks in the DiskSeek() functions.
- Explicitly call PcDisk* functions in machpc.c and pcdisk.c, and
  XboxDisk* functions in machxbox.c (the code in these files is not
  called cross-platform).

CORE-16216 CORE-16248
This commit is contained in:
Hermès Bélusca-Maïto 2019-09-18 01:06:15 +02:00
parent ff85aa0c38
commit dd46d40fd2
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
6 changed files with 54 additions and 17 deletions

View file

@ -63,7 +63,15 @@ DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
RtlZeroMemory(Information, sizeof(*Information));
Information->EndingAddress.QuadPart = Context->SectorCount * Context->SectorSize;
/*
* The ARC specification mentions that for partitions, StartingAddress and
* EndingAddress are the start and end positions of the partition in terms
* of byte offsets from the start of the disk.
* CurrentAddress is the current offset into (i.e. relative to) the partition.
*/
Information->StartingAddress.QuadPart = Context->SectorOffset * Context->SectorSize;
Information->EndingAddress.QuadPart = (Context->SectorOffset + Context->SectorCount) * Context->SectorSize;
Information->CurrentAddress.QuadPart = Context->SectorNumber * Context->SectorSize;
return ESUCCESS;
@ -113,12 +121,21 @@ DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
SectorCount = PartitionTableEntry.PartitionSectorCount;
}
#if 0 // FIXME: Investigate
else
{
SectorCount = 0; /* FIXME */
GEOMETRY Geometry;
if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry))
return EINVAL;
if (SectorSize != Geometry.BytesPerSector)
{
ERR("SectorSize (%lu) != Geometry.BytesPerSector (%lu), expect problems!\n",
SectorSize, Geometry.BytesPerSector);
}
SectorOffset = 0;
SectorCount = (ULONGLONG)Geometry.Cylinders * Geometry.Heads * Geometry.Sectors;
}
#endif
Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
if (!Context)
@ -147,7 +164,7 @@ DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
TotalSectors = (N + Context->SectorSize - 1) / Context->SectorSize;
MaxSectors = DiskReadBufferSize / Context->SectorSize;
SectorOffset = Context->SectorNumber + Context->SectorOffset;
SectorOffset = Context->SectorOffset + Context->SectorNumber;
// If MaxSectors is 0, this will lead to infinite loop.
// In release builds assertions are disabled, however we also have sanity checks in DiskOpen()
@ -189,13 +206,18 @@ static ARC_STATUS
DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
ULONGLONG SectorNumber;
if (SeekMode != SeekAbsolute)
return EINVAL;
if (Position->LowPart & (Context->SectorSize - 1))
return EINVAL;
Context->SectorNumber = Position->QuadPart / Context->SectorSize;
SectorNumber = Position->QuadPart / Context->SectorSize;
if (SectorNumber >= Context->SectorCount)
return EINVAL;
Context->SectorNumber = SectorNumber;
return ESUCCESS;
}

View file

@ -147,7 +147,7 @@ PcGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack;
DiskGeometry->NumberOfHeads = ExtGeometry.Heads;
}
else if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
else if (PcDiskGetDriveGeometry(DriveNumber, &Geometry))
{
DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
DiskGeometry->NumberOfCylinders = Geometry.Cylinders;

View file

@ -133,7 +133,7 @@ XboxGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
/* Get the disk geometry */
//ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
if (XboxDiskGetDriveGeometry(DriveNumber, &Geometry))
{
DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
DiskGeometry->NumberOfCylinders = Geometry.Cylinders;

View file

@ -240,9 +240,11 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
TRACE("PcDiskReadLogicalSectorsCHS()\n");
/* Get the drive geometry */
if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
DriveGeometry.Sectors == 0 ||
DriveGeometry.Heads == 0)
//
// TODO: Cache this information for the given drive.
//
if (!PcDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
DriveGeometry.Sectors == 0 || DriveGeometry.Heads == 0)
{
return FALSE;
}

View file

@ -178,7 +178,15 @@ static ARC_STATUS DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Informat
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
RtlZeroMemory(Information, sizeof(*Information));
Information->EndingAddress.QuadPart = Context->SectorCount * Context->SectorSize;
/*
* The ARC specification mentions that for partitions, StartingAddress and
* EndingAddress are the start and end positions of the partition in terms
* of byte offsets from the start of the disk.
* CurrentAddress is the current offset into (i.e. relative to) the partition.
*/
Information->StartingAddress.QuadPart = Context->SectorOffset * Context->SectorSize;
Information->EndingAddress.QuadPart = (Context->SectorOffset + Context->SectorCount) * Context->SectorSize;
Information->CurrentAddress.QuadPart = Context->SectorNumber * Context->SectorSize;
return ESUCCESS;
@ -276,7 +284,7 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
/* Read full sectors */
ASSERT(Context->SectorNumber < 0xFFFFFFFF);
Lba = (ULONG)Context->SectorNumber;
Lba = (ULONG)(Context->SectorOffset + Context->SectorNumber);
if (FullSectors > 0)
{
Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
@ -365,13 +373,18 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
static ARC_STATUS DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
ULONGLONG SectorNumber;
if (SeekMode != SeekAbsolute)
return EINVAL;
if (Position->QuadPart & (Context->SectorSize - 1))
return EINVAL;
Context->SectorNumber = Position->QuadPart / Context->SectorSize;
SectorNumber = Position->QuadPart / Context->SectorSize;
if (SectorNumber >= Context->SectorCount)
return EINVAL;
Context->SectorNumber = SectorNumber;
return ESUCCESS;
}

View file

@ -1570,7 +1570,7 @@ const DEVVTBL* FatMount(ULONG DeviceId)
FrLdrTempFree(Volume, TAG_FAT_VOLUME);
return NULL;
}
SectorCount.QuadPart = FileInformation.EndingAddress.QuadPart;
SectorCount.QuadPart = (FileInformation.EndingAddress.QuadPart - FileInformation.StartingAddress.QuadPart);
SectorCount.QuadPart /= SECTOR_SIZE;
//