https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2580889cfa3c8620999e8579eab91a5c8ebb317a

commit 2580889cfa3c8620999e8579eab91a5c8ebb317a
Author:     Vadim Galyant <[email protected]>
AuthorDate: Wed Oct 19 03:02:24 2022 +0300
Commit:     GitHub <[email protected]>
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

Reply via email to