https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2580889cfa3c8620999e8…
commit 2580889cfa3c8620999e8579eab91a5c8ebb317a
Author: Vadim Galyant <vgal(a)rambler.ru>
AuthorDate: Wed Oct 19 03:02:24 2022 +0300
Commit: GitHub <noreply(a)github.com>
CommitDate: Wed Oct 19 02:02:24 2022 +0200
[SETUPLIB] Add NTFS boot support. (#3778)
---
base/setup/lib/bootsup.c | 108 +++++++++++++++++++++++++++++++++++++++++++++--
base/setup/lib/fsutil.c | 89 ++++++++++++++++++++++++++++++++++++++
base/setup/lib/fsutil.h | 7 +++
3 files changed, 200 insertions(+), 4 deletions(-)
diff --git a/base/setup/lib/bootsup.c b/base/setup/lib/bootsup.c
index 58c17e79bed..c34950cc3e3 100644
--- a/base/setup/lib/bootsup.c
+++ b/base/setup/lib/bootsup.c
@@ -1227,6 +1227,107 @@ InstallBtrfsBootcodeToPartition(
return STATUS_SUCCESS;
}
+static
+NTSTATUS
+InstallNtfsBootcodeToPartition(
+ IN PUNICODE_STRING SystemRootPath,
+ IN PUNICODE_STRING SourceRootPath,
+ IN PUNICODE_STRING DestinationArcPath)
+{
+ NTSTATUS Status;
+ BOOLEAN DoesFreeLdrExist;
+ WCHAR SrcPath[MAX_PATH];
+ WCHAR DstPath[MAX_PATH];
+
+ /* NTFS partition */
+ DPRINT("System path: '%wZ'\n", SystemRootPath);
+
+ /* Copy FreeLoader to the system partition, always overwriting the older version */
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\freeldr.sys");
+ CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer,
L"freeldr.sys");
+
+ DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
+ Status = SetupCopyFile(SrcPath, DstPath, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /* Prepare for possibly updating 'freeldr.ini' */
+ DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer,
L"freeldr.ini");
+ if (DoesFreeLdrExist)
+ {
+ /* Update existing 'freeldr.ini' */
+ DPRINT1("Update existing 'freeldr.ini'\n");
+ Status = UpdateFreeLoaderIni(SystemRootPath->Buffer,
DestinationArcPath->Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ /* Check for *nix bootloaders */
+
+ DPRINT1("Create new 'freeldr.ini'\n");
+
+ /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
+ DPRINT1("*nix or unknown boot loader found\n");
+
+ if (IsThereAValidBootSector(SystemRootPath->Buffer))
+ {
+ PCWSTR BootSector = L"BOOTSECT.OLD";
+
+ Status = CreateFreeLoaderIniForReactOSAndBootSector(
+ SystemRootPath->Buffer, DestinationArcPath->Buffer,
+ L"Linux", L"\"Linux\"",
+ L"hd0", L"1", BootSector);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status
%lx)\n", Status);
+ return Status;
+ }
+
+ /* Save current bootsector */
+ CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer,
BootSector);
+
+ DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer,
DstPath);
+ Status = SaveBootSector(SystemRootPath->Buffer, DstPath,
NTFS_BOOTSECTOR_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ }
+ else
+ {
+ Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer,
DestinationArcPath->Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n",
Status);
+ return Status;
+ }
+ }
+
+ /* Install new bootsector on the disk */
+
+ /* Install NTFS bootcode */
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\ntfs.bin");
+
+ DPRINT1("Install NTFS bootcode: %S ==> %S\n", SrcPath,
SystemRootPath->Buffer);
+ Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer,
InstallNtfsBootCode);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("InstallBootCodeToDisk(NTFS) failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
InstallVBRToPartition(
@@ -1243,13 +1344,12 @@ InstallVBRToPartition(
DestinationArcPath,
FileSystemName);
}
- /*
else if (wcsicmp(FileSystemName, L"NTFS") == 0)
{
- DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
- return STATUS_NOT_SUPPORTED;
+ return InstallNtfsBootcodeToPartition(SystemRootPath,
+ SourceRootPath,
+ DestinationArcPath);
}
- */
else if (wcsicmp(FileSystemName, L"BTRFS") == 0)
{
return InstallBtrfsBootcodeToPartition(SystemRootPath,
diff --git a/base/setup/lib/fsutil.c b/base/setup/lib/fsutil.c
index 8ef241ece05..b58633e2df2 100644
--- a/base/setup/lib/fsutil.c
+++ b/base/setup/lib/fsutil.c
@@ -111,6 +111,35 @@ typedef struct _BTRFS_BOOTSECTOR
} BTRFS_BOOTSECTOR, *PBTRFS_BOOTSECTOR;
C_ASSERT(sizeof(BTRFS_BOOTSECTOR) == BTRFS_BOOTSECTOR_SIZE);
+typedef struct _NTFS_BOOTSECTOR
+{
+ UCHAR Jump[3];
+ UCHAR OEMID[8];
+ USHORT BytesPerSector;
+ UCHAR SectorsPerCluster;
+ UCHAR Unused0[7];
+ UCHAR MediaId;
+ UCHAR Unused1[2];
+ USHORT SectorsPerTrack;
+ USHORT Heads;
+ UCHAR Unused2[4];
+ UCHAR Unused3[4];
+ USHORT Unknown[2];
+ ULONGLONG SectorCount;
+ ULONGLONG MftLocation;
+ ULONGLONG MftMirrLocation;
+ CHAR ClustersPerMftRecord;
+ UCHAR Unused4[3];
+ CHAR ClustersPerIndexRecord;
+ UCHAR Unused5[3];
+ ULONGLONG SerialNumber;
+ UCHAR Checksum[4];
+ UCHAR BootStrap[426];
+ USHORT EndSector;
+ UCHAR BootCodeAndData[7680]; // The remainder of the boot sector (8192 - 512)
+} NTFS_BOOTSECTOR, *PNTFS_BOOTSECTOR;
+C_ASSERT(sizeof(NTFS_BOOTSECTOR) == NTFS_BOOTSECTOR_SIZE);
+
// TODO: Add more bootsector structures!
#include <poppack.h>
@@ -659,6 +688,66 @@ Quit:
return Status;
}
+NTSTATUS
+InstallNtfsBootCode(
+ IN PCWSTR SrcPath, // NTFS bootsector source file (on the installation
medium)
+ IN HANDLE DstPath, // Where to save the bootsector built from the source +
partition information
+ IN HANDLE RootPartition) // Partition holding the (old) NTFS information
+{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER FileOffset;
+ BOOTCODE OrigBootSector = {0};
+ BOOTCODE NewBootSector = {0};
+
+ /* Allocate and read the current original partition bootsector */
+ Status = ReadBootCodeByHandle(&OrigBootSector, RootPartition,
NTFS_BOOTSECTOR_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("InstallNtfsBootCode: Status %lx\n", Status);
+ return Status;
+ }
+
+ /* Allocate and read the new bootsector (16 sectors) from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+ Status = ReadBootCodeFromFile(&NewBootSector, &Name, NTFS_BOOTSECTOR_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("InstallNtfsBootCode: Status %lx\n", Status);
+ FreeBootCode(&OrigBootSector);
+ return Status;
+ }
+
+ /* Adjust the bootsector (copy a part of the NTFS BPB) */
+ RtlCopyMemory(&((PNTFS_BOOTSECTOR)NewBootSector.BootCode)->OEMID,
+ &((PNTFS_BOOTSECTOR)OrigBootSector.BootCode)->OEMID,
+ FIELD_OFFSET(NTFS_BOOTSECTOR, BootStrap) -
FIELD_OFFSET(NTFS_BOOTSECTOR, OEMID));
+
+ /* Write sector 0 */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector.BootCode,
+ NewBootSector.Length,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ goto Quit;
+ }
+
+Quit:
+ /* Free the new bootsector */
+ FreeBootCode(&NewBootSector);
+
+ return Status;
+}
+
//
// Formatting routines
diff --git a/base/setup/lib/fsutil.h b/base/setup/lib/fsutil.h
index 1056cfb658d..51877faa0fd 100644
--- a/base/setup/lib/fsutil.h
+++ b/base/setup/lib/fsutil.h
@@ -68,6 +68,7 @@ FormatFileSystem(
#define FAT_BOOTSECTOR_SIZE (1 * SECTORSIZE)
#define FAT32_BOOTSECTOR_SIZE (1 * SECTORSIZE) // Counts only the primary sector.
#define BTRFS_BOOTSECTOR_SIZE (3 * SECTORSIZE)
+#define NTFS_BOOTSECTOR_SIZE (16 * SECTORSIZE)
typedef NTSTATUS
(/*NTAPI*/ *PFS_INSTALL_BOOTCODE)(
@@ -96,6 +97,12 @@ InstallBtrfsBootCode(
IN HANDLE DstPath,
IN HANDLE RootPartition);
+NTSTATUS
+InstallNtfsBootCode(
+ IN PCWSTR SrcPath,
+ IN HANDLE DstPath,
+ IN HANDLE RootPartition);
+
//
// Formatting routines