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