[SETUPLIB] Add NTFS boot support. (#3778)

This commit is contained in:
Vadim Galyant 2022-10-19 03:02:24 +03:00 committed by GitHub
parent a33719500c
commit 2580889cfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 200 additions and 4 deletions

View file

@ -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,

View file

@ -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

View file

@ -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