1 /* 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 6 * PROGRAMMERS: ... 7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr) 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "precomp.h" 13 14 #include "bldrsup.h" 15 #include "filesup.h" 16 #include "partlist.h" 17 #include "bootcode.h" 18 #include "fsutil.h" 19 20 #include "setuplib.h" // HAXX for IsUnattendedSetup!! 21 22 #include "bootsup.h" 23 24 #define NDEBUG 25 #include <debug.h> 26 27 /* 28 * BIG FIXME!! 29 * =========== 30 * 31 * bootsup.c can deal with MBR code (actually it'll have at some point 32 * to share or give it to partlist.c, because when we'll support GPT disks, 33 * things will change a bit). 34 * And, bootsup.c can manage initializing / adding boot entries into NTLDR 35 * and FREELDR, and installing the latter, and saving the old MBR / boot 36 * sectors in files. 37 */ 38 39 /* FUNCTIONS ****************************************************************/ 40 41 static VOID 42 TrimTrailingPathSeparators_UStr( 43 IN OUT PUNICODE_STRING UnicodeString) 44 { 45 while (UnicodeString->Length >= sizeof(WCHAR) && 46 UnicodeString->Buffer[UnicodeString->Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR) 47 { 48 UnicodeString->Length -= sizeof(WCHAR); 49 } 50 } 51 52 53 static VOID 54 CreateFreeLoaderReactOSEntries( 55 IN PVOID BootStoreHandle, 56 IN PCWSTR ArcPath) 57 { 58 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)]; 59 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; 60 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; 61 BOOT_STORE_OPTIONS BootOptions; 62 63 BootEntry->Version = FreeLdr; 64 BootEntry->BootFilePath = NULL; 65 66 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS); 67 RtlCopyMemory(Options->Signature, 68 NTOS_OPTIONS_SIGNATURE, 69 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)); 70 71 Options->OsLoadPath = ArcPath; 72 73 /* ReactOS */ 74 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS"); 75 BootEntry->FriendlyName = L"\"ReactOS\""; 76 Options->OsLoadOptions = L"/FASTDETECT"; 77 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS")); 78 79 /* ReactOS_Debug */ 80 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug"); 81 BootEntry->FriendlyName = L"\"ReactOS (Debug)\""; 82 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS"; 83 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Debug")); 84 85 #ifdef _WINKD_ 86 /* ReactOS_VBoxDebug */ 87 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug"); 88 BootEntry->FriendlyName = L"\"ReactOS (VBox Debug)\""; 89 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=VBOX /SOS"; 90 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_VBoxDebug")); 91 #endif 92 #if DBG 93 #ifndef _WINKD_ 94 /* ReactOS_KdSerial */ 95 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial"); 96 BootEntry->FriendlyName = L"\"ReactOS (RosDbg)\""; 97 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL"; 98 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_KdSerial")); 99 #endif 100 101 /* ReactOS_Screen */ 102 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen"); 103 BootEntry->FriendlyName = L"\"ReactOS (Screen)\""; 104 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=SCREEN /SOS"; 105 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Screen")); 106 107 /* ReactOS_LogFile */ 108 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile"); 109 BootEntry->FriendlyName = L"\"ReactOS (Log file)\""; 110 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=FILE /SOS"; 111 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_LogFile")); 112 113 /* ReactOS_Ram */ 114 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram"); 115 BootEntry->FriendlyName = L"\"ReactOS (RAM Disk)\""; 116 Options->OsLoadPath = L"ramdisk(0)\\ReactOS"; 117 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256"; 118 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Ram")); 119 120 /* ReactOS_EMS */ 121 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS"); 122 BootEntry->FriendlyName = L"\"ReactOS (Emergency Management Services)\""; 123 Options->OsLoadPath = ArcPath; 124 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200"; 125 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_EMS")); 126 #endif 127 128 129 /* DefaultOS=ReactOS */ 130 #if DBG && !defined(_WINKD_) 131 if (IsUnattendedSetup) 132 { 133 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial"); 134 } 135 else 136 #endif 137 { 138 #if DBG 139 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_Debug"); 140 #else 141 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS"); 142 #endif 143 } 144 145 #if DBG 146 if (IsUnattendedSetup) 147 #endif 148 { 149 /* Timeout=0 for unattended or non debug */ 150 BootOptions.Timeout = 0; 151 } 152 #if DBG 153 else 154 { 155 /* Timeout=10 */ 156 BootOptions.Timeout = 10; 157 } 158 #endif 159 160 BootOptions.Version = FreeLdr; 161 SetBootStoreOptions(BootStoreHandle, &BootOptions, 2 | 1); 162 } 163 164 static NTSTATUS 165 CreateFreeLoaderIniForReactOS( 166 IN PCWSTR IniPath, 167 IN PCWSTR ArcPath) 168 { 169 NTSTATUS Status; 170 PVOID BootStoreHandle; 171 172 /* Initialize the INI file and create the common FreeLdr sections */ 173 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE); 174 if (!NT_SUCCESS(Status)) 175 return Status; 176 177 /* Add the ReactOS entries */ 178 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath); 179 180 /* Close the INI file */ 181 CloseBootStore(BootStoreHandle); 182 return STATUS_SUCCESS; 183 } 184 185 static NTSTATUS 186 CreateFreeLoaderIniForReactOSAndBootSector( 187 IN PCWSTR IniPath, 188 IN PCWSTR ArcPath, 189 IN PCWSTR Section, 190 IN PCWSTR Description, 191 IN PCWSTR BootDrive, 192 IN PCWSTR BootPartition, 193 IN PCWSTR BootSector) 194 { 195 NTSTATUS Status; 196 PVOID BootStoreHandle; 197 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOT_SECTOR_OPTIONS)]; 198 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; 199 PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions; 200 201 /* Initialize the INI file and create the common FreeLdr sections */ 202 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE); 203 if (!NT_SUCCESS(Status)) 204 return Status; 205 206 /* Add the ReactOS entries */ 207 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath); 208 209 BootEntry->Version = FreeLdr; 210 BootEntry->BootFilePath = NULL; 211 212 BootEntry->OsOptionsLength = sizeof(BOOT_SECTOR_OPTIONS); 213 RtlCopyMemory(Options->Signature, 214 BOOT_SECTOR_OPTIONS_SIGNATURE, 215 RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS, Signature)); 216 217 Options->Drive = BootDrive; 218 Options->Partition = BootPartition; 219 Options->BootSectorFileName = BootSector; 220 221 // BootEntry->BootEntryKey = MAKESTRKEY(Section); 222 BootEntry->FriendlyName = Description; 223 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section)); 224 225 /* Close the INI file */ 226 CloseBootStore(BootStoreHandle); 227 return STATUS_SUCCESS; 228 } 229 230 // 231 // I think this function can be generalizable as: 232 // "find the corresponding 'ReactOS' boot entry in this loader config file 233 // (here abstraction comes there), and if none, add a new one". 234 // 235 236 typedef struct _ENUM_REACTOS_ENTRIES_DATA 237 { 238 ULONG i; 239 BOOLEAN UseExistingEntry; 240 PCWSTR ArcPath; 241 WCHAR SectionName[80]; 242 WCHAR OsName[80]; 243 } ENUM_REACTOS_ENTRIES_DATA, *PENUM_REACTOS_ENTRIES_DATA; 244 245 // PENUM_BOOT_ENTRIES_ROUTINE 246 static NTSTATUS 247 NTAPI 248 EnumerateReactOSEntries( 249 IN BOOT_STORE_TYPE Type, 250 IN PBOOT_STORE_ENTRY BootEntry, 251 IN PVOID Parameter OPTIONAL) 252 { 253 NTSTATUS Status; 254 PENUM_REACTOS_ENTRIES_DATA Data = (PENUM_REACTOS_ENTRIES_DATA)Parameter; 255 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; 256 WCHAR SystemPath[MAX_PATH]; 257 258 /* We have a boot entry */ 259 260 /* Check for supported boot type "Windows2003" */ 261 if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) || 262 RtlCompareMemory(&BootEntry->OsOptions /* Signature */, 263 NTOS_OPTIONS_SIGNATURE, 264 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)) != 265 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)) 266 { 267 /* This is not a ReactOS entry */ 268 // DPRINT(" An installation '%S' of unsupported type '%S'\n", 269 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a"); 270 DPRINT(" An installation '%S' of unsupported type %lu\n", 271 BootEntry->FriendlyName, BootEntry->OsOptionsLength); 272 /* Continue the enumeration */ 273 goto SkipThisEntry; 274 } 275 276 /* BootType is Windows2003, now check OsLoadPath */ 277 if (!Options->OsLoadPath || !*Options->OsLoadPath) 278 { 279 /* Certainly not a ReactOS installation */ 280 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName); 281 /* Continue the enumeration */ 282 goto SkipThisEntry; 283 } 284 285 if (_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0) 286 { 287 /* Not found, retry with a quoted path */ 288 Status = RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath); 289 if (!NT_SUCCESS(Status) || _wcsicmp(Options->OsLoadPath, SystemPath) != 0) 290 { 291 /* 292 * This entry is a ReactOS entry, but the SystemRoot 293 * does not match the one we are looking for. 294 */ 295 /* Continue the enumeration */ 296 goto SkipThisEntry; 297 } 298 } 299 300 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n", 301 BootEntry->FriendlyName, Options->OsLoadPath); 302 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n", 303 // BootEntry->FriendlyName, Options->OsLoadPath); 304 305 DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath); 306 307 Data->UseExistingEntry = TRUE; 308 RtlStringCchCopyW(Data->OsName, ARRAYSIZE(Data->OsName), BootEntry->FriendlyName); 309 310 /* We have found our entry, stop the enumeration now! */ 311 return STATUS_NO_MORE_ENTRIES; 312 313 SkipThisEntry: 314 Data->UseExistingEntry = FALSE; 315 if (Type == FreeLdr && wcscmp(Data->SectionName, (PWSTR)BootEntry->BootEntryKey)== 0) 316 { 317 RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName), 318 L"ReactOS_%lu", Data->i); 319 RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName), 320 L"\"ReactOS %lu\"", Data->i); 321 Data->i++; 322 } 323 return STATUS_SUCCESS; 324 } 325 326 static 327 NTSTATUS 328 UpdateFreeLoaderIni( 329 IN PCWSTR IniPath, 330 IN PCWSTR ArcPath) 331 { 332 NTSTATUS Status; 333 PVOID BootStoreHandle; 334 ENUM_REACTOS_ENTRIES_DATA Data; 335 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)]; 336 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; 337 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; 338 339 /* Open the INI file */ 340 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, /*TRUE*/ FALSE); 341 if (!NT_SUCCESS(Status)) 342 return Status; 343 344 /* Find an existing usable or an unused section name */ 345 Data.UseExistingEntry = TRUE; 346 Data.i = 1; 347 Data.ArcPath = ArcPath; 348 RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS"); 349 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\""); 350 351 // 352 // FIXME: We temporarily use EnumerateBootStoreEntries, until 353 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented. 354 // 355 Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data); 356 357 /* Create a new "ReactOS" entry if there is none already existing that suits us */ 358 if (!Data.UseExistingEntry) 359 { 360 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i); 361 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i); 362 363 BootEntry->Version = FreeLdr; 364 BootEntry->BootFilePath = NULL; 365 366 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS); 367 RtlCopyMemory(Options->Signature, 368 NTOS_OPTIONS_SIGNATURE, 369 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)); 370 371 Options->OsLoadPath = ArcPath; 372 373 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName); 374 BootEntry->FriendlyName = Data.OsName; 375 Options->OsLoadOptions = NULL; // L""; 376 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName)); 377 } 378 379 /* Close the INI file */ 380 CloseBootStore(BootStoreHandle); 381 return STATUS_SUCCESS; 382 } 383 384 static 385 NTSTATUS 386 UpdateBootIni( 387 IN PCWSTR IniPath, 388 IN PCWSTR EntryName, // ~= ArcPath 389 IN PCWSTR EntryValue) 390 { 391 NTSTATUS Status; 392 PVOID BootStoreHandle; 393 ENUM_REACTOS_ENTRIES_DATA Data; 394 395 // NOTE: Technically it would be "BootSector"... 396 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)]; 397 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; 398 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; 399 400 /* Open the INI file */ 401 Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr, FALSE); 402 if (!NT_SUCCESS(Status)) 403 return Status; 404 405 /* Find an existing usable or an unused section name */ 406 Data.UseExistingEntry = TRUE; 407 // Data.i = 1; 408 Data.ArcPath = EntryName; 409 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS"); 410 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\""); 411 412 // 413 // FIXME: We temporarily use EnumerateBootStoreEntries, until 414 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented. 415 // 416 Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data); 417 418 /* If either the key was not found, or contains something else, add a new one */ 419 if (!Data.UseExistingEntry /* || 420 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */) 421 { 422 BootEntry->Version = NtLdr; 423 BootEntry->BootFilePath = NULL; 424 425 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS); 426 RtlCopyMemory(Options->Signature, 427 NTOS_OPTIONS_SIGNATURE, 428 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)); 429 430 Options->OsLoadPath = EntryName; 431 432 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName); 433 // BootEntry->FriendlyName = Data.OsName; 434 BootEntry->FriendlyName = EntryValue; 435 Options->OsLoadOptions = NULL; // L""; 436 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/)); 437 } 438 439 /* Close the INI file */ 440 CloseBootStore(BootStoreHandle); 441 return STATUS_SUCCESS; // Status; 442 } 443 444 445 static 446 BOOLEAN 447 IsThereAValidBootSector( 448 IN PCWSTR RootPath) 449 { 450 /* 451 * We first demand that the bootsector has a valid signature at its end. 452 * We then check the first 3 bytes (as a ULONG) of the bootsector for a 453 * potential "valid" instruction (the BIOS starts execution of the bootsector 454 * at its beginning). Currently this criterium is that this ULONG must be 455 * non-zero. If both these tests pass, then the bootsector is valid; otherwise 456 * it is invalid and certainly needs to be overwritten. 457 */ 458 459 BOOLEAN IsValid = FALSE; 460 NTSTATUS Status; 461 UNICODE_STRING RootPartition; 462 BOOTCODE BootSector = {0}; 463 464 /* Allocate and read the root partition bootsector. 465 * Remove any trailing backslash if needed. */ 466 RtlInitUnicodeString(&RootPartition, RootPath); 467 TrimTrailingPathSeparators_UStr(&RootPartition); 468 Status = ReadBootCodeFromFile(&BootSector, &RootPartition, SECTORSIZE); 469 if (!NT_SUCCESS(Status)) 470 return FALSE; 471 472 /* Check for the existence of the bootsector signature */ 473 IsValid = (*(PUSHORT)((PUCHAR)BootSector.BootCode + 0x1FE) == 0xAA55); 474 if (IsValid) 475 { 476 /* Check for the first instruction encoded on three bytes */ 477 IsValid = (((*(PULONG)BootSector.BootCode) & 0x00FFFFFF) != 0x00000000); 478 } 479 480 /* Free the bootsector and return */ 481 FreeBootCode(&BootSector); 482 return IsValid; 483 } 484 485 static 486 NTSTATUS 487 SaveBootSector( 488 IN PCWSTR RootPath, 489 IN PCWSTR DstPath, 490 IN ULONG Length) 491 { 492 NTSTATUS Status; 493 UNICODE_STRING Name; 494 OBJECT_ATTRIBUTES ObjectAttributes; 495 IO_STATUS_BLOCK IoStatusBlock; 496 HANDLE FileHandle; 497 // LARGE_INTEGER FileOffset; 498 BOOTCODE BootSector = {0}; 499 500 /* Allocate and read the root partition bootsector. 501 * Remove any trailing backslash if needed. */ 502 RtlInitUnicodeString(&Name, RootPath); 503 TrimTrailingPathSeparators_UStr(&Name); 504 Status = ReadBootCodeFromFile(&BootSector, &Name, Length); 505 if (!NT_SUCCESS(Status)) 506 return Status; 507 508 /* Write the bootsector to DstPath */ 509 RtlInitUnicodeString(&Name, DstPath); 510 InitializeObjectAttributes(&ObjectAttributes, 511 &Name, 512 OBJ_CASE_INSENSITIVE, 513 NULL, 514 NULL); 515 516 Status = NtCreateFile(&FileHandle, 517 GENERIC_WRITE | SYNCHRONIZE, 518 &ObjectAttributes, 519 &IoStatusBlock, 520 NULL, 521 FILE_ATTRIBUTE_NORMAL, 522 0, 523 FILE_SUPERSEDE, 524 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, 525 NULL, 526 0); 527 if (!NT_SUCCESS(Status)) 528 { 529 FreeBootCode(&BootSector); 530 return Status; 531 } 532 533 Status = NtWriteFile(FileHandle, 534 NULL, 535 NULL, 536 NULL, 537 &IoStatusBlock, 538 BootSector.BootCode, 539 BootSector.Length, 540 NULL, 541 NULL); 542 NtClose(FileHandle); 543 544 /* Free the bootsector and return */ 545 FreeBootCode(&BootSector); 546 return Status; 547 } 548 549 550 static 551 NTSTATUS 552 InstallBootCodeToDisk( 553 IN PCWSTR SrcPath, 554 IN PCWSTR RootPath, 555 IN PFS_INSTALL_BOOTCODE InstallBootCode) 556 { 557 NTSTATUS Status, LockStatus; 558 UNICODE_STRING Name; 559 OBJECT_ATTRIBUTES ObjectAttributes; 560 IO_STATUS_BLOCK IoStatusBlock; 561 HANDLE PartitionHandle; 562 563 /* 564 * Open the root partition from which the bootcode (MBR, VBR) parameters 565 * will be obtained; this is also where we will write the updated bootcode. 566 * Remove any trailing backslash if needed. 567 */ 568 RtlInitUnicodeString(&Name, RootPath); 569 TrimTrailingPathSeparators_UStr(&Name); 570 571 InitializeObjectAttributes(&ObjectAttributes, 572 &Name, 573 OBJ_CASE_INSENSITIVE, 574 NULL, 575 NULL); 576 577 Status = NtOpenFile(&PartitionHandle, 578 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 579 &ObjectAttributes, 580 &IoStatusBlock, 581 FILE_SHARE_READ | FILE_SHARE_WRITE, 582 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */); 583 if (!NT_SUCCESS(Status)) 584 return Status; 585 586 /* Lock the volume */ 587 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0); 588 if (!NT_SUCCESS(LockStatus)) 589 { 590 DPRINT1("Unable to lock the volume before installing boot code. Status 0x%08x. Expect problems.\n", LockStatus); 591 } 592 593 /* Install the bootcode (MBR, VBR) */ 594 Status = InstallBootCode(SrcPath, PartitionHandle, PartitionHandle); 595 596 /* dismount & Unlock the volume */ 597 if (NT_SUCCESS(LockStatus)) 598 { 599 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); 600 if (!NT_SUCCESS(LockStatus)) 601 { 602 DPRINT1("Unable to dismount the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus); 603 } 604 605 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0); 606 if (!NT_SUCCESS(LockStatus)) 607 { 608 DPRINT1("Unable to unlock the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus); 609 } 610 } 611 612 /* Close the partition */ 613 NtClose(PartitionHandle); 614 615 return Status; 616 } 617 618 static 619 NTSTATUS 620 InstallBootCodeToFile( 621 IN PCWSTR SrcPath, 622 IN PCWSTR DstPath, 623 IN PCWSTR RootPath, 624 IN PFS_INSTALL_BOOTCODE InstallBootCode) 625 { 626 NTSTATUS Status; 627 UNICODE_STRING Name; 628 OBJECT_ATTRIBUTES ObjectAttributes; 629 IO_STATUS_BLOCK IoStatusBlock; 630 HANDLE PartitionHandle, FileHandle; 631 632 /* 633 * Open the root partition from which the bootcode (MBR, VBR) 634 * parameters will be obtained. 635 * 636 * FIXME? It might be possible that we need to also open it for writing 637 * access in case we really need to still write the second portion of 638 * the boot sector ???? 639 * 640 * Remove any trailing backslash if needed. 641 */ 642 RtlInitUnicodeString(&Name, RootPath); 643 TrimTrailingPathSeparators_UStr(&Name); 644 645 InitializeObjectAttributes(&ObjectAttributes, 646 &Name, 647 OBJ_CASE_INSENSITIVE, 648 NULL, 649 NULL); 650 651 Status = NtOpenFile(&PartitionHandle, 652 GENERIC_READ | SYNCHRONIZE, 653 &ObjectAttributes, 654 &IoStatusBlock, 655 FILE_SHARE_READ | FILE_SHARE_WRITE, 656 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */); 657 if (!NT_SUCCESS(Status)) 658 return Status; 659 660 /* Open or create the file where the new bootsector will be saved */ 661 RtlInitUnicodeString(&Name, DstPath); 662 InitializeObjectAttributes(&ObjectAttributes, 663 &Name, 664 OBJ_CASE_INSENSITIVE, 665 NULL, 666 NULL); 667 668 Status = NtCreateFile(&FileHandle, 669 GENERIC_WRITE | SYNCHRONIZE, 670 &ObjectAttributes, 671 &IoStatusBlock, 672 NULL, 673 FILE_ATTRIBUTE_NORMAL, 674 0, 675 FILE_SUPERSEDE, // FILE_OVERWRITE_IF 676 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, 677 NULL, 678 0); 679 if (!NT_SUCCESS(Status)) 680 { 681 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status); 682 NtClose(PartitionHandle); 683 return Status; 684 } 685 686 /* Install the bootcode (MBR, VBR) */ 687 Status = InstallBootCode(SrcPath, FileHandle, PartitionHandle); 688 689 /* Close the file and the partition */ 690 NtClose(FileHandle); 691 NtClose(PartitionHandle); 692 693 return Status; 694 } 695 696 697 static 698 NTSTATUS 699 InstallMbrBootCode( 700 IN PCWSTR SrcPath, // MBR source file (on the installation medium) 701 IN HANDLE DstPath, // Where to save the bootsector built from the source + disk information 702 IN HANDLE DiskHandle) // Disk holding the (old) MBR information 703 { 704 NTSTATUS Status; 705 UNICODE_STRING Name; 706 IO_STATUS_BLOCK IoStatusBlock; 707 LARGE_INTEGER FileOffset; 708 BOOTCODE OrigBootSector = {0}; 709 BOOTCODE NewBootSector = {0}; 710 711 C_ASSERT(sizeof(PARTITION_SECTOR) == SECTORSIZE); 712 713 /* Allocate and read the current original MBR bootsector */ 714 Status = ReadBootCodeByHandle(&OrigBootSector, 715 DiskHandle, 716 sizeof(PARTITION_SECTOR)); 717 if (!NT_SUCCESS(Status)) 718 return Status; 719 720 /* Allocate and read the new bootsector from SrcPath */ 721 RtlInitUnicodeString(&Name, SrcPath); 722 Status = ReadBootCodeFromFile(&NewBootSector, 723 &Name, 724 sizeof(PARTITION_SECTOR)); 725 if (!NT_SUCCESS(Status)) 726 { 727 FreeBootCode(&OrigBootSector); 728 return Status; 729 } 730 731 /* 732 * Copy the disk signature, the reserved fields and 733 * the partition table from the old MBR to the new one. 734 */ 735 RtlCopyMemory(&((PPARTITION_SECTOR)NewBootSector.BootCode)->Signature, 736 &((PPARTITION_SECTOR)OrigBootSector.BootCode)->Signature, 737 sizeof(PARTITION_SECTOR) - 738 FIELD_OFFSET(PARTITION_SECTOR, Signature) 739 /* Length of partition table */); 740 741 /* Free the original bootsector */ 742 FreeBootCode(&OrigBootSector); 743 744 /* Write the new bootsector to DstPath */ 745 FileOffset.QuadPart = 0ULL; 746 Status = NtWriteFile(DstPath, 747 NULL, 748 NULL, 749 NULL, 750 &IoStatusBlock, 751 NewBootSector.BootCode, 752 NewBootSector.Length, 753 &FileOffset, 754 NULL); 755 756 /* Free the new bootsector */ 757 FreeBootCode(&NewBootSector); 758 759 return Status; 760 } 761 762 NTSTATUS 763 InstallMbrBootCodeToDisk( 764 IN PUNICODE_STRING SystemRootPath, 765 IN PUNICODE_STRING SourceRootPath, 766 IN PCWSTR DestinationDevicePathBuffer) 767 { 768 NTSTATUS Status; 769 WCHAR SourceMbrPathBuffer[MAX_PATH]; 770 WCHAR DstPath[MAX_PATH]; 771 772 #if 0 773 /* 774 * The DestinationDevicePathBuffer parameter has been built with 775 * the following instruction by the caller; I'm not yet sure whether 776 * I actually want this function to build the path instead, hence 777 * I keep this code here but disabled for now... 778 */ 779 WCHAR DestinationDevicePathBuffer[MAX_PATH]; 780 RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer), 781 L"\\Device\\Harddisk%d\\Partition0", 782 DiskNumber); 783 #endif 784 785 CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2, 786 SourceRootPath->Buffer, L"\\loader\\dosmbr.bin"); 787 788 if (IsThereAValidBootSector(DestinationDevicePathBuffer)) 789 { 790 /* Save current MBR */ 791 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, 792 SystemRootPath->Buffer, L"mbr.old"); 793 794 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath); 795 Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR)); 796 if (!NT_SUCCESS(Status)) 797 { 798 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); 799 // Don't care if we succeeded or not saving the old MBR, just go ahead. 800 } 801 } 802 803 DPRINT1("Install MBR bootcode: %S ==> %S\n", 804 SourceMbrPathBuffer, DestinationDevicePathBuffer); 805 806 /* Install the MBR */ 807 return InstallBootCodeToDisk(SourceMbrPathBuffer, 808 DestinationDevicePathBuffer, 809 InstallMbrBootCode); 810 } 811 812 813 static 814 NTSTATUS 815 InstallFatBootcodeToPartition( 816 IN PUNICODE_STRING SystemRootPath, 817 IN PUNICODE_STRING SourceRootPath, 818 IN PUNICODE_STRING DestinationArcPath, 819 IN PCWSTR FileSystemName) 820 { 821 NTSTATUS Status; 822 BOOLEAN DoesFreeLdrExist; 823 WCHAR SrcPath[MAX_PATH]; 824 WCHAR DstPath[MAX_PATH]; 825 826 /* FAT or FAT32 partition */ 827 DPRINT("System path: '%wZ'\n", SystemRootPath); 828 829 /* Copy FreeLoader to the system partition, always overwriting the older version */ 830 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys"); 831 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys"); 832 833 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); 834 Status = SetupCopyFile(SrcPath, DstPath, FALSE); 835 if (!NT_SUCCESS(Status)) 836 { 837 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); 838 return Status; 839 } 840 841 /* Prepare for possibly updating 'freeldr.ini' */ 842 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini"); 843 if (DoesFreeLdrExist) 844 { 845 /* Update existing 'freeldr.ini' */ 846 DPRINT1("Update existing 'freeldr.ini'\n"); 847 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer); 848 if (!NT_SUCCESS(Status)) 849 { 850 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); 851 return Status; 852 } 853 } 854 855 /* Check for NT and other bootloaders */ 856 857 // FIXME: Check for Vista+ bootloader! 858 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/ 859 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/ 860 if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE || 861 DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE) 862 { 863 /* Search root directory for 'NTLDR' and 'BOOT.INI' */ 864 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n"); 865 866 /* Create or update 'freeldr.ini' */ 867 if (DoesFreeLdrExist == FALSE) 868 { 869 /* Create new 'freeldr.ini' */ 870 DPRINT1("Create new 'freeldr.ini'\n"); 871 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer); 872 if (!NT_SUCCESS(Status)) 873 { 874 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 875 return Status; 876 } 877 878 /* Install new bootcode into a file */ 879 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros"); 880 881 if (wcsicmp(FileSystemName, L"FAT32") == 0) 882 { 883 /* Install FAT32 bootcode */ 884 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin"); 885 886 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath); 887 Status = InstallBootCodeToFile(SrcPath, DstPath, 888 SystemRootPath->Buffer, 889 InstallFat32BootCode); 890 if (!NT_SUCCESS(Status)) 891 { 892 DPRINT1("InstallBootCodeToFile(FAT32) failed (Status %lx)\n", Status); 893 return Status; 894 } 895 } 896 else // if (wcsicmp(FileSystemName, L"FAT") == 0) 897 { 898 /* Install FAT16 bootcode */ 899 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin"); 900 901 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, DstPath); 902 Status = InstallBootCodeToFile(SrcPath, DstPath, 903 SystemRootPath->Buffer, 904 InstallFat16BootCode); 905 if (!NT_SUCCESS(Status)) 906 { 907 DPRINT1("InstallBootCodeToFile(FAT16) failed (Status %lx)\n", Status); 908 return Status; 909 } 910 } 911 } 912 913 /* Update 'boot.ini' */ 914 /* Windows' NTLDR loads an external bootsector file when the specified drive 915 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */ 916 DPRINT1("Update 'boot.ini'\n"); 917 Status = UpdateBootIni(SystemRootPath->Buffer, 918 L"C:\\bootsect.ros", 919 L"\"ReactOS\""); 920 if (!NT_SUCCESS(Status)) 921 { 922 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status); 923 return Status; 924 } 925 } 926 else 927 { 928 /* Non-NT bootloaders: install our own bootloader */ 929 930 PCWSTR Section; 931 PCWSTR Description; 932 PCWSTR BootDrive; 933 PCWSTR BootPartition; 934 PCWSTR BootSector; 935 936 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */ 937 if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE || 938 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE) 939 { 940 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n"); 941 942 Section = L"CPQDOS"; 943 Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\""; 944 BootDrive = L"hd0"; 945 BootPartition = L"1"; 946 BootSector = L"BOOTSECT.DOS"; 947 } 948 else 949 /* Search for Microsoft DOS or Windows 9x boot loader */ 950 if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE || 951 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE) 952 // WINBOOT.SYS 953 { 954 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n"); 955 956 Section = L"MSDOS"; 957 Description = L"\"MS-DOS/Windows\""; 958 BootDrive = L"hd0"; 959 BootPartition = L"1"; 960 BootSector = L"BOOTSECT.DOS"; 961 } 962 else 963 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */ 964 if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM... 965 DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE || 966 DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE) 967 { 968 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n"); 969 970 Section = L"IBMDOS"; 971 Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\""; 972 BootDrive = L"hd0"; 973 BootPartition = L"1"; 974 BootSector = L"BOOTSECT.DOS"; 975 } 976 else 977 /* Search for DR-DOS 3.x boot loader */ 978 if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE || 979 DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE) 980 { 981 DPRINT1("Found DR-DOS 3.x\n"); 982 983 Section = L"DRDOS"; 984 Description = L"\"DR-DOS 3.x\""; 985 BootDrive = L"hd0"; 986 BootPartition = L"1"; 987 BootSector = L"BOOTSECT.DOS"; 988 } 989 else 990 /* Search for Dell Real-Mode Kernel (DRMK) OS */ 991 if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE || 992 DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE) 993 { 994 DPRINT1("Found Dell Real-Mode Kernel OS\n"); 995 996 Section = L"DRMK"; 997 Description = L"\"Dell Real-Mode Kernel OS\""; 998 BootDrive = L"hd0"; 999 BootPartition = L"1"; 1000 BootSector = L"BOOTSECT.DOS"; 1001 } 1002 else 1003 /* Search for MS OS/2 1.x */ 1004 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE || 1005 DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE || 1006 DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE) 1007 { 1008 DPRINT1("Found MS OS/2 1.x\n"); 1009 1010 Section = L"MSOS2"; 1011 Description = L"\"MS OS/2 1.x\""; 1012 BootDrive = L"hd0"; 1013 BootPartition = L"1"; 1014 BootSector = L"BOOTSECT.OS2"; 1015 } 1016 else 1017 /* Search for MS or IBM OS/2 */ 1018 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE || 1019 DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE || 1020 DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE) 1021 { 1022 DPRINT1("Found MS/IBM OS/2\n"); 1023 1024 Section = L"IBMOS2"; 1025 Description = L"\"MS/IBM OS/2\""; 1026 BootDrive = L"hd0"; 1027 BootPartition = L"1"; 1028 BootSector = L"BOOTSECT.OS2"; 1029 } 1030 else 1031 /* Search for FreeDOS boot loader */ 1032 if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE) 1033 { 1034 DPRINT1("Found FreeDOS boot loader\n"); 1035 1036 Section = L"FDOS"; 1037 Description = L"\"FreeDOS\""; 1038 BootDrive = L"hd0"; 1039 BootPartition = L"1"; 1040 BootSector = L"BOOTSECT.DOS"; 1041 } 1042 else 1043 { 1044 /* No or unknown boot loader */ 1045 DPRINT1("No or unknown boot loader found\n"); 1046 1047 Section = L"Unknown"; 1048 Description = L"\"Unknown Operating System\""; 1049 BootDrive = L"hd0"; 1050 BootPartition = L"1"; 1051 BootSector = L"BOOTSECT.OLD"; 1052 } 1053 1054 /* Create or update 'freeldr.ini' */ 1055 if (DoesFreeLdrExist == FALSE) 1056 { 1057 /* Create new 'freeldr.ini' */ 1058 DPRINT1("Create new 'freeldr.ini'\n"); 1059 1060 if (IsThereAValidBootSector(SystemRootPath->Buffer)) 1061 { 1062 Status = CreateFreeLoaderIniForReactOSAndBootSector( 1063 SystemRootPath->Buffer, DestinationArcPath->Buffer, 1064 Section, Description, 1065 BootDrive, BootPartition, BootSector); 1066 if (!NT_SUCCESS(Status)) 1067 { 1068 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status); 1069 return Status; 1070 } 1071 1072 /* Save current bootsector */ 1073 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector); 1074 1075 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath); 1076 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE); 1077 if (!NT_SUCCESS(Status)) 1078 { 1079 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); 1080 return Status; 1081 } 1082 } 1083 else 1084 { 1085 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer); 1086 if (!NT_SUCCESS(Status)) 1087 { 1088 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 1089 return Status; 1090 } 1091 } 1092 1093 /* Install new bootsector on the disk */ 1094 if (wcsicmp(FileSystemName, L"FAT32") == 0) 1095 { 1096 /* Install FAT32 bootcode */ 1097 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin"); 1098 1099 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); 1100 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat32BootCode); 1101 DPRINT1("Status: 0x%08X\n", Status); 1102 if (!NT_SUCCESS(Status)) 1103 { 1104 DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status %lx)\n", Status); 1105 return Status; 1106 } 1107 } 1108 else // if (wcsicmp(FileSystemName, L"FAT") == 0) 1109 { 1110 /* Install FAT16 bootcode */ 1111 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin"); 1112 1113 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); 1114 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat16BootCode); 1115 if (!NT_SUCCESS(Status)) 1116 { 1117 DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status %lx)\n", Status); 1118 return Status; 1119 } 1120 } 1121 } 1122 } 1123 1124 return STATUS_SUCCESS; 1125 } 1126 1127 static 1128 NTSTATUS 1129 InstallBtrfsBootcodeToPartition( 1130 IN PUNICODE_STRING SystemRootPath, 1131 IN PUNICODE_STRING SourceRootPath, 1132 IN PUNICODE_STRING DestinationArcPath) 1133 { 1134 NTSTATUS Status; 1135 BOOLEAN DoesFreeLdrExist; 1136 WCHAR SrcPath[MAX_PATH]; 1137 WCHAR DstPath[MAX_PATH]; 1138 1139 /* BTRFS partition */ 1140 DPRINT("System path: '%wZ'\n", SystemRootPath); 1141 1142 /* Copy FreeLoader to the system partition, always overwriting the older version */ 1143 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys"); 1144 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys"); 1145 1146 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); 1147 Status = SetupCopyFile(SrcPath, DstPath, FALSE); 1148 if (!NT_SUCCESS(Status)) 1149 { 1150 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); 1151 return Status; 1152 } 1153 1154 /* Prepare for possibly updating 'freeldr.ini' */ 1155 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini"); 1156 if (DoesFreeLdrExist) 1157 { 1158 /* Update existing 'freeldr.ini' */ 1159 DPRINT1("Update existing 'freeldr.ini'\n"); 1160 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer); 1161 if (!NT_SUCCESS(Status)) 1162 { 1163 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); 1164 return Status; 1165 } 1166 } 1167 1168 /* Check for *nix bootloaders */ 1169 1170 /* Create or update 'freeldr.ini' */ 1171 if (DoesFreeLdrExist == FALSE) 1172 { 1173 /* Create new 'freeldr.ini' */ 1174 DPRINT1("Create new 'freeldr.ini'\n"); 1175 1176 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */ 1177 DPRINT1("*nix or unknown boot loader found\n"); 1178 1179 if (IsThereAValidBootSector(SystemRootPath->Buffer)) 1180 { 1181 PCWSTR BootSector = L"BOOTSECT.OLD"; 1182 1183 Status = CreateFreeLoaderIniForReactOSAndBootSector( 1184 SystemRootPath->Buffer, DestinationArcPath->Buffer, 1185 L"Linux", L"\"Linux\"", 1186 L"hd0", L"1", BootSector); 1187 if (!NT_SUCCESS(Status)) 1188 { 1189 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status); 1190 return Status; 1191 } 1192 1193 /* Save current bootsector */ 1194 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector); 1195 1196 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath); 1197 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, BTRFS_BOOTSECTOR_SIZE); 1198 if (!NT_SUCCESS(Status)) 1199 { 1200 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); 1201 return Status; 1202 } 1203 } 1204 else 1205 { 1206 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer); 1207 if (!NT_SUCCESS(Status)) 1208 { 1209 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 1210 return Status; 1211 } 1212 } 1213 1214 /* Install new bootsector on the disk */ 1215 /* Install BTRFS bootcode */ 1216 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin"); 1217 1218 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); 1219 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallBtrfsBootCode); 1220 if (!NT_SUCCESS(Status)) 1221 { 1222 DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n", Status); 1223 return Status; 1224 } 1225 } 1226 1227 return STATUS_SUCCESS; 1228 } 1229 1230 static 1231 NTSTATUS 1232 InstallNtfsBootcodeToPartition( 1233 IN PUNICODE_STRING SystemRootPath, 1234 IN PUNICODE_STRING SourceRootPath, 1235 IN PUNICODE_STRING DestinationArcPath) 1236 { 1237 NTSTATUS Status; 1238 BOOLEAN DoesFreeLdrExist; 1239 WCHAR SrcPath[MAX_PATH]; 1240 WCHAR DstPath[MAX_PATH]; 1241 1242 /* NTFS partition */ 1243 DPRINT("System path: '%wZ'\n", SystemRootPath); 1244 1245 /* Copy FreeLoader to the system partition, always overwriting the older version */ 1246 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys"); 1247 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys"); 1248 1249 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath); 1250 Status = SetupCopyFile(SrcPath, DstPath, FALSE); 1251 if (!NT_SUCCESS(Status)) 1252 { 1253 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); 1254 return Status; 1255 } 1256 1257 /* Prepare for possibly updating 'freeldr.ini' */ 1258 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini"); 1259 if (DoesFreeLdrExist) 1260 { 1261 /* Update existing 'freeldr.ini' */ 1262 DPRINT1("Update existing 'freeldr.ini'\n"); 1263 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer); 1264 if (!NT_SUCCESS(Status)) 1265 { 1266 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); 1267 return Status; 1268 } 1269 1270 return STATUS_SUCCESS; 1271 } 1272 1273 /* Check for *nix bootloaders */ 1274 1275 DPRINT1("Create new 'freeldr.ini'\n"); 1276 1277 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */ 1278 DPRINT1("*nix or unknown boot loader found\n"); 1279 1280 if (IsThereAValidBootSector(SystemRootPath->Buffer)) 1281 { 1282 PCWSTR BootSector = L"BOOTSECT.OLD"; 1283 1284 Status = CreateFreeLoaderIniForReactOSAndBootSector( 1285 SystemRootPath->Buffer, DestinationArcPath->Buffer, 1286 L"Linux", L"\"Linux\"", 1287 L"hd0", L"1", BootSector); 1288 if (!NT_SUCCESS(Status)) 1289 { 1290 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status); 1291 return Status; 1292 } 1293 1294 /* Save current bootsector */ 1295 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector); 1296 1297 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath); 1298 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, NTFS_BOOTSECTOR_SIZE); 1299 if (!NT_SUCCESS(Status)) 1300 { 1301 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); 1302 return Status; 1303 } 1304 } 1305 else 1306 { 1307 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer); 1308 if (!NT_SUCCESS(Status)) 1309 { 1310 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 1311 return Status; 1312 } 1313 } 1314 1315 /* Install new bootsector on the disk */ 1316 1317 /* Install NTFS bootcode */ 1318 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\ntfs.bin"); 1319 1320 DPRINT1("Install NTFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); 1321 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallNtfsBootCode); 1322 if (!NT_SUCCESS(Status)) 1323 { 1324 DPRINT1("InstallBootCodeToDisk(NTFS) failed (Status %lx)\n", Status); 1325 return Status; 1326 } 1327 1328 return STATUS_SUCCESS; 1329 } 1330 1331 1332 NTSTATUS 1333 InstallVBRToPartition( 1334 IN PUNICODE_STRING SystemRootPath, 1335 IN PUNICODE_STRING SourceRootPath, 1336 IN PUNICODE_STRING DestinationArcPath, 1337 IN PCWSTR FileSystemName) 1338 { 1339 if (wcsicmp(FileSystemName, L"FAT") == 0 || 1340 wcsicmp(FileSystemName, L"FAT32") == 0) 1341 { 1342 return InstallFatBootcodeToPartition(SystemRootPath, 1343 SourceRootPath, 1344 DestinationArcPath, 1345 FileSystemName); 1346 } 1347 else if (wcsicmp(FileSystemName, L"NTFS") == 0) 1348 { 1349 return InstallNtfsBootcodeToPartition(SystemRootPath, 1350 SourceRootPath, 1351 DestinationArcPath); 1352 } 1353 else if (wcsicmp(FileSystemName, L"BTRFS") == 0) 1354 { 1355 return InstallBtrfsBootcodeToPartition(SystemRootPath, 1356 SourceRootPath, 1357 DestinationArcPath); 1358 } 1359 /* 1360 else if (wcsicmp(FileSystemName, L"EXT2") == 0 || 1361 wcsicmp(FileSystemName, L"EXT3") == 0 || 1362 wcsicmp(FileSystemName, L"EXT4") == 0) 1363 { 1364 return STATUS_NOT_SUPPORTED; 1365 } 1366 */ 1367 else 1368 { 1369 /* Unknown file system */ 1370 DPRINT1("Unknown file system '%S'\n", FileSystemName); 1371 } 1372 1373 return STATUS_NOT_SUPPORTED; 1374 } 1375 1376 1377 NTSTATUS 1378 InstallFatBootcodeToFloppy( 1379 IN PUNICODE_STRING SourceRootPath, 1380 IN PUNICODE_STRING DestinationArcPath) 1381 { 1382 static const PCWSTR FloppyDevice = L"\\Device\\Floppy0\\"; 1383 1384 NTSTATUS Status; 1385 WCHAR SrcPath[MAX_PATH]; 1386 WCHAR DstPath[MAX_PATH]; 1387 1388 /* Verify that the floppy disk is accessible */ 1389 if (DoesDirExist(NULL, FloppyDevice) == FALSE) 1390 return STATUS_DEVICE_NOT_READY; 1391 1392 /* Format the floppy disk */ 1393 // FormatPartition(...) 1394 Status = FormatFileSystem(FloppyDevice, 1395 L"FAT", 1396 FMIFS_FLOPPY, 1397 NULL, 1398 TRUE, 1399 0, 1400 NULL); 1401 if (!NT_SUCCESS(Status)) 1402 { 1403 if (Status == STATUS_NOT_SUPPORTED) 1404 DPRINT1("FAT FS non existent on this system?!\n"); 1405 else 1406 DPRINT1("VfatFormat() failed (Status %lx)\n", Status); 1407 1408 return Status; 1409 } 1410 1411 /* Copy FreeLoader to the boot partition */ 1412 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys"); 1413 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice, L"freeldr.sys"); 1414 1415 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); 1416 Status = SetupCopyFile(SrcPath, DstPath, FALSE); 1417 if (!NT_SUCCESS(Status)) 1418 { 1419 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); 1420 return Status; 1421 } 1422 1423 /* Create new 'freeldr.ini' */ 1424 DPRINT("Create new 'freeldr.ini'\n"); 1425 Status = CreateFreeLoaderIniForReactOS(FloppyDevice, DestinationArcPath->Buffer); 1426 if (!NT_SUCCESS(Status)) 1427 { 1428 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 1429 return Status; 1430 } 1431 1432 /* Install FAT12 boosector */ 1433 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin"); 1434 CombinePaths(DstPath, ARRAYSIZE(DstPath), 1, FloppyDevice); 1435 1436 DPRINT("Install FAT12 bootcode: %S ==> %S\n", SrcPath, DstPath); 1437 Status = InstallBootCodeToDisk(SrcPath, DstPath, InstallFat12BootCode); 1438 if (!NT_SUCCESS(Status)) 1439 { 1440 DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status %lx)\n", Status); 1441 return Status; 1442 } 1443 1444 return STATUS_SUCCESS; 1445 } 1446 1447 /* EOF */ 1448