- Fix incorrect sector size detection which caused seeking to fail when booting...
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / hardware.c
index 2f800be..d4654cc 100644 (file)
@@ -2,6 +2,7 @@
  *  FreeLoader
  *
  *  Copyright (C) 2003, 2004  Eric Kohl
  *  FreeLoader
  *
  *  Copyright (C) 2003, 2004  Eric Kohl
+ *  Copyright (C) 2009  HervĂ© Poussineau
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -13,9 +14,9 @@
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #include <freeldr.h>
  */
 
 #include <freeldr.h>
@@ -402,6 +403,7 @@ typedef struct tagDISKCONTEXT
     ULONG DriveNumber;
     ULONG SectorSize;
     ULONGLONG SectorOffset;
     ULONG DriveNumber;
     ULONG SectorSize;
     ULONGLONG SectorOffset;
+    ULONGLONG SectorCount;
     ULONGLONG SectorNumber;
 } DISKCONTEXT;
 
     ULONGLONG SectorNumber;
 } DISKCONTEXT;
 
@@ -415,7 +417,13 @@ static LONG DiskClose(ULONG FileId)
 
 static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
 {
 
 static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
 {
-    return EINVAL;
+    DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
+
+    RtlZeroMemory(Information, sizeof(FILEINFORMATION));
+    Information->EndingAddress.QuadPart = (Context->SectorOffset + Context->SectorCount) * Context->SectorSize;
+    Information->CurrentAddress.LowPart = (Context->SectorOffset + Context->SectorNumber) * Context->SectorSize;
+
+    return ESUCCESS;
 }
 
 static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
 }
 
 static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
@@ -423,17 +431,35 @@ static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
     DISKCONTEXT* Context;
     ULONG DriveNumber, DrivePartition, SectorSize;
     ULONGLONG SectorOffset = 0;
     DISKCONTEXT* Context;
     ULONG DriveNumber, DrivePartition, SectorSize;
     ULONGLONG SectorOffset = 0;
+    ULONGLONG SectorCount = 0;
     PARTITION_TABLE_ENTRY PartitionTableEntry;
     PARTITION_TABLE_ENTRY PartitionTableEntry;
+    GEOMETRY Geometry;
+    EXTENDED_GEOMETRY ExtGeometry;
     CHAR FileName[1];
 
     if (!DissectArcPath(Path, FileName, &DriveNumber, &DrivePartition))
         return EINVAL;
     CHAR FileName[1];
 
     if (!DissectArcPath(Path, FileName, &DriveNumber, &DrivePartition))
         return EINVAL;
-    SectorSize = (DrivePartition == 0xff ? 2048 : 512);
+
+    ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
+    if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
+    {
+        SectorSize = ExtGeometry.BytesPerSector;
+        SectorCount = ExtGeometry.Sectors;
+    }
+    else if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
+    {
+        SectorSize = Geometry.BytesPerSector;
+        SectorCount = Geometry.Sectors;
+    }
+    else
+        return EINVAL;
+
     if (DrivePartition != 0xff && DrivePartition != 0)
     {
     if (DrivePartition != 0xff && DrivePartition != 0)
     {
-        if (!MachDiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
+        if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
             return EINVAL;
         SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
             return EINVAL;
         SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
+        SectorCount = PartitionTableEntry.PartitionSectorCount;
     }
 
     Context = MmHeapAlloc(sizeof(DISKCONTEXT));
     }
 
     Context = MmHeapAlloc(sizeof(DISKCONTEXT));
@@ -442,6 +468,7 @@ static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
     Context->DriveNumber = DriveNumber;
     Context->SectorSize = SectorSize;
     Context->SectorOffset = SectorOffset;
     Context->DriveNumber = DriveNumber;
     Context->SectorSize = SectorSize;
     Context->SectorOffset = SectorOffset;
+    Context->SectorCount = SectorCount;
     Context->SectorNumber = 0;
     FsSetDeviceSpecific(*FileId, Context);
 
     Context->SectorNumber = 0;
     FsSetDeviceSpecific(*FileId, Context);
 
@@ -452,15 +479,16 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
 {
     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
     UCHAR* Ptr = (UCHAR*)Buffer;
 {
     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
     UCHAR* Ptr = (UCHAR*)Buffer;
-    ULONG i;
+    ULONG i, Length;
     BOOLEAN ret;
 
     *Count = 0;
     BOOLEAN ret;
 
     *Count = 0;
-    if (N & (Context->SectorSize - 1))
-        return EINVAL;
-
-    for (i = 0; i < N / Context->SectorSize; i++)
+    i = 0;
+    while (N > 0)
     {
     {
+        Length = N;
+        if (Length > Context->SectorSize)
+            Length = Context->SectorSize;
         ret = MachDiskReadLogicalSectors(
             Context->DriveNumber,
             Context->SectorNumber + Context->SectorOffset + i,
         ret = MachDiskReadLogicalSectors(
             Context->DriveNumber,
             Context->SectorNumber + Context->SectorOffset + i,
@@ -468,11 +496,13 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
             (PVOID)DISKREADBUFFER);
         if (!ret)
             return EIO;
             (PVOID)DISKREADBUFFER);
         if (!ret)
             return EIO;
-        RtlCopyMemory(Ptr, (PVOID)DISKREADBUFFER, Context->SectorSize);
-        Ptr += Context->SectorSize;
+        RtlCopyMemory(Ptr, (PVOID)DISKREADBUFFER, Length);
+        Ptr += Length;
+        *Count += Length;
+        N -= Length;
+        i++;
     }
 
     }
 
-    *Count = N;
     return ESUCCESS;
 }
 
     return ESUCCESS;
 }
 
@@ -545,9 +575,9 @@ GetHarddiskIdentifier(PCHAR Identifier,
   FsRegisterDevice(ArcName, &DiskVtbl);
 
   /* Add partitions */
   FsRegisterDevice(ArcName, &DiskVtbl);
 
   /* Add partitions */
-  i = 0;
+  i = 1;
   DiskReportError(FALSE);
   DiskReportError(FALSE);
-  while (MachDiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry))
+  while (DiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry))
   {
     if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED)
     {
   {
     if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED)
     {
@@ -903,7 +933,7 @@ GetDiskCount(PCONFIGURATION_COMPONENT_DATA BusKey)
     //
     // Return number of disks
     //
     //
     // Return number of disks
     //
-    DPRINTM(DPRINT_HWDETECT, "Retrieving %lu INT13 disks\\0\n");
+    DPRINTM(DPRINT_HWDETECT, "Retrieving %lu INT13 disks\\0\n", DiskCount);
     return DiskCount;
 };
 
     return DiskCount;
 };
 
@@ -963,6 +993,29 @@ DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA BusKey)
         DiskIsDriveRemovable(BootDrive))
     {
         /* TODO: Check if it's really a cdrom drive */
         DiskIsDriveRemovable(BootDrive))
     {
         /* TODO: Check if it's really a cdrom drive */
+        ULONG* Buffer;
+        ULONG Checksum = 0;
+
+        /* Read the MBR */
+        if (!MachDiskReadLogicalSectors(BootDrive, 16ULL, 1, (PVOID)DISKREADBUFFER))
+        {
+          DPRINTM(DPRINT_HWDETECT, "Reading MBR failed\n");
+          return;
+        }
+
+        Buffer = (ULONG*)DISKREADBUFFER;
+
+        /* Calculate the MBR checksum */
+        for (i = 0; i < 2048 / sizeof(ULONG); i++) Checksum += Buffer[i];
+        DPRINTM(DPRINT_HWDETECT, "Checksum: %x\n", Checksum);
+
+        /* Fill out the ARC disk block */
+        reactos_arc_disk_info[reactos_disk_count].CheckSum = Checksum;
+        strcpy(reactos_arc_strings[reactos_disk_count], BootPath);
+        reactos_arc_disk_info[reactos_disk_count].ArcName =
+            reactos_arc_strings[reactos_disk_count];
+        reactos_disk_count++;
+
         FsRegisterDevice(BootPath, &DiskVtbl);
     }
 }
         FsRegisterDevice(BootPath, &DiskVtbl);
     }
 }