https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2580889cfa3c8620999e85...
commit 2580889cfa3c8620999e8579eab91a5c8ebb317a Author: Vadim Galyant vgal@rambler.ru AuthorDate: Wed Oct 19 03:02:24 2022 +0300 Commit: GitHub noreply@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