[FREELDR] Simplify code by using a AddReactOSArcDiskInfo() helper, and few extra...
[reactos.git] / boot / freeldr / freeldr / arch / i386 / hwdisk.c
index 4c344e2..6123fc1 100644 (file)
 
 #include <freeldr.h>
 
-#define NDEBUG
 #include <debug.h>
 
 DBG_DEFAULT_CHANNEL(HWDETECT);
 
+/*
+ * This is the common code for harddisk for both the PC and the XBOX.
+ */
+
 typedef struct tagDISKCONTEXT
 {
     UCHAR DriveNumber;
@@ -35,16 +38,20 @@ typedef struct tagDISKCONTEXT
     ULONGLONG SectorNumber;
 } DISKCONTEXT;
 
-extern ULONG reactos_disk_count;
-extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
-extern CHAR reactos_arc_strings[32][256];
-
 static CHAR Hex[] = "0123456789abcdef";
+
+/* Data cache for BIOS disks pre-enumeration */
 UCHAR PcBiosDiskCount = 0;
-CHAR PcDiskIdentifier[32][20];
+static CHAR PcDiskIdentifier[32][20];
 
+PVOID DiskReadBuffer;
+SIZE_T DiskReadBufferSize;
 
-static LONG DiskClose(ULONG FileId)
+
+/* FUNCTIONS *****************************************************************/
+
+static ARC_STATUS
+DiskClose(ULONG FileId)
 {
     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
 
@@ -52,7 +59,8 @@ static LONG DiskClose(ULONG FileId)
     return ESUCCESS;
 }
 
-static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
+static ARC_STATUS
+DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
 {
     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
 
@@ -63,7 +71,8 @@ static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
     return ESUCCESS;
 }
 
-static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
+static ARC_STATUS
+DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
 {
     DISKCONTEXT* Context;
     UCHAR DriveNumber;
@@ -83,9 +92,12 @@ static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
     }
     else
     {
-        /* This is either a floppy disk device (DrivePartition == 0) or
-         * a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
-         * it doesn't matter which one because they both have 512 bytes per sector */
+        /*
+         * This is either a floppy disk device (DrivePartition == 0) or
+         * a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF)
+         * but it doesn't matter which one because they both have 512 bytes
+         * per sector.
+         */
         SectorSize = 512;
     }
 
@@ -93,13 +105,21 @@ static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
     {
         if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
             return EINVAL;
+
         SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
         SectorCount = PartitionTableEntry.PartitionSectorCount;
     }
+#if 0 // FIXME: Investigate
+    else
+    {
+        SectorCount = 0; /* FIXME */
+    }
+#endif
 
     Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
     if (!Context)
         return ENOMEM;
+
     Context->DriveNumber = DriveNumber;
     Context->SectorSize = SectorSize;
     Context->SectorOffset = SectorOffset;
@@ -110,7 +130,8 @@ static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
     return ESUCCESS;
 }
 
-static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
+static ARC_STATUS
+DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
 {
     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
     UCHAR* Ptr = (UCHAR*)Buffer;
@@ -119,10 +140,10 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
     ULONGLONG SectorOffset;
 
     TotalSectors = (N + Context->SectorSize - 1) / Context->SectorSize;
-    MaxSectors   = DISKREADBUFFER_SIZE / Context->SectorSize;
+    MaxSectors   = DiskReadBufferSize / Context->SectorSize;
     SectorOffset = Context->SectorNumber + Context->SectorOffset;
 
-    ret = 1;
+    ret = TRUE;
 
     while (TotalSectors)
     {
@@ -130,11 +151,10 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
         if (ReadSectors > MaxSectors)
             ReadSectors = MaxSectors;
 
-        ret = MachDiskReadLogicalSectors(
-            Context->DriveNumber,
-            SectorOffset,
-            ReadSectors,
-            (PVOID)DISKREADBUFFER);
+        ret = MachDiskReadLogicalSectors(Context->DriveNumber,
+                                         SectorOffset,
+                                         ReadSectors,
+                                         DiskReadBuffer);
         if (!ret)
             break;
 
@@ -142,7 +162,7 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
         if (Length > N)
             Length = N;
 
-        RtlCopyMemory(Ptr, (PVOID)DISKREADBUFFER, Length);
+        RtlCopyMemory(Ptr, DiskReadBuffer, Length);
 
         Ptr += Length;
         N -= Length;
@@ -155,7 +175,8 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
     return (!ret) ? EIO : ESUCCESS;
 }
 
-static LONG DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
+static ARC_STATUS
+DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
 {
     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
 
@@ -164,11 +185,12 @@ static LONG DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
     if (Position->LowPart & (Context->SectorSize - 1))
         return EINVAL;
 
-    Context->SectorNumber = (ULONG)(Position->QuadPart / Context->SectorSize);
+    Context->SectorNumber = Position->QuadPart / Context->SectorSize;
     return ESUCCESS;
 }
 
-static const DEVVTBL DiskVtbl = {
+static const DEVVTBL DiskVtbl =
+{
     DiskClose,
     DiskGetFileInformation,
     DiskOpen,
@@ -176,56 +198,55 @@ static const DEVVTBL DiskVtbl = {
     DiskSeek,
 };
 
+
 PCHAR
-GetHarddiskIdentifier(
-    UCHAR DriveNumber)
+GetHarddiskIdentifier(UCHAR DriveNumber)
 {
     return PcDiskIdentifier[DriveNumber - 0x80];
 }
 
-VOID
-GetHarddiskInformation(
-    UCHAR DriveNumber)
+static VOID
+GetHarddiskInformation(UCHAR DriveNumber)
 {
     PMASTER_BOOT_RECORD Mbr;
-    ULONG *Buffer;
+    PULONG Buffer;
     ULONG i;
     ULONG Checksum;
     ULONG Signature;
-    CHAR ArcName[256];
+    BOOLEAN ValidPartitionTable;
+    CHAR ArcName[MAX_PATH];
     PARTITION_TABLE_ENTRY PartitionTableEntry;
     PCHAR Identifier = PcDiskIdentifier[DriveNumber - 0x80];
 
     /* Read the MBR */
-    if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
+    if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
     {
         ERR("Reading MBR failed\n");
+        /* We failed, use a default identifier */
+        sprintf(Identifier, "BIOSDISK%d", DriveNumber - 0x80 + 1);
         return;
     }
 
-    Buffer = (ULONG*)DISKREADBUFFER;
-    Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
+    Buffer = (ULONG*)DiskReadBuffer;
+    Mbr = (PMASTER_BOOT_RECORD)DiskReadBuffer;
 
-    Signature =  Mbr->Signature;
+    Signature = Mbr->Signature;
     TRACE("Signature: %x\n", Signature);
 
     /* Calculate the MBR checksum */
     Checksum = 0;
-    for (i = 0; i < 128; i++)
+    for (i = 0; i < 512 / sizeof(ULONG); i++)
     {
         Checksum += Buffer[i];
     }
     Checksum = ~Checksum + 1;
     TRACE("Checksum: %x\n", Checksum);
 
+    ValidPartitionTable = (Mbr->MasterBootRecordMagic == 0xAA55);
+
     /* Fill out the ARC disk block */
-    reactos_arc_disk_info[reactos_disk_count].Signature = Signature;
-    reactos_arc_disk_info[reactos_disk_count].CheckSum = Checksum;
-    sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count);
-    strcpy(reactos_arc_strings[reactos_disk_count], ArcName);
-    reactos_arc_disk_info[reactos_disk_count].ArcName =
-        reactos_arc_strings[reactos_disk_count];
-    reactos_disk_count++;
+    sprintf(ArcName, "multi(0)disk(0)rdisk(%u)", DriveNumber - 0x80);
+    AddReactOSArcDiskInfo(ArcName, Signature, Checksum, ValidPartitionTable);
 
     sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(0)", DriveNumber - 0x80);
     FsRegisterDevice(ArcName, &DiskVtbl);
@@ -263,57 +284,77 @@ GetHarddiskInformation(
     Identifier[15] = Hex[(Signature >> 4) & 0x0F];
     Identifier[16] = Hex[Signature & 0x0F];
     Identifier[17] = '-';
-    Identifier[18] = 'A';
+    Identifier[18] = (ValidPartitionTable ? 'A' : 'X');
     Identifier[19] = 0;
     TRACE("Identifier: %s\n", Identifier);
 }
 
-
-BOOLEAN
-HwInitializeBiosDisks(VOID)
+static UCHAR
+EnumerateHarddisks(OUT PBOOLEAN BootDriveReported)
 {
     UCHAR DiskCount, DriveNumber;
     ULONG i;
     BOOLEAN Changed;
-    CHAR BootPath[512];
-    BOOLEAN BootDriveReported = FALSE;
 
-    /* Count the number of visible drives */
+    *BootDriveReported = FALSE;
+
+    /* Count the number of visible harddisk drives */
     DiskReportError(FALSE);
     DiskCount = 0;
     DriveNumber = 0x80;
 
-    /* There are some really broken BIOSes out there. There are even BIOSes
-        * that happily report success when you ask them to read from non-existent
-        * harddisks. So, we set the buffer to known contents first, then try to
-        * read. If the BIOS reports success but the buffer contents haven't
-        * changed then we fail anyway */
-    memset((PVOID) DISKREADBUFFER, 0xcd, 512);
-    while (MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
+    /*
+     * There are some really broken BIOSes out there. There are even BIOSes
+     * that happily report success when you ask them to read from non-existent
+     * harddisks. So, we set the buffer to known contents first, then try to
+     * read. If the BIOS reports success but the buffer contents haven't
+     * changed then we fail anyway.
+     */
+    memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
+    while (MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
     {
         Changed = FALSE;
-        for (i = 0; ! Changed && i < 512; i++)
+        for (i = 0; !Changed && i < DiskReadBufferSize; i++)
         {
-            Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
+            Changed = ((PUCHAR)DiskReadBuffer)[i] != 0xcd;
         }
-        if (! Changed)
+        if (!Changed)
         {
-            TRACE("BIOS reports success for disk %d but data didn't change\n",
-                      (int)DiskCount);
+            TRACE("BIOS reports success for disk %d (0x%02X) but data didn't change\n",
+                  (int)DiskCount, DriveNumber);
             break;
         }
 
+        /* Cache the BIOS hard disk information for later use */
         GetHarddiskInformation(DriveNumber);
 
+        /* Check if we have seen the boot drive */
         if (FrldrBootDrive == DriveNumber)
-            BootDriveReported = TRUE;
+            *BootDriveReported = TRUE;
 
         DiskCount++;
         DriveNumber++;
-        memset((PVOID) DISKREADBUFFER, 0xcd, 512);
+        memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
     }
     DiskReportError(TRUE);
 
+    PcBiosDiskCount = DiskCount;
+    TRACE("BIOS reports %d harddisk%s\n",
+          (int)DiskCount, (DiskCount == 1) ? "" : "s");
+
+    return DiskCount;
+}
+
+BOOLEAN
+PcInitializeBootDevices(VOID)
+{
+    UCHAR DiskCount;
+    BOOLEAN BootDriveReported = FALSE;
+    ULONG i;
+    CHAR BootPath[MAX_PATH];
+
+    DiskCount = EnumerateHarddisks(&BootDriveReported);
+
     /* Get the drive we're booting from */
     MachDiskGetBootPath(BootPath, sizeof(BootPath));
 
@@ -321,38 +362,41 @@ HwInitializeBiosDisks(VOID)
     if ((FrldrBootDrive >= 0x80 && !BootDriveReported) ||
         DiskIsDriveRemovable(FrldrBootDrive))
     {
-        /* TODO: Check if it's really a cdrom drive */
-        ULONG* Buffer;
+        /* TODO: Check if it's really a CDROM drive */
+
+        PMASTER_BOOT_RECORD Mbr;
+        PULONG Buffer;
         ULONG Checksum = 0;
+        ULONG Signature;
 
         /* Read the MBR */
-        if (!MachDiskReadLogicalSectors(FrldrBootDrive, 16ULL, 1, (PVOID)DISKREADBUFFER))
+        if (!MachDiskReadLogicalSectors(FrldrBootDrive, 16ULL, 1, DiskReadBuffer))
         {
-          ERR("Reading MBR failed\n");
-          return FALSE;
+            ERR("Reading MBR failed\n");
+            return FALSE;
         }
 
-        Buffer = (ULONG*)DISKREADBUFFER;
+        Buffer = (ULONG*)DiskReadBuffer;
+        Mbr = (PMASTER_BOOT_RECORD)DiskReadBuffer;
+
+        Signature = Mbr->Signature;
+        TRACE("Signature: %x\n", Signature);
 
         /* Calculate the MBR checksum */
-        for (i = 0; i < 2048 / sizeof(ULONG); i++) Checksum += Buffer[i];
+        for (i = 0; i < 2048 / sizeof(ULONG); i++)
+        {
+            Checksum += Buffer[i];
+        }
         Checksum = ~Checksum + 1;
         TRACE("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++;
+        AddReactOSArcDiskInfo(BootPath, Signature, Checksum, TRUE);
 
         FsRegisterDevice(BootPath, &DiskVtbl);
-        DiskCount++;
+        DiskCount++; // This is not accounted for in the number of pre-enumerated BIOS drives!
+        TRACE("Additional boot drive detected: 0x%02X\n", (int)FrldrBootDrive);
     }
 
-    PcBiosDiskCount = DiskCount;
-    TRACE("BIOS reports %d harddisk%s\n",
-          (int)DiskCount, (DiskCount == 1) ? "": "s");
-
-    return DiskCount != 0;
+    return (DiskCount != 0);
 }