https://git.reactos.org/?p=reactos.git;a=commitdiff;h=593bcce9991d56de97e6e…
commit 593bcce9991d56de97e6e34c8acbf0b1bc1fa0cc
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sat Oct 17 20:29:47 2020 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sun Oct 18 20:56:16 2020 +0200
[SETUPLIB] Code re-organization in bootsup.c and fsutil.c.
- Move the actual VBR bootcode installation helpers into fsutil.c
(they depend on the selected filesystem).
- Introduce InstallBootCodeToDisk() and InstallBootCodeToFile()
and bootcode.c helpers, in order to replace the several functions
that were duplicating the same code.
---
base/setup/lib/CMakeLists.txt | 1 +
base/setup/lib/bootcode.c | 116 ++++
base/setup/lib/bootcode.h | 37 +
base/setup/lib/bootsup.c | 1535 ++++++-----------------------------------
base/setup/lib/fsutil.c | 380 +++++++++-
base/setup/lib/fsutil.h | 38 +-
base/setup/lib/setuplib.h | 5 +-
7 files changed, 792 insertions(+), 1320 deletions(-)
diff --git a/base/setup/lib/CMakeLists.txt b/base/setup/lib/CMakeLists.txt
index ff23bc57d16..68b00922b14 100644
--- a/base/setup/lib/CMakeLists.txt
+++ b/base/setup/lib/CMakeLists.txt
@@ -16,6 +16,7 @@ list(APPEND SOURCE
utils/osdetect.c
utils/partlist.c
utils/regutil.c
+ bootcode.c
bootsup.c
fsutil.c
install.c
diff --git a/base/setup/lib/bootcode.c b/base/setup/lib/bootcode.c
new file mode 100644
index 00000000000..b72ac1fab42
--- /dev/null
+++ b/base/setup/lib/bootcode.c
@@ -0,0 +1,116 @@
+/*
+ * PROJECT: ReactOS Setup Library
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: BootCode support functions.
+ * COPYRIGHT: Copyright 2020 Hermes Belusca-Maito
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "precomp.h"
+
+#include "bootcode.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS
+ReadBootCodeByHandle(
+ IN OUT PBOOTCODE BootCodeInfo,
+ IN HANDLE FileHandle,
+ IN ULONG Length OPTIONAL)
+{
+ NTSTATUS Status;
+ PVOID BootCode;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER FileOffset;
+
+ ASSERT(BootCodeInfo);
+
+ /* Normalize the bootcode length */
+ if (Length == 0 || Length == (ULONG)-1)
+ Length = SECTORSIZE;
+
+ /* Allocate a buffer for the bootcode */
+ BootCode = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, Length);
+ if (BootCode == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Read the bootcode from the file into the buffer */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BootCode,
+ Length,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, BootCode);
+ return Status;
+ }
+
+ /* Update the bootcode information */
+ if (BootCodeInfo->BootCode)
+ RtlFreeHeap(ProcessHeap, 0, BootCodeInfo->BootCode);
+ BootCodeInfo->BootCode = BootCode;
+ /**/ BootCodeInfo->Length = Length; /**/
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+ReadBootCodeFromFile(
+ IN OUT PBOOTCODE BootCodeInfo,
+ IN PUNICODE_STRING FilePath,
+ IN ULONG Length OPTIONAL)
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+
+ ASSERT(BootCodeInfo);
+
+ /* Open the file */
+ InitializeObjectAttributes(&ObjectAttributes,
+ FilePath,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, // Is FILE_SHARE_WRITE
necessary?
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ Status = ReadBootCodeByHandle(BootCodeInfo, FileHandle, Length);
+
+ /* Close the file and return */
+ NtClose(FileHandle);
+ return Status;
+}
+
+VOID
+FreeBootCode(
+ IN OUT PBOOTCODE BootCodeInfo)
+{
+ ASSERT(BootCodeInfo);
+
+ /* Update the bootcode information */
+ if (BootCodeInfo->BootCode)
+ RtlFreeHeap(ProcessHeap, 0, BootCodeInfo->BootCode);
+ BootCodeInfo->BootCode = NULL;
+ /**/ BootCodeInfo->Length = 0; /**/
+}
+
+/* EOF */
diff --git a/base/setup/lib/bootcode.h b/base/setup/lib/bootcode.h
new file mode 100644
index 00000000000..cd8c8269e21
--- /dev/null
+++ b/base/setup/lib/bootcode.h
@@ -0,0 +1,37 @@
+/*
+ * PROJECT: ReactOS Setup Library
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: BootCode support functions.
+ * COPYRIGHT: Copyright 2020 Hermes Belusca-Maito
+ */
+
+#pragma once
+
+#ifdef SECTORSIZE
+#undef SECTORSIZE
+#endif
+#define SECTORSIZE 512
+
+typedef struct _BOOTCODE
+{
+ PVOID BootCode;
+ ULONG Length;
+} BOOTCODE, *PBOOTCODE;
+
+NTSTATUS
+ReadBootCodeByHandle(
+ IN OUT PBOOTCODE BootCodeInfo,
+ IN HANDLE FileHandle,
+ IN ULONG Length OPTIONAL);
+
+NTSTATUS
+ReadBootCodeFromFile(
+ IN OUT PBOOTCODE BootCodeInfo,
+ IN PUNICODE_STRING FilePath,
+ IN ULONG Length OPTIONAL);
+
+VOID
+FreeBootCode(
+ IN OUT PBOOTCODE BootCodeInfo);
+
+/* EOF */
diff --git a/base/setup/lib/bootsup.c b/base/setup/lib/bootsup.c
index ec9a1a4cf56..c7462403630 100644
--- a/base/setup/lib/bootsup.c
+++ b/base/setup/lib/bootsup.c
@@ -13,8 +13,9 @@
#include "bldrsup.h"
#include "filesup.h"
-#include "fsutil.h"
#include "partlist.h"
+#include "bootcode.h"
+#include "fsutil.h"
#include "setuplib.h" // HAXX for IsUnattendedSetup!!
@@ -23,108 +24,17 @@
#define NDEBUG
#include <debug.h>
-
-/* TYPEDEFS *****************************************************************/
-
/*
* BIG FIXME!!
* ===========
*
- * All that stuff *MUST* go into the fsutil.c module.
- * Indeed, all that relates to filesystem formatting details and as such
- * *MUST* be abstracted out from this module (bootsup.c).
- * However, bootsup.c can still deal with MBR code (actually it'll have
- * at some point to share or give it to partlist.c, because when we'll
- * support GPT disks, things will change a bit).
- * And, bootsup.c can still manage initializing / adding boot entries
- * into NTLDR and FREELDR, and installing the latter, and saving the old
- * MBR / boot sectors in files.
+ * bootsup.c can deal with MBR code (actually it'll have at some point
+ * to share or give it to partlist.c, because when we'll support GPT disks,
+ * things will change a bit).
+ * And, bootsup.c can manage initializing / adding boot entries into NTLDR
+ * and FREELDR, and installing the latter, and saving the old MBR / boot
+ * sectors in files.
*/
-#define SECTORSIZE 512
-
-#include <pshpack1.h>
-typedef struct _FAT_BOOTSECTOR
-{
- UCHAR JumpBoot[3]; // Jump instruction to boot code
- CHAR OemName[8]; // "MSWIN4.1" for MS formatted
volumes
- USHORT BytesPerSector; // Bytes per sector
- UCHAR SectorsPerCluster; // Number of sectors in a cluster
- USHORT ReservedSectors; // Reserved sectors, usually 1 (the
bootsector)
- UCHAR NumberOfFats; // Number of FAT tables
- USHORT RootDirEntries; // Number of root directory entries
(fat12/16)
- USHORT TotalSectors; // Number of total sectors on the drive,
16-bit
- UCHAR MediaDescriptor; // Media descriptor byte
- USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
- USHORT SectorsPerTrack; // Number of sectors in a track
- USHORT NumberOfHeads; // Number of heads on the disk
- ULONG HiddenSectors; // Hidden sectors (sectors before the
partition start like the partition table)
- ULONG TotalSectorsBig; // This field is the new 32-bit total count
of sectors on the volume
- UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
- UCHAR Reserved1; // Reserved (used by Windows NT). Code that
formats FAT volumes should always set this byte to 0.
- UCHAR BootSignature; // Extended boot signature (0x29). This is a
signature byte that indicates that the following three fields in the boot sector are
present.
- ULONG VolumeSerialNumber; // Volume serial number
- CHAR VolumeLabel[11]; // Volume label. This field matches the
11-byte volume label recorded in the root directory
- CHAR FileSystemType[8]; // One of the strings "FAT12 ",
"FAT16 ", or "FAT "
-
- UCHAR BootCodeAndData[448]; // The remainder of the boot sector
-
- USHORT BootSectorMagic; // 0xAA55
-
-} FAT_BOOTSECTOR, *PFAT_BOOTSECTOR;
-
-typedef struct _FAT32_BOOTSECTOR
-{
- UCHAR JumpBoot[3]; // Jump instruction to boot code
- CHAR OemName[8]; // "MSWIN4.1" for MS formatted
volumes
- USHORT BytesPerSector; // Bytes per sector
- UCHAR SectorsPerCluster; // Number of sectors in a cluster
- USHORT ReservedSectors; // Reserved sectors, usually 1 (the
bootsector)
- UCHAR NumberOfFats; // Number of FAT tables
- USHORT RootDirEntries; // Number of root directory entries
(fat12/16)
- USHORT TotalSectors; // Number of total sectors on the drive,
16-bit
- UCHAR MediaDescriptor; // Media descriptor byte
- USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
- USHORT SectorsPerTrack; // Number of sectors in a track
- USHORT NumberOfHeads; // Number of heads on the disk
- ULONG HiddenSectors; // Hidden sectors (sectors before the
partition start like the partition table)
- ULONG TotalSectorsBig; // This field is the new 32-bit total count
of sectors on the volume
- ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of
sectors occupied by ONE FAT. BPB_FATSz16 must be 0
- USHORT ExtendedFlags; // Extended flags (fat32)
- USHORT FileSystemVersion; // File system version (fat32)
- ULONG RootDirStartCluster; // Starting cluster of the root directory
(fat32)
- USHORT FsInfo; // Sector number of FSINFO structure in the
reserved area of the FAT32 volume. Usually 1.
- USHORT BackupBootSector; // If non-zero, indicates the sector number
in the reserved area of the volume of a copy of the boot record. Usually 6.
- UCHAR Reserved[12]; // Reserved for future expansion
- UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
- UCHAR Reserved1; // Reserved (used by Windows NT). Code that
formats FAT volumes should always set this byte to 0.
- UCHAR BootSignature; // Extended boot signature (0x29). This is a
signature byte that indicates that the following three fields in the boot sector are
present.
- ULONG VolumeSerialNumber; // Volume serial number
- CHAR VolumeLabel[11]; // Volume label. This field matches the
11-byte volume label recorded in the root directory
- CHAR FileSystemType[8]; // Always set to the string "FAT32
"
-
- UCHAR BootCodeAndData[420]; // The remainder of the boot sector
-
- USHORT BootSectorMagic; // 0xAA55
-
-} FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR;
-
-typedef struct _BTRFS_BOOTSECTOR
-{
- UCHAR JumpBoot[3];
- UCHAR ChunkMapSize;
- UCHAR BootDrive;
- ULONGLONG PartitionStartLBA;
- UCHAR Fill[1521]; // 1536 - 15
- USHORT BootSectorMagic;
-} BTRFS_BOOTSECTOR, *PBTRFS_BOOTSECTOR;
-C_ASSERT(sizeof(BTRFS_BOOTSECTOR) == 3 * 512);
-
-// TODO: Add more bootsector structures!
-
-#include <poppack.h>
-
-/* End of BIG FIXME!! */
-
/* FUNCTIONS ****************************************************************/
@@ -550,63 +460,26 @@ IsThereAValidBootSector(
BOOLEAN IsValid = FALSE;
NTSTATUS Status;
UNICODE_STRING RootPartition;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- LARGE_INTEGER FileOffset;
- PUCHAR BootSector;
+ BOOTCODE BootSector = {0};
- /* Allocate buffer for bootsector */
- BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
- if (BootSector == NULL)
- return FALSE; // STATUS_INSUFFICIENT_RESOURCES;
- RtlZeroMemory(BootSector, SECTORSIZE);
-
- /* Open the root partition - Remove any trailing backslash if needed */
+ /* Allocate and read the root partition bootsector.
+ * Remove any trailing backslash if needed. */
RtlInitUnicodeString(&RootPartition, RootPath);
TrimTrailingPathSeparators_UStr(&RootPartition);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &RootPartition,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- goto Quit;
-
- /* Read current boot sector into buffer */
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- BootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- NtClose(FileHandle);
+ Status = ReadBootCodeFromFile(&BootSector, &RootPartition, SECTORSIZE);
if (!NT_SUCCESS(Status))
- goto Quit;
+ return FALSE;
/* Check for the existence of the bootsector signature */
- IsValid = (*(PUSHORT)(BootSector + 0x1FE) == 0xAA55);
+ IsValid = (*(PUSHORT)((PUCHAR)BootSector.BootCode + 0x1FE) == 0xAA55);
if (IsValid)
{
/* Check for the first instruction encoded on three bytes */
- IsValid = (((*(PULONG)BootSector) & 0x00FFFFFF) != 0x00000000);
+ IsValid = (((*(PULONG)BootSector.BootCode) & 0x00FFFFFF) != 0x00000000);
}
-Quit:
- /* Free the boot sector */
- RtlFreeHeap(ProcessHeap, 0, BootSector);
+ /* Free the bootsector and return */
+ FreeBootCode(&BootSector);
return IsValid;
}
@@ -622,55 +495,18 @@ SaveBootSector(
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
- LARGE_INTEGER FileOffset;
- PUCHAR BootSector;
-
- /* Allocate buffer for bootsector */
- BootSector = RtlAllocateHeap(ProcessHeap, 0, Length);
- if (BootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ // LARGE_INTEGER FileOffset;
+ BOOTCODE BootSector = {0};
- /* Open the root partition - Remove any trailing backslash if needed */
+ /* Allocate and read the root partition bootsector.
+ * Remove any trailing backslash if needed. */
RtlInitUnicodeString(&Name, RootPath);
TrimTrailingPathSeparators_UStr(&Name);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, BootSector);
- return Status;
- }
-
- /* Read current boot sector into buffer */
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- BootSector,
- Length,
- &FileOffset,
- NULL);
- NtClose(FileHandle);
+ Status = ReadBootCodeFromFile(&BootSector, &Name, Length);
if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, BootSector);
return Status;
- }
- /* Write bootsector to DstPath */
+ /* Write the bootsector to DstPath */
RtlInitUnicodeString(&Name, DstPath);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
@@ -691,7 +527,7 @@ SaveBootSector(
0);
if (!NT_SUCCESS(Status))
{
- RtlFreeHeap(ProcessHeap, 0, BootSector);
+ FreeBootCode(&BootSector);
return Status;
}
@@ -700,40 +536,36 @@ SaveBootSector(
NULL,
NULL,
&IoStatusBlock,
- BootSector,
- Length,
+ BootSector.BootCode,
+ BootSector.Length,
NULL,
NULL);
NtClose(FileHandle);
- /* Free the boot sector */
- RtlFreeHeap(ProcessHeap, 0, BootSector);
-
+ /* Free the bootsector and return */
+ FreeBootCode(&BootSector);
return Status;
}
static
NTSTATUS
-InstallMbrBootCodeToDiskHelper(
+InstallBootCodeToDisk(
IN PCWSTR SrcPath,
- IN PCWSTR RootPath)
+ IN PCWSTR RootPath,
+ IN PFS_INSTALL_BOOTCODE InstallBootCode)
{
NTSTATUS Status;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- LARGE_INTEGER FileOffset;
- PPARTITION_SECTOR OrigBootSector;
- PPARTITION_SECTOR NewBootSector;
-
- /* Allocate buffer for original bootsector */
- OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR));
- if (OrigBootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ HANDLE PartitionHandle;
- /* Open the root partition - Remove any trailing backslash if needed */
+ /*
+ * Open the root partition from which the bootcode (MBR, VBR) parameters
+ * will be obtained; this is also where we will write the updated bootcode.
+ * Remove any trailing backslash if needed.
+ */
RtlInitUnicodeString(&Name, RootPath);
TrimTrailingPathSeparators_UStr(&Name);
@@ -743,132 +575,164 @@ InstallMbrBootCodeToDiskHelper(
NULL,
NULL);
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
+ Status = NtOpenFile(&PartitionHandle,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT);
+ FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return Status;
- }
- /* Read current boot sector into buffer */
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- OrigBootSector,
- sizeof(PARTITION_SECTOR),
- &FileOffset,
- NULL);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return Status;
- }
+ /* Install the bootcode (MBR, VBR) */
+ Status = InstallBootCode(SrcPath, PartitionHandle, PartitionHandle);
- /* Allocate buffer for new bootsector */
- NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR));
- if (NewBootSector == NULL)
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ /* Close the partition */
+ NtClose(PartitionHandle);
+
+ return Status;
+}
+
+static
+NTSTATUS
+InstallBootCodeToFile(
+ IN PCWSTR SrcPath,
+ IN PCWSTR DstPath,
+ IN PCWSTR RootPath,
+ IN PFS_INSTALL_BOOTCODE InstallBootCode)
+{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE PartitionHandle, FileHandle;
+
+ /*
+ * Open the root partition from which the bootcode (MBR, VBR)
+ * parameters will be obtained.
+ *
+ * FIXME? It might be possible that we need to also open it for writing
+ * access in case we really need to still write the second portion of
+ * the boot sector ????
+ *
+ * Remove any trailing backslash if needed.
+ */
+ RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
- /* Read new bootsector from SrcPath */
- RtlInitUnicodeString(&Name, SrcPath);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtOpenFile(&FileHandle,
+ Status = NtOpenFile(&PartitionHandle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
- }
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- sizeof(PARTITION_SECTOR),
- NULL,
- NULL);
- NtClose(FileHandle);
+ /* Open or create the file where the new bootsector will be saved */
+ RtlInitUnicodeString(&Name, DstPath);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_SUPERSEDE, // FILE_OVERWRITE_IF
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
if (!NT_SUCCESS(Status))
{
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
+ NtClose(PartitionHandle);
return Status;
}
- /*
- * Copy the disk signature, the reserved fields and
- * the partition table from the old MBR to the new one.
- */
- RtlCopyMemory(&NewBootSector->Signature,
- &OrigBootSector->Signature,
- sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature)
- /* Length of partition table */);
+ /* Install the bootcode (MBR, VBR) */
+ Status = InstallBootCode(SrcPath, FileHandle, PartitionHandle);
- /* Free the original boot sector */
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ /* Close the file and the partition */
+ NtClose(FileHandle);
+ NtClose(PartitionHandle);
- /* Open the root partition - Remove any trailing backslash if needed */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
+ return Status;
+}
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- Status = NtOpenFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
+static
+NTSTATUS
+InstallMbrBootCode(
+ IN PCWSTR SrcPath, // MBR source file (on the installation medium)
+ IN HANDLE DstPath, // Where to save the bootsector built from the source + disk
information
+ IN HANDLE DiskHandle) // Disk holding the (old) MBR information
+{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER FileOffset;
+ BOOTCODE OrigBootSector = {0};
+ BOOTCODE NewBootSector = {0};
+
+C_ASSERT(sizeof(PARTITION_SECTOR) == SECTORSIZE);
+
+ /* Allocate and read the current original MBR bootsector */
+ Status = ReadBootCodeByHandle(&OrigBootSector,
+ DiskHandle,
+ sizeof(PARTITION_SECTOR));
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Allocate and read the new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+ Status = ReadBootCodeFromFile(&NewBootSector,
+ &Name,
+ sizeof(PARTITION_SECTOR));
if (!NT_SUCCESS(Status))
{
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ FreeBootCode(&OrigBootSector);
return Status;
}
- /* Write new bootsector to RootPath */
+ /*
+ * Copy the disk signature, the reserved fields and
+ * the partition table from the old MBR to the new one.
+ */
+ RtlCopyMemory(&((PPARTITION_SECTOR)NewBootSector.BootCode)->Signature,
+ &((PPARTITION_SECTOR)OrigBootSector.BootCode)->Signature,
+ sizeof(PARTITION_SECTOR) -
+ FIELD_OFFSET(PARTITION_SECTOR, Signature)
+ /* Length of partition table */);
+
+ /* Free the original bootsector */
+ FreeBootCode(&OrigBootSector);
+
+ /* Write the new bootsector to DstPath */
FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(FileHandle,
+ Status = NtWriteFile(DstPath,
NULL,
NULL,
NULL,
&IoStatusBlock,
- NewBootSector,
- sizeof(PARTITION_SECTOR),
+ NewBootSector.BootCode,
+ NewBootSector.Length,
&FileOffset,
NULL);
- NtClose(FileHandle);
- /* Free the new boot sector */
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ /* Free the new bootsector */
+ FreeBootCode(&NewBootSector);
return Status;
}
@@ -917,1023 +781,65 @@ InstallMbrBootCodeToDisk(
DPRINT1("Install MBR bootcode: %S ==> %S\n",
SourceMbrPathBuffer, DestinationDevicePathBuffer);
- return InstallMbrBootCodeToDiskHelper(SourceMbrPathBuffer,
- DestinationDevicePathBuffer);
+ /* Install the MBR */
+ return InstallBootCodeToDisk(SourceMbrPathBuffer,
+ DestinationDevicePathBuffer,
+ InstallMbrBootCode);
}
static
NTSTATUS
-InstallFat12BootCodeToFloppy(
- IN PCWSTR SrcPath,
- IN PCWSTR RootPath)
+InstallFatBootcodeToPartition(
+ IN PUNICODE_STRING SystemRootPath,
+ IN PUNICODE_STRING SourceRootPath,
+ IN PUNICODE_STRING DestinationArcPath,
+ IN UCHAR PartitionType)
{
NTSTATUS Status;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- LARGE_INTEGER FileOffset;
- PFAT_BOOTSECTOR OrigBootSector;
- PFAT_BOOTSECTOR NewBootSector;
-
- /* Allocate buffer for original bootsector */
- OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
- if (OrigBootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- /* Open the root partition - Remove any trailing backslash if needed */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
+ BOOLEAN DoesFreeLdrExist;
+ WCHAR SrcPath[MAX_PATH];
+ WCHAR DstPath[MAX_PATH];
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
+ /* FAT or FAT32 partition */
+ DPRINT("System path: '%wZ'\n", SystemRootPath);
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return Status;
- }
+ /* 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");
- /* Read current boot sector into buffer */
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- OrigBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- NtClose(FileHandle);
+ DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
+ Status = SetupCopyFile(SrcPath, DstPath, FALSE);
if (!NT_SUCCESS(Status))
{
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
return Status;
}
- /* Allocate buffer for new bootsector */
- NewBootSector = RtlAllocateHeap(ProcessHeap,
- 0,
- SECTORSIZE);
- if (NewBootSector == NULL)
+ /* Prepare for possibly updating 'freeldr.ini' */
+ DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer,
L"freeldr.ini");
+ if (DoesFreeLdrExist)
{
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return STATUS_INSUFFICIENT_RESOURCES;
+ /* 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;
+ }
}
- /* Read new bootsector from SrcPath */
- RtlInitUnicodeString(&Name, SrcPath);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
+ /* Check for NT and other bootloaders */
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
+ // FIXME: Check for Vista+ bootloader!
+ /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
+ /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
+ if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
+ DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
{
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- NULL,
- NULL);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- /* Adjust bootsector (copy a part of the FAT16 BPB) */
- memcpy(&NewBootSector->OemName,
- &OrigBootSector->OemName,
- FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
- FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
-
- /* Free the original boot sector */
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
-
- /* Open the root partition - Remove any trailing backslash if needed */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- /* Write new bootsector to RootPath */
- FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- NtClose(FileHandle);
-
- /* Free the new boot sector */
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
-
- return Status;
-}
-
-static
-NTSTATUS
-InstallFat16BootCode(
- IN PCWSTR SrcPath, // FAT16 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) FAT16 information
-{
- NTSTATUS Status;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- LARGE_INTEGER FileOffset;
- PFAT_BOOTSECTOR OrigBootSector;
- PFAT_BOOTSECTOR NewBootSector;
-
- /* Allocate a buffer for the original bootsector */
- OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
- if (OrigBootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- /* Read the current partition boot sector into the buffer */
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(RootPartition,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- OrigBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return Status;
- }
-
- /* Allocate a buffer for the new bootsector */
- NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
- if (NewBootSector == NULL)
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Read the new bootsector from SrcPath */
- RtlInitUnicodeString(&Name, SrcPath);
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- /* Adjust the bootsector (copy a part of the FAT16 BPB) */
- memcpy(&NewBootSector->OemName,
- &OrigBootSector->OemName,
- FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
- FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
-
- /* Free the original boot sector */
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
-
- /* Write the new bootsector to DstPath */
- FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(DstPath,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
-
- /* Free the new boot sector */
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
-
- return Status;
-}
-
-static
-NTSTATUS
-InstallFat16BootCodeToFile(
- IN PCWSTR SrcPath,
- IN PCWSTR DstPath,
- IN PCWSTR RootPath)
-{
- NTSTATUS Status;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE PartitionHandle, FileHandle;
-
- /*
- * Open the root partition from which the boot sector
- * parameters will be obtained.
- * Remove any trailing backslash if needed.
- */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&PartitionHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
- if (!NT_SUCCESS(Status))
- return Status;
-
- /* Open or create the file where the new bootsector will be saved */
- RtlInitUnicodeString(&Name, DstPath);
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtCreateFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- 0,
- FILE_OVERWRITE_IF,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
- NtClose(PartitionHandle);
- return Status;
- }
-
- /* Install the FAT16 boot sector */
- Status = InstallFat16BootCode(SrcPath, FileHandle, PartitionHandle);
-
- /* Close the file and the partition */
- NtClose(FileHandle);
- NtClose(PartitionHandle);
-
- return Status;
-}
-
-static
-NTSTATUS
-InstallFat16BootCodeToDisk(
- IN PCWSTR SrcPath,
- IN PCWSTR RootPath)
-{
- NTSTATUS Status;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE PartitionHandle;
-
- /*
- * Open the root partition from which the boot sector parameters will be
- * obtained; this is also where we will write the updated boot sector.
- * Remove any trailing backslash if needed.
- */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&PartitionHandle,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
- if (!NT_SUCCESS(Status))
- return Status;
-
- /* Install the FAT16 boot sector */
- Status = InstallFat16BootCode(SrcPath, PartitionHandle, PartitionHandle);
-
- /* Close the partition */
- NtClose(PartitionHandle);
-
- return Status;
-}
-
-
-static
-NTSTATUS
-InstallFat32BootCode(
- IN PCWSTR SrcPath, // FAT32 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) FAT32 information
-{
- NTSTATUS Status;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- LARGE_INTEGER FileOffset;
- PFAT32_BOOTSECTOR OrigBootSector;
- PFAT32_BOOTSECTOR NewBootSector;
- USHORT BackupBootSector;
-
- /* Allocate a buffer for the original bootsector */
- OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
- if (OrigBootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- /* Read the current boot sector into the buffer */
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(RootPartition,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- OrigBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return Status;
- }
-
- /* Allocate a buffer for the new bootsector (2 sectors) */
- NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
- if (NewBootSector == NULL)
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Read the new bootsector from SrcPath */
- RtlInitUnicodeString(&Name, SrcPath);
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- 2 * SECTORSIZE,
- &FileOffset,
- NULL);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- /* Adjust the bootsector (copy a part of the FAT32 BPB) */
- memcpy(&NewBootSector->OemName,
- &OrigBootSector->OemName,
- FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
- FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
-
- /*
- * We know we copy the boot code to a file only when DstPath != RootPartition,
- * otherwise the boot code is copied to the specified root partition.
- */
- if (DstPath != RootPartition)
- {
- /* Copy to a file: Disable the backup boot sector */
- NewBootSector->BackupBootSector = 0;
- }
- else
- {
- /* Copy to a disk: Get the location of the backup boot sector */
- BackupBootSector = OrigBootSector->BackupBootSector;
- }
-
- /* Free the original boot sector */
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
-
- /* Write the first sector of the new bootcode to DstPath sector 0 */
- FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(DstPath,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- if (DstPath == RootPartition)
- {
- /* Copy to a disk: Write the backup boot sector */
- if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
- {
- FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
- Status = NtWriteFile(DstPath,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
- }
- }
-
- /* Write the second sector of the new bootcode to boot disk sector 14 */
- // FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
- FileOffset.QuadPart = 14 * SECTORSIZE;
- Status = NtWriteFile(DstPath, // or really RootPartition ???
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- ((PUCHAR)NewBootSector + SECTORSIZE),
- SECTORSIZE,
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
- }
-
- /* Free the new boot sector */
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
-
- return Status;
-}
-
-static
-NTSTATUS
-InstallFat32BootCodeToFile(
- IN PCWSTR SrcPath,
- IN PCWSTR DstPath,
- IN PCWSTR RootPath)
-{
- NTSTATUS Status;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE PartitionHandle, FileHandle;
-
- /*
- * Open the root partition from which the boot sector parameters
- * will be obtained.
- * FIXME? It might be possible that we need to also open it for writing
- * access in case we really need to still write the second portion of
- * the boot sector ????
- *
- * Remove any trailing backslash if needed.
- */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&PartitionHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
- if (!NT_SUCCESS(Status))
- return Status;
-
- /* Open or create the file where (the first sector of ????) the new bootsector will
be saved */
- RtlInitUnicodeString(&Name, DstPath);
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtCreateFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- 0,
- FILE_SUPERSEDE, // FILE_OVERWRITE_IF, <- is used for FAT16
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
- NtClose(PartitionHandle);
- return Status;
- }
-
- /* Install the FAT32 boot sector */
- Status = InstallFat32BootCode(SrcPath, FileHandle, PartitionHandle);
-
- /* Close the file and the partition */
- NtClose(FileHandle);
- NtClose(PartitionHandle);
-
- return Status;
-}
-
-static
-NTSTATUS
-InstallFat32BootCodeToDisk(
- IN PCWSTR SrcPath,
- IN PCWSTR RootPath)
-{
- NTSTATUS Status;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE PartitionHandle;
-
- /*
- * Open the root partition from which the boot sector parameters will be
- * obtained; this is also where we will write the updated boot sector.
- * Remove any trailing backslash if needed.
- */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&PartitionHandle,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
- if (!NT_SUCCESS(Status))
- return Status;
-
- /* Install the FAT32 boot sector */
- Status = InstallFat32BootCode(SrcPath, PartitionHandle, PartitionHandle);
-
- /* Close the partition */
- NtClose(PartitionHandle);
-
- return Status;
-}
-
-static
-NTSTATUS
-InstallBtrfsBootCodeToDisk(
- IN PCWSTR SrcPath,
- IN PCWSTR RootPath)
-{
- NTSTATUS Status;
- NTSTATUS LockStatus;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- LARGE_INTEGER FileOffset;
-// PEXT2_BOOTSECTOR OrigBootSector;
- PBTRFS_BOOTSECTOR NewBootSector;
- // USHORT BackupBootSector;
- PARTITION_INFORMATION_EX PartInfo;
-
-#if 0
- /* Allocate buffer for original bootsector */
- OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
- if (OrigBootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- /* Open the root partition - Remove any trailing backslash if needed */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return Status;
- }
-
- /* Read current boot sector into buffer */
- FileOffset.QuadPart = 0ULL;
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- OrigBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return Status;
- }
-#endif
-
- /* Allocate buffer for new bootsector */
- NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(BTRFS_BOOTSECTOR));
- if (NewBootSector == NULL)
- {
- // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Read new bootsector from SrcPath */
- RtlInitUnicodeString(&Name, SrcPath);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- sizeof(BTRFS_BOOTSECTOR),
- NULL,
- NULL);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
-#if 0
- /* Adjust bootsector (copy a part of the FAT32 BPB) */
- memcpy(&NewBootSector->OemName,
- &OrigBootSector->OemName,
- FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
- FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
-
- /* Get the location of the backup boot sector */
- BackupBootSector = OrigBootSector->BackupBootSector;
-
- /* Free the original boot sector */
- // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
-#endif
-
- /* Open the root partition - Remove any trailing backslash if needed */
- RtlInitUnicodeString(&Name, RootPath);
- TrimTrailingPathSeparators_UStr(&Name);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- /*
- * The BTRFS driver requires the volume to be locked in order to modify
- * the first sectors of the partition, even though they are outside the
- * file-system space / in the reserved area (they are situated before
- * the super-block at 0x1000) and is in principle allowed by the NT
- * storage stack.
- * So we lock here in order to write the bootsector at sector 0.
- * If locking fails, we ignore and continue nonetheless.
- */
- LockStatus = NtFsControlFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- FSCTL_LOCK_VOLUME,
- NULL,
- 0,
- NULL,
- 0);
- if (!NT_SUCCESS(LockStatus))
- {
- DPRINT1("WARNING: Failed to lock BTRFS volume for writing bootsector!
Operations may fail! (Status 0x%lx)\n", LockStatus);
- }
-
- /* Obtaining partition info and writing it to bootsector */
- Status = NtDeviceIoControlFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- IOCTL_DISK_GET_PARTITION_INFO_EX,
- NULL,
- 0,
- &PartInfo,
- sizeof(PartInfo));
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n",
Status);
- goto Quit;
- }
-
- /* Write new bootsector to RootPath */
-
- NewBootSector->PartitionStartLBA = PartInfo.StartingOffset.QuadPart / SECTORSIZE;
-
- /* Write sector 0 */
- FileOffset.QuadPart = 0ULL;
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- sizeof(BTRFS_BOOTSECTOR),
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
- goto Quit;
- }
-
-#if 0
- /* Write backup boot sector */
- if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
- {
- FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
- goto Quit;
- }
- }
-
- /* Write sector 14 */
- FileOffset.QuadPart = 14 * SECTORSIZE;
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- ((PUCHAR)NewBootSector + SECTORSIZE),
- SECTORSIZE,
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
- }
-#endif
-
-Quit:
- /* Unlock the volume */
- LockStatus = NtFsControlFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- FSCTL_UNLOCK_VOLUME,
- NULL,
- 0,
- NULL,
- 0);
- if (!NT_SUCCESS(LockStatus))
- {
- DPRINT1("Failed to unlock BTRFS volume (Status 0x%lx)\n", LockStatus);
- }
-
- /* Close the volume */
- NtClose(FileHandle);
-
- /* Free the new boot sector */
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
-
- return Status;
-}
-
-
-static
-NTSTATUS
-InstallFatBootcodeToPartition(
- IN PUNICODE_STRING SystemRootPath,
- IN PUNICODE_STRING SourceRootPath,
- IN PUNICODE_STRING DestinationArcPath,
- IN UCHAR PartitionType)
-{
- NTSTATUS Status;
- BOOLEAN DoesFreeLdrExist;
- WCHAR SrcPath[MAX_PATH];
- WCHAR DstPath[MAX_PATH];
-
- /* FAT or FAT32 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");
-
- DPRINT("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;
- }
- }
-
- /* Check for NT and other bootloaders */
-
- // FIXME: Check for Vista+ bootloader!
- /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
- /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
- if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
- DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
- {
- /* Search root directory for 'NTLDR' and 'BOOT.INI' */
- DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
+ /* Search root directory for 'NTLDR' and 'BOOT.INI' */
+ DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
/* Create or update 'freeldr.ini' */
if (DoesFreeLdrExist == FALSE)
@@ -1957,11 +863,12 @@ InstallFatBootcodeToPartition(
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\fat32.bin");
DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath,
DstPath);
- Status = InstallFat32BootCodeToFile(SrcPath, DstPath,
- SystemRootPath->Buffer);
+ Status = InstallBootCodeToFile(SrcPath, DstPath,
+ SystemRootPath->Buffer,
+ InstallFat32BootCode);
if (!NT_SUCCESS(Status))
{
- DPRINT1("InstallFat32BootCodeToFile() failed (Status
%lx)\n", Status);
+ DPRINT1("InstallBootCodeToFile(FAT32) failed (Status
%lx)\n", Status);
return Status;
}
}
@@ -1970,12 +877,13 @@ InstallFatBootcodeToPartition(
/* Install FAT16 bootcode */
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\fat.bin");
- DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath,
DstPath);
- Status = InstallFat16BootCodeToFile(SrcPath, DstPath,
- SystemRootPath->Buffer);
+ DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath,
DstPath);
+ Status = InstallBootCodeToFile(SrcPath, DstPath,
+ SystemRootPath->Buffer,
+ InstallFat16BootCode);
if (!NT_SUCCESS(Status))
{
- DPRINT1("InstallFat16BootCodeToFile() failed (Status
%lx)\n", Status);
+ DPRINT1("InstallBootCodeToFile(FAT16) failed (Status
%lx)\n", Status);
return Status;
}
}
@@ -2169,10 +1077,10 @@ InstallFatBootcodeToPartition(
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\fat32.bin");
DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath,
SystemRootPath->Buffer);
- Status = InstallFat32BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
+ Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer,
InstallFat32BootCode);
if (!NT_SUCCESS(Status))
{
- DPRINT1("InstallFat32BootCodeToDisk() failed (Status
%lx)\n", Status);
+ DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status
%lx)\n", Status);
return Status;
}
}
@@ -2182,10 +1090,10 @@ InstallFatBootcodeToPartition(
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\fat.bin");
DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath,
SystemRootPath->Buffer);
- Status = InstallFat16BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
+ Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer,
InstallFat16BootCode);
if (!NT_SUCCESS(Status))
{
- DPRINT1("InstallFat16BootCodeToDisk() failed (Status
%lx)\n", Status);
+ DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status
%lx)\n", Status);
return Status;
}
}
@@ -2200,8 +1108,7 @@ NTSTATUS
InstallBtrfsBootcodeToPartition(
IN PUNICODE_STRING SystemRootPath,
IN PUNICODE_STRING SourceRootPath,
- IN PUNICODE_STRING DestinationArcPath,
- IN UCHAR PartitionType)
+ IN PUNICODE_STRING DestinationArcPath)
{
NTSTATUS Status;
BOOLEAN DoesFreeLdrExist;
@@ -2266,7 +1173,7 @@ InstallBtrfsBootcodeToPartition(
CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer,
BootSector);
DPRINT1("Save bootsector: %S ==> %S\n",
SystemRootPath->Buffer, DstPath);
- Status = SaveBootSector(SystemRootPath->Buffer, DstPath,
sizeof(BTRFS_BOOTSECTOR));
+ Status = SaveBootSector(SystemRootPath->Buffer, DstPath,
BTRFS_BOOTSECTOR_SIZE);
if (!NT_SUCCESS(Status))
{
DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
@@ -2284,18 +1191,15 @@ InstallBtrfsBootcodeToPartition(
}
/* Install new bootsector on the disk */
- // if (PartitionType == PARTITION_EXT2)
- {
- /* Install BTRFS bootcode */
- CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\btrfs.bin");
+ /* Install BTRFS bootcode */
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\btrfs.bin");
- DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath,
SystemRootPath->Buffer);
- Status = InstallBtrfsBootCodeToDisk(SrcPath, SystemRootPath->Buffer);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n",
Status);
- return Status;
- }
+ DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath,
SystemRootPath->Buffer);
+ Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer,
InstallBtrfsBootCode);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n",
Status);
+ return Status;
}
}
@@ -2329,8 +1233,7 @@ InstallVBRToPartition(
{
return InstallBtrfsBootcodeToPartition(SystemRootPath,
SourceRootPath,
- DestinationArcPath,
- PartitionType);
+ DestinationArcPath);
}
case PARTITION_IFS:
@@ -2405,11 +1308,11 @@ InstallFatBootcodeToFloppy(
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer,
L"\\loader\\fat.bin");
CombinePaths(DstPath, ARRAYSIZE(DstPath), 1, FloppyDevice);
- DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
- Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
+ DPRINT("Install FAT12 bootcode: %S ==> %S\n", SrcPath, DstPath);
+ Status = InstallBootCodeToDisk(SrcPath, DstPath, InstallFat12BootCode);
if (!NT_SUCCESS(Status))
{
- DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n",
Status);
+ DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status %lx)\n", Status);
return Status;
}
diff --git a/base/setup/lib/fsutil.c b/base/setup/lib/fsutil.c
index 2abe8e4c7a8..9bd0aee4c2a 100644
--- a/base/setup/lib/fsutil.c
+++ b/base/setup/lib/fsutil.c
@@ -3,7 +3,7 @@
* LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Filesystem support functions
* COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns(a)users.sourceforge.net)
- * Copyright 2017-2019 Hermes Belusca-Maito
+ * Copyright 2017-2020 Hermes Belusca-Maito
*/
//
@@ -18,6 +18,7 @@
#include "partlist.h"
#include "fsrec.h"
+#include "bootcode.h"
#include "fsutil.h"
#include <fslib/vfatlib.h>
@@ -29,6 +30,92 @@
#include <debug.h>
+/* TYPEDEFS *****************************************************************/
+
+#include <pshpack1.h>
+typedef struct _FAT_BOOTSECTOR
+{
+ UCHAR JumpBoot[3]; // Jump instruction to boot code
+ CHAR OemName[8]; // "MSWIN4.1" for MS formatted
volumes
+ USHORT BytesPerSector; // Bytes per sector
+ UCHAR SectorsPerCluster; // Number of sectors in a cluster
+ USHORT ReservedSectors; // Reserved sectors, usually 1 (the
bootsector)
+ UCHAR NumberOfFats; // Number of FAT tables
+ USHORT RootDirEntries; // Number of root directory entries
(fat12/16)
+ USHORT TotalSectors; // Number of total sectors on the drive,
16-bit
+ UCHAR MediaDescriptor; // Media descriptor byte
+ USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
+ USHORT SectorsPerTrack; // Number of sectors in a track
+ USHORT NumberOfHeads; // Number of heads on the disk
+ ULONG HiddenSectors; // Hidden sectors (sectors before the
partition start like the partition table)
+ ULONG TotalSectorsBig; // This field is the new 32-bit total count
of sectors on the volume
+ UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
+ UCHAR Reserved1; // Reserved (used by Windows NT). Code that
formats FAT volumes should always set this byte to 0.
+ UCHAR BootSignature; // Extended boot signature (0x29). This is a
signature byte that indicates that the following three fields in the boot sector are
present.
+ ULONG VolumeSerialNumber; // Volume serial number
+ CHAR VolumeLabel[11]; // Volume label. This field matches the
11-byte volume label recorded in the root directory
+ CHAR FileSystemType[8]; // One of the strings "FAT12 ",
"FAT16 ", or "FAT "
+
+ UCHAR BootCodeAndData[448]; // The remainder of the boot sector
+
+ USHORT BootSectorMagic; // 0xAA55
+
+} FAT_BOOTSECTOR, *PFAT_BOOTSECTOR;
+C_ASSERT(sizeof(FAT_BOOTSECTOR) == FAT_BOOTSECTOR_SIZE);
+
+typedef struct _FAT32_BOOTSECTOR
+{
+ UCHAR JumpBoot[3]; // Jump instruction to boot code
+ CHAR OemName[8]; // "MSWIN4.1" for MS formatted
volumes
+ USHORT BytesPerSector; // Bytes per sector
+ UCHAR SectorsPerCluster; // Number of sectors in a cluster
+ USHORT ReservedSectors; // Reserved sectors, usually 1 (the
bootsector)
+ UCHAR NumberOfFats; // Number of FAT tables
+ USHORT RootDirEntries; // Number of root directory entries
(fat12/16)
+ USHORT TotalSectors; // Number of total sectors on the drive,
16-bit
+ UCHAR MediaDescriptor; // Media descriptor byte
+ USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
+ USHORT SectorsPerTrack; // Number of sectors in a track
+ USHORT NumberOfHeads; // Number of heads on the disk
+ ULONG HiddenSectors; // Hidden sectors (sectors before the
partition start like the partition table)
+ ULONG TotalSectorsBig; // This field is the new 32-bit total count
of sectors on the volume
+ ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of
sectors occupied by ONE FAT. BPB_FATSz16 must be 0
+ USHORT ExtendedFlags; // Extended flags (fat32)
+ USHORT FileSystemVersion; // File system version (fat32)
+ ULONG RootDirStartCluster; // Starting cluster of the root directory
(fat32)
+ USHORT FsInfo; // Sector number of FSINFO structure in the
reserved area of the FAT32 volume. Usually 1.
+ USHORT BackupBootSector; // If non-zero, indicates the sector number
in the reserved area of the volume of a copy of the boot record. Usually 6.
+ UCHAR Reserved[12]; // Reserved for future expansion
+ UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
+ UCHAR Reserved1; // Reserved (used by Windows NT). Code that
formats FAT volumes should always set this byte to 0.
+ UCHAR BootSignature; // Extended boot signature (0x29). This is a
signature byte that indicates that the following three fields in the boot sector are
present.
+ ULONG VolumeSerialNumber; // Volume serial number
+ CHAR VolumeLabel[11]; // Volume label. This field matches the
11-byte volume label recorded in the root directory
+ CHAR FileSystemType[8]; // Always set to the string "FAT32
"
+
+ UCHAR BootCodeAndData[420]; // The remainder of the boot sector
+
+ USHORT BootSectorMagic; // 0xAA55
+
+} FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR;
+C_ASSERT(sizeof(FAT32_BOOTSECTOR) == FAT32_BOOTSECTOR_SIZE);
+
+typedef struct _BTRFS_BOOTSECTOR
+{
+ UCHAR JumpBoot[3];
+ UCHAR ChunkMapSize;
+ UCHAR BootDrive;
+ ULONGLONG PartitionStartLBA;
+ UCHAR Fill[1521]; // 1536 - 15
+ USHORT BootSectorMagic;
+} BTRFS_BOOTSECTOR, *PBTRFS_BOOTSECTOR;
+C_ASSERT(sizeof(BTRFS_BOOTSECTOR) == BTRFS_BOOTSECTOR_SIZE);
+
+// TODO: Add more bootsector structures!
+
+#include <poppack.h>
+
+
/* LOCALS *******************************************************************/
/** IFS_PROVIDER **/
@@ -238,6 +325,297 @@ FormatFileSystem(
}
+//
+// Bootsector routines
+//
+
+NTSTATUS
+InstallFat1216BootCode(
+ IN PCWSTR SrcPath, // FAT12/16 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) FAT12/16 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,
+ FAT_BOOTSECTOR_SIZE);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Allocate and read the new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+ Status = ReadBootCodeFromFile(&NewBootSector,
+ &Name,
+ FAT_BOOTSECTOR_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ FreeBootCode(&OrigBootSector);
+ return Status;
+ }
+
+ /* Adjust the bootsector (copy a part of the FAT12/16 BPB) */
+ RtlCopyMemory(&((PFAT_BOOTSECTOR)NewBootSector.BootCode)->OemName,
+ &((PFAT_BOOTSECTOR)OrigBootSector.BootCode)->OemName,
+ FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
+
+ /* Free the original bootsector */
+ FreeBootCode(&OrigBootSector);
+
+ /* Write the new bootsector to DstPath */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector.BootCode,
+ NewBootSector.Length,
+ &FileOffset,
+ NULL);
+
+ /* Free the new bootsector */
+ FreeBootCode(&NewBootSector);
+
+ return Status;
+}
+
+NTSTATUS
+InstallFat32BootCode(
+ IN PCWSTR SrcPath, // FAT32 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) FAT32 information
+{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER FileOffset;
+ USHORT BackupBootSector = 0;
+ BOOTCODE OrigBootSector = {0};
+ BOOTCODE NewBootSector = {0};
+
+ /* Allocate and read the current original partition bootsector */
+ Status = ReadBootCodeByHandle(&OrigBootSector,
+ RootPartition,
+ FAT32_BOOTSECTOR_SIZE);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Allocate and read the new bootsector (2 sectors) from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+ Status = ReadBootCodeFromFile(&NewBootSector,
+ &Name,
+ 2 * FAT32_BOOTSECTOR_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ FreeBootCode(&OrigBootSector);
+ return Status;
+ }
+
+ /* Adjust the bootsector (copy a part of the FAT32 BPB) */
+ RtlCopyMemory(&((PFAT32_BOOTSECTOR)NewBootSector.BootCode)->OemName,
+ &((PFAT32_BOOTSECTOR)OrigBootSector.BootCode)->OemName,
+ FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
+
+ /*
+ * We know we copy the boot code to a file only when DstPath != RootPartition,
+ * otherwise the boot code is copied to the specified root partition.
+ */
+ if (DstPath != RootPartition)
+ {
+ /* Copy to a file: Disable the backup bootsector */
+ ((PFAT32_BOOTSECTOR)NewBootSector.BootCode)->BackupBootSector = 0;
+ }
+ else
+ {
+ /* Copy to a disk: Get the location of the backup bootsector */
+ BackupBootSector =
((PFAT32_BOOTSECTOR)OrigBootSector.BootCode)->BackupBootSector;
+ }
+
+ /* Free the original bootsector */
+ FreeBootCode(&OrigBootSector);
+
+ /* Write the first sector of the new bootcode to DstPath sector 0 */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector.BootCode,
+ FAT32_BOOTSECTOR_SIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ FreeBootCode(&NewBootSector);
+ return Status;
+ }
+
+ if (DstPath == RootPartition)
+ {
+ /* Copy to a disk: Write the backup bootsector */
+ if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
+ {
+ FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector *
FAT32_BOOTSECTOR_SIZE);
+ Status = NtWriteFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector.BootCode,
+ FAT32_BOOTSECTOR_SIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ FreeBootCode(&NewBootSector);
+ return Status;
+ }
+ }
+ }
+
+ /* Write the second sector of the new bootcode to boot disk sector 14 */
+ // FileOffset.QuadPart = (ULONGLONG)(14 * FAT32_BOOTSECTOR_SIZE);
+ FileOffset.QuadPart = 14 * FAT32_BOOTSECTOR_SIZE;
+ Status = NtWriteFile(DstPath, // or really RootPartition ???
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ ((PUCHAR)NewBootSector.BootCode + FAT32_BOOTSECTOR_SIZE),
+ FAT32_BOOTSECTOR_SIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ }
+
+ /* Free the new bootsector */
+ FreeBootCode(&NewBootSector);
+
+ return Status;
+}
+
+NTSTATUS
+InstallBtrfsBootCode(
+ IN PCWSTR SrcPath, // BTRFS 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) BTRFS information
+{
+ NTSTATUS Status;
+ NTSTATUS LockStatus;
+ UNICODE_STRING Name;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER FileOffset;
+ PARTITION_INFORMATION_EX PartInfo;
+ BOOTCODE NewBootSector = {0};
+
+ /* Allocate and read the new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+ Status = ReadBootCodeFromFile(&NewBootSector,
+ &Name,
+ BTRFS_BOOTSECTOR_SIZE);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /*
+ * The BTRFS driver requires the volume to be locked in order to modify
+ * the first sectors of the partition, even though they are outside the
+ * file-system space / in the reserved area (they are situated before
+ * the super-block at 0x1000) and is in principle allowed by the NT
+ * storage stack.
+ * So we lock here in order to write the bootsector at sector 0.
+ * If locking fails, we ignore and continue nonetheless.
+ */
+ LockStatus = NtFsControlFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_LOCK_VOLUME,
+ NULL,
+ 0,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(LockStatus))
+ {
+ DPRINT1("WARNING: Failed to lock BTRFS volume for writing bootsector!
Operations may fail! (Status 0x%lx)\n", LockStatus);
+ }
+
+ /* Obtain partition info and write it to the bootsector */
+ Status = NtDeviceIoControlFile(RootPartition,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ IOCTL_DISK_GET_PARTITION_INFO_EX,
+ NULL,
+ 0,
+ &PartInfo,
+ sizeof(PartInfo));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n",
Status);
+ goto Quit;
+ }
+
+ /* Write new bootsector to RootPath */
+ ((PBTRFS_BOOTSECTOR)NewBootSector.BootCode)->PartitionStartLBA =
+ PartInfo.StartingOffset.QuadPart / SECTORSIZE;
+
+ /* 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:
+ /* Unlock the volume */
+ LockStatus = NtFsControlFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_UNLOCK_VOLUME,
+ NULL,
+ 0,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(LockStatus))
+ {
+ DPRINT1("Failed to unlock BTRFS volume (Status 0x%lx)\n", LockStatus);
+ }
+
+ /* 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 dd2fb3e5964..d4518885b9f 100644
--- a/base/setup/lib/fsutil.h
+++ b/base/setup/lib/fsutil.h
@@ -3,7 +3,7 @@
* LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Filesystem support functions
* COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns(a)users.sourceforge.net)
- * Copyright 2017-2019 Hermes Belusca-Maito
+ * Copyright 2017-2020 Hermes Belusca-Maito
*/
#pragma once
@@ -61,6 +61,42 @@ FormatFileSystem(
IN PFMIFSCALLBACK Callback);
+//
+// Bootsector routines
+//
+
+#define FAT_BOOTSECTOR_SIZE (1 * SECTORSIZE)
+#define FAT32_BOOTSECTOR_SIZE (1 * SECTORSIZE) // Counts only the primary sector.
+#define BTRFS_BOOTSECTOR_SIZE (3 * SECTORSIZE)
+
+typedef NTSTATUS
+(/*NTAPI*/ *PFS_INSTALL_BOOTCODE)(
+ IN PCWSTR SrcPath, // 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) bootsector data
information
+
+NTSTATUS
+InstallFat1216BootCode(
+ IN PCWSTR SrcPath,
+ IN HANDLE DstPath,
+ IN HANDLE RootPartition);
+
+#define InstallFat12BootCode InstallFat1216BootCode
+#define InstallFat16BootCode InstallFat1216BootCode
+
+NTSTATUS
+InstallFat32BootCode(
+ IN PCWSTR SrcPath,
+ IN HANDLE DstPath,
+ IN HANDLE RootPartition);
+
+NTSTATUS
+InstallBtrfsBootCode(
+ IN PCWSTR SrcPath,
+ IN HANDLE DstPath,
+ IN HANDLE RootPartition);
+
+
//
// Formatting routines
//
diff --git a/base/setup/lib/setuplib.h b/base/setup/lib/setuplib.h
index 15358f24885..2dcb349f369 100644
--- a/base/setup/lib/setuplib.h
+++ b/base/setup/lib/setuplib.h
@@ -31,16 +31,17 @@ extern HANDLE ProcessHeap;
#include "utils/ntverrsrc.h"
// #include "utils/arcname.h"
#include "utils/bldrsup.h"
-#include "bootsup.h"
#include "utils/filesup.h"
#include "utils/fsrec.h"
-#include "fsutil.h"
#include "utils/genlist.h"
#include "utils/inicache.h"
#include "utils/partlist.h"
#include "utils/arcname.h"
#include "utils/osdetect.h"
#include "utils/regutil.h"
+#include "bootcode.h"
+#include "fsutil.h"
+#include "bootsup.h"
#include "registry.h"
#include "mui.h"
#include "settings.h"