[SETUPLIB][USETUP] Improve disk HW numbering, removable disk support, and "super...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 11 Mar 2019 23:13:25 +0000 (00:13 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 12 Mar 2019 01:17:11 +0000 (02:17 +0100)
Nowadays more and more people try to install ReactOS from removable
drives (e.g. USB sticks) onto fixed HDDs, or try to install it into
USB sticks too.

Both fixed and removable drives, as well as partitions on these, are
represented in NT using the same device name format:

  \Device\HarddiskM\PartitionN ,

with an increasing disk number M. Using this number for building the
corresponding firmware-specific ARC multi(x)disk(y)rdisk(z) path used
by the NT/ROS loader (FreeLdr, ...) is then prone to error since there
may have  been  removable drives  inserted  and  accounted for in the
calculation  of  the disk number.  These drives must be  correctly
subtracted in order to generate the correct ARC path, valid once all
the removable drives have been ejected (which should also be the
situation seen from the BIOS when booting up, except of course if you
boot on a USB stick).

This problem is now solved. Note that it matters only for the disks
that have also been enumerated by the firmware (BIOS; Int 13h). We
don't have to care about the other drives, since the ARC path will be
of a different format and will not use the disk number (instead, the
SCSI coordinates are used).

We also try to enumerate all the disks found in all the possible disk
adapters and  controllers enumerated  in the Hardware registry tree
(and that are visible by FreeLdr) in order to cover all.

Finally, we detect whether a disk reports as  a "super-floppy",  i.e.
an unpartitioned disk with a valid VBR. This is indeed how a standard
floppy disk looks like, or how USB sticks are partitioned on Windows.
Such disk is reported has having only one single partition starting at
the beginning of the disk, with partition number == 0, its type being
FAT16 non-bootable.
This allows us to forbid creating any new partitions on such disks.
Note that accessing either \Device\HarddiskN\Partition0 or Partition1
on such a disk returns the same data.
Note also that on the contrary, regular MBR-partitioned disks would
report at least four partitions entries, instead of just one.

The other improvements are:

- Do *NOT* write any MBR on a disk partitioned as "super-floppy".
  CORE-13703

- Fix the computed disk identifier, of format: %08x-%08x-%c .
  The numbers are respectively the checksum of the first sector, and
  the disk signature. The terminating letter is A or X, depending
  whether the first sector ends with 0x55AA/0xAA55 or not (see also
  commit 5053f1f5).

- Warn if the user attempts to install ReactOS on a disk that is not
  visible by the  firmware of his computer,  because it may not be
  bootable.

base/setup/lib/setuplib.c
base/setup/lib/utils/partlist.c
base/setup/lib/utils/partlist.h
base/setup/reactos/drivepage.c
base/setup/usetup/usetup.c

index fff6272..be71e81 100644 (file)
@@ -662,10 +662,54 @@ InitDestinationPaths(
 /** Equivalent of 'NTOS_INSTALLATION::SystemArcPath' **/
     /* Create 'pSetupData->DestinationArcPath' */
     RtlFreeUnicodeString(&pSetupData->DestinationArcPath);
-    Status = RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
-                     L"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
-                     DiskEntry->BiosDiskNumber,
-                     PartEntry->OnDiskPartitionNumber);
+
+    if (DiskEntry->MediaType == FixedMedia)
+    {
+        if (DiskEntry->BiosFound)
+        {
+#if 1
+            Status = RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                             L"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
+                             DiskEntry->HwFixedDiskNumber,
+                             PartEntry->OnDiskPartitionNumber);
+#else
+            Status = RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                             L"multi(%lu)disk(%lu)rdisk(%lu)partition(%lu)\\",
+                             DiskEntry->HwAdapterNumber,
+                             DiskEntry->HwControllerNumber,
+                             DiskEntry->HwFixedDiskNumber,
+                             PartEntry->OnDiskPartitionNumber);
+#endif
+            DPRINT1("Fixed disk found by BIOS, using MULTI ARC path '%S'\n", PathBuffer);
+        }
+        else
+        {
+            Status = RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                             L"scsi(%u)disk(%u)rdisk(%u)partition(%lu)\\",
+                             DiskEntry->Port,
+                             DiskEntry->Bus,
+                             DiskEntry->Id,
+                             PartEntry->OnDiskPartitionNumber);
+            DPRINT1("Fixed disk not found by BIOS, using SCSI ARC path '%S'\n", PathBuffer);
+        }
+    }
+    else // if (DiskEntry->MediaType == RemovableMedia)
+    {
+#if 1
+        Status = RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                         L"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
+                         0, 1);
+        DPRINT1("Removable disk, using MULTI ARC path '%S'\n", PathBuffer);
+#else
+        Status = RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                         L"signature(%08x)disk(%u)rdisk(%u)partition(%lu)\\",
+                         DiskEntry->LayoutBuffer->Signature,
+                         DiskEntry->Bus,
+                         DiskEntry->Id,
+                         PartEntry->OnDiskPartitionNumber);
+        DPRINT1("Removable disk, using SIGNATURE ARC path '%S'\n", PathBuffer);
+#endif
+    }
 
     if (!NT_SUCCESS(Status))
     {
@@ -701,8 +745,8 @@ InitDestinationPaths(
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("CombinePaths() failed with status 0x%08lx\n", Status);
-        RtlFreeUnicodeString(&pSetupData->DestinationRootPath);
         RtlFreeUnicodeString(&pSetupData->DestinationArcPath);
+        RtlFreeUnicodeString(&pSetupData->DestinationRootPath);
         return Status;
     }
 
@@ -711,8 +755,8 @@ InitDestinationPaths(
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("RtlCreateUnicodeString() failed with status 0x%08lx\n", Status);
-        RtlFreeUnicodeString(&pSetupData->DestinationRootPath);
         RtlFreeUnicodeString(&pSetupData->DestinationArcPath);
+        RtlFreeUnicodeString(&pSetupData->DestinationRootPath);
         return Status;
     }
 
@@ -723,9 +767,9 @@ InitDestinationPaths(
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("RtlCreateUnicodeString() failed with status 0x%08lx\n", Status);
-        RtlFreeUnicodeString(&pSetupData->DestinationRootPath);
-        RtlFreeUnicodeString(&pSetupData->DestinationArcPath);
         RtlFreeUnicodeString(&pSetupData->DestinationPath);
+        RtlFreeUnicodeString(&pSetupData->DestinationArcPath);
+        RtlFreeUnicodeString(&pSetupData->DestinationRootPath);
         return Status;
     }
 
index 90dfe7c..1930748 100644 (file)
@@ -404,7 +404,8 @@ DiskIdentifierQueryRoutine(
     UNICODE_STRING NameU;
 
     if (ValueType == REG_SZ &&
-        ValueLength == 20 * sizeof(WCHAR))
+        ValueLength == 20 * sizeof(WCHAR) &&
+        ((PWCHAR)ValueData)[8] == L'-')
     {
         NameU.Buffer = (PWCHAR)ValueData;
         NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
@@ -517,6 +518,7 @@ EnumerateBiosDiskEntries(
     RTL_QUERY_REGISTRY_TABLE QueryTable[3];
     WCHAR Name[120];
     ULONG AdapterCount;
+    ULONG ControllerCount;
     ULONG DiskCount;
     NTSTATUS Status;
     PCM_INT13_DRIVE_PARAMETER Int13Drives;
@@ -540,8 +542,7 @@ EnumerateBiosDiskEntries(
         return;
     }
 
-    AdapterCount = 0;
-    while (TRUE)
+    for (AdapterCount = 0; ; ++AdapterCount)
     {
         RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
                             L"%s\\%lu",
@@ -566,11 +567,11 @@ EnumerateBiosDiskEntries(
                                         NULL);
         if (NT_SUCCESS(Status))
         {
-            while (TRUE)
+            for (ControllerCount = 0; ; ++ControllerCount)
             {
                 RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
-                                    L"%s\\%lu\\DiskController\\0",
-                                    ROOT_NAME, AdapterCount);
+                                    L"%s\\%lu\\DiskController\\%lu",
+                                    ROOT_NAME, AdapterCount, ControllerCount);
                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
                                                 Name,
                                                 &QueryTable[2],
@@ -583,8 +584,8 @@ EnumerateBiosDiskEntries(
                 }
 
                 RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
-                                    L"%s\\%lu\\DiskController\\0\\DiskPeripheral",
-                                    ROOT_NAME, AdapterCount);
+                                    L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral",
+                                    ROOT_NAME, AdapterCount, ControllerCount);
                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
                                                 Name,
                                                 &QueryTable[2],
@@ -597,18 +598,18 @@ EnumerateBiosDiskEntries(
                     QueryTable[1].Name = L"Configuration Data";
                     QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
 
-                    DiskCount = 0;
-                    while (TRUE)
+                    for (DiskCount = 0; ; ++DiskCount)
                     {
                         BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
                         if (BiosDiskEntry == NULL)
                         {
-                            break;
+                            RtlFreeHeap(ProcessHeap, 0, Int13Drives);
+                            return;
                         }
 
                         RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
-                                            L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu",
-                                            ROOT_NAME, AdapterCount, DiskCount);
+                                            L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu",
+                                            ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
                         Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
                                                         Name,
                                                         QueryTable,
@@ -617,11 +618,14 @@ EnumerateBiosDiskEntries(
                         if (!NT_SUCCESS(Status))
                         {
                             RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
-                            break;
+                            RtlFreeHeap(ProcessHeap, 0, Int13Drives);
+                            return;
                         }
 
+                        BiosDiskEntry->AdapterNumber = 0; // And NOT "AdapterCount" as it needs to be hardcoded for BIOS!
+                        BiosDiskEntry->ControllerNumber = ControllerCount;
                         BiosDiskEntry->DiskNumber = DiskCount;
-                        BiosDiskEntry->Recognized = FALSE;
+                        BiosDiskEntry->DiskEntry = NULL;
 
                         if (DiskCount < Int13Drives[0].NumberDrives)
                         {
@@ -629,11 +633,14 @@ EnumerateBiosDiskEntries(
                         }
                         else
                         {
-                            DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
+                            DPRINT1("Didn't find Int13 drive data for disk %u\n", DiskCount);
                         }
 
                         InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
 
+                        DPRINT("--->\n");
+                        DPRINT("AdapterNumber:     %lu\n", BiosDiskEntry->AdapterNumber);
+                        DPRINT("ControllerNumber:  %lu\n", BiosDiskEntry->ControllerNumber);
                         DPRINT("DiskNumber:        %lu\n", BiosDiskEntry->DiskNumber);
                         DPRINT("Signature:         %08lx\n", BiosDiskEntry->Signature);
                         DPRINT("Checksum:          %08lx\n", BiosDiskEntry->Checksum);
@@ -645,17 +652,11 @@ EnumerateBiosDiskEntries(
                         DPRINT("SectorsPerTrack:   %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
                         DPRINT("MaxHeads:          %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
                         DPRINT("NumberDrives:      %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
-
-                        DiskCount++;
+                        DPRINT("<---\n");
                     }
                 }
-
-                RtlFreeHeap(ProcessHeap, 0, Int13Drives);
-                return;
             }
         }
-
-        AdapterCount++;
     }
 
     RtlFreeHeap(ProcessHeap, 0, Int13Drives);
@@ -664,6 +665,81 @@ EnumerateBiosDiskEntries(
 }
 
 
+/*
+ * Detects whether a disk reports as a "super-floppy", i.e. an unpartitioned
+ * disk with a valid VBR, following the criteria used by IoReadPartitionTable()
+ * and IoWritePartitionTable():
+ * only one single partition starting at the beginning of the disk; the reported
+ * defaults are: partition number being zero and its type being FAT16 non-bootable.
+ * Note also that accessing \Device\HarddiskN\Partition0 or Partition1 returns
+ * the same data.
+ */
+// static
+BOOLEAN
+IsSuperFloppy(
+    IN PDISKENTRY DiskEntry)
+{
+    PPARTITION_INFORMATION PartitionInfo;
+    ULONGLONG PartitionLengthEstimate;
+
+    /* No layout buffer: we cannot say anything yet */
+    if (DiskEntry->LayoutBuffer == NULL)
+        return FALSE;
+
+    /* We must have only one partition */
+    if (DiskEntry->LayoutBuffer->PartitionCount != 1)
+        return FALSE;
+
+    /* Get the single partition entry */
+    PartitionInfo = DiskEntry->LayoutBuffer->PartitionEntry;
+
+    /* The single partition must start at the beginning of the disk */
+    if (!(PartitionInfo->StartingOffset.QuadPart == 0 &&
+          PartitionInfo->HiddenSectors == 0))
+    {
+        return FALSE;
+    }
+
+    /* The disk signature is usually set to one; warn in case it's not */
+    if (DiskEntry->LayoutBuffer->Signature != 1)
+    {
+        DPRINT1("Super-Floppy disk %lu signature %08x != 1!\n",
+                DiskEntry->DiskNumber, DiskEntry->LayoutBuffer->Signature);
+    }
+
+    /*
+     * The partition number must be zero or one, be recognized,
+     * have FAT16 type and report as non-bootable.
+     */
+    if ((PartitionInfo->PartitionNumber != 0 &&
+         PartitionInfo->PartitionNumber != 1) ||
+        PartitionInfo->RecognizedPartition != TRUE ||
+        PartitionInfo->PartitionType != PARTITION_FAT_16 ||
+        PartitionInfo->BootIndicator != FALSE)
+    {
+        DPRINT1("Super-Floppy disk %lu does not return default settings!\n"
+                "    PartitionNumber = %lu, expected 0\n"
+                "    RecognizedPartition = %s, expected TRUE\n"
+                "    PartitionType = 0x%02x, expected 0x04 (PARTITION_FAT_16)\n"
+                "    BootIndicator = %s, expected FALSE\n",
+                DiskEntry->DiskNumber,
+                PartitionInfo->PartitionNumber,
+                PartitionInfo->RecognizedPartition ? "TRUE" : "FALSE",
+                PartitionInfo->PartitionType,
+                PartitionInfo->BootIndicator ? "TRUE" : "FALSE");
+    }
+
+    /* The partition lengths should agree */
+    PartitionLengthEstimate = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+    if (PartitionInfo->PartitionLength.QuadPart != PartitionLengthEstimate)
+    {
+        DPRINT1("PartitionLength = %I64u is different from PartitionLengthEstimate = %I64u\n",
+                PartitionInfo->PartitionLength.QuadPart, PartitionLengthEstimate);
+    }
+
+    return TRUE;
+}
+
 
 /*
  * Inserts the disk region represented by PartEntry into either the primary
@@ -1293,6 +1369,67 @@ UpdateDiskSignatures(
     }
 }
 
+static
+VOID
+UpdateHwDiskNumbers(
+    IN PPARTLIST List)
+{
+    PLIST_ENTRY ListEntry;
+    PBIOSDISKENTRY BiosDiskEntry;
+    PDISKENTRY DiskEntry;
+    ULONG HwAdapterNumber = 0;
+    ULONG HwControllerNumber = 0;
+    ULONG RemovableDiskCount = 0;
+
+    /*
+     * Enumerate the disks recognized by the BIOS and recompute the disk
+     * numbers on the system when *ALL* removable disks are not connected.
+     * The entries are inserted in increasing order of AdapterNumber,
+     * ControllerNumber and DiskNumber.
+     */
+    for (ListEntry = List->BiosDiskListHead.Flink;
+         ListEntry != &List->BiosDiskListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
+        DiskEntry = BiosDiskEntry->DiskEntry;
+
+        /*
+         * If the adapter or controller numbers change, update them and reset
+         * the number of removable disks on this adapter/controller.
+         */
+        if (HwAdapterNumber != BiosDiskEntry->AdapterNumber ||
+            HwControllerNumber != BiosDiskEntry->ControllerNumber)
+        {
+            HwAdapterNumber = BiosDiskEntry->AdapterNumber;
+            HwControllerNumber = BiosDiskEntry->ControllerNumber;
+            RemovableDiskCount = 0;
+        }
+
+        /* Adjust the actual hardware disk number */
+        if (DiskEntry)
+        {
+            ASSERT(DiskEntry->HwDiskNumber == BiosDiskEntry->DiskNumber);
+
+            if (DiskEntry->MediaType == RemovableMedia)
+            {
+                /* Increase the number of removable disks and set the disk number to zero */
+                ++RemovableDiskCount;
+                DiskEntry->HwFixedDiskNumber = 0;
+            }
+            else // if (DiskEntry->MediaType == FixedMedia)
+            {
+                /* Adjust the fixed disk number, offset by the number of removable disks found before this one */
+                DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber - RemovableDiskCount;
+            }
+        }
+        else
+        {
+            DPRINT1("BIOS disk %lu is not recognized by NTOS!\n", BiosDiskEntry->DiskNumber);
+        }
+    }
+}
+
 static
 VOID
 AddDiskToList(
@@ -1394,7 +1531,9 @@ AddDiskToList(
     Checksum = ~Checksum + 1;
 
     RtlStringCchPrintfW(Identifier, ARRAYSIZE(Identifier),
-                        L"%08x-%08x-A", Checksum, Signature);
+                        L"%08x-%08x-%c",
+                        Checksum, Signature,
+                        (Mbr->Magic == PARTITION_MAGIC) ? L'A' : L'X');
     DPRINT("Identifier: %S\n", Identifier);
 
     DiskEntry = RtlAllocateHeap(ProcessHeap,
@@ -1409,6 +1548,37 @@ AddDiskToList(
 
     DiskEntry->PartList = List;
 
+#if 0
+    {
+        FILE_FS_DEVICE_INFORMATION FileFsDevice;
+
+        /* Query the device for its type */
+        Status = NtQueryVolumeInformationFile(FileHandle,
+                                              &Iosb,
+                                              &FileFsDevice,
+                                              sizeof(FileFsDevice),
+                                              FileFsDeviceInformation);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Couldn't detect device type for disk %lu of identifier '%S'...\n", DiskNumber, Identifier);
+        }
+        else
+        {
+            DPRINT1("Disk %lu : DeviceType: 0x%08x ; Characteristics: 0x%08x\n", DiskNumber, FileFsDevice.DeviceType, FileFsDevice.Characteristics);
+        }
+    }
+    // NOTE: We may also use NtQueryVolumeInformationFile(FileFsDeviceInformation).
+#endif
+    DiskEntry->MediaType = DiskGeometry.MediaType;
+    if (DiskEntry->MediaType == RemovableMedia)
+    {
+        DPRINT1("Disk %lu of identifier '%S' is removable\n", DiskNumber, Identifier);
+    }
+    else // if (DiskEntry->MediaType == FixedMedia)
+    {
+        DPRINT1("Disk %lu of identifier '%S' is fixed\n", DiskNumber, Identifier);
+    }
+
 //    DiskEntry->Checksum = Checksum;
 //    DiskEntry->Signature = Signature;
     DiskEntry->BiosFound = FALSE;
@@ -1459,34 +1629,42 @@ AddDiskToList(
          */
         if (BiosDiskEntry->Signature == Signature &&
             BiosDiskEntry->Checksum == Checksum &&
-            !BiosDiskEntry->Recognized)
+            BiosDiskEntry->DiskEntry == NULL)
         {
             if (!DiskEntry->BiosFound)
             {
-                DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
+                DiskEntry->HwAdapterNumber = BiosDiskEntry->AdapterNumber;
+                DiskEntry->HwControllerNumber = BiosDiskEntry->ControllerNumber;
+                DiskEntry->HwDiskNumber = BiosDiskEntry->DiskNumber;
+
+                if (DiskEntry->MediaType == RemovableMedia)
+                {
+                    /* Set the removable disk number to zero */
+                    DiskEntry->HwFixedDiskNumber = 0;
+                }
+                else // if (DiskEntry->MediaType == FixedMedia)
+                {
+                    /* The fixed disk number will later be adjusted using the number of removable disks */
+                    DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber;
+                }
+
                 DiskEntry->BiosFound = TRUE;
-                BiosDiskEntry->Recognized = TRUE;
+                BiosDiskEntry->DiskEntry = DiskEntry;
+                break;
             }
             else
             {
                 // FIXME: What to do?
+                DPRINT1("Disk %lu of identifier '%S' has already been found?!\n", DiskNumber, Identifier);
             }
         }
     }
 
     if (!DiskEntry->BiosFound)
     {
-#if 0
-        RtlFreeHeap(ProcessHeap, 0, DiskEntry);
-        return;
-#else
-        DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
-#endif
+        DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %lu may not be bootable by the BIOS!\n", DiskNumber);
     }
 
-    InitializeListHead(&DiskEntry->PrimaryPartListHead);
-    InitializeListHead(&DiskEntry->LogicalPartListHead);
-
     DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
     DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
     DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
@@ -1530,6 +1708,9 @@ AddDiskToList(
      * See examples in https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/ntoskrnl/io/iomgr/error.c;hb=2f3a93ee9cec8322a86bf74b356f1ad83fc912dc#l267
      */
 
+    InitializeListHead(&DiskEntry->PrimaryPartListHead);
+    InitializeListHead(&DiskEntry->LogicalPartListHead);
+
     InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
 
 
@@ -1602,6 +1783,9 @@ AddDiskToList(
     DumpPartitionTable(DiskEntry);
 #endif
 
+    if (IsSuperFloppy(DiskEntry))
+        DPRINT1("Disk %lu is a super-floppy\n", DiskNumber);
+
     if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
         DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
         DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != PARTITION_ENTRY_UNUSED)
@@ -1723,7 +1907,7 @@ CreatePartitionList(VOID)
     }
 
     UpdateDiskSignatures(List);
-
+    UpdateHwDiskNumbers(List);
     AssignDriveLetters(List);
 
     return List;
@@ -1789,7 +1973,7 @@ DestroyPartitionList(
 PDISKENTRY
 GetDiskByBiosNumber(
     IN PPARTLIST List,
-    IN ULONG BiosDiskNumber)
+    IN ULONG HwDiskNumber)
 {
     PDISKENTRY DiskEntry;
     PLIST_ENTRY Entry;
@@ -1801,7 +1985,7 @@ GetDiskByBiosNumber(
     {
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
 
-        if (DiskEntry->BiosDiskNumber == BiosDiskNumber)
+        if (DiskEntry->HwDiskNumber == HwDiskNumber)
         {
             /* Disk found */
             return DiskEntry;
@@ -2879,6 +3063,7 @@ DeletePartition(
     if (List->SystemPartition == PartEntry)
     {
         ASSERT(List->SystemPartition);
+        ASSERT(List->SystemPartition->DiskEntry->MediaType != RemovableMedia);
 
         if (List->SystemPartition == List->OriginalSystemPartition)
             List->OriginalSystemPartition = NULL;
@@ -3604,7 +3789,7 @@ WritePartitions(
     //
     // NOTE: Originally (see r40437), we used to install here also a new MBR
     // for this disk (by calling InstallMbrBootCodeToDisk), only if:
-    // DiskEntry->NewDisk == TRUE and DiskEntry->BiosDiskNumber == 0.
+    // DiskEntry->NewDisk == TRUE and DiskEntry->HwDiskNumber == 0.
     // Then after that, both DiskEntry->NewDisk and DiskEntry->NoMbr were set
     // to FALSE. In the other place (in usetup.c) where InstallMbrBootCodeToDisk
     // was called too, the installation test was modified by checking whether
@@ -3823,6 +4008,10 @@ PrimaryPartitionCreationChecks(
     if (PartEntry->IsPartitioned)
         return ERROR_NEW_PARTITION;
 
+    /* Only one primary partition is allowed on super-floppy */
+    if (IsSuperFloppy(DiskEntry))
+        return ERROR_PARTITION_TABLE_FULL;
+
     /* Fail if there are already 4 primary partitions in the list */
     if (GetPrimaryPartitionCount(DiskEntry) >= 4)
         return ERROR_PARTITION_TABLE_FULL;
@@ -3846,6 +4035,10 @@ ExtendedPartitionCreationChecks(
     if (PartEntry->IsPartitioned)
         return ERROR_NEW_PARTITION;
 
+    /* Only one primary partition is allowed on super-floppy */
+    if (IsSuperFloppy(DiskEntry))
+        return ERROR_PARTITION_TABLE_FULL;
+
     /* Fail if there are already 4 primary partitions in the list */
     if (GetPrimaryPartitionCount(DiskEntry) >= 4)
         return ERROR_PARTITION_TABLE_FULL;
@@ -3873,6 +4066,10 @@ LogicalPartitionCreationChecks(
     if (PartEntry->IsPartitioned)
         return ERROR_NEW_PARTITION;
 
+    /* Only one primary partition is allowed on super-floppy */
+    if (IsSuperFloppy(DiskEntry))
+        return ERROR_PARTITION_TABLE_FULL;
+
     return ERROR_SUCCESS;
 }
 
index 2ed7f58..fc31cc1 100644 (file)
@@ -72,19 +72,6 @@ typedef struct _PARTENTRY
 
 } PARTENTRY, *PPARTENTRY;
 
-
-typedef struct _BIOSDISKENTRY
-{
-    LIST_ENTRY ListEntry;
-    ULONG DiskNumber;
-    ULONG Signature;
-    ULONG Checksum;
-    BOOLEAN Recognized;
-    CM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
-    CM_INT13_DRIVE_PARAMETER Int13DiskData;
-} BIOSDISKENTRY, *PBIOSDISKENTRY;
-
-
 typedef struct _DISKENTRY
 {
     LIST_ENTRY ListEntry;
@@ -92,6 +79,8 @@ typedef struct _DISKENTRY
     /* The list of disks/partitions this disk belongs to */
     struct _PARTLIST *PartList;
 
+    MEDIA_TYPE MediaType;   /* FixedMedia or RemovableMedia */
+
     /* Disk geometry */
 
     ULONGLONG Cylinders;
@@ -103,9 +92,12 @@ typedef struct _DISKENTRY
     ULONG SectorAlignment;
     ULONG CylinderAlignment;
 
-    /* BIOS parameters */
+    /* BIOS Firmware parameters */
     BOOLEAN BiosFound;
-    ULONG BiosDiskNumber;
+    ULONG HwAdapterNumber;
+    ULONG HwControllerNumber;
+    ULONG HwDiskNumber;         /* Disk number currently assigned on the system */
+    ULONG HwFixedDiskNumber;    /* Disk number on the system when *ALL* removable disks are not connected */
 //    ULONG Signature;  // Obtained from LayoutBuffer->Signature
 //    ULONG Checksum;
 
@@ -138,6 +130,18 @@ typedef struct _DISKENTRY
 
 } DISKENTRY, *PDISKENTRY;
 
+typedef struct _BIOSDISKENTRY
+{
+    LIST_ENTRY ListEntry;
+    ULONG AdapterNumber;
+    ULONG ControllerNumber;
+    ULONG DiskNumber;
+    ULONG Signature;
+    ULONG Checksum;
+    PDISKENTRY DiskEntry;   /* Corresponding recognized disk; is NULL if the disk is not recognized */ // RecognizedDiskEntry;
+    CM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
+    CM_INT13_DRIVE_PARAMETER Int13DiskData;
+} BIOSDISKENTRY, *PBIOSDISKENTRY;
 
 typedef struct _PARTLIST
 {
@@ -223,6 +227,10 @@ RoundingDivide(
    IN ULONGLONG Divisor);
 
 
+BOOLEAN
+IsSuperFloppy(
+    IN PDISKENTRY DiskEntry);
+
 
 PPARTLIST
 CreatePartitionList(VOID);
@@ -234,7 +242,7 @@ DestroyPartitionList(
 PDISKENTRY
 GetDiskByBiosNumber(
     IN PPARTLIST List,
-    IN ULONG BiosDiskNumber);
+    IN ULONG HwDiskNumber);
 
 PDISKENTRY
 GetDiskByNumber(
index 216f887..65ad2b9 100644 (file)
@@ -791,7 +791,8 @@ DisableWizNext:
                     DISKENTRY DiskEntry;
                     PARTENTRY PartEntry;
                     DiskEntry.DiskNumber = 0;
-                    DiskEntry.BiosDiskNumber = 0;
+                    DiskEntry.HwDiskNumber = 0;
+                    DiskEntry.HwFixedDiskNumber = 0;
                     PartEntry.DiskEntry = &DiskEntry;
                     PartEntry.PartitionNumber = 1; // 4;
                     /****/
index 4367361..82716f6 100644 (file)
@@ -1636,6 +1636,23 @@ SelectPartitionPage(PINPUT_RECORD Ir)
             if (IsContainerPartition(CurrentPartition->PartitionType))
                 continue; // return SELECT_PARTITION_PAGE;
 
+            /*
+             * Check whether the user wants to install ReactOS on a disk that
+             * is not recognized by the computer's firmware and if so, display
+             * a warning since such disks may not be bootable.
+             */
+            if (CurrentPartition->DiskEntry->MediaType == FixedMedia &&
+                !CurrentPartition->DiskEntry->BiosFound)
+            {
+                PopupError("The disk you have selected for installing ReactOS\n"
+                           "is not visible by the firmware of your computer,\n"
+                           "and so may not be bootable.\n"
+                           "Press ENTER to continue nonetheless.",
+                           MUIGetString(STRING_CONTINUE),
+                           Ir, POPUP_WAIT_ENTER);
+                // return SELECT_PARTITION_PAGE;
+            }
+
             if (CurrentPartition->IsPartitioned == FALSE)
             {
                 if (CurrentPartition->LogicalPartition)
@@ -4428,18 +4445,21 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
         return QUIT_PAGE;
     }
 
-    /* Step 2: Write the MBR */
-    RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
-            L"\\Device\\Harddisk%d\\Partition0",
-            PartitionList->SystemPartition->DiskEntry->DiskNumber);
-    Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath,
-                                      &USetupData.SourceRootPath,
-                                      DestinationDevicePathBuffer);
-    if (!NT_SUCCESS(Status))
+    /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
+    if (!IsSuperFloppy(PartitionList->SystemPartition->DiskEntry))
     {
-        DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status);
-        MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER, L"MBR");
-        return QUIT_PAGE;
+        RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
+                L"\\Device\\Harddisk%d\\Partition0",
+                PartitionList->SystemPartition->DiskEntry->DiskNumber);
+        Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath,
+                                          &USetupData.SourceRootPath,
+                                          DestinationDevicePathBuffer);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status);
+            MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER, L"MBR");
+            return QUIT_PAGE;
+        }
     }
 
     return SUCCESS_PAGE;