https://git.reactos.org/?p=reactos.git;a=commitdiff;h=47a1acedf7b28252674211d12314755f7ba96be7

commit 47a1acedf7b28252674211d12314755f7ba96be7
Author:     Hermès Bélusca-Maïto <[email protected]>
AuthorDate: Tue Mar 12 00:13:25 2019 +0100
Commit:     Hermès Bélusca-Maïto <[email protected]>
CommitDate: Tue Mar 12 02:17:11 2019 +0100

    [SETUPLIB][USETUP] Improve disk HW numbering, removable disk support, and 
"super-floppy" partitioning.
    
    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       |  60 +++++++--
 base/setup/lib/utils/partlist.c | 277 ++++++++++++++++++++++++++++++++++------
 base/setup/lib/utils/partlist.h |  40 +++---
 base/setup/reactos/drivepage.c  |   3 +-
 base/setup/usetup/usetup.c      |  42 ++++--
 5 files changed, 346 insertions(+), 76 deletions(-)

diff --git a/base/setup/lib/setuplib.c b/base/setup/lib/setuplib.c
index fff627215b7..be71e8191c0 100644
--- a/base/setup/lib/setuplib.c
+++ b/base/setup/lib/setuplib.c
@@ -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;
     }
 
diff --git a/base/setup/lib/utils/partlist.c b/base/setup/lib/utils/partlist.c
index 90dfe7ca8de..1930748ab80 100644
--- a/base/setup/lib/utils/partlist.c
+++ b/base/setup/lib/utils/partlist.c
@@ -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;
 }
 
diff --git a/base/setup/lib/utils/partlist.h b/base/setup/lib/utils/partlist.h
index 2ed7f583e8f..fc31cc13331 100644
--- a/base/setup/lib/utils/partlist.h
+++ b/base/setup/lib/utils/partlist.h
@@ -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(
diff --git a/base/setup/reactos/drivepage.c b/base/setup/reactos/drivepage.c
index 216f887659d..65ad2b927ba 100644
--- a/base/setup/reactos/drivepage.c
+++ b/base/setup/reactos/drivepage.c
@@ -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;
                     /****/
diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c
index 43673613a37..82716f61b5b 100644
--- a/base/setup/usetup/usetup.c
+++ b/base/setup/usetup/usetup.c
@@ -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;

Reply via email to