From c15a2bb8efd5df7057cba3a462325abf4899edf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Mon, 23 Nov 2020 04:38:51 +0100 Subject: [PATCH] WIP - [SETUPLIB][USETUP] Isolate and decouple the filesystem volume operations code from the UI. The idea is similar to the SetupCommitFileQueue() function: filesystem volume operations are "queued" (and are retrieved via the GetNextUnformatted/UncheckedPartition() helpers) and processed via a "commit queue", that employs a user-specified callback. That latter one can deal with displaying the appropriate UI screens, etc. --- base/setup/lib/fsutil.c | 428 +++++++++++++- base/setup/lib/fsutil.h | 139 ++++- base/setup/lib/setuplib.c | 89 +++ base/setup/lib/setuplib.h | 10 + base/setup/lib/utils/partlist.c | 13 +- base/setup/usetup/chkdsk.c | 35 +- base/setup/usetup/chkdsk.h | 10 +- base/setup/usetup/format.c | 41 +- base/setup/usetup/format.h | 13 +- base/setup/usetup/partlist.h | 13 - base/setup/usetup/usetup.c | 955 +++++++++++++++----------------- base/setup/usetup/usetup.h | 5 +- 12 files changed, 1115 insertions(+), 636 deletions(-) diff --git a/base/setup/lib/fsutil.c b/base/setup/lib/fsutil.c index b58633e2df26e..1c72ff373aa03 100644 --- a/base/setup/lib/fsutil.c +++ b/base/setup/lib/fsutil.c @@ -242,13 +242,13 @@ GetFileSystemByName( /** ChkdskEx() **/ NTSTATUS ChkdskFileSystem_UStr( - IN PUNICODE_STRING DriveRoot, - IN PCWSTR FileSystemName, - IN BOOLEAN FixErrors, - IN BOOLEAN Verbose, - IN BOOLEAN CheckOnlyIfDirty, - IN BOOLEAN ScanDrive, - IN PFMIFSCALLBACK Callback) + _In_ PUNICODE_STRING DriveRoot, + _In_ PCWSTR FileSystemName, + _In_ BOOLEAN FixErrors, + _In_ BOOLEAN Verbose, + _In_ BOOLEAN CheckOnlyIfDirty, + _In_ BOOLEAN ScanDrive, + _In_opt_ PFMIFSCALLBACK Callback) { PFILE_SYSTEM FileSystem; NTSTATUS Status; @@ -285,13 +285,13 @@ ChkdskFileSystem_UStr( NTSTATUS ChkdskFileSystem( - IN PCWSTR DriveRoot, - IN PCWSTR FileSystemName, - IN BOOLEAN FixErrors, - IN BOOLEAN Verbose, - IN BOOLEAN CheckOnlyIfDirty, - IN BOOLEAN ScanDrive, - IN PFMIFSCALLBACK Callback) + _In_ PCWSTR DriveRoot, + _In_ PCWSTR FileSystemName, + _In_ BOOLEAN FixErrors, + _In_ BOOLEAN Verbose, + _In_ BOOLEAN CheckOnlyIfDirty, + _In_ BOOLEAN ScanDrive, + _In_opt_ PFMIFSCALLBACK Callback) { UNICODE_STRING DriveRootU; @@ -309,13 +309,13 @@ ChkdskFileSystem( /** FormatEx() **/ NTSTATUS FormatFileSystem_UStr( - IN PUNICODE_STRING DriveRoot, - IN PCWSTR FileSystemName, - IN FMIFS_MEDIA_FLAG MediaFlag, - IN PUNICODE_STRING Label, - IN BOOLEAN QuickFormat, - IN ULONG ClusterSize, - IN PFMIFSCALLBACK Callback) + _In_ PUNICODE_STRING DriveRoot, + _In_ PCWSTR FileSystemName, + _In_ FMIFS_MEDIA_FLAG MediaFlag, + _In_opt_ PUNICODE_STRING Label, + _In_ BOOLEAN QuickFormat, + _In_ ULONG ClusterSize, + _In_opt_ PFMIFSCALLBACK Callback) { PFILE_SYSTEM FileSystem; BOOLEAN Success; @@ -374,13 +374,13 @@ FormatFileSystem_UStr( NTSTATUS FormatFileSystem( - IN PCWSTR DriveRoot, - IN PCWSTR FileSystemName, - IN FMIFS_MEDIA_FLAG MediaFlag, - IN PCWSTR Label, - IN BOOLEAN QuickFormat, - IN ULONG ClusterSize, - IN PFMIFSCALLBACK Callback) + _In_ PCWSTR DriveRoot, + _In_ PCWSTR FileSystemName, + _In_ FMIFS_MEDIA_FLAG MediaFlag, + _In_opt_ PCWSTR Label, + _In_ BOOLEAN QuickFormat, + _In_ ULONG ClusterSize, + _In_opt_ PFMIFSCALLBACK Callback) { UNICODE_STRING DriveRootU; UNICODE_STRING LabelU; @@ -910,4 +910,376 @@ FormatPartition( return STATUS_SUCCESS; } + +// +// FileSystem Volume Operations Queue +// + +static FSVOL_OP +DoFormatting( + IN PPARTENTRY PartEntry, + IN PVOID Context OPTIONAL, + IN PFSVOL_CALLBACK FsVolCallback OPTIONAL) +{ + FSVOL_OP Result; + NTSTATUS Status; + FORMAT_PARTITION_INFO PartInfo; + + ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0); + + PartInfo.PartEntry = PartEntry; + +RetryFormat: + Result = FsVolCallback(Context, + FSVOLNOTIFY_STARTFORMAT, + (ULONG_PTR)&PartInfo, + FSVOL_FORMAT); + if (Result != FSVOL_DOIT) + goto EndFormat; + + ASSERT(PartInfo.FileSystemName && *PartInfo.FileSystemName); + + /* Format the partition */ + Status = FormatPartition(PartEntry, + PartInfo.FileSystemName, + PartInfo.MediaFlag, + PartInfo.Label, + PartInfo.QuickFormat, + PartInfo.ClusterSize, + PartInfo.Callback); + if (!NT_SUCCESS(Status)) + { + // PartInfo.NtPathPartition = PathBuffer; + PartInfo.ErrorStatus = Status; + + Result = FsVolCallback(Context, + FSVOLNOTIFY_FORMATERROR, + (ULONG_PTR)&PartInfo, + 0); + if (Result == FSVOL_RETRY) + goto RetryFormat; + // else if (Result == FSVOL_ABORT || Result == FSVOL_SKIP), stop. + } + +EndFormat: + /* This notification is always sent, even in case of error or abort */ + PartInfo.ErrorStatus = Status; + FsVolCallback(Context, + FSVOLNOTIFY_ENDFORMAT, + (ULONG_PTR)&PartInfo, + 0); + return Result; +} + +static FSVOL_OP +DoChecking( + IN PPARTENTRY PartEntry, + IN PVOID Context OPTIONAL, + IN PFSVOL_CALLBACK FsVolCallback OPTIONAL) +{ + FSVOL_OP Result; + NTSTATUS Status = STATUS_SUCCESS; + CHECK_PARTITION_INFO PartInfo; + + ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0); + +#if 0 + /* HACK: Do not try to check a partition with an unknown filesystem */ + if (!*PartEntry->FileSystem) + { + PartEntry->NeedsCheck = FALSE; + return FSVOL_SKIP; + } +#else + ASSERT(*PartEntry->FileSystem); +#endif + + PartInfo.PartEntry = PartEntry; + +RetryCheck: + Result = FsVolCallback(Context, + FSVOLNOTIFY_STARTCHECK, + (ULONG_PTR)&PartInfo, + FSVOL_CHECK); + if (Result != FSVOL_DOIT) + goto EndCheck; + + /* Check the partition */ + Status = ChkdskPartition(PartEntry, + PartInfo.FixErrors, + PartInfo.Verbose, + PartInfo.CheckOnlyIfDirty, + PartInfo.ScanDrive, + PartInfo.Callback); + if (!NT_SUCCESS(Status)) + { + // PartInfo.NtPathPartition = PathBuffer; + PartInfo.ErrorStatus = Status; + + Result = FsVolCallback(Context, + FSVOLNOTIFY_CHECKERROR, + (ULONG_PTR)&PartInfo, + 0); + if (Result == FSVOL_RETRY) + goto RetryCheck; + // else if (Result == FSVOL_ABORT || Result == FSVOL_SKIP), stop. + } + +EndCheck: + /* This notification is always sent, even in case of error or abort */ + PartInfo.ErrorStatus = Status; + FsVolCallback(Context, + FSVOLNOTIFY_ENDCHECK, + (ULONG_PTR)&PartInfo, + 0); + return Result; +} + +BOOLEAN +FsVolCommitOpsQueue( + IN PPARTLIST PartitionList, + IN PPARTENTRY InstallPartition, + IN PPARTENTRY SystemPartition, + IN PFSVOL_CALLBACK FsVolCallback OPTIONAL, + IN PVOID Context OPTIONAL) +{ + BOOLEAN Success = TRUE; // Suppose success. + FSVOL_OP Result; + PPARTENTRY PartEntry; + + /* Machine state for the format step */ + typedef enum _FORMATMACHINESTATE + { + Start, + FormatSystemPartition, + FormatInstallPartition, + FormatOtherPartition, + FormatDone + } FORMATMACHINESTATE; + FORMATMACHINESTATE FormatState = Start; + + ASSERT(PartitionList && InstallPartition && SystemPartition); + + /* Commit all partition changes to all the disks */ + if (!WritePartitionsToDisk(PartitionList)) + { + DPRINT("WritePartitionsToDisk() failed\n"); + /* Result = */ FsVolCallback(Context, + SystemPartitionError, // FIXME + STATUS_PARTITION_FAILURE, // FIXME + 0); + return FALSE; + } + +// +// FIXME: TODO: Do we do the following here, or in the caller ?? +// + /* + * In all cases, whether or not we are going to perform a formatting, + * we must perform a filesystem check of both the system and the + * installation partitions. + */ + SystemPartition->NeedsCheck = TRUE; + InstallPartition->NeedsCheck = TRUE; + + Result = FsVolCallback(Context, + FSVOLNOTIFY_STARTQUEUE, + 0, 0); + if (Result == FSVOL_ABORT) + return FALSE; + + /* + * Commit the Format queue + */ + + /* Reset the formatter machine state */ + FormatState = Start; + + Result = FsVolCallback(Context, + FSVOLNOTIFY_STARTSUBQUEUE, + FSVOL_FORMAT, + 0); + if (Result == FSVOL_ABORT) + return FALSE; + /** HACK!! **/ + if (Result == FSVOL_SKIP) + goto StartCheckQueue; + /** END HACK!! **/ + + // ASSERT(SystemPartition->IsPartitioned); + +NextFormat: + PartEntry = NULL; + switch (FormatState) + { + case Start: + { + /* + * We start by formatting the system partition in case it is new + * (it didn't exist before) and is not the same as the installation + * partition. Otherwise we just require a filesystem check on it, + * and start by formatting the installation partition instead. + */ + + ASSERT(SystemPartition->IsPartitioned); + + if ((SystemPartition != InstallPartition) && + (SystemPartition->FormatState == Unformatted)) + { + PartEntry = SystemPartition; + PartEntry->NeedsCheck = TRUE; + + // TODO: Should we let the user use a custom file-system, + // or should we always use FAT(32) for it? + // For "compatibility", FAT(32) would be best indeed. + + DPRINT1("FormatState: Start --> FormatSystemPartition\n"); + FormatState = FormatSystemPartition; + } + else + { + PartEntry = InstallPartition; + PartEntry->NeedsCheck = TRUE; + + if (SystemPartition != InstallPartition) + { + /* The system partition is separate, so it had better be formatted! */ + ASSERT((SystemPartition->FormatState == Preformatted) || + (SystemPartition->FormatState == Formatted)); + + /* Require a filesystem check on the system partition too */ + SystemPartition->NeedsCheck = TRUE; + } + + DPRINT1("FormatState: Start --> FormatInstallPartition\n"); + FormatState = FormatInstallPartition; + } + break; + } + + case FormatSystemPartition: + { + PartEntry = InstallPartition; + PartEntry->NeedsCheck = TRUE; + + DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n"); + FormatState = FormatInstallPartition; + break; + } + + case FormatInstallPartition: + case FormatOtherPartition: + { + if (GetNextUnformattedPartition(PartitionList, + NULL, + &PartEntry)) + { + ASSERT(PartEntry); + PartEntry->NeedsCheck = TRUE; + + if (FormatState == FormatInstallPartition) + DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n"); + else + DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n"); + + FormatState = FormatOtherPartition; + } + else + { + if (FormatState == FormatInstallPartition) + DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n"); + else + DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n"); + + FormatState = FormatDone; + Success = TRUE; + goto EndFormat; + } + break; + } + + case FormatDone: + { + DPRINT1("FormatState: FormatDone\n"); + Success = TRUE; + goto EndFormat; + } + + default: + { + DPRINT1("FormatState: Invalid value %ld\n", FormatState); + ASSERT(FALSE); + Success = FALSE; + goto Quit; + } + } + + ASSERT(PartEntry); + Result = DoFormatting(PartEntry, Context, FsVolCallback); + if (Result == FSVOL_ABORT) + { + Success = FALSE; + goto Quit; + } + else + { + /* Go to the next partition to be formatted */ + goto NextFormat; + } + +EndFormat: + FsVolCallback(Context, + FSVOLNOTIFY_ENDSUBQUEUE, + FSVOL_FORMAT, + 0); + + + /* + * Commit the CheckFS queue + */ + +StartCheckQueue: + Result = FsVolCallback(Context, + FSVOLNOTIFY_STARTSUBQUEUE, + FSVOL_CHECK, + 0); + if (Result == FSVOL_ABORT) + return FALSE; + +NextCheck: + if (!GetNextUncheckedPartition(PartitionList, NULL, &PartEntry)) + { + Success = TRUE; + goto EndCheck; + } + + ASSERT(PartEntry); + Result = DoChecking(PartEntry, Context, FsVolCallback); + if (Result == FSVOL_ABORT) + { + Success = FALSE; + goto Quit; + } + else + { + /* Go to the next partition to be checked */ + goto NextCheck; + } + +EndCheck: + FsVolCallback(Context, + FSVOLNOTIFY_ENDSUBQUEUE, + FSVOL_CHECK, + 0); + + +Quit: + /* All the queues have been committed */ + FsVolCallback(Context, + FSVOLNOTIFY_ENDQUEUE, + Success, + 0); + return Success; +} + /* EOF */ diff --git a/base/setup/lib/fsutil.h b/base/setup/lib/fsutil.h index 51877faa0fd59..f333967c9fabb 100644 --- a/base/setup/lib/fsutil.h +++ b/base/setup/lib/fsutil.h @@ -20,45 +20,45 @@ GetRegisteredFileSystems( /** ChkdskEx() **/ NTSTATUS ChkdskFileSystem_UStr( - IN PUNICODE_STRING DriveRoot, - IN PCWSTR FileSystemName, - IN BOOLEAN FixErrors, - IN BOOLEAN Verbose, - IN BOOLEAN CheckOnlyIfDirty, - IN BOOLEAN ScanDrive, - IN PFMIFSCALLBACK Callback); + _In_ PUNICODE_STRING DriveRoot, + _In_ PCWSTR FileSystemName, + _In_ BOOLEAN FixErrors, + _In_ BOOLEAN Verbose, + _In_ BOOLEAN CheckOnlyIfDirty, + _In_ BOOLEAN ScanDrive, + _In_opt_ PFMIFSCALLBACK Callback); NTSTATUS ChkdskFileSystem( - IN PCWSTR DriveRoot, - IN PCWSTR FileSystemName, - IN BOOLEAN FixErrors, - IN BOOLEAN Verbose, - IN BOOLEAN CheckOnlyIfDirty, - IN BOOLEAN ScanDrive, - IN PFMIFSCALLBACK Callback); + _In_ PCWSTR DriveRoot, + _In_ PCWSTR FileSystemName, + _In_ BOOLEAN FixErrors, + _In_ BOOLEAN Verbose, + _In_ BOOLEAN CheckOnlyIfDirty, + _In_ BOOLEAN ScanDrive, + _In_opt_ PFMIFSCALLBACK Callback); /** FormatEx() **/ NTSTATUS FormatFileSystem_UStr( - IN PUNICODE_STRING DriveRoot, - IN PCWSTR FileSystemName, - IN FMIFS_MEDIA_FLAG MediaFlag, - IN PUNICODE_STRING Label, - IN BOOLEAN QuickFormat, - IN ULONG ClusterSize, - IN PFMIFSCALLBACK Callback); + _In_ PUNICODE_STRING DriveRoot, + _In_ PCWSTR FileSystemName, + _In_ FMIFS_MEDIA_FLAG MediaFlag, + _In_opt_ PUNICODE_STRING Label, + _In_ BOOLEAN QuickFormat, + _In_ ULONG ClusterSize, + _In_opt_ PFMIFSCALLBACK Callback); NTSTATUS FormatFileSystem( - IN PCWSTR DriveRoot, - IN PCWSTR FileSystemName, - IN FMIFS_MEDIA_FLAG MediaFlag, - IN PCWSTR Label, - IN BOOLEAN QuickFormat, - IN ULONG ClusterSize, - IN PFMIFSCALLBACK Callback); + _In_ PCWSTR DriveRoot, + _In_ PCWSTR FileSystemName, + _In_ FMIFS_MEDIA_FLAG MediaFlag, + _In_opt_ PCWSTR Label, + _In_ BOOLEAN QuickFormat, + _In_ ULONG ClusterSize, + _In_opt_ PFMIFSCALLBACK Callback); // @@ -127,4 +127,87 @@ FormatPartition( IN ULONG ClusterSize, IN PFMIFSCALLBACK Callback); + +// +// FileSystem Volume Operations Queue +// + +// Like the SPFILENOTIFY_xxxx values +typedef enum _FSVOLNOTIFY +{ + FSVOLNOTIFY_STARTQUEUE = 0, + FSVOLNOTIFY_ENDQUEUE, + FSVOLNOTIFY_STARTSUBQUEUE, + FSVOLNOTIFY_ENDSUBQUEUE, + ChangeSystemPartition, // FIXME: Deprecate! + SystemPartitionError, // FIXME: Deprecate! +// FSVOLNOTIFY_STARTPARTITION, FSVOLNOTIFY_ENDPARTITION, FSVOLNOTIFY_PARTITIONERROR, + FSVOLNOTIFY_STARTFORMAT, + FSVOLNOTIFY_ENDFORMAT, + FSVOLNOTIFY_FORMATERROR, + FSVOLNOTIFY_STARTCHECK, + FSVOLNOTIFY_ENDCHECK, + FSVOLNOTIFY_CHECKERROR +} FSVOLNOTIFY; + +// Like the FILEOP_xxxx values +typedef enum _FSVOL_OP +{ +/* Operations ****/ + FSVOL_FORMAT = 0, + FSVOL_CHECK, +/* Response actions ****/ + FSVOL_ABORT = 0, + FSVOL_DOIT, + FSVOL_RETRY = FSVOL_DOIT, + FSVOL_SKIP, +} FSVOL_OP; + +typedef struct _FORMAT_PARTITION_INFO +{ + PPARTENTRY PartEntry; + // PCWSTR NtPathPartition; + NTSTATUS ErrorStatus; + +/* Input information given by the 'FSVOLNOTIFY_STARTFORMAT' step ****/ + PCWSTR FileSystemName; + FMIFS_MEDIA_FLAG MediaFlag; + PCWSTR Label; + BOOLEAN QuickFormat; + ULONG ClusterSize; + PFMIFSCALLBACK Callback; + +} FORMAT_PARTITION_INFO, *PFORMAT_PARTITION_INFO; + +typedef struct _CHECK_PARTITION_INFO +{ + PPARTENTRY PartEntry; + // PCWSTR NtPathPartition; + NTSTATUS ErrorStatus; + +/* Input information given by the 'FSVOLNOTIFY_STARTCHECK' step ****/ + // PCWSTR FileSystemName; // Obtained from PartEntry! + BOOLEAN FixErrors; + BOOLEAN Verbose; + BOOLEAN CheckOnlyIfDirty; + BOOLEAN ScanDrive; + PFMIFSCALLBACK Callback; + +} CHECK_PARTITION_INFO, *PCHECK_PARTITION_INFO; + +typedef FSVOL_OP +(CALLBACK *PFSVOL_CALLBACK)( + IN PVOID Context OPTIONAL, + IN FSVOLNOTIFY FormatStatus, + IN ULONG_PTR Param1, + IN ULONG_PTR Param2); + +BOOLEAN +FsVolCommitOpsQueue( + IN PPARTLIST PartitionList, + IN PPARTENTRY InstallPartition, + IN PPARTENTRY SystemPartition, + IN PFSVOL_CALLBACK FsVolCallback OPTIONAL, + IN PVOID Context OPTIONAL); + /* EOF */ diff --git a/base/setup/lib/setuplib.c b/base/setup/lib/setuplib.c index 1ee70e6216a71..0574024b03ab7 100644 --- a/base/setup/lib/setuplib.c +++ b/base/setup/lib/setuplib.c @@ -623,6 +623,95 @@ LoadSetupInf( return ERROR_SUCCESS; } +/** + * @brief Find or set the active system partition. + **/ +BOOLEAN +InitSystemPartition( + /**/_In_ PPARTLIST PartitionList, /* HACK HACK! */ + /**/_In_ PPARTENTRY InstallPartition, /* HACK HACK! */ + /**/_Out_ PPARTENTRY* pSystemPartition, /* HACK HACK! */ + _In_opt_ PFSVOL_CALLBACK FsVolCallback, + _In_opt_ PVOID Context) +{ + FSVOL_OP Result; + PPARTENTRY SystemPartition; + PPARTENTRY OldActivePart; + + /* + * If we install on a fixed disk, try to find a supported system + * partition on the system. Otherwise if we install on a removable disk + * use the install partition as the system partition. + */ + if (InstallPartition->DiskEntry->MediaType == FixedMedia) + { + SystemPartition = FindSupportedSystemPartition(PartitionList, + FALSE, + InstallPartition->DiskEntry, + InstallPartition); + /* Use the original system partition as the old active partition hint */ + OldActivePart = PartitionList->SystemPartition; + + if ( SystemPartition && PartitionList->SystemPartition && + (SystemPartition != PartitionList->SystemPartition) ) + { + DPRINT1("We are using a different system partition!!\n"); + + Result = FsVolCallback(Context, + ChangeSystemPartition, + (ULONG_PTR)SystemPartition, + 0); + if (Result != FSVOL_DOIT) + return FALSE; + } + } + else // if (InstallPartition->DiskEntry->MediaType == RemovableMedia) + { + SystemPartition = InstallPartition; + /* Don't specify any old active partition hint */ + OldActivePart = NULL; + } + + if (!SystemPartition) + { + FsVolCallback(Context, + SystemPartitionError, + ERROR_SYSTEM_PARTITION_NOT_FOUND, + 0); + return FALSE; + } + + *pSystemPartition = SystemPartition; + + /* + * If the system partition can be created in some + * non-partitioned space, create it now. + */ + if (!SystemPartition->IsPartitioned) + { + CreatePartition(PartitionList, + SystemPartition, + 0LL, // SystemPartition->SectorCount.QuadPart, + TRUE); + ASSERT(SystemPartition->IsPartitioned); + } + + /* Set it as such */ + if (!SetActivePartition(PartitionList, SystemPartition, OldActivePart)) + { + DPRINT1("SetActivePartition(0x%p) failed?!\n", SystemPartition); + ASSERT(FALSE); + } + + /* + * In all cases, whether or not we are going to perform a formatting, + * we must perform a filesystem check of the system partition. + */ + SystemPartition->NeedsCheck = TRUE; + + return TRUE; +} + NTSTATUS InitDestinationPaths( IN OUT PUSETUP_DATA pSetupData, diff --git a/base/setup/lib/setuplib.h b/base/setup/lib/setuplib.h index 5d643ec3458e2..5eb6d1867c5e2 100644 --- a/base/setup/lib/setuplib.h +++ b/base/setup/lib/setuplib.h @@ -160,6 +160,16 @@ ERROR_NUMBER LoadSetupInf( IN OUT PUSETUP_DATA pSetupData); +#define ERROR_SYSTEM_PARTITION_NOT_FOUND (ERROR_LAST_ERROR_CODE + 1) + +BOOLEAN +InitSystemPartition( + /**/_In_ PPARTLIST PartitionList, /* HACK HACK! */ + /**/_In_ PPARTENTRY InstallPartition, /* HACK HACK! */ + /**/_Out_ PPARTENTRY* pSystemPartition, /* HACK HACK! */ + _In_opt_ PFSVOL_CALLBACK FsVolCallback, + _In_opt_ PVOID Context); + NTSTATUS InitDestinationPaths( IN OUT PUSETUP_DATA pSetupData, diff --git a/base/setup/lib/utils/partlist.c b/base/setup/lib/utils/partlist.c index 5f1044335ed8d..6b853bfa45d5a 100644 --- a/base/setup/lib/utils/partlist.c +++ b/base/setup/lib/utils/partlist.c @@ -2641,7 +2641,18 @@ UpdateDiskLayout( HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart; LinkInfo->HiddenSectors = HiddenSectors64.LowPart; LinkInfo->PartitionNumber = 0; - LinkInfo->PartitionType = PARTITION_EXTENDED; + + if (PartEntry->StartSector.QuadPart < 1450560) + { + /* Partition starts below the 8.4GB boundary ==> CHS partition */ + LinkInfo->PartitionType = PARTITION_EXTENDED; + } + else + { + /* Partition starts above the 8.4GB boundary ==> LBA partition */ + LinkInfo->PartitionType = PARTITION_XINT13_EXTENDED; + } + LinkInfo->BootIndicator = FALSE; LinkInfo->RecognizedPartition = FALSE; LinkInfo->RewritePartition = TRUE; diff --git a/base/setup/usetup/chkdsk.c b/base/setup/usetup/chkdsk.c index b302dc9458129..92e94db78e02d 100644 --- a/base/setup/usetup/chkdsk.c +++ b/base/setup/usetup/chkdsk.c @@ -39,9 +39,9 @@ static BOOLEAN NTAPI ChkdskCallback( - IN CALLBACKCOMMAND Command, - IN ULONG Modifier, - IN PVOID Argument) + _In_ CALLBACKCOMMAND Command, + _In_ ULONG Modifier, + _In_ PVOID Argument) { switch (Command) { @@ -53,11 +53,17 @@ ChkdskCallback( return TRUE; } -NTSTATUS -DoChkdsk( - IN PPARTENTRY PartEntry) +VOID +StartCheck( + _Inout_ PCHECK_PARTITION_INFO PartInfo) { - NTSTATUS Status; + // TODO: Think about which values could be defaulted... + // PartInfo->FileSystemName = PartInfo->PartEntry->FileSystem; + PartInfo->FixErrors = TRUE; + PartInfo->Verbose = FALSE; + PartInfo->CheckOnlyIfDirty = TRUE; + PartInfo->ScanDrive = FALSE; + PartInfo->Callback = ChkdskCallback; ChkdskProgressBar = CreateProgressBar(6, yScreen - 14, @@ -69,21 +75,16 @@ DoChkdsk( MUIGetString(STRING_CHECKINGDISK)); ProgressSetStepCount(ChkdskProgressBar, 100); +} - // TODO: Think about which values could be defaulted... - Status = ChkdskPartition(PartEntry, - TRUE, /* FixErrors */ - FALSE, /* Verbose */ - TRUE, /* CheckOnlyIfDirty */ - FALSE, /* ScanDrive */ - ChkdskCallback); /* Callback */ - +VOID +EndCheck( + _In_ NTSTATUS Status) +{ DestroyProgressBar(ChkdskProgressBar); ChkdskProgressBar = NULL; DPRINT("ChkdskPartition() finished with status 0x%08lx\n", Status); - - return Status; } /* EOF */ diff --git a/base/setup/usetup/chkdsk.h b/base/setup/usetup/chkdsk.h index 594c9b13b6147..6848a03bde1a6 100644 --- a/base/setup/usetup/chkdsk.h +++ b/base/setup/usetup/chkdsk.h @@ -26,8 +26,12 @@ #pragma once -NTSTATUS -DoChkdsk( - IN PPARTENTRY PartEntry); +VOID +StartCheck( + _Inout_ PCHECK_PARTITION_INFO PartInfo); + +VOID +EndCheck( + _In_ NTSTATUS Status); /* EOF */ diff --git a/base/setup/usetup/format.c b/base/setup/usetup/format.c index 21d4d1f87d5d9..0dfd4b44c59fb 100644 --- a/base/setup/usetup/format.c +++ b/base/setup/usetup/format.c @@ -39,9 +39,9 @@ static BOOLEAN NTAPI FormatCallback( - IN CALLBACKCOMMAND Command, - IN ULONG Modifier, - IN PVOID Argument) + _In_ CALLBACKCOMMAND Command, + _In_ ULONG Modifier, + _In_ PVOID Argument) { switch (Command) { @@ -88,13 +88,20 @@ FormatCallback( return TRUE; } -NTSTATUS -DoFormat( - IN PPARTENTRY PartEntry, - IN PCWSTR FileSystemName, - IN BOOLEAN QuickFormat) +VOID +StartFormat( + _Inout_ PFORMAT_PARTITION_INFO PartInfo, + _In_ PFILE_SYSTEM_ITEM SelectedFileSystem) { - NTSTATUS Status; + ASSERT(SelectedFileSystem && SelectedFileSystem->FileSystem); + + // TODO: Think about which values could be defaulted... + PartInfo->FileSystemName = SelectedFileSystem->FileSystem; + PartInfo->MediaFlag = FMIFS_HARDDISK; + PartInfo->Label = NULL; + PartInfo->QuickFormat = SelectedFileSystem->QuickFormat; + PartInfo->ClusterSize = 0; + PartInfo->Callback = FormatCallback; FormatProgressBar = CreateProgressBar(6, yScreen - 14, @@ -106,22 +113,16 @@ DoFormat( MUIGetString(STRING_FORMATTINGPART)); ProgressSetStepCount(FormatProgressBar, 100); +} - // TODO: Think about which values could be defaulted... - Status = FormatPartition(PartEntry, - FileSystemName, - FMIFS_HARDDISK, /* MediaFlag */ - NULL, /* Label */ - QuickFormat, /* QuickFormat */ - 0, /* ClusterSize */ - FormatCallback); /* Callback */ - +VOID +EndFormat( + _In_ NTSTATUS Status) +{ DestroyProgressBar(FormatProgressBar); FormatProgressBar = NULL; DPRINT("FormatPartition() finished with status 0x%08lx\n", Status); - - return Status; } /* EOF */ diff --git a/base/setup/usetup/format.h b/base/setup/usetup/format.h index 80c5a85039c7a..d9d9bd0e6f0df 100644 --- a/base/setup/usetup/format.h +++ b/base/setup/usetup/format.h @@ -26,10 +26,13 @@ #pragma once -NTSTATUS -DoFormat( - IN PPARTENTRY PartEntry, - IN PCWSTR FileSystemName, - IN BOOLEAN QuickFormat); +VOID +StartFormat( + _Inout_ PFORMAT_PARTITION_INFO PartInfo, + _In_ PFILE_SYSTEM_ITEM SelectedFileSystem); + +VOID +EndFormat( + _In_ NTSTATUS Status); /* EOF */ diff --git a/base/setup/usetup/partlist.h b/base/setup/usetup/partlist.h index 02972fd8f5581..df459c141d968 100644 --- a/base/setup/usetup/partlist.h +++ b/base/setup/usetup/partlist.h @@ -28,19 +28,6 @@ // #include "../lib/utils/partlist.h" -typedef enum _FORMATMACHINESTATE -{ - Start, - FormatSystemPartition, - FormatInstallPartition, - FormatOtherPartition, - FormatDone, - // CheckSystemPartition, - // CheckInstallPartition, - // CheckOtherPartition, - // CheckDone -} FORMATMACHINESTATE, *PFORMATMACHINESTATE; - typedef struct _PARTLIST_UI { PPARTLIST List; diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c index 447616b74d33a..4b01f2ad999e9 100644 --- a/base/setup/usetup/usetup.c +++ b/base/setup/usetup/usetup.c @@ -29,7 +29,6 @@ #include #include -#include "bootsup.h" #include "chkdsk.h" #include "cmdcons.h" #include "devinst.h" @@ -82,10 +81,6 @@ static enum { /* List of supported file systems for the partition to be formatted */ static PFILE_SYSTEM_LIST FileSystemList = NULL; -/* Machine state for the formatter */ -static PPARTENTRY TempPartition = NULL; -static FORMATMACHINESTATE FormatState = Start; - /*****************************************************/ static PNTOS_INSTALLATION CurrentInstallation = NULL; @@ -939,10 +934,6 @@ UpgradeRepairPage(PINPUT_RECORD Ir) MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } - - /* Reset the formatter machine state */ - TempPartition = NULL; - FormatState = Start; } /**************/ @@ -1558,10 +1549,6 @@ SelectPartitionPage(PINPUT_RECORD Ir) MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } - - /* Reset the formatter machine state */ - TempPartition = NULL; - FormatState = Start; } if (RepairUpdateFlag) @@ -1579,7 +1566,7 @@ SelectPartitionPage(PINPUT_RECORD Ir) } ASSERT(!IsContainerPartition(InstallPartition->PartitionType)); - return SELECT_FILE_SYSTEM_PAGE; + return START_PARTITION_OPERATIONS_PAGE; } MUIDisplayPage(SELECT_PARTITION_PAGE); @@ -1620,7 +1607,7 @@ SelectPartitionPage(PINPUT_RECORD Ir) } InstallPartition = CurrentPartition; - return SELECT_FILE_SYSTEM_PAGE; + return START_PARTITION_OPERATIONS_PAGE; } } else @@ -1637,7 +1624,7 @@ SelectPartitionPage(PINPUT_RECORD Ir) return SELECT_PARTITION_PAGE; /* let the user select another partition */ } - return SELECT_FILE_SYSTEM_PAGE; + return START_PARTITION_OPERATIONS_PAGE; } } @@ -1744,7 +1731,7 @@ SelectPartitionPage(PINPUT_RECORD Ir) } InstallPartition = CurrentPartition; - return SELECT_FILE_SYSTEM_PAGE; + return START_PARTITION_OPERATIONS_PAGE; } else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P') /* P */ { @@ -2265,44 +2252,39 @@ DeletePartitionPage(PINPUT_RECORD Ir) } -static VOID -ResetFileSystemList(VOID) -{ - if (!FileSystemList) - return; - - DestroyFileSystemList(FileSystemList); - FileSystemList = NULL; -} - /* * Displays the SelectFileSystemPage. * * Next pages: * CheckFileSystemPage (At once if RepairUpdate is selected) * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition) - * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition) + * FormatPartitionPage (Default, at once if Unattended and USetupData.FormatPartition) * SelectPartitionPage (If the user aborts) - * FormatPartitionPage (Default) * QuitPage * - * SIDEEFFECTS - * Calls UpdatePartitionType() - * Calls FindSupportedSystemPartition() - * * RETURNS * Number of the next page. */ -static PAGE_NUMBER -SelectFileSystemPage(PINPUT_RECORD Ir) +// PFSVOL_CALLBACK +static FSVOL_OP +CALLBACK +FsVolCallback( + IN PVOID Context OPTIONAL, + IN FSVOLNOTIFY FormatStatus, + IN ULONG_PTR Param1, + IN ULONG_PTR Param2); + +typedef struct _FSVOL_CONTEXT { - PPARTENTRY PartEntry; - PDISKENTRY DiskEntry; - FORMATMACHINESTATE PreviousFormatState; - PCWSTR DefaultFs; - CHAR LineBuffer[100]; + PINPUT_RECORD Ir; + PAGE_NUMBER NextPageOnAbort; +} FSVOL_CONTEXT, *PFSVOL_CONTEXT; - DPRINT("SelectFileSystemPage()\n"); +static PAGE_NUMBER +StartPartitionOperationsPage(PINPUT_RECORD Ir) +{ + BOOLEAN Success; + FSVOL_CONTEXT FsVolContext = {Ir, QUIT_PAGE}; if (PartitionList == NULL || InstallPartition == NULL) { @@ -2310,255 +2292,106 @@ SelectFileSystemPage(PINPUT_RECORD Ir) return QUIT_PAGE; } - /* Find or set the active system partition when starting formatting */ - if (FormatState == Start) - { - /* - * If we install on a fixed disk, try to find a supported system - * partition on the system. Otherwise if we install on a removable disk - * use the install partition as the system partition. - */ - if (InstallPartition->DiskEntry->MediaType == FixedMedia) - { - SystemPartition = FindSupportedSystemPartition(PartitionList, - FALSE, - InstallPartition->DiskEntry, - InstallPartition); - /* Use the original system partition as the old active partition hint */ - PartEntry = PartitionList->SystemPartition; - - if ( SystemPartition && PartitionList->SystemPartition && - (SystemPartition != PartitionList->SystemPartition) ) - { - DPRINT1("We are using a different system partition!!!!\n"); - - MUIDisplayPage(CHANGE_SYSTEM_PARTITION); - - { - PPARTENTRY PartEntry; // Shadow variable - - PartEntry = PartitionList->SystemPartition; - DiskEntry = PartEntry->DiskEntry; - - PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer)); - CONSOLE_SetTextXY(8, 10, LineBuffer); - - DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer)); - CONSOLE_PrintTextXY(8, 14, MUIGetString(STRING_HDDISK1), - LineBuffer); - + /* Find or set the active system partition before starting formatting */ + Success = InitSystemPartition(PartitionList, + InstallPartition, + &SystemPartition, + FsVolCallback, + &FsVolContext); + if (!Success) + return FsVolContext.NextPageOnAbort; + // + // FIXME?? If cannot use any system partition, install FreeLdr on floppy / removable media?? + // - PartEntry = SystemPartition; - DiskEntry = PartEntry->DiskEntry; - - PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer)); - CONSOLE_SetTextXY(8, 23, LineBuffer); - } - - while (TRUE) - { - CONSOLE_ConInKey(Ir); - - if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ - { - break; - } - else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */ - { - return SELECT_PARTITION_PAGE; - } - } - - CONSOLE_ClearScreen(); - CONSOLE_Flush(); - } - } - else // if (InstallPartition->DiskEntry->MediaType == RemovableMedia) - { - SystemPartition = InstallPartition; - /* Don't specify any old active partition hint */ - PartEntry = NULL; - } + CONSOLE_ClearScreen(); + CONSOLE_Flush(); - if (!SystemPartition) - { - /* FIXME: improve the error dialog */ - // - // Error dialog should say that we cannot find a suitable - // system partition and create one on the system. At this point, - // it may be nice to ask the user whether he wants to continue, - // or use an external drive as the system drive/partition - // (e.g. floppy, USB drive, etc...) - // - PopupError("The ReactOS Setup could not find a supported system partition\n" - "on your system or could not create a new one. Without such partition\n" - "the Setup program cannot install ReactOS.\n" - "Press ENTER to return to the partition selection list.", - MUIGetString(STRING_CONTINUE), - Ir, POPUP_WAIT_ENTER); - return SELECT_PARTITION_PAGE; - } + /* Apply all pending operations on partitions: formatting and checking */ + Success = FsVolCommitOpsQueue(PartitionList, + InstallPartition, + SystemPartition, + FsVolCallback, + &FsVolContext); + if (!Success) + return FsVolContext.NextPageOnAbort; + return BOOTLOADER_SELECT_PAGE; +} - /* - * If the system partition can be created in some - * non-partitioned space, create it now. - */ - if (!SystemPartition->IsPartitioned) - { - CreatePartition(PartitionList, - SystemPartition, - 0LL, // SystemPartition->SectorCount.QuadPart, - TRUE); - ASSERT(SystemPartition->IsPartitioned); - } +static BOOLEAN +ChangeSystemPartitionPage( + IN PINPUT_RECORD Ir, + IN PPARTENTRY SystemPartition) +{ + PPARTENTRY PartEntry; + PDISKENTRY DiskEntry; + CHAR LineBuffer[100]; - /* Set it as such */ - if (!SetActivePartition(PartitionList, SystemPartition, PartEntry)) - { - DPRINT1("SetActivePartition(0x%p) failed?!\n", SystemPartition); - ASSERT(FALSE); - } + // CONSOLE_ClearScreen(); + // CONSOLE_Flush(); + MUIDisplayPage(CHANGE_SYSTEM_PARTITION); - /* Commit all partition changes to all the disks */ - if (!WritePartitionsToDisk(PartitionList)) - { - DPRINT("WritePartitionsToDisk() failed\n"); - MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } + PartEntry = PartitionList->SystemPartition; + DiskEntry = PartEntry->DiskEntry; - /* - * In all cases, whether or not we are going to perform a formatting, - * we must perform a filesystem check of both the system and the - * installation partitions. - */ - InstallPartition->NeedsCheck = TRUE; - if (SystemPartition != InstallPartition) - SystemPartition->NeedsCheck = TRUE; + PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer)); + CONSOLE_SetTextXY(8, 10, LineBuffer); - /* - * In case we just repair an existing installation, or make - * an unattended setup without formatting, just go to the - * filesystem check step. - */ - if (RepairUpdateFlag) - return CHECK_FILE_SYSTEM_PAGE; + DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer)); + CONSOLE_PrintTextXY(8, 14, MUIGetString(STRING_HDDISK1), + LineBuffer); - if (IsUnattendedSetup && !USetupData.FormatPartition) - return CHECK_FILE_SYSTEM_PAGE; - } - // ASSERT(SystemPartition->IsPartitioned); + PartEntry = SystemPartition; + DiskEntry = PartEntry->DiskEntry; - /* Reset the filesystem list for each partition that is to be formatted */ - ResetFileSystemList(); + PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer)); + CONSOLE_SetTextXY(8, 23, LineBuffer); - PreviousFormatState = FormatState; - switch (FormatState) + while (TRUE) { - case Start: - { - /* - * We start by formatting the system partition in case it is new - * (it didn't exist before) and is not the same as the installation - * partition. Otherwise we just require a filesystem check on it, - * and start by formatting the installation partition instead. - */ - - ASSERT(SystemPartition->IsPartitioned); - - if ((SystemPartition != InstallPartition) && - (SystemPartition->FormatState == Unformatted)) - { - TempPartition = SystemPartition; - TempPartition->NeedsCheck = TRUE; - - // TODO: Should we let the user using a custom file-system, - // or should we always use FAT(32) for it? - // For "compatibility", FAT(32) would be best indeed. - - FormatState = FormatSystemPartition; - DPRINT1("FormatState: Start --> FormatSystemPartition\n"); - } - else - { - TempPartition = InstallPartition; - TempPartition->NeedsCheck = TRUE; - - if (SystemPartition != InstallPartition) - { - /* The system partition is separate, so it had better be formatted! */ - ASSERT((SystemPartition->FormatState == Preformatted) || - (SystemPartition->FormatState == Formatted)); - - /* Require a filesystem check on the system partition too */ - SystemPartition->NeedsCheck = TRUE; - } - - FormatState = FormatInstallPartition; - DPRINT1("FormatState: Start --> FormatInstallPartition\n"); - } - break; - } - - case FormatSystemPartition: - { - TempPartition = InstallPartition; - TempPartition->NeedsCheck = TRUE; + CONSOLE_ConInKey(Ir); - FormatState = FormatInstallPartition; - DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n"); + if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ break; - } + else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */ + return FALSE; + } - case FormatInstallPartition: - case FormatOtherPartition: - { - if (GetNextUnformattedPartition(PartitionList, - NULL, - &TempPartition)) - { - FormatState = FormatOtherPartition; - TempPartition->NeedsCheck = TRUE; + return TRUE; +} - if (FormatState == FormatInstallPartition) - DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n"); - else - DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n"); - } - else - { - FormatState = FormatDone; +static VOID +ResetFileSystemList(VOID) +{ + if (!FileSystemList) + return; - if (FormatState == FormatInstallPartition) - DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n"); - else - DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n"); + DestroyFileSystemList(FileSystemList); + FileSystemList = NULL; +} - return CHECK_FILE_SYSTEM_PAGE; - } - break; - } +static FSVOL_OP +SelectFileSystemPage( + IN PFSVOL_CONTEXT FsVolContext, + IN PPARTENTRY PartEntry) +{ + PINPUT_RECORD Ir = FsVolContext->Ir; + PDISKENTRY DiskEntry = PartEntry->DiskEntry; + PCWSTR DefaultFs; + CHAR LineBuffer[100]; - case FormatDone: - { - DPRINT1("FormatState: FormatDone\n"); - return CHECK_FILE_SYSTEM_PAGE; - } + DPRINT("SelectFileSystemPage()\n"); - default: - { - DPRINT1("FormatState: Invalid value %ld\n", FormatState); - ASSERT(FALSE); - return QUIT_PAGE; - } - } + ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0); - PartEntry = TempPartition; - DiskEntry = TempPartition->DiskEntry; +Restart: - ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0); + /* Reset the filesystem list for each partition that is to be formatted */ + ResetFileSystemList(); + CONSOLE_ClearScreen(); + CONSOLE_Flush(); MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE); if (PartEntry->AutoCreate) @@ -2569,24 +2402,16 @@ SelectFileSystemPage(PINPUT_RECORD Ir) } else if (PartEntry->New) { - switch (FormatState) - { - case FormatSystemPartition: - CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART)); - break; - - case FormatInstallPartition: - CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART)); - break; + ULONG uID; - case FormatOtherPartition: - CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART)); - break; + if (PartEntry == SystemPartition) // FormatSystemPartition + uID = STRING_NONFORMATTEDSYSTEMPART; + else if (PartEntry == InstallPartition) // FormatInstallPartition + uID = STRING_NONFORMATTEDPART; + else // FormatOtherPartition + uID = STRING_NONFORMATTEDOTHERPART; - default: - ASSERT(FALSE); - break; - } + CONSOLE_SetTextXY(6, 8, MUIGetString(uID)); } else { @@ -2638,13 +2463,14 @@ SelectFileSystemPage(PINPUT_RECORD Ir) if (FileSystemList == NULL) { /* FIXME: show an error dialog */ - return QUIT_PAGE; + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; } if (IsUnattendedSetup) { ASSERT(USetupData.FormatPartition); - return FORMAT_PARTITION_PAGE; + return FSVOL_DOIT; } DrawFileSystemList(FileSystemList); @@ -2658,23 +2484,20 @@ SelectFileSystemPage(PINPUT_RECORD Ir) { if (ConfirmQuit(Ir)) { - /* Reset the filesystem list */ - ResetFileSystemList(); - return QUIT_PAGE; + // /* Reset the filesystem list */ + // ResetFileSystemList(); + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; } break; } else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESC */ { - /* Reset the formatter machine state */ - TempPartition = NULL; - FormatState = Start; - - /* Reset the filesystem list */ - ResetFileSystemList(); - - return SELECT_PARTITION_PAGE; + // /* Reset the filesystem list */ + // ResetFileSystemList(); + FsVolContext->NextPageOnAbort = SELECT_PARTITION_PAGE; + return FSVOL_ABORT; } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */ @@ -2690,84 +2513,57 @@ SelectFileSystemPage(PINPUT_RECORD Ir) { if (!FileSystemList->Selected->FileSystem) { - ASSERT(!TempPartition->New && TempPartition->FormatState != Unformatted); + ASSERT(!PartEntry->New && PartEntry->FormatState != Unformatted); /* * Skip formatting this partition. We will also ignore * filesystem checks on it, unless it is either the system * or the installation partition. */ - if (TempPartition != SystemPartition && - TempPartition != InstallPartition) + if (PartEntry != SystemPartition && + PartEntry != InstallPartition) { PartEntry->NeedsCheck = FALSE; } - return SELECT_FILE_SYSTEM_PAGE; + // /* Reset the filesystem list */ + // ResetFileSystemList(); + return FSVOL_SKIP; } else { /* Format this partition */ - return FORMAT_PARTITION_PAGE; + return FSVOL_DOIT; } } } - FormatState = PreviousFormatState; + // /* Reset the filesystem list */ + // ResetFileSystemList(); - return SELECT_FILE_SYSTEM_PAGE; + goto Restart; } - -/* - * Displays the FormatPartitionPage. - * - * Next pages: - * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut) - * SelectPartitionPage (At once) - * QuitPage - * - * SIDEEFFECTS - * Sets InstallPartition->FormatState - * Sets USetupData.DestinationRootPath - * - * RETURNS - * Number of the next page. - */ -static PAGE_NUMBER -FormatPartitionPage(PINPUT_RECORD Ir) +static FSVOL_OP +FormatPartitionPage( + IN PFSVOL_CONTEXT FsVolContext, + IN PPARTENTRY PartEntry) { - NTSTATUS Status; - PPARTENTRY PartEntry; - PDISKENTRY DiskEntry; - PFILE_SYSTEM_ITEM SelectedFileSystem; - WCHAR PathBuffer[MAX_PATH]; - CHAR Buffer[MAX_PATH]; - - DPRINT("FormatPartitionPage()\n"); - - if (PartitionList == NULL || TempPartition == NULL) - { - /* FIXME: show an error dialog */ - return QUIT_PAGE; - } - - PartEntry = TempPartition; - DiskEntry = TempPartition->DiskEntry; - - ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0); - - SelectedFileSystem = FileSystemList->Selected; - ASSERT(SelectedFileSystem && SelectedFileSystem->FileSystem); + PINPUT_RECORD Ir = FsVolContext->Ir; + PDISKENTRY DiskEntry = PartEntry->DiskEntry; + CHAR LineBuffer[100]; +Restart: + CONSOLE_ClearScreen(); + CONSOLE_Flush(); MUIDisplayPage(FORMAT_PARTITION_PAGE); - PartitionDescription(PartEntry, Buffer, ARRAYSIZE(Buffer)); - CONSOLE_SetTextXY(6, 10, Buffer); + PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer)); + CONSOLE_SetTextXY(6, 10, LineBuffer); - DiskDescription(DiskEntry, Buffer, ARRAYSIZE(Buffer)); + DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer)); CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDDISK2), - Buffer); + LineBuffer); while (TRUE) { @@ -2779,12 +2575,11 @@ FormatPartitionPage(PINPUT_RECORD Ir) { if (ConfirmQuit(Ir)) { - /* Reset the filesystem list */ - ResetFileSystemList(); - return QUIT_PAGE; + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; } - break; + goto Restart; } else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN || IsUnattendedSetup) /* ENTER */ { @@ -2795,190 +2590,325 @@ FormatPartitionPage(PINPUT_RECORD Ir) MUIClearStyledText(FORMAT_PARTITION_PAGE, TEXT_ID_FORMAT_PROMPT, TEXT_TYPE_REGULAR); CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); - /* Format the partition */ - Status = DoFormat(PartEntry, - SelectedFileSystem->FileSystem, - SelectedFileSystem->QuickFormat); - if (Status == STATUS_PARTITION_FAILURE) - { - MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER); + return FSVOL_DOIT; + } + } +} - /* Reset the filesystem list */ - ResetFileSystemList(); - return QUIT_PAGE; - } - else if (Status == STATUS_UNRECOGNIZED_VOLUME) - { - /* FIXME: show an error dialog */ - // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer); +static VOID +CheckFileSystemPage( + IN PPARTENTRY PartEntry) +{ + PDISKENTRY DiskEntry = PartEntry->DiskEntry; + CHAR LineBuffer[100]; - /* Reset the filesystem list */ - ResetFileSystemList(); - return QUIT_PAGE; - } - else if (Status == STATUS_NOT_SUPPORTED) - { - RtlStringCbPrintfA(Buffer, - sizeof(Buffer), - "Setup is currently unable to format a partition in %S.\n" - "\n" - " \x07 Press ENTER to continue Setup.\n" - " \x07 Press F3 to quit Setup.", - SelectedFileSystem->FileSystem); - - PopupError(Buffer, - MUIGetString(STRING_QUITCONTINUE), - NULL, POPUP_WAIT_NONE); - - while (TRUE) - { - CONSOLE_ConInKey(Ir); + CONSOLE_ClearScreen(); + CONSOLE_Flush(); + MUIDisplayPage(CHECK_FILE_SYSTEM_PAGE); - if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 && - Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */ - { - if (ConfirmQuit(Ir)) - { - /* Reset the filesystem list */ - ResetFileSystemList(); - return QUIT_PAGE; - } - else - { - return SELECT_FILE_SYSTEM_PAGE; - } - } - else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */ - { - return SELECT_FILE_SYSTEM_PAGE; - } - } - } - else if (!NT_SUCCESS(Status)) - { - /** HACK!! **/ - RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), - L"\\Device\\Harddisk%lu\\Partition%lu", - DiskEntry->DiskNumber, - PartEntry->PartitionNumber); + PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer)); + CONSOLE_SetTextXY(6, 10, LineBuffer); - DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status); - MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer); + DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer)); + CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDDISK2), + LineBuffer); +} - /* Reset the filesystem list */ - ResetFileSystemList(); - return QUIT_PAGE; - } +// PFSVOL_CALLBACK +static FSVOL_OP +CALLBACK +FsVolCallback( + IN PVOID Context OPTIONAL, + IN FSVOLNOTIFY FormatStatus, + IN ULONG_PTR Param1, + IN ULONG_PTR Param2) +{ + PFSVOL_CONTEXT FsVolContext = (PFSVOL_CONTEXT)Context; + PINPUT_RECORD Ir = FsVolContext->Ir; - return SELECT_FILE_SYSTEM_PAGE; - } + if ((FormatStatus == FSVOLNOTIFY_STARTQUEUE) || + (FormatStatus == FSVOLNOTIFY_ENDQUEUE)) + { + // NOTE: If needed, clear screen and flush input. + return FSVOL_DOIT; } - return FORMAT_PARTITION_PAGE; -} + if (FormatStatus == FSVOLNOTIFY_STARTSUBQUEUE) + { + if ((FSVOL_OP)Param1 == FSVOL_FORMAT) + { + /* + * In case we just repair an existing installation, or make + * an unattended setup without formatting, just go to the + * filesystem check step. + */ + if (RepairUpdateFlag) + return FSVOL_SKIP; /** HACK!! **/ + if (IsUnattendedSetup && !USetupData.FormatPartition) + return FSVOL_SKIP; /** HACK!! **/ + } + return FSVOL_DOIT; + } -/* - * Displays the CheckFileSystemPage. - * - * Next pages: - * InstallDirectoryPage (At once) - * QuitPage - * - * SIDEEFFECTS - * Inits or reloads FileSystemList - * - * RETURNS - * Number of the next page. - */ -static PAGE_NUMBER -CheckFileSystemPage(PINPUT_RECORD Ir) -{ - NTSTATUS Status; - PPARTENTRY PartEntry; - CHAR Buffer[MAX_PATH]; + if (FormatStatus == FSVOLNOTIFY_ENDSUBQUEUE) + { + if ((FSVOL_OP)Param1 == FSVOL_FORMAT) + { + /* Reset the filesystem list */ + ResetFileSystemList(); + } + return 0; + } - if (PartitionList == NULL) + // FIXME: Deprecate! + if (FormatStatus == ChangeSystemPartition) { - /* FIXME: show an error dialog */ - return QUIT_PAGE; + PPARTENTRY SystemPartition = (PPARTENTRY)Param1; + + FsVolContext->NextPageOnAbort = SELECT_PARTITION_PAGE; + if (ChangeSystemPartitionPage(Ir, SystemPartition)) + return FSVOL_DOIT; + else + return FSVOL_ABORT; } - if (!GetNextUncheckedPartition(PartitionList, NULL, &PartEntry)) + // FIXME: Deprecate! + if (FormatStatus == SystemPartitionError) { - return BOOTLOADER_SELECT_PAGE; + switch (Param1) + { + case STATUS_PARTITION_FAILURE: + { + MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER); + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; + } + + case ERROR_SYSTEM_PARTITION_NOT_FOUND: + { + /* FIXME: improve the error dialog */ + // + // Error dialog should say that we cannot find a suitable + // system partition and create one on the system. At this point, + // it may be nice to ask the user whether he wants to continue, + // or use an external drive as the system drive/partition + // (e.g. floppy, USB drive, etc...) + // + PopupError("The ReactOS Setup could not find a supported system partition\n" + "on your system or could not create a new one. Without such partition\n" + "the Setup program cannot install ReactOS.\n" + "Press ENTER to return to the partition selection list.", + MUIGetString(STRING_CONTINUE), + Ir, POPUP_WAIT_ENTER); + + FsVolContext->NextPageOnAbort = SELECT_PARTITION_PAGE; + return FSVOL_ABORT; + } + + default: + return FSVOL_ABORT; + } } - ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0); + if (FormatStatus == FSVOLNOTIFY_FORMATERROR) + { + PFORMAT_PARTITION_INFO PartInfo = (PFORMAT_PARTITION_INFO)Param1; + CHAR Buffer[MAX_PATH]; - DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n", - PartEntry->PartitionType, (*PartEntry->FileSystem ? PartEntry->FileSystem : L"n/a")); + // FIXME: See also SystemPartitionError + if (PartInfo->ErrorStatus == STATUS_PARTITION_FAILURE) + { + MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER); + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; + } + else + if (PartInfo->ErrorStatus == STATUS_UNRECOGNIZED_VOLUME) + { + /* FIXME: show an error dialog */ + // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer); + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; + } + else + if (PartInfo->ErrorStatus == STATUS_NOT_SUPPORTED) + { + RtlStringCbPrintfA(Buffer, + sizeof(Buffer), + "Setup is currently unable to format a partition in %S.\n" + "\n" + " \x07 Press ENTER to continue Setup.\n" + " \x07 Press F3 to quit Setup.", + PartInfo->FileSystemName); - MUIDisplayPage(CHECK_FILE_SYSTEM_PAGE); + PopupError(Buffer, + MUIGetString(STRING_QUITCONTINUE), + NULL, POPUP_WAIT_NONE); - PartitionDescription(PartEntry, Buffer, ARRAYSIZE(Buffer)); - CONSOLE_SetTextXY(6, 10, Buffer); + while (TRUE) + { + CONSOLE_ConInKey(Ir); - DiskDescription(PartEntry->DiskEntry, Buffer, ARRAYSIZE(Buffer)); - CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDDISK2), - Buffer); + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 && + Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */ + { + if (ConfirmQuit(Ir)) + { + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; + } + else + { + return FSVOL_RETRY; + } + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */ + { + return FSVOL_RETRY; + } + } + } + else if (!NT_SUCCESS(PartInfo->ErrorStatus)) + { + WCHAR PathBuffer[MAX_PATH]; - /* Check the partition */ - Status = DoChkdsk(PartEntry); - if (Status == STATUS_NOT_SUPPORTED) - { - /* - * Partition checking is not supported with the current filesystem, - * so disable FS checks on it. - */ - PartEntry->NeedsCheck = FALSE; + /** HACK!! **/ + RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), + L"\\Device\\Harddisk%lu\\Partition%lu", + PartInfo->PartEntry->DiskEntry->DiskNumber, + PartInfo->PartEntry->PartitionNumber); + + DPRINT1("FormatPartition() failed with status 0x%08lx\n", PartInfo->ErrorStatus); + MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer); + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; + } - RtlStringCbPrintfA(Buffer, - sizeof(Buffer), - "Setup is currently unable to check a partition formatted in %S.\n" - "\n" - " \x07 Press ENTER to continue Setup.\n" - " \x07 Press F3 to quit Setup.", - PartEntry->FileSystem); + return FSVOL_RETRY; + } - PopupError(Buffer, - MUIGetString(STRING_QUITCONTINUE), - NULL, POPUP_WAIT_NONE); + if (FormatStatus == FSVOLNOTIFY_CHECKERROR) + { + PCHECK_PARTITION_INFO PartInfo = (PCHECK_PARTITION_INFO)Param1; + CHAR Buffer[MAX_PATH]; - while (TRUE) + if (PartInfo->ErrorStatus == STATUS_NOT_SUPPORTED) { - CONSOLE_ConInKey(Ir); + /* + * Partition checking is not supported with the current filesystem, + * so disable FS checks on it. + */ + PartInfo->PartEntry->NeedsCheck = FALSE; - if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 && - Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */ - { - if (ConfirmQuit(Ir)) - return QUIT_PAGE; - else - return CHECK_FILE_SYSTEM_PAGE; - } - else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */ + RtlStringCbPrintfA(Buffer, + sizeof(Buffer), + "Setup is currently unable to check a partition formatted in %S.\n" + "\n" + " \x07 Press ENTER to continue Setup.\n" + " \x07 Press F3 to quit Setup.", + PartInfo->PartEntry->FileSystem /* PartInfo->FileSystemName */); + + PopupError(Buffer, + MUIGetString(STRING_QUITCONTINUE), + NULL, POPUP_WAIT_NONE); + + while (TRUE) { - return CHECK_FILE_SYSTEM_PAGE; + CONSOLE_ConInKey(Ir); + + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 && + Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */ + { + if (ConfirmQuit(Ir)) + { + FsVolContext->NextPageOnAbort = QUIT_PAGE; + return FSVOL_ABORT; + } + else + { + return FSVOL_SKIP; + } + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */ + { + return FSVOL_SKIP; + } } } + else if (!NT_SUCCESS(PartInfo->ErrorStatus)) + { + DPRINT1("ChkdskPartition() failed with status 0x%08lx\n", PartInfo->ErrorStatus); + + RtlStringCbPrintfA(Buffer, + sizeof(Buffer), + "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n", + PartInfo->ErrorStatus); + + PopupError(Buffer, + MUIGetString(STRING_CONTINUE), + Ir, POPUP_WAIT_ENTER); + return FSVOL_SKIP; + } + + PartInfo->PartEntry->NeedsCheck = FALSE; + return FSVOL_SKIP; + } + + if (FormatStatus == FSVOLNOTIFY_STARTFORMAT) + { + PFORMAT_PARTITION_INFO PartInfo = (PFORMAT_PARTITION_INFO)Param1; + FSVOL_OP Result; + + ASSERT(PartInfo); + ASSERT((FSVOL_OP)Param2 == FSVOL_FORMAT); + + /* Select the filesystem */ + Result = SelectFileSystemPage(FsVolContext, PartInfo->PartEntry); + if (Result != FSVOL_DOIT) + return Result; + + /* Display the formatting page */ + Result = FormatPartitionPage(FsVolContext, PartInfo->PartEntry); + if (Result != FSVOL_DOIT) + return Result; + + StartFormat(PartInfo, FileSystemList->Selected); + return FSVOL_DOIT; } - else if (!NT_SUCCESS(Status)) + + if (FormatStatus == FSVOLNOTIFY_ENDFORMAT) + { + PFORMAT_PARTITION_INFO PartInfo = (PFORMAT_PARTITION_INFO)Param1; + + ASSERT(PartInfo); + EndFormat(PartInfo->ErrorStatus); + return 0; + } + + if (FormatStatus == FSVOLNOTIFY_STARTCHECK) { - DPRINT1("ChkdskPartition() failed with status 0x%08lx\n", Status); + PCHECK_PARTITION_INFO PartInfo = (PCHECK_PARTITION_INFO)Param1; - RtlStringCbPrintfA(Buffer, - sizeof(Buffer), - "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n", - Status); + ASSERT(PartInfo); + ASSERT((FSVOL_OP)Param2 == FSVOL_CHECK); - PopupError(Buffer, - MUIGetString(STRING_CONTINUE), - Ir, POPUP_WAIT_ENTER); + CheckFileSystemPage(PartInfo->PartEntry); + StartCheck(PartInfo); + return FSVOL_DOIT; } - PartEntry->NeedsCheck = FALSE; - return CHECK_FILE_SYSTEM_PAGE; + if (FormatStatus == FSVOLNOTIFY_ENDCHECK) + { + PCHECK_PARTITION_INFO PartInfo = (PCHECK_PARTITION_INFO)Param1; + + ASSERT(PartInfo); + EndCheck(PartInfo->ErrorStatus); + // PartInfo->PartEntry->NeedsCheck = FALSE; + return 0; + } + + return 0; } @@ -3046,9 +2976,6 @@ InstallDirectoryPage(PINPUT_RECORD Ir) WCHAR c; WCHAR InstallDir[MAX_PATH]; - /* We do not need the filesystem list anymore */ - ResetFileSystemList(); - if (PartitionList == NULL || InstallPartition == NULL) { /* FIXME: show an error dialog */ @@ -3640,6 +3567,7 @@ BootLoaderSelectPage(PINPUT_RECORD Ir) } } +#if 0 // Deprecated code, whose global logic may need to be moved elsewhere... /* * We may install an MBR or VBR, but before that, check whether * we need to actually install the VBR on removable disk if the @@ -3651,6 +3579,7 @@ BootLoaderSelectPage(PINPUT_RECORD Ir) USetupData.MBRInstallType = 1; goto Quit; } +#endif /* Is it an unattended install on hdd? */ if (IsUnattendedSetup) @@ -4141,13 +4070,6 @@ QuitPage(PINPUT_RECORD Ir) PartitionList = NULL; } - /* Reset the formatter machine state */ - TempPartition = NULL; - FormatState = Start; - - /* Destroy the filesystem list */ - ResetFileSystemList(); - CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2)); /* Wait for maximum 15 seconds or an ENTER key before quitting */ @@ -4324,16 +4246,8 @@ RunUSetup(VOID) break; /* Filesystem partition operations pages */ - case SELECT_FILE_SYSTEM_PAGE: - Page = SelectFileSystemPage(&Ir); - break; - - case FORMAT_PARTITION_PAGE: - Page = FormatPartitionPage(&Ir); - break; - - case CHECK_FILE_SYSTEM_PAGE: - Page = CheckFileSystemPage(&Ir); + case START_PARTITION_OPERATIONS_PAGE: + Page = StartPartitionOperationsPage(&Ir); break; /* Bootloader selection page */ @@ -4387,6 +4301,9 @@ RunUSetup(VOID) /* Virtual pages */ case SETUP_INIT_PAGE: + case SELECT_FILE_SYSTEM_PAGE: + case FORMAT_PARTITION_PAGE: + // case CHECK_FILE_SYSTEM_PAGE: case REBOOT_PAGE: case RECOVERY_PAGE: break; diff --git a/base/setup/usetup/usetup.h b/base/setup/usetup/usetup.h index 54f3ba771e39d..91b94ac969924 100644 --- a/base/setup/usetup/usetup.h +++ b/base/setup/usetup/usetup.h @@ -99,8 +99,9 @@ typedef enum _PAGE_NUMBER CONFIRM_DELETE_SYSTEM_PARTITION_PAGE, DELETE_PARTITION_PAGE, - SELECT_FILE_SYSTEM_PAGE, - FORMAT_PARTITION_PAGE, + START_PARTITION_OPERATIONS_PAGE, /* Virtual page */ + SELECT_FILE_SYSTEM_PAGE, /* Virtual page */ + FORMAT_PARTITION_PAGE, /* Virtual page */ CHECK_FILE_SYSTEM_PAGE, BOOTLOADER_SELECT_PAGE,