From 47a1acedf7b28252674211d12314755f7ba96be7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Tue, 12 Mar 2019 00:13:25 +0100 Subject: [PATCH 1/1] [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; -- 2.17.1