2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Setup Library
4 * FILE: base/setup/lib/bootsup.c
5 * PURPOSE: Bootloader support functions
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *****************************************************************/
19 #include "setuplib.h" // HAXX for IsUnattendedSetup!!
27 /* TYPEDEFS *****************************************************************/
33 * All that stuff *MUST* go into the fsutil.c module.
34 * Indeed, all that relates to filesystem formatting details and as such
35 * *MUST* be abstracted out from this module (bootsup.c).
36 * However, bootsup.c can still deal with MBR code (actually it'll have
37 * at some point to share or give it to partlist.c, because when we'll
38 * support GPT disks, things will change a bit).
39 * And, bootsup.c can still manage initializing / adding boot entries
40 * into NTLDR and FREELDR, and installing the latter, and saving the old
41 * MBR / boot sectors in files.
43 #define SECTORSIZE 512
46 typedef struct _FAT_BOOTSECTOR
48 UCHAR JumpBoot
[3]; // Jump instruction to boot code
49 CHAR OemName
[8]; // "MSWIN4.1" for MS formatted volumes
50 USHORT BytesPerSector
; // Bytes per sector
51 UCHAR SectorsPerCluster
; // Number of sectors in a cluster
52 USHORT ReservedSectors
; // Reserved sectors, usually 1 (the bootsector)
53 UCHAR NumberOfFats
; // Number of FAT tables
54 USHORT RootDirEntries
; // Number of root directory entries (fat12/16)
55 USHORT TotalSectors
; // Number of total sectors on the drive, 16-bit
56 UCHAR MediaDescriptor
; // Media descriptor byte
57 USHORT SectorsPerFat
; // Sectors per FAT table (fat12/16)
58 USHORT SectorsPerTrack
; // Number of sectors in a track
59 USHORT NumberOfHeads
; // Number of heads on the disk
60 ULONG HiddenSectors
; // Hidden sectors (sectors before the partition start like the partition table)
61 ULONG TotalSectorsBig
; // This field is the new 32-bit total count of sectors on the volume
62 UCHAR DriveNumber
; // Int 0x13 drive number (e.g. 0x80)
63 UCHAR Reserved1
; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
64 UCHAR BootSignature
; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
65 ULONG VolumeSerialNumber
; // Volume serial number
66 CHAR VolumeLabel
[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
67 CHAR FileSystemType
[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT "
69 UCHAR BootCodeAndData
[448]; // The remainder of the boot sector
71 USHORT BootSectorMagic
; // 0xAA55
73 } FAT_BOOTSECTOR
, *PFAT_BOOTSECTOR
;
75 typedef struct _FAT32_BOOTSECTOR
77 UCHAR JumpBoot
[3]; // Jump instruction to boot code
78 CHAR OemName
[8]; // "MSWIN4.1" for MS formatted volumes
79 USHORT BytesPerSector
; // Bytes per sector
80 UCHAR SectorsPerCluster
; // Number of sectors in a cluster
81 USHORT ReservedSectors
; // Reserved sectors, usually 1 (the bootsector)
82 UCHAR NumberOfFats
; // Number of FAT tables
83 USHORT RootDirEntries
; // Number of root directory entries (fat12/16)
84 USHORT TotalSectors
; // Number of total sectors on the drive, 16-bit
85 UCHAR MediaDescriptor
; // Media descriptor byte
86 USHORT SectorsPerFat
; // Sectors per FAT table (fat12/16)
87 USHORT SectorsPerTrack
; // Number of sectors in a track
88 USHORT NumberOfHeads
; // Number of heads on the disk
89 ULONG HiddenSectors
; // Hidden sectors (sectors before the partition start like the partition table)
90 ULONG TotalSectorsBig
; // This field is the new 32-bit total count of sectors on the volume
91 ULONG SectorsPerFatBig
; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
92 USHORT ExtendedFlags
; // Extended flags (fat32)
93 USHORT FileSystemVersion
; // File system version (fat32)
94 ULONG RootDirStartCluster
; // Starting cluster of the root directory (fat32)
95 USHORT FsInfo
; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
96 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.
97 UCHAR Reserved
[12]; // Reserved for future expansion
98 UCHAR DriveNumber
; // Int 0x13 drive number (e.g. 0x80)
99 UCHAR Reserved1
; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
100 UCHAR BootSignature
; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
101 ULONG VolumeSerialNumber
; // Volume serial number
102 CHAR VolumeLabel
[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
103 CHAR FileSystemType
[8]; // Always set to the string "FAT32 "
105 UCHAR BootCodeAndData
[420]; // The remainder of the boot sector
107 USHORT BootSectorMagic
; // 0xAA55
109 } FAT32_BOOTSECTOR
, *PFAT32_BOOTSECTOR
;
111 typedef struct _BTRFS_BOOTSECTOR
116 ULONGLONG PartitionStartLBA
;
117 UCHAR Fill
[1521]; // 1536 - 15
118 USHORT BootSectorMagic
;
119 } BTRFS_BOOTSECTOR
, *PBTRFS_BOOTSECTOR
;
120 C_ASSERT(sizeof(BTRFS_BOOTSECTOR
) == 3 * 512);
122 // TODO: Add more bootsector structures!
126 /* End of BIG FIXME!! */
129 /* FUNCTIONS ****************************************************************/
132 TrimTrailingPathSeparators_UStr(
133 IN OUT PUNICODE_STRING UnicodeString
)
135 while (UnicodeString
->Length
>= sizeof(WCHAR
) &&
136 UnicodeString
->Buffer
[UnicodeString
->Length
/ sizeof(WCHAR
) - 1] == OBJ_NAME_PATH_SEPARATOR
)
138 UnicodeString
->Length
-= sizeof(WCHAR
);
144 CreateFreeLoaderReactOSEntries(
145 IN PVOID BootStoreHandle
,
148 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
149 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
150 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
151 BOOT_STORE_OPTIONS BootOptions
;
153 BootEntry
->Version
= FreeLdr
;
154 BootEntry
->BootFilePath
= NULL
;
156 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
157 RtlCopyMemory(Options
->Signature
,
158 NTOS_OPTIONS_SIGNATURE
,
159 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
161 Options
->OsLoadPath
= ArcPath
;
164 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
165 BootEntry
->FriendlyName
= L
"\"ReactOS\"";
166 Options
->OsLoadOptions
= NULL
; // L"";
167 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS"));
170 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
171 BootEntry
->FriendlyName
= L
"\"ReactOS (Debug)\"";
172 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
173 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Debug"));
176 /* ReactOS_VBoxDebug */
177 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
178 BootEntry
->FriendlyName
= L
"\"ReactOS (VBoxDebug)\"";
179 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=VBOX /SOS";
180 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_VBoxDebug"));
184 /* ReactOS_KdSerial */
185 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
186 BootEntry
->FriendlyName
= L
"\"ReactOS (RosDbg)\"";
187 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
188 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_KdSerial"));
192 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
193 BootEntry
->FriendlyName
= L
"\"ReactOS (Screen)\"";
194 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=SCREEN /SOS";
195 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Screen"));
197 /* ReactOS_LogFile */
198 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
199 BootEntry
->FriendlyName
= L
"\"ReactOS (Log file)\"";
200 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=FILE /SOS";
201 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_LogFile"));
204 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
205 BootEntry
->FriendlyName
= L
"\"ReactOS (RAM Disk)\"";
206 Options
->OsLoadPath
= L
"ramdisk(0)\\ReactOS";
207 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
208 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Ram"));
211 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
212 BootEntry
->FriendlyName
= L
"\"ReactOS (Emergency Management Services)\"";
213 Options
->OsLoadPath
= ArcPath
;
214 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
215 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_EMS"));
220 if (IsUnattendedSetup
)
222 /* DefaultOS=ReactOS */
224 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS_KdSerial");
226 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS_Debug");
232 /* DefaultOS=ReactOS */
233 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS");
237 if (IsUnattendedSetup
)
240 /* Timeout=0 for unattended or non debug */
241 BootOptions
.Timeout
= 0;
247 BootOptions
.Timeout
= 10;
251 BootOptions
.Version
= FreeLdr
;
252 SetBootStoreOptions(BootStoreHandle
, &BootOptions
, 2 | 1);
256 CreateFreeLoaderIniForReactOS(
261 PVOID BootStoreHandle
;
263 /* Initialize the INI file and create the common FreeLdr sections */
264 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, TRUE
);
265 if (!NT_SUCCESS(Status
))
268 /* Add the ReactOS entries */
269 CreateFreeLoaderReactOSEntries(BootStoreHandle
, ArcPath
);
271 /* Close the INI file */
272 CloseBootStore(BootStoreHandle
);
273 return STATUS_SUCCESS
;
277 CreateFreeLoaderIniForReactOSAndBootSector(
281 IN PCWSTR Description
,
283 IN PCWSTR BootPartition
,
284 IN PCWSTR BootSector
)
287 PVOID BootStoreHandle
;
288 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(BOOT_SECTOR_OPTIONS
)];
289 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
290 PBOOT_SECTOR_OPTIONS Options
= (PBOOT_SECTOR_OPTIONS
)&BootEntry
->OsOptions
;
292 /* Initialize the INI file and create the common FreeLdr sections */
293 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, TRUE
);
294 if (!NT_SUCCESS(Status
))
297 /* Add the ReactOS entries */
298 CreateFreeLoaderReactOSEntries(BootStoreHandle
, ArcPath
);
300 BootEntry
->Version
= FreeLdr
;
301 BootEntry
->BootFilePath
= NULL
;
303 BootEntry
->OsOptionsLength
= sizeof(BOOT_SECTOR_OPTIONS
);
304 RtlCopyMemory(Options
->Signature
,
305 BOOT_SECTOR_OPTIONS_SIGNATURE
,
306 RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS
, Signature
));
308 Options
->Drive
= BootDrive
;
309 Options
->Partition
= BootPartition
;
310 Options
->BootSectorFileName
= BootSector
;
312 // BootEntry->BootEntryKey = MAKESTRKEY(Section);
313 BootEntry
->FriendlyName
= Description
;
314 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(Section
));
316 /* Close the INI file */
317 CloseBootStore(BootStoreHandle
);
318 return STATUS_SUCCESS
;
322 // I think this function can be generalizable as:
323 // "find the corresponding 'ReactOS' boot entry in this loader config file
324 // (here abstraction comes there), and if none, add a new one".
327 typedef struct _ENUM_REACTOS_ENTRIES_DATA
330 BOOLEAN UseExistingEntry
;
332 WCHAR SectionName
[80];
334 } ENUM_REACTOS_ENTRIES_DATA
, *PENUM_REACTOS_ENTRIES_DATA
;
336 // PENUM_BOOT_ENTRIES_ROUTINE
339 EnumerateReactOSEntries(
340 IN BOOT_STORE_TYPE Type
,
341 IN PBOOT_STORE_ENTRY BootEntry
,
342 IN PVOID Parameter OPTIONAL
)
345 PENUM_REACTOS_ENTRIES_DATA Data
= (PENUM_REACTOS_ENTRIES_DATA
)Parameter
;
346 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
347 WCHAR SystemPath
[MAX_PATH
];
349 /* We have a boot entry */
351 /* Check for supported boot type "Windows2003" */
352 if (BootEntry
->OsOptionsLength
< sizeof(NTOS_OPTIONS
) ||
353 RtlCompareMemory(&BootEntry
->OsOptions
/* Signature */,
354 NTOS_OPTIONS_SIGNATURE
,
355 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
)) !=
356 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
))
358 /* This is not a ReactOS entry */
359 // DPRINT(" An installation '%S' of unsupported type '%S'\n",
360 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
361 DPRINT(" An installation '%S' of unsupported type %lu\n",
362 BootEntry
->FriendlyName
, BootEntry
->OsOptionsLength
);
363 /* Continue the enumeration */
367 /* BootType is Windows2003, now check OsLoadPath */
368 if (!Options
->OsLoadPath
|| !*Options
->OsLoadPath
)
370 /* Certainly not a ReactOS installation */
371 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry
->FriendlyName
);
372 /* Continue the enumeration */
376 if (_wcsicmp(Options
->OsLoadPath
, Data
->ArcPath
) != 0)
378 /* Not found, retry with a quoted path */
379 Status
= RtlStringCchPrintfW(SystemPath
, ARRAYSIZE(SystemPath
), L
"\"%s\"", Data
->ArcPath
);
380 if (!NT_SUCCESS(Status
) || _wcsicmp(Options
->OsLoadPath
, SystemPath
) != 0)
383 * This entry is a ReactOS entry, but the SystemRoot
384 * does not match the one we are looking for.
386 /* Continue the enumeration */
391 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
392 BootEntry
->FriendlyName
, Options
->OsLoadPath
);
393 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
394 // BootEntry->FriendlyName, Options->OsLoadPath);
396 DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options
->OsLoadPath
);
398 Data
->UseExistingEntry
= TRUE
;
399 RtlStringCchCopyW(Data
->OsName
, ARRAYSIZE(Data
->OsName
), BootEntry
->FriendlyName
);
401 /* We have found our entry, stop the enumeration now! */
402 return STATUS_NO_MORE_ENTRIES
;
405 Data
->UseExistingEntry
= FALSE
;
406 if (Type
== FreeLdr
&& wcscmp(Data
->SectionName
, (PWSTR
)BootEntry
->BootEntryKey
)== 0)
408 RtlStringCchPrintfW(Data
->SectionName
, ARRAYSIZE(Data
->SectionName
),
409 L
"ReactOS_%lu", Data
->i
);
410 RtlStringCchPrintfW(Data
->OsName
, ARRAYSIZE(Data
->OsName
),
411 L
"\"ReactOS %lu\"", Data
->i
);
414 return STATUS_SUCCESS
;
424 PVOID BootStoreHandle
;
425 ENUM_REACTOS_ENTRIES_DATA Data
;
426 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
427 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
428 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
430 /* Open the INI file */
431 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, /*TRUE*/ FALSE
);
432 if (!NT_SUCCESS(Status
))
435 /* Find an existing usable or an unused section name */
436 Data
.UseExistingEntry
= TRUE
;
438 Data
.ArcPath
= ArcPath
;
439 RtlStringCchCopyW(Data
.SectionName
, ARRAYSIZE(Data
.SectionName
), L
"ReactOS");
440 RtlStringCchCopyW(Data
.OsName
, ARRAYSIZE(Data
.OsName
), L
"\"ReactOS\"");
443 // FIXME: We temporarily use EnumerateBootStoreEntries, until
444 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
446 Status
= EnumerateBootStoreEntries(BootStoreHandle
, EnumerateReactOSEntries
, &Data
);
448 /* Create a new "ReactOS" entry if there is none already existing that suits us */
449 if (!Data
.UseExistingEntry
)
451 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
452 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
454 BootEntry
->Version
= FreeLdr
;
455 BootEntry
->BootFilePath
= NULL
;
457 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
458 RtlCopyMemory(Options
->Signature
,
459 NTOS_OPTIONS_SIGNATURE
,
460 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
462 Options
->OsLoadPath
= ArcPath
;
464 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
465 BootEntry
->FriendlyName
= Data
.OsName
;
466 Options
->OsLoadOptions
= NULL
; // L"";
467 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(Data
.SectionName
));
470 /* Close the INI file */
471 CloseBootStore(BootStoreHandle
);
472 return STATUS_SUCCESS
;
479 IN PCWSTR EntryName
, // ~= ArcPath
480 IN PCWSTR EntryValue
)
483 PVOID BootStoreHandle
;
484 ENUM_REACTOS_ENTRIES_DATA Data
;
486 // NOTE: Technically it would be "BootSector"...
487 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
488 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
489 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
491 /* Open the INI file */
492 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, NtLdr
, FALSE
);
493 if (!NT_SUCCESS(Status
))
496 /* Find an existing usable or an unused section name */
497 Data
.UseExistingEntry
= TRUE
;
499 Data
.ArcPath
= EntryName
;
500 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
501 RtlStringCchCopyW(Data
.OsName
, ARRAYSIZE(Data
.OsName
), L
"\"ReactOS\"");
504 // FIXME: We temporarily use EnumerateBootStoreEntries, until
505 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
507 Status
= EnumerateBootStoreEntries(BootStoreHandle
, EnumerateReactOSEntries
, &Data
);
509 /* If either the key was not found, or contains something else, add a new one */
510 if (!Data
.UseExistingEntry
/* ||
511 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
513 BootEntry
->Version
= NtLdr
;
514 BootEntry
->BootFilePath
= NULL
;
516 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
517 RtlCopyMemory(Options
->Signature
,
518 NTOS_OPTIONS_SIGNATURE
,
519 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
521 Options
->OsLoadPath
= EntryName
;
523 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
524 // BootEntry->FriendlyName = Data.OsName;
525 BootEntry
->FriendlyName
= EntryValue
;
526 Options
->OsLoadOptions
= NULL
; // L"";
527 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(0 /*Data.SectionName*/));
530 /* Close the INI file */
531 CloseBootStore(BootStoreHandle
);
532 return STATUS_SUCCESS
; // Status;
538 IsThereAValidBootSector(
542 * We first demand that the bootsector has a valid signature at its end.
543 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
544 * potential "valid" instruction (the BIOS starts execution of the bootsector
545 * at its beginning). Currently this criterium is that this ULONG must be
546 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
547 * it is invalid and certainly needs to be overwritten.
550 BOOLEAN IsValid
= FALSE
;
552 UNICODE_STRING RootPartition
;
553 OBJECT_ATTRIBUTES ObjectAttributes
;
554 IO_STATUS_BLOCK IoStatusBlock
;
556 LARGE_INTEGER FileOffset
;
559 /* Allocate buffer for bootsector */
560 BootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
561 if (BootSector
== NULL
)
562 return FALSE
; // STATUS_INSUFFICIENT_RESOURCES;
563 RtlZeroMemory(BootSector
, SECTORSIZE
);
565 /* Open the root partition - Remove any trailing backslash if needed */
566 RtlInitUnicodeString(&RootPartition
, RootPath
);
567 TrimTrailingPathSeparators_UStr(&RootPartition
);
569 InitializeObjectAttributes(&ObjectAttributes
,
571 OBJ_CASE_INSENSITIVE
,
575 Status
= NtOpenFile(&FileHandle
,
576 GENERIC_READ
| SYNCHRONIZE
,
580 FILE_SYNCHRONOUS_IO_NONALERT
);
581 if (!NT_SUCCESS(Status
))
584 /* Read current boot sector into buffer */
585 FileOffset
.QuadPart
= 0ULL;
586 Status
= NtReadFile(FileHandle
,
596 if (!NT_SUCCESS(Status
))
599 /* Check for the existence of the bootsector signature */
600 IsValid
= (*(PUSHORT
)(BootSector
+ 0x1FE) == 0xAA55);
603 /* Check for the first instruction encoded on three bytes */
604 IsValid
= (((*(PULONG
)BootSector
) & 0x00FFFFFF) != 0x00000000);
608 /* Free the boot sector */
609 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
622 OBJECT_ATTRIBUTES ObjectAttributes
;
623 IO_STATUS_BLOCK IoStatusBlock
;
625 LARGE_INTEGER FileOffset
;
628 /* Allocate buffer for bootsector */
629 BootSector
= RtlAllocateHeap(ProcessHeap
, 0, Length
);
630 if (BootSector
== NULL
)
631 return STATUS_INSUFFICIENT_RESOURCES
;
633 /* Open the root partition - Remove any trailing backslash if needed */
634 RtlInitUnicodeString(&Name
, RootPath
);
635 TrimTrailingPathSeparators_UStr(&Name
);
637 InitializeObjectAttributes(&ObjectAttributes
,
639 OBJ_CASE_INSENSITIVE
,
643 Status
= NtOpenFile(&FileHandle
,
644 GENERIC_READ
| SYNCHRONIZE
,
648 FILE_SYNCHRONOUS_IO_NONALERT
);
649 if (!NT_SUCCESS(Status
))
651 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
655 /* Read current boot sector into buffer */
656 FileOffset
.QuadPart
= 0ULL;
657 Status
= NtReadFile(FileHandle
,
667 if (!NT_SUCCESS(Status
))
669 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
673 /* Write bootsector to DstPath */
674 RtlInitUnicodeString(&Name
, DstPath
);
675 InitializeObjectAttributes(&ObjectAttributes
,
677 OBJ_CASE_INSENSITIVE
,
681 Status
= NtCreateFile(&FileHandle
,
682 GENERIC_WRITE
| SYNCHRONIZE
,
686 FILE_ATTRIBUTE_NORMAL
,
689 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
692 if (!NT_SUCCESS(Status
))
694 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
698 Status
= NtWriteFile(FileHandle
,
709 /* Free the boot sector */
710 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
718 InstallMbrBootCodeToDiskHelper(
724 OBJECT_ATTRIBUTES ObjectAttributes
;
725 IO_STATUS_BLOCK IoStatusBlock
;
727 LARGE_INTEGER FileOffset
;
728 PPARTITION_SECTOR OrigBootSector
;
729 PPARTITION_SECTOR NewBootSector
;
731 /* Allocate buffer for original bootsector */
732 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(PARTITION_SECTOR
));
733 if (OrigBootSector
== NULL
)
734 return STATUS_INSUFFICIENT_RESOURCES
;
736 /* Open the root partition - Remove any trailing backslash if needed */
737 RtlInitUnicodeString(&Name
, RootPath
);
738 TrimTrailingPathSeparators_UStr(&Name
);
740 InitializeObjectAttributes(&ObjectAttributes
,
742 OBJ_CASE_INSENSITIVE
,
746 Status
= NtOpenFile(&FileHandle
,
747 GENERIC_READ
| SYNCHRONIZE
,
751 FILE_SYNCHRONOUS_IO_NONALERT
);
752 if (!NT_SUCCESS(Status
))
754 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
758 /* Read current boot sector into buffer */
759 FileOffset
.QuadPart
= 0ULL;
760 Status
= NtReadFile(FileHandle
,
766 sizeof(PARTITION_SECTOR
),
770 if (!NT_SUCCESS(Status
))
772 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
776 /* Allocate buffer for new bootsector */
777 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(PARTITION_SECTOR
));
778 if (NewBootSector
== NULL
)
780 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
781 return STATUS_INSUFFICIENT_RESOURCES
;
784 /* Read new bootsector from SrcPath */
785 RtlInitUnicodeString(&Name
, SrcPath
);
786 InitializeObjectAttributes(&ObjectAttributes
,
788 OBJ_CASE_INSENSITIVE
,
792 Status
= NtOpenFile(&FileHandle
,
793 GENERIC_READ
| SYNCHRONIZE
,
797 FILE_SYNCHRONOUS_IO_NONALERT
);
798 if (!NT_SUCCESS(Status
))
800 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
801 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
805 Status
= NtReadFile(FileHandle
,
811 sizeof(PARTITION_SECTOR
),
815 if (!NT_SUCCESS(Status
))
817 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
818 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
823 * Copy the disk signature, the reserved fields and
824 * the partition table from the old MBR to the new one.
826 RtlCopyMemory(&NewBootSector
->Signature
,
827 &OrigBootSector
->Signature
,
828 sizeof(PARTITION_SECTOR
) - offsetof(PARTITION_SECTOR
, Signature
)
829 /* Length of partition table */);
831 /* Free the original boot sector */
832 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
834 /* Open the root partition - Remove any trailing backslash if needed */
835 RtlInitUnicodeString(&Name
, RootPath
);
836 TrimTrailingPathSeparators_UStr(&Name
);
838 InitializeObjectAttributes(&ObjectAttributes
,
840 OBJ_CASE_INSENSITIVE
,
844 Status
= NtOpenFile(&FileHandle
,
845 GENERIC_WRITE
| SYNCHRONIZE
,
849 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
850 if (!NT_SUCCESS(Status
))
852 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
853 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
857 /* Write new bootsector to RootPath */
858 FileOffset
.QuadPart
= 0ULL;
859 Status
= NtWriteFile(FileHandle
,
865 sizeof(PARTITION_SECTOR
),
870 /* Free the new boot sector */
871 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
877 InstallMbrBootCodeToDisk(
878 IN PUNICODE_STRING SystemRootPath
,
879 IN PUNICODE_STRING SourceRootPath
,
880 IN PCWSTR DestinationDevicePathBuffer
)
883 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
884 WCHAR DstPath
[MAX_PATH
];
888 * The DestinationDevicePathBuffer parameter has been built with
889 * the following instruction by the caller; I'm not yet sure whether
890 * I actually want this function to build the path instead, hence
891 * I keep this code here but disabled for now...
893 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
894 RtlStringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
895 L
"\\Device\\Harddisk%d\\Partition0",
899 CombinePaths(SourceMbrPathBuffer
, ARRAYSIZE(SourceMbrPathBuffer
), 2,
900 SourceRootPath
->Buffer
, L
"\\loader\\dosmbr.bin");
902 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
904 /* Save current MBR */
905 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2,
906 SystemRootPath
->Buffer
, L
"mbr.old");
908 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
909 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
910 if (!NT_SUCCESS(Status
))
912 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
913 // Don't care if we succeeded or not saving the old MBR, just go ahead.
917 DPRINT1("Install MBR bootcode: %S ==> %S\n",
918 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
920 return InstallMbrBootCodeToDiskHelper(SourceMbrPathBuffer
,
921 DestinationDevicePathBuffer
);
927 InstallFat12BootCodeToFloppy(
933 OBJECT_ATTRIBUTES ObjectAttributes
;
934 IO_STATUS_BLOCK IoStatusBlock
;
936 LARGE_INTEGER FileOffset
;
937 PFAT_BOOTSECTOR OrigBootSector
;
938 PFAT_BOOTSECTOR NewBootSector
;
940 /* Allocate buffer for original bootsector */
941 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
942 if (OrigBootSector
== NULL
)
943 return STATUS_INSUFFICIENT_RESOURCES
;
945 /* Open the root partition - Remove any trailing backslash if needed */
946 RtlInitUnicodeString(&Name
, RootPath
);
947 TrimTrailingPathSeparators_UStr(&Name
);
949 InitializeObjectAttributes(&ObjectAttributes
,
951 OBJ_CASE_INSENSITIVE
,
955 Status
= NtOpenFile(&FileHandle
,
956 GENERIC_READ
| SYNCHRONIZE
,
960 FILE_SYNCHRONOUS_IO_NONALERT
);
961 if (!NT_SUCCESS(Status
))
963 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
967 /* Read current boot sector into buffer */
968 FileOffset
.QuadPart
= 0ULL;
969 Status
= NtReadFile(FileHandle
,
979 if (!NT_SUCCESS(Status
))
981 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
985 /* Allocate buffer for new bootsector */
986 NewBootSector
= RtlAllocateHeap(ProcessHeap
,
989 if (NewBootSector
== NULL
)
991 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
992 return STATUS_INSUFFICIENT_RESOURCES
;
995 /* Read new bootsector from SrcPath */
996 RtlInitUnicodeString(&Name
, SrcPath
);
998 InitializeObjectAttributes(&ObjectAttributes
,
1000 OBJ_CASE_INSENSITIVE
,
1004 Status
= NtOpenFile(&FileHandle
,
1005 GENERIC_READ
| SYNCHRONIZE
,
1009 FILE_SYNCHRONOUS_IO_NONALERT
);
1010 if (!NT_SUCCESS(Status
))
1012 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1013 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1017 Status
= NtReadFile(FileHandle
,
1026 NtClose(FileHandle
);
1027 if (!NT_SUCCESS(Status
))
1029 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1030 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1034 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1035 memcpy(&NewBootSector
->OemName
,
1036 &OrigBootSector
->OemName
,
1037 FIELD_OFFSET(FAT_BOOTSECTOR
, BootCodeAndData
) -
1038 FIELD_OFFSET(FAT_BOOTSECTOR
, OemName
));
1040 /* Free the original boot sector */
1041 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1043 /* Open the root partition - Remove any trailing backslash if needed */
1044 RtlInitUnicodeString(&Name
, RootPath
);
1045 TrimTrailingPathSeparators_UStr(&Name
);
1047 InitializeObjectAttributes(&ObjectAttributes
,
1049 OBJ_CASE_INSENSITIVE
,
1053 Status
= NtOpenFile(&FileHandle
,
1054 GENERIC_WRITE
| SYNCHRONIZE
,
1058 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1059 if (!NT_SUCCESS(Status
))
1061 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1062 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1066 /* Write new bootsector to RootPath */
1067 FileOffset
.QuadPart
= 0ULL;
1068 Status
= NtWriteFile(FileHandle
,
1077 NtClose(FileHandle
);
1079 /* Free the new boot sector */
1080 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1087 InstallFat16BootCode(
1088 IN PCWSTR SrcPath
, // FAT16 bootsector source file (on the installation medium)
1089 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
1090 IN HANDLE RootPartition
) // Partition holding the (old) FAT16 information
1093 UNICODE_STRING Name
;
1094 OBJECT_ATTRIBUTES ObjectAttributes
;
1095 IO_STATUS_BLOCK IoStatusBlock
;
1097 LARGE_INTEGER FileOffset
;
1098 PFAT_BOOTSECTOR OrigBootSector
;
1099 PFAT_BOOTSECTOR NewBootSector
;
1101 /* Allocate a buffer for the original bootsector */
1102 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1103 if (OrigBootSector
== NULL
)
1104 return STATUS_INSUFFICIENT_RESOURCES
;
1106 /* Read the current partition boot sector into the buffer */
1107 FileOffset
.QuadPart
= 0ULL;
1108 Status
= NtReadFile(RootPartition
,
1117 if (!NT_SUCCESS(Status
))
1119 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1123 /* Allocate a buffer for the new bootsector */
1124 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1125 if (NewBootSector
== NULL
)
1127 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1128 return STATUS_INSUFFICIENT_RESOURCES
;
1131 /* Read the new bootsector from SrcPath */
1132 RtlInitUnicodeString(&Name
, SrcPath
);
1133 InitializeObjectAttributes(&ObjectAttributes
,
1135 OBJ_CASE_INSENSITIVE
,
1139 Status
= NtOpenFile(&FileHandle
,
1140 GENERIC_READ
| SYNCHRONIZE
,
1144 FILE_SYNCHRONOUS_IO_NONALERT
);
1145 if (!NT_SUCCESS(Status
))
1147 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1148 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1152 FileOffset
.QuadPart
= 0ULL;
1153 Status
= NtReadFile(FileHandle
,
1162 NtClose(FileHandle
);
1163 if (!NT_SUCCESS(Status
))
1165 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1166 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1170 /* Adjust the bootsector (copy a part of the FAT16 BPB) */
1171 memcpy(&NewBootSector
->OemName
,
1172 &OrigBootSector
->OemName
,
1173 FIELD_OFFSET(FAT_BOOTSECTOR
, BootCodeAndData
) -
1174 FIELD_OFFSET(FAT_BOOTSECTOR
, OemName
));
1176 /* Free the original boot sector */
1177 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1179 /* Write the new bootsector to DstPath */
1180 FileOffset
.QuadPart
= 0ULL;
1181 Status
= NtWriteFile(DstPath
,
1191 /* Free the new boot sector */
1192 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1199 InstallFat16BootCodeToFile(
1205 UNICODE_STRING Name
;
1206 OBJECT_ATTRIBUTES ObjectAttributes
;
1207 IO_STATUS_BLOCK IoStatusBlock
;
1208 HANDLE PartitionHandle
, FileHandle
;
1211 * Open the root partition from which the boot sector
1212 * parameters will be obtained.
1213 * Remove any trailing backslash if needed.
1215 RtlInitUnicodeString(&Name
, RootPath
);
1216 TrimTrailingPathSeparators_UStr(&Name
);
1218 InitializeObjectAttributes(&ObjectAttributes
,
1220 OBJ_CASE_INSENSITIVE
,
1224 Status
= NtOpenFile(&PartitionHandle
,
1225 GENERIC_READ
| SYNCHRONIZE
,
1229 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1230 if (!NT_SUCCESS(Status
))
1233 /* Open or create the file where the new bootsector will be saved */
1234 RtlInitUnicodeString(&Name
, DstPath
);
1235 InitializeObjectAttributes(&ObjectAttributes
,
1237 OBJ_CASE_INSENSITIVE
,
1241 Status
= NtCreateFile(&FileHandle
,
1242 GENERIC_WRITE
| SYNCHRONIZE
,
1246 FILE_ATTRIBUTE_NORMAL
,
1249 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
1252 if (!NT_SUCCESS(Status
))
1254 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
1255 NtClose(PartitionHandle
);
1259 /* Install the FAT16 boot sector */
1260 Status
= InstallFat16BootCode(SrcPath
, FileHandle
, PartitionHandle
);
1262 /* Close the file and the partition */
1263 NtClose(FileHandle
);
1264 NtClose(PartitionHandle
);
1271 InstallFat16BootCodeToDisk(
1276 UNICODE_STRING Name
;
1277 OBJECT_ATTRIBUTES ObjectAttributes
;
1278 IO_STATUS_BLOCK IoStatusBlock
;
1279 HANDLE PartitionHandle
;
1282 * Open the root partition from which the boot sector parameters will be
1283 * obtained; this is also where we will write the updated boot sector.
1284 * Remove any trailing backslash if needed.
1286 RtlInitUnicodeString(&Name
, RootPath
);
1287 TrimTrailingPathSeparators_UStr(&Name
);
1289 InitializeObjectAttributes(&ObjectAttributes
,
1291 OBJ_CASE_INSENSITIVE
,
1295 Status
= NtOpenFile(&PartitionHandle
,
1296 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1300 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1301 if (!NT_SUCCESS(Status
))
1304 /* Install the FAT16 boot sector */
1305 Status
= InstallFat16BootCode(SrcPath
, PartitionHandle
, PartitionHandle
);
1307 /* Close the partition */
1308 NtClose(PartitionHandle
);
1316 InstallFat32BootCode(
1317 IN PCWSTR SrcPath
, // FAT32 bootsector source file (on the installation medium)
1318 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
1319 IN HANDLE RootPartition
) // Partition holding the (old) FAT32 information
1322 UNICODE_STRING Name
;
1323 OBJECT_ATTRIBUTES ObjectAttributes
;
1324 IO_STATUS_BLOCK IoStatusBlock
;
1326 LARGE_INTEGER FileOffset
;
1327 PFAT32_BOOTSECTOR OrigBootSector
;
1328 PFAT32_BOOTSECTOR NewBootSector
;
1329 USHORT BackupBootSector
;
1331 /* Allocate a buffer for the original bootsector */
1332 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1333 if (OrigBootSector
== NULL
)
1334 return STATUS_INSUFFICIENT_RESOURCES
;
1336 /* Read the current boot sector into the buffer */
1337 FileOffset
.QuadPart
= 0ULL;
1338 Status
= NtReadFile(RootPartition
,
1347 if (!NT_SUCCESS(Status
))
1349 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1353 /* Allocate a buffer for the new bootsector (2 sectors) */
1354 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, 2 * SECTORSIZE
);
1355 if (NewBootSector
== NULL
)
1357 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1358 return STATUS_INSUFFICIENT_RESOURCES
;
1361 /* Read the new bootsector from SrcPath */
1362 RtlInitUnicodeString(&Name
, SrcPath
);
1363 InitializeObjectAttributes(&ObjectAttributes
,
1365 OBJ_CASE_INSENSITIVE
,
1369 Status
= NtOpenFile(&FileHandle
,
1370 GENERIC_READ
| SYNCHRONIZE
,
1374 FILE_SYNCHRONOUS_IO_NONALERT
);
1375 if (!NT_SUCCESS(Status
))
1377 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1378 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1382 FileOffset
.QuadPart
= 0ULL;
1383 Status
= NtReadFile(FileHandle
,
1392 NtClose(FileHandle
);
1393 if (!NT_SUCCESS(Status
))
1395 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1396 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1400 /* Adjust the bootsector (copy a part of the FAT32 BPB) */
1401 memcpy(&NewBootSector
->OemName
,
1402 &OrigBootSector
->OemName
,
1403 FIELD_OFFSET(FAT32_BOOTSECTOR
, BootCodeAndData
) -
1404 FIELD_OFFSET(FAT32_BOOTSECTOR
, OemName
));
1407 * We know we copy the boot code to a file only when DstPath != RootPartition,
1408 * otherwise the boot code is copied to the specified root partition.
1410 if (DstPath
!= RootPartition
)
1412 /* Copy to a file: Disable the backup boot sector */
1413 NewBootSector
->BackupBootSector
= 0;
1417 /* Copy to a disk: Get the location of the backup boot sector */
1418 BackupBootSector
= OrigBootSector
->BackupBootSector
;
1421 /* Free the original boot sector */
1422 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1424 /* Write the first sector of the new bootcode to DstPath sector 0 */
1425 FileOffset
.QuadPart
= 0ULL;
1426 Status
= NtWriteFile(DstPath
,
1435 if (!NT_SUCCESS(Status
))
1437 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1438 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1442 if (DstPath
== RootPartition
)
1444 /* Copy to a disk: Write the backup boot sector */
1445 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
1447 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* SECTORSIZE
);
1448 Status
= NtWriteFile(DstPath
,
1457 if (!NT_SUCCESS(Status
))
1459 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1460 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1466 /* Write the second sector of the new bootcode to boot disk sector 14 */
1467 // FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1468 FileOffset
.QuadPart
= 14 * SECTORSIZE
;
1469 Status
= NtWriteFile(DstPath
, // or really RootPartition ???
1474 ((PUCHAR
)NewBootSector
+ SECTORSIZE
),
1478 if (!NT_SUCCESS(Status
))
1480 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1483 /* Free the new boot sector */
1484 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1491 InstallFat32BootCodeToFile(
1497 UNICODE_STRING Name
;
1498 OBJECT_ATTRIBUTES ObjectAttributes
;
1499 IO_STATUS_BLOCK IoStatusBlock
;
1500 HANDLE PartitionHandle
, FileHandle
;
1503 * Open the root partition from which the boot sector parameters
1505 * FIXME? It might be possible that we need to also open it for writing
1506 * access in case we really need to still write the second portion of
1507 * the boot sector ????
1509 * Remove any trailing backslash if needed.
1511 RtlInitUnicodeString(&Name
, RootPath
);
1512 TrimTrailingPathSeparators_UStr(&Name
);
1514 InitializeObjectAttributes(&ObjectAttributes
,
1516 OBJ_CASE_INSENSITIVE
,
1520 Status
= NtOpenFile(&PartitionHandle
,
1521 GENERIC_READ
| SYNCHRONIZE
,
1525 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1526 if (!NT_SUCCESS(Status
))
1529 /* Open or create the file where (the first sector of ????) the new bootsector will be saved */
1530 RtlInitUnicodeString(&Name
, DstPath
);
1531 InitializeObjectAttributes(&ObjectAttributes
,
1533 OBJ_CASE_INSENSITIVE
,
1537 Status
= NtCreateFile(&FileHandle
,
1538 GENERIC_WRITE
| SYNCHRONIZE
,
1542 FILE_ATTRIBUTE_NORMAL
,
1544 FILE_SUPERSEDE
, // FILE_OVERWRITE_IF, <- is used for FAT16
1545 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
1548 if (!NT_SUCCESS(Status
))
1550 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
1551 NtClose(PartitionHandle
);
1555 /* Install the FAT32 boot sector */
1556 Status
= InstallFat32BootCode(SrcPath
, FileHandle
, PartitionHandle
);
1558 /* Close the file and the partition */
1559 NtClose(FileHandle
);
1560 NtClose(PartitionHandle
);
1567 InstallFat32BootCodeToDisk(
1572 UNICODE_STRING Name
;
1573 OBJECT_ATTRIBUTES ObjectAttributes
;
1574 IO_STATUS_BLOCK IoStatusBlock
;
1575 HANDLE PartitionHandle
;
1578 * Open the root partition from which the boot sector parameters will be
1579 * obtained; this is also where we will write the updated boot sector.
1580 * Remove any trailing backslash if needed.
1582 RtlInitUnicodeString(&Name
, RootPath
);
1583 TrimTrailingPathSeparators_UStr(&Name
);
1585 InitializeObjectAttributes(&ObjectAttributes
,
1587 OBJ_CASE_INSENSITIVE
,
1591 Status
= NtOpenFile(&PartitionHandle
,
1592 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1596 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1597 if (!NT_SUCCESS(Status
))
1600 /* Install the FAT32 boot sector */
1601 Status
= InstallFat32BootCode(SrcPath
, PartitionHandle
, PartitionHandle
);
1603 /* Close the partition */
1604 NtClose(PartitionHandle
);
1611 InstallBtrfsBootCodeToDisk(
1616 UNICODE_STRING Name
;
1617 OBJECT_ATTRIBUTES ObjectAttributes
;
1618 IO_STATUS_BLOCK IoStatusBlock
;
1620 LARGE_INTEGER FileOffset
;
1621 // PEXT2_BOOTSECTOR OrigBootSector;
1622 PBTRFS_BOOTSECTOR NewBootSector
;
1623 // USHORT BackupBootSector;
1624 PARTITION_INFORMATION_EX PartInfo
;
1627 /* Allocate buffer for original bootsector */
1628 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1629 if (OrigBootSector
== NULL
)
1630 return STATUS_INSUFFICIENT_RESOURCES
;
1632 /* Open the root partition - Remove any trailing backslash if needed */
1633 RtlInitUnicodeString(&Name
, RootPath
);
1634 TrimTrailingPathSeparators_UStr(&Name
);
1636 InitializeObjectAttributes(&ObjectAttributes
,
1638 OBJ_CASE_INSENSITIVE
,
1642 Status
= NtOpenFile(&FileHandle
,
1643 GENERIC_READ
| SYNCHRONIZE
,
1647 FILE_SYNCHRONOUS_IO_NONALERT
);
1648 if (!NT_SUCCESS(Status
))
1650 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1654 /* Read current boot sector into buffer */
1655 FileOffset
.QuadPart
= 0ULL;
1656 Status
= NtReadFile(FileHandle
,
1665 NtClose(FileHandle
);
1666 if (!NT_SUCCESS(Status
))
1668 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1673 /* Allocate buffer for new bootsector */
1674 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(BTRFS_BOOTSECTOR
));
1675 if (NewBootSector
== NULL
)
1677 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1678 return STATUS_INSUFFICIENT_RESOURCES
;
1681 /* Read new bootsector from SrcPath */
1682 RtlInitUnicodeString(&Name
, SrcPath
);
1684 InitializeObjectAttributes(&ObjectAttributes
,
1686 OBJ_CASE_INSENSITIVE
,
1690 Status
= NtOpenFile(&FileHandle
,
1691 GENERIC_READ
| SYNCHRONIZE
,
1695 FILE_SYNCHRONOUS_IO_NONALERT
);
1696 if (!NT_SUCCESS(Status
))
1698 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1699 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1703 Status
= NtReadFile(FileHandle
,
1709 sizeof(BTRFS_BOOTSECTOR
),
1712 NtClose(FileHandle
);
1713 if (!NT_SUCCESS(Status
))
1715 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1716 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1721 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1722 memcpy(&NewBootSector
->OemName
,
1723 &OrigBootSector
->OemName
,
1724 FIELD_OFFSET(FAT32_BOOTSECTOR
, BootCodeAndData
) -
1725 FIELD_OFFSET(FAT32_BOOTSECTOR
, OemName
));
1727 /* Get the location of the backup boot sector */
1728 BackupBootSector
= OrigBootSector
->BackupBootSector
;
1730 /* Free the original boot sector */
1731 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1734 /* Open the root partition - Remove any trailing backslash if needed */
1735 RtlInitUnicodeString(&Name
, RootPath
);
1736 TrimTrailingPathSeparators_UStr(&Name
);
1738 InitializeObjectAttributes(&ObjectAttributes
,
1740 OBJ_CASE_INSENSITIVE
,
1744 Status
= NtOpenFile(&FileHandle
,
1745 GENERIC_WRITE
| SYNCHRONIZE
,
1749 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1750 if (!NT_SUCCESS(Status
))
1752 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1753 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1757 /* Obtaining partition info and writing it to bootsector */
1758 Status
= NtDeviceIoControlFile(FileHandle
,
1763 IOCTL_DISK_GET_PARTITION_INFO_EX
,
1768 if (!NT_SUCCESS(Status
))
1770 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status
);
1771 NtClose(FileHandle
);
1772 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1776 /* Write new bootsector to RootPath */
1778 NewBootSector
->PartitionStartLBA
= PartInfo
.StartingOffset
.QuadPart
/ SECTORSIZE
;
1780 /* Write sector 0 */
1781 FileOffset
.QuadPart
= 0ULL;
1782 Status
= NtWriteFile(FileHandle
,
1788 sizeof(BTRFS_BOOTSECTOR
),
1792 if (!NT_SUCCESS(Status
))
1794 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1795 NtClose(FileHandle
);
1796 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1800 /* Write backup boot sector */
1801 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
1803 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* SECTORSIZE
);
1804 Status
= NtWriteFile(FileHandle
,
1813 if (!NT_SUCCESS(Status
))
1815 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1816 NtClose(FileHandle
);
1817 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1822 /* Write sector 14 */
1823 FileOffset
.QuadPart
= 14 * SECTORSIZE
;
1824 Status
= NtWriteFile(FileHandle
,
1829 ((PUCHAR
)NewBootSector
+ SECTORSIZE
),
1833 if (!NT_SUCCESS(Status
))
1835 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1838 NtClose(FileHandle
);
1840 /* Free the new boot sector */
1841 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1849 InstallFatBootcodeToPartition(
1850 IN PUNICODE_STRING SystemRootPath
,
1851 IN PUNICODE_STRING SourceRootPath
,
1852 IN PUNICODE_STRING DestinationArcPath
,
1853 IN UCHAR PartitionType
)
1856 BOOLEAN DoesFreeLdrExist
;
1857 WCHAR SrcPath
[MAX_PATH
];
1858 WCHAR DstPath
[MAX_PATH
];
1860 /* FAT or FAT32 partition */
1861 DPRINT("System path: '%wZ'\n", SystemRootPath
);
1863 /* Copy FreeLoader to the system partition, always overwriting the older version */
1864 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
1865 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"freeldr.sys");
1867 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
1868 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
1869 if (!NT_SUCCESS(Status
))
1871 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
1875 /* Prepare for possibly updating 'freeldr.ini' */
1876 DoesFreeLdrExist
= DoesFileExist_2(SystemRootPath
->Buffer
, L
"freeldr.ini");
1877 if (DoesFreeLdrExist
)
1879 /* Update existing 'freeldr.ini' */
1880 DPRINT1("Update existing 'freeldr.ini'\n");
1881 Status
= UpdateFreeLoaderIni(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1882 if (!NT_SUCCESS(Status
))
1884 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
1889 /* Check for NT and other bootloaders */
1891 // FIXME: Check for Vista+ bootloader!
1892 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
1893 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
1894 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"NTLDR") == TRUE
||
1895 DoesFileExist_2(SystemRootPath
->Buffer
, L
"BOOT.INI") == TRUE
)
1897 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
1898 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
1900 /* Create or update 'freeldr.ini' */
1901 if (DoesFreeLdrExist
== FALSE
)
1903 /* Create new 'freeldr.ini' */
1904 DPRINT1("Create new 'freeldr.ini'\n");
1905 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1906 if (!NT_SUCCESS(Status
))
1908 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
1912 /* Install new bootcode into a file */
1913 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"bootsect.ros");
1915 if (PartitionType
== PARTITION_FAT32
||
1916 PartitionType
== PARTITION_FAT32_XINT13
)
1918 /* Install FAT32 bootcode */
1919 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat32.bin");
1921 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, DstPath
);
1922 Status
= InstallFat32BootCodeToFile(SrcPath
, DstPath
,
1923 SystemRootPath
->Buffer
);
1924 if (!NT_SUCCESS(Status
))
1926 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status
);
1932 /* Install FAT16 bootcode */
1933 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
1935 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath
, DstPath
);
1936 Status
= InstallFat16BootCodeToFile(SrcPath
, DstPath
,
1937 SystemRootPath
->Buffer
);
1938 if (!NT_SUCCESS(Status
))
1940 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status
);
1946 /* Update 'boot.ini' */
1947 /* Windows' NTLDR loads an external bootsector file when the specified drive
1948 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
1949 DPRINT1("Update 'boot.ini'\n");
1950 Status
= UpdateBootIni(SystemRootPath
->Buffer
,
1951 L
"C:\\bootsect.ros",
1953 if (!NT_SUCCESS(Status
))
1955 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status
);
1961 /* Non-NT bootloaders: install our own bootloader */
1966 PCWSTR BootPartition
;
1969 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
1970 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IOSYS.COM") == TRUE
||
1971 DoesFileExist_2(SystemRootPath
->Buffer
, L
"MSDOS.COM") == TRUE
)
1973 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
1975 Section
= L
"CPQDOS";
1976 Description
= L
"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
1978 BootPartition
= L
"1";
1979 BootSector
= L
"BOOTSECT.DOS";
1982 /* Search for Microsoft DOS or Windows 9x boot loader */
1983 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IO.SYS") == TRUE
||
1984 DoesFileExist_2(SystemRootPath
->Buffer
, L
"MSDOS.SYS") == TRUE
)
1987 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1990 Description
= L
"\"MS-DOS/Windows\"";
1992 BootPartition
= L
"1";
1993 BootSector
= L
"BOOTSECT.DOS";
1996 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
1997 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMIO.COM" ) == TRUE
|| // Some people refer to this file instead of IBMBIO.COM...
1998 DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMBIO.COM") == TRUE
||
1999 DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMDOS.COM") == TRUE
)
2001 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
2003 Section
= L
"IBMDOS";
2004 Description
= L
"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
2006 BootPartition
= L
"1";
2007 BootSector
= L
"BOOTSECT.DOS";
2010 /* Search for DR-DOS 3.x boot loader */
2011 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"DRBIOS.SYS") == TRUE
||
2012 DoesFileExist_2(SystemRootPath
->Buffer
, L
"DRBDOS.SYS") == TRUE
)
2014 DPRINT1("Found DR-DOS 3.x\n");
2017 Description
= L
"\"DR-DOS 3.x\"";
2019 BootPartition
= L
"1";
2020 BootSector
= L
"BOOTSECT.DOS";
2023 /* Search for Dell Real-Mode Kernel (DRMK) OS */
2024 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"DELLBIO.BIN") == TRUE
||
2025 DoesFileExist_2(SystemRootPath
->Buffer
, L
"DELLRMK.BIN") == TRUE
)
2027 DPRINT1("Found Dell Real-Mode Kernel OS\n");
2030 Description
= L
"\"Dell Real-Mode Kernel OS\"";
2032 BootPartition
= L
"1";
2033 BootSector
= L
"BOOTSECT.DOS";
2036 /* Search for MS OS/2 1.x */
2037 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BOOT.COM") == TRUE
||
2038 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BIO.COM" ) == TRUE
||
2039 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2DOS.COM" ) == TRUE
)
2041 DPRINT1("Found MS OS/2 1.x\n");
2044 Description
= L
"\"MS OS/2 1.x\"";
2046 BootPartition
= L
"1";
2047 BootSector
= L
"BOOTSECT.OS2";
2050 /* Search for MS or IBM OS/2 */
2051 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BOOT") == TRUE
||
2052 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2LDR" ) == TRUE
||
2053 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2KRNL") == TRUE
)
2055 DPRINT1("Found MS/IBM OS/2\n");
2057 Section
= L
"IBMOS2";
2058 Description
= L
"\"MS/IBM OS/2\"";
2060 BootPartition
= L
"1";
2061 BootSector
= L
"BOOTSECT.OS2";
2064 /* Search for FreeDOS boot loader */
2065 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"kernel.sys") == TRUE
)
2067 DPRINT1("Found FreeDOS boot loader\n");
2070 Description
= L
"\"FreeDOS\"";
2072 BootPartition
= L
"1";
2073 BootSector
= L
"BOOTSECT.DOS";
2077 /* No or unknown boot loader */
2078 DPRINT1("No or unknown boot loader found\n");
2080 Section
= L
"Unknown";
2081 Description
= L
"\"Unknown Operating System\"";
2083 BootPartition
= L
"1";
2084 BootSector
= L
"BOOTSECT.OLD";
2087 /* Create or update 'freeldr.ini' */
2088 if (DoesFreeLdrExist
== FALSE
)
2090 /* Create new 'freeldr.ini' */
2091 DPRINT1("Create new 'freeldr.ini'\n");
2093 if (IsThereAValidBootSector(SystemRootPath
->Buffer
))
2095 Status
= CreateFreeLoaderIniForReactOSAndBootSector(
2096 SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
,
2097 Section
, Description
,
2098 BootDrive
, BootPartition
, BootSector
);
2099 if (!NT_SUCCESS(Status
))
2101 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status
);
2105 /* Save current bootsector */
2106 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, BootSector
);
2108 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath
->Buffer
, DstPath
);
2109 Status
= SaveBootSector(SystemRootPath
->Buffer
, DstPath
, SECTORSIZE
);
2110 if (!NT_SUCCESS(Status
))
2112 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
2118 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2119 if (!NT_SUCCESS(Status
))
2121 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2126 /* Install new bootsector on the disk */
2127 if (PartitionType
== PARTITION_FAT32
||
2128 PartitionType
== PARTITION_FAT32_XINT13
)
2130 /* Install FAT32 bootcode */
2131 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat32.bin");
2133 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2134 Status
= InstallFat32BootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2135 if (!NT_SUCCESS(Status
))
2137 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status
);
2143 /* Install FAT16 bootcode */
2144 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
2146 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2147 Status
= InstallFat16BootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2148 if (!NT_SUCCESS(Status
))
2150 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status
);
2157 return STATUS_SUCCESS
;
2162 InstallBtrfsBootcodeToPartition(
2163 IN PUNICODE_STRING SystemRootPath
,
2164 IN PUNICODE_STRING SourceRootPath
,
2165 IN PUNICODE_STRING DestinationArcPath
,
2166 IN UCHAR PartitionType
)
2169 BOOLEAN DoesFreeLdrExist
;
2170 WCHAR SrcPath
[MAX_PATH
];
2171 WCHAR DstPath
[MAX_PATH
];
2173 /* BTRFS partition */
2174 DPRINT("System path: '%wZ'\n", SystemRootPath
);
2176 /* Copy FreeLoader to the system partition, always overwriting the older version */
2177 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
2178 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"freeldr.sys");
2180 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2181 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
2182 if (!NT_SUCCESS(Status
))
2184 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2188 /* Prepare for possibly updating 'freeldr.ini' */
2189 DoesFreeLdrExist
= DoesFileExist_2(SystemRootPath
->Buffer
, L
"freeldr.ini");
2190 if (DoesFreeLdrExist
)
2192 /* Update existing 'freeldr.ini' */
2193 DPRINT1("Update existing 'freeldr.ini'\n");
2194 Status
= UpdateFreeLoaderIni(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2195 if (!NT_SUCCESS(Status
))
2197 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
2202 /* Check for *nix bootloaders */
2204 /* Create or update 'freeldr.ini' */
2205 if (DoesFreeLdrExist
== FALSE
)
2207 /* Create new 'freeldr.ini' */
2208 DPRINT1("Create new 'freeldr.ini'\n");
2210 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
2211 DPRINT1("*nix or unknown boot loader found\n");
2213 if (IsThereAValidBootSector(SystemRootPath
->Buffer
))
2215 PCWSTR BootSector
= L
"BOOTSECT.OLD";
2217 Status
= CreateFreeLoaderIniForReactOSAndBootSector(
2218 SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
,
2219 L
"Linux", L
"\"Linux\"",
2220 L
"hd0", L
"1", BootSector
);
2221 if (!NT_SUCCESS(Status
))
2223 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status
);
2227 /* Save current bootsector */
2228 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, BootSector
);
2230 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath
->Buffer
, DstPath
);
2231 Status
= SaveBootSector(SystemRootPath
->Buffer
, DstPath
, sizeof(BTRFS_BOOTSECTOR
));
2232 if (!NT_SUCCESS(Status
))
2234 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
2240 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2241 if (!NT_SUCCESS(Status
))
2243 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2248 /* Install new bootsector on the disk */
2249 // if (PartitionType == PARTITION_EXT2)
2251 /* Install BTRFS bootcode */
2252 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\btrfs.bin");
2254 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2255 Status
= InstallBtrfsBootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2256 if (!NT_SUCCESS(Status
))
2258 DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n", Status
);
2264 return STATUS_SUCCESS
;
2269 InstallVBRToPartition(
2270 IN PUNICODE_STRING SystemRootPath
,
2271 IN PUNICODE_STRING SourceRootPath
,
2272 IN PUNICODE_STRING DestinationArcPath
,
2273 IN UCHAR PartitionType
)
2275 switch (PartitionType
)
2277 case PARTITION_FAT_12
:
2278 case PARTITION_FAT_16
:
2279 case PARTITION_HUGE
:
2280 case PARTITION_XINT13
:
2281 case PARTITION_FAT32
:
2282 case PARTITION_FAT32_XINT13
:
2284 return InstallFatBootcodeToPartition(SystemRootPath
,
2290 case PARTITION_LINUX
:
2292 return InstallBtrfsBootcodeToPartition(SystemRootPath
,
2299 DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
2303 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType
);
2307 return STATUS_UNSUCCESSFUL
;
2312 InstallFatBootcodeToFloppy(
2313 IN PUNICODE_STRING SourceRootPath
,
2314 IN PUNICODE_STRING DestinationArcPath
)
2318 UNICODE_STRING FloppyDevice
= RTL_CONSTANT_STRING(L
"\\Device\\Floppy0\\");
2319 WCHAR SrcPath
[MAX_PATH
];
2320 WCHAR DstPath
[MAX_PATH
];
2322 /* Verify that the floppy disk is accessible */
2323 if (DoesDirExist(NULL
, FloppyDevice
.Buffer
) == FALSE
)
2324 return STATUS_DEVICE_NOT_READY
;
2326 /* Format the floppy disk */
2327 FatFS
= GetFileSystemByName(L
"FAT");
2330 DPRINT1("FAT FS non existent on this system?!\n");
2331 return STATUS_NOT_SUPPORTED
;
2333 Status
= FatFS
->FormatFunc(&FloppyDevice
,
2339 if (!NT_SUCCESS(Status
))
2341 DPRINT1("VfatFormat() failed (Status %lx)\n", Status
);
2345 /* Copy FreeLoader to the boot partition */
2346 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
2347 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, FloppyDevice
.Buffer
, L
"freeldr.sys");
2349 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2350 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
2351 if (!NT_SUCCESS(Status
))
2353 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2357 /* Create new 'freeldr.ini' */
2358 DPRINT("Create new 'freeldr.ini'\n");
2359 Status
= CreateFreeLoaderIniForReactOS(FloppyDevice
.Buffer
, DestinationArcPath
->Buffer
);
2360 if (!NT_SUCCESS(Status
))
2362 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2366 /* Install FAT12 boosector */
2367 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
2368 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 1, FloppyDevice
.Buffer
);
2370 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath
, DstPath
);
2371 Status
= InstallFat12BootCodeToFloppy(SrcPath
, DstPath
);
2372 if (!NT_SUCCESS(Status
))
2374 DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n", Status
);
2378 return STATUS_SUCCESS
;