- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.

CORE-10898

svn path=/trunk/; revision=70837
This commit is contained in:
Hermès Bélusca-Maïto 2016-03-01 15:00:56 +00:00
parent a91cef7070
commit e3445e18d1
8 changed files with 275 additions and 62 deletions

View file

@ -626,7 +626,6 @@ UpdateFreeLoaderIni(
return STATUS_SUCCESS;
}
static
BOOLEAN
IsThereAValidBootSector(PWSTR RootPath)
{
@ -695,9 +694,8 @@ IsThereAValidBootSector(PWSTR RootPath)
return (Instruction != 0x00000000);
}
static
NTSTATUS
SaveCurrentBootSector(
SaveBootSector(
PWSTR RootPath,
PWSTR DstPath,
ULONG Length)
@ -1210,7 +1208,7 @@ InstallMbrBootCodeToDisk(
NULL,
&IoStatusBlock,
OrigBootSector,
SECTORSIZE,
sizeof(PARTITION_SECTOR),
&FileOffset,
NULL);
NtClose(FileHandle);
@ -1306,7 +1304,7 @@ InstallMbrBootCodeToDisk(
NULL,
&IoStatusBlock,
NewBootSector,
SECTORSIZE,
sizeof(PARTITION_SECTOR),
&FileOffset,
NULL);
NtClose(FileHandle);
@ -2447,10 +2445,10 @@ InstallFatBootcodeToPartition(
wcscat(DstPath, BootSectorFileName);
DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
Status = SaveCurrentBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
if (!NT_SUCCESS(Status))
{
DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
return Status;
}
}
@ -2582,10 +2580,10 @@ InstallExt2BootcodeToPartition(
wcscat(DstPath, L"\\bootsect.old");
DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
Status = SaveCurrentBootSector(SystemRootPath->Buffer, DstPath, sizeof(EXT2_BOOTSECTOR));
Status = SaveBootSector(SystemRootPath->Buffer, DstPath, sizeof(EXT2_BOOTSECTOR));
if (!NT_SUCCESS(Status))
{
DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
return Status;
}
}

View file

@ -26,6 +26,15 @@
#pragma once
BOOLEAN
IsThereAValidBootSector(PWSTR RootPath);
NTSTATUS
SaveBootSector(
PWSTR RootPath,
PWSTR DstPath,
ULONG Length);
NTSTATUS
InstallMbrBootCodeToDisk(
PWSTR SrcPath,

View file

@ -91,7 +91,7 @@ GetFileSystemByName(
PFILE_SYSTEM_ITEM
GetFileSystem(
IN PFILE_SYSTEM_LIST FileSystemList,
IN PPARTENTRY PartEntry)
IN struct _PARTENTRY* PartEntry)
{
PFILE_SYSTEM_ITEM CurrentFileSystem;
LPWSTR FileSystemName = NULL;
@ -102,6 +102,8 @@ GetFileSystem(
if (CurrentFileSystem != NULL && CurrentFileSystem->FileSystemName != NULL)
return CurrentFileSystem;
DPRINT1("File system not found, try to guess one...\n");
CurrentFileSystem = NULL;
/*
@ -121,9 +123,9 @@ GetFileSystem(
*/
if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
(PartEntry->PartitionType == PARTITION_FAT_16) ||
(PartEntry->PartitionType == PARTITION_HUGE) ||
(PartEntry->PartitionType == PARTITION_HUGE ) ||
(PartEntry->PartitionType == PARTITION_XINT13) ||
(PartEntry->PartitionType == PARTITION_FAT32) ||
(PartEntry->PartitionType == PARTITION_FAT32 ) ||
(PartEntry->PartitionType == PARTITION_FAT32_XINT13))
{
FileSystemName = L"FAT";
@ -139,9 +141,9 @@ GetFileSystem(
FileSystemName = L"NTFS"; /* FIXME: Not quite correct! */
}
// WARNING: We cannot write on this FS yet!
// HACK: WARNING: We cannot write on this FS yet!
if (PartEntry->PartitionType == PARTITION_EXT2 || PartEntry->PartitionType == PARTITION_IFS)
DPRINT1("Recognized FileSystem %S that doesn't support write support yet!\n", FileSystemName);
DPRINT1("Recognized file system %S that doesn't support write support yet!\n", FileSystemName);
DPRINT1("GetFileSystem -- PartitionType: 0x%02X ; FileSystemName (guessed): %S\n",
PartEntry->PartitionType, FileSystemName);

View file

@ -57,10 +57,11 @@ GetFileSystemByName(
IN PFILE_SYSTEM_LIST List,
IN LPWSTR FileSystemName);
struct _PARTENTRY; // Defined in partlist.h
PFILE_SYSTEM_ITEM
GetFileSystem(
IN PFILE_SYSTEM_LIST FileSystemList,
IN PPARTENTRY PartEntry);
IN struct _PARTENTRY* PartEntry);
PFILE_SYSTEM_LIST
CreateFileSystemList(

View file

@ -1731,8 +1731,11 @@ SelectPartitionPage(PINPUT_RECORD Ir)
return SELECT_PARTITION_PAGE;
}
if (PartitionList->CurrentPartition->BootIndicator)
if (PartitionList->CurrentPartition->BootIndicator ||
PartitionList->CurrentPartition == PartitionList->SystemPartition)
{
return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE;
}
return DELETE_PARTITION_PAGE;
}
@ -2553,8 +2556,21 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
return QUIT_PAGE;
}
/*** HACK! ***/
if (FileSystemList == NULL)
{
FileSystemList = CreateFileSystemList(6, 26, PartitionList->CurrentPartition->New, L"FAT");
if (FileSystemList == NULL)
{
/* FIXME: show an error dialog */
return QUIT_PAGE;
}
/* FIXME: Add file systems to list */
}
/* Find or set the active system partition */
CheckActiveSystemPartition(PartitionList);
CheckActiveSystemPartition(PartitionList, FileSystemList);
if (PartitionList->SystemDisk == NULL ||
PartitionList->SystemPartition == NULL)
@ -4130,7 +4146,7 @@ BootLoaderPage(PINPUT_RECORD Ir)
PartitionList->SystemDisk->DiskNumber,
PartitionList->SystemPartition->PartitionNumber);
RtlCreateUnicodeString(&SystemRootPath, PathBuffer);
DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath);
PartitionType = PartitionList->SystemPartition->PartitionType;
@ -4382,6 +4398,7 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
NTSTATUS Status;
WCHAR DestinationDevicePathBuffer[MAX_PATH];
WCHAR SourceMbrPathBuffer[MAX_PATH];
WCHAR DstPath[MAX_PATH];
/* Step 1: Write the VBR */
PartitionType = PartitionList->SystemPartition->PartitionType;
@ -4404,9 +4421,24 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
wcscpy(SourceMbrPathBuffer, SourceRootPath.Buffer);
wcscat(SourceMbrPathBuffer, L"\\loader\\dosmbr.bin");
DPRINT("Install MBR bootcode: %S ==> %S\n",
DPRINT1("Install MBR bootcode: %S ==> %S\n",
SourceMbrPathBuffer, DestinationDevicePathBuffer);
if (IsThereAValidBootSector(DestinationDevicePathBuffer))
{
/* Save current MBR */
wcscpy(DstPath, SystemRootPath.Buffer);
wcscat(DstPath, L"\\mbr.old");
DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR));
if (!NT_SUCCESS(Status))
{
DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
// Don't care if we succeeded or not saving the old MBR, just go ahead.
}
}
Status = InstallMbrBootCodeToDisk(SourceMbrPathBuffer,
DestinationDevicePathBuffer);
if (!NT_SUCCESS(Status))

View file

@ -1430,6 +1430,8 @@ CreatePartitionList(
List->SystemDisk = NULL;
List->SystemPartition = NULL;
List->OriginalSystemDisk = NULL;
List->OriginalSystemPartition = NULL;
List->TempDisk = NULL;
List->TempPartition = NULL;
@ -3111,29 +3113,26 @@ DeleteCurrentPartition(
VOID
CheckActiveSystemPartition(
PPARTLIST List)
IN PPARTLIST List,
IN PFILE_SYSTEM_LIST FileSystemList /* Needed for checking the FS of the candidate system partition */
)
{
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
PLIST_ENTRY ListEntry;
PFILE_SYSTEM_ITEM FileSystem;
/* Check for empty disk list */
if (IsListEmpty(&List->DiskListHead))
{
List->SystemDisk = NULL;
List->SystemPartition = NULL;
List->OriginalSystemDisk = NULL;
List->OriginalSystemPartition = NULL;
return;
}
#if 0
if (List->SystemDisk != NULL &&
List->SystemPartition != NULL)
{
/* We already have an active system partition */
return;
}
#endif
/* Choose the currently selected disk */
DiskEntry = List->CurrentDisk;
@ -3142,64 +3141,226 @@ CheckActiveSystemPartition(
{
List->SystemDisk = NULL;
List->SystemPartition = NULL;
List->OriginalSystemDisk = NULL;
List->OriginalSystemPartition = NULL;
return;
}
/*
* Check the first partition of the disk in case it is fresh new,
* and if so, use it as the system partition.
*/
if (List->SystemDisk != NULL && List->SystemPartition != NULL)
{
/* We already have an active system partition */
DPRINT1("Use the current system partition %lu in disk %lu, drive letter %c\n",
List->SystemPartition->PartitionNumber,
List->SystemDisk->DiskNumber,
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
return;
}
DPRINT1("We are here (1)!\n");
List->SystemDisk = NULL;
List->SystemPartition = NULL;
List->OriginalSystemDisk = NULL;
List->OriginalSystemPartition = NULL;
/* Retrieve the first partition of the disk */
PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
PARTENTRY,
ListEntry);
List->SystemDisk = DiskEntry;
List->SystemPartition = PartEntry;
/* Set active system partition */
if ((DiskEntry->NewDisk == TRUE) ||
(PartEntry->BootIndicator == FALSE))
//
// See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
//
/* Check if the disk is new and if so, use its first partition as the active system partition */
if (DiskEntry->NewDisk)
{
PartEntry->BootIndicator = TRUE;
DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].BootIndicator = TRUE;
DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
DiskEntry->Dirty = TRUE;
if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator == FALSE)
{
/* FIXME: Might be incorrect if partitions were created by Linux FDISK */
List->SystemDisk = DiskEntry;
List->SystemPartition = PartEntry;
/* FIXME: Might be incorrect if partitions were created by Linux FDISK */
List->SystemDisk = DiskEntry;
List->SystemPartition = PartEntry;
List->OriginalSystemDisk = List->SystemDisk;
List->OriginalSystemPartition = List->SystemPartition;
return;
DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %c\n",
List->SystemPartition->PartitionNumber,
List->SystemDisk->DiskNumber,
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
goto SetSystemPartition;
}
// FIXME: What to do??
DPRINT1("NewDisk TRUE but first partition is used?\n");
}
/* Disk is not new, scan all partitions to find a bootable one */
List->SystemDisk = NULL;
List->SystemPartition = NULL;
DPRINT1("We are here (2)!\n");
/*
* The disk is not new, check if any partition is initialized;
* if not, the first one becomes the system partition.
*/
ListEntry = DiskEntry->PrimaryPartListHead.Flink;
while (ListEntry != &DiskEntry->PrimaryPartListHead)
{
/* Retrieve the partition and go to the next one */
PartEntry = CONTAINING_RECORD(ListEntry,
PARTENTRY,
ListEntry);
/* Check if it is partitioned */
if (PartEntry->IsPartitioned)
/* Check if the partition is partitioned and is used */
if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator != FALSE)
{
if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED &&
PartEntry->BootIndicator)
{
/* Yes, we found it */
List->SystemDisk = DiskEntry;
List->SystemPartition = PartEntry;
DPRINT("Found bootable partition disk %d, drive letter %c\n",
DiskEntry->DiskNumber, PartEntry->DriveLetter);
break;
}
break;
}
/* Go to the next one */
ListEntry = ListEntry->Flink;
}
if (ListEntry == &DiskEntry->PrimaryPartListHead)
{
/*
* OK we haven't encountered any used and active partition,
* so use the first one as the system partition.
*/
/* FIXME: Might be incorrect if partitions were created by Linux FDISK */
List->OriginalSystemDisk = List->SystemDisk; // DiskEntry
List->OriginalSystemPartition = List->SystemPartition; // First PartEntry
DPRINT1("Use first active system partition %lu in disk %lu, drive letter %c\n",
List->SystemPartition->PartitionNumber,
List->SystemDisk->DiskNumber,
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
goto SetSystemPartition;
}
List->SystemDisk = NULL;
List->SystemPartition = NULL;
List->OriginalSystemDisk = NULL;
List->OriginalSystemPartition = NULL;
DPRINT1("We are here (3)!\n");
/* The disk is not new, scan all partitions to find the (active) system partition */
ListEntry = DiskEntry->PrimaryPartListHead.Flink;
while (ListEntry != &DiskEntry->PrimaryPartListHead)
{
/* Retrieve the partition and go to the next one */
PartEntry = CONTAINING_RECORD(ListEntry,
PARTENTRY,
ListEntry);
ListEntry = ListEntry->Flink;
/* Check if the partition is partitioned and used */
if (PartEntry->IsPartitioned &&
PartEntry->PartitionType != PARTITION_ENTRY_UNUSED)
{
/* Check if the partition is active */
if (PartEntry->BootIndicator)
{
/* Yes, we found it */
List->SystemDisk = DiskEntry;
List->SystemPartition = PartEntry;
DPRINT1("Found active system partition %lu in disk %lu, drive letter %c\n",
PartEntry->PartitionNumber,
DiskEntry->DiskNumber,
(PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter);
break;
}
}
}
/* Check if we have found the system partition */
if (List->SystemDisk == NULL || List->SystemPartition == NULL)
{
/* Nothing, use the alternative system partition */
DPRINT1("No system partition found, use the alternative partition!\n");
goto UseAlternativeSystemPartition;
}
/* Save them */
List->OriginalSystemDisk = List->SystemDisk;
List->OriginalSystemPartition = List->SystemPartition;
/*
* ADDITIONAL CHECKS / BIG HACK:
*
* Retrieve its file system and check whether we have
* write support for it. If that is the case we are fine
* and we can use it directly. However if we don't have
* write support we will need to change the active system
* partition.
*
* NOTE that this is completely useless on architectures
* where a real system partition is required, as on these
* architectures the partition uses the FAT FS, for which
* we do have write support.
* NOTE also that for those architectures looking for a
* partition boot indicator is insufficient.
*/
FileSystem = GetFileSystem(FileSystemList, List->OriginalSystemPartition);
if (FileSystem == NULL)
{
DPRINT1("System partition %lu in disk %lu with no FS?!\n",
List->OriginalSystemPartition->PartitionNumber,
List->OriginalSystemDisk->DiskNumber);
goto FindAndUseAlternativeSystemPartition;
}
// HACK: WARNING: We cannot write on this FS yet!
// See fslist.c:GetFileSystem()
if (List->OriginalSystemPartition->PartitionType == PARTITION_EXT2 ||
List->OriginalSystemPartition->PartitionType == PARTITION_IFS)
{
DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
FileSystem->FileSystemName);
goto FindAndUseAlternativeSystemPartition;
}
DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %c\n",
List->SystemPartition->PartitionNumber,
List->SystemDisk->DiskNumber,
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
return;
FindAndUseAlternativeSystemPartition:
/*
* We are here because we have not found any (active) candidate
* system partition that we know how to support. What we are going
* to do is to change the existing system partition and use the
* partition on which we install ReactOS as the new system partition,
* and then we will need to add in FreeLdr's entry a boot entry to boot
* from the original system partition.
*/
/* Unset the old system partition */
List->SystemPartition->BootIndicator = FALSE;
List->SystemDisk->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = FALSE;
List->SystemDisk->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
List->SystemDisk->Dirty = TRUE;
UseAlternativeSystemPartition:
List->SystemDisk = List->CurrentDisk;
List->SystemPartition = List->CurrentPartition;
DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %c\n",
List->SystemPartition->PartitionNumber,
List->SystemDisk->DiskNumber,
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
SetSystemPartition:
/* Set the new active system partition */
List->SystemPartition->BootIndicator = TRUE;
List->SystemDisk->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = TRUE;
List->SystemDisk->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
List->SystemDisk->Dirty = TRUE;
}

View file

@ -155,6 +155,15 @@ typedef struct _PARTLIST
/* The system disk and partition where the boot manager resides */
PDISKENTRY SystemDisk;
PPARTENTRY SystemPartition;
/*
* The original system disk and partition in case we are redefining them
* because we do not have write support on them.
* Please not that this is partly a HACK and MUST NEVER happen on
* architectures where real system partitions are mandatory (because then
* they are formatted in FAT FS and we support write operation on them).
*/
PDISKENTRY OriginalSystemDisk;
PPARTENTRY OriginalSystemPartition;
PDISKENTRY TempDisk;
PPARTENTRY TempPartition;
@ -258,7 +267,8 @@ DeleteCurrentPartition(
VOID
CheckActiveSystemPartition(
PPARTLIST List);
IN PPARTLIST List,
IN PFILE_SYSTEM_LIST FileSystemList);
BOOLEAN
WritePartitionsToDisk(

View file

@ -60,7 +60,6 @@
/* Internal Headers */
#include "interface/consup.h"
#include "partlist.h"
#include "inffile.h"
#include "inicache.h"
#include "progress.h"
@ -70,6 +69,7 @@
#endif
#include "registry.h"
#include "fslist.h"
#include "partlist.h"
#include "cabinet.h"
#include "filesup.h"
#include "genlist.h"