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