[SETUPLIB] Code re-organization in bootsup.c and fsutil.c.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 17 Oct 2020 18:29:47 +0000 (20:29 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 18 Oct 2020 18:56:16 +0000 (20:56 +0200)
- 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
base/setup/lib/bootcode.c [new file with mode: 0644]
base/setup/lib/bootcode.h [new file with mode: 0644]
base/setup/lib/bootsup.c
base/setup/lib/fsutil.c
base/setup/lib/fsutil.h
base/setup/lib/setuplib.h

index ff23bc5..68b0092 100644 (file)
@@ -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 (file)
index 0000000..b72ac1f
--- /dev/null
@@ -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 (file)
index 0000000..cd8c826
--- /dev/null
@@ -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 */
index ec9a1a4..c746240 100644 (file)
@@ -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!!
 
 #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;
     }
 
index 2abe8e4..9bd0aee 100644 (file)
@@ -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@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>
 #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
 //
index dd2fb3e..d451888 100644 (file)
@@ -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@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
 //
index 15358f2..2dcb349 100644 (file)
@@ -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"