1 /* 2 * COPYRIGHT: See COPYING.ARM in the top level directory 3 * PROJECT: ReactOS UEFI Boot Library 4 * FILE: boot/environ/lib/firmware/efi/firmware.c 5 * PURPOSE: Boot Library Firmware Initialization for EFI 6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "bl.h" 12 13 /* DATA VARIABLES ************************************************************/ 14 15 PBL_FIRMWARE_DESCRIPTOR EfiFirmwareParameters; 16 BL_FIRMWARE_DESCRIPTOR EfiFirmwareData; 17 EFI_HANDLE EfiImageHandle; 18 EFI_SYSTEM_TABLE* EfiSystemTable; 19 20 EFI_SYSTEM_TABLE *EfiST; 21 EFI_BOOT_SERVICES *EfiBS; 22 EFI_RUNTIME_SERVICES *EfiRT; 23 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *EfiConOut; 24 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *EfiConIn; 25 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx; 26 PHYSICAL_ADDRESS EfiRsdt; 27 28 EFI_GUID EfiGraphicsOutputProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; 29 EFI_GUID EfiUgaDrawProtocol = EFI_UGA_DRAW_PROTOCOL_GUID; 30 EFI_GUID EfiLoadedImageProtocol = EFI_LOADED_IMAGE_PROTOCOL_GUID; 31 EFI_GUID EfiDevicePathProtocol = EFI_DEVICE_PATH_PROTOCOL_GUID; 32 EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; 33 EFI_GUID EfiBlockIoProtocol = EFI_BLOCK_IO_PROTOCOL_GUID; 34 EFI_GUID EfiRootAcpiTableGuid = EFI_ACPI_20_TABLE_GUID; 35 EFI_GUID EfiRootAcpiTable10Guid = EFI_ACPI_TABLE_GUID; 36 EFI_GUID EfiGlobalVariable = EFI_GLOBAL_VARIABLE; 37 EFI_GUID BlpEfiSecureBootPrivateNamespace = { 0x77FA9ABD , 0x0359, 0x4D32, { 0xBD, 0x60, 0x28, 0xF4, 0xE7, 0x8F, 0x78, 0x4B } }; 38 39 WCHAR BlScratchBuffer[8192]; 40 41 BOOLEAN BlpFirmwareChecked; 42 BOOLEAN BlpFirmwareEnabled; 43 44 /* FUNCTIONS *****************************************************************/ 45 46 EFI_DEVICE_PATH * 47 EfiIsDevicePathParent ( 48 _In_ EFI_DEVICE_PATH *DevicePath1, 49 _In_ EFI_DEVICE_PATH *DevicePath2 50 ) 51 { 52 EFI_DEVICE_PATH* CurrentPath1; 53 EFI_DEVICE_PATH* CurrentPath2; 54 USHORT Length1, Length2; 55 56 /* Start with the current nodes */ 57 CurrentPath1 = DevicePath1; 58 CurrentPath2 = DevicePath2; 59 60 /* Loop each element of the device path */ 61 while (!(IsDevicePathEndType(CurrentPath1)) && 62 !(IsDevicePathEndType(CurrentPath2))) 63 { 64 /* Check if the element has a different length */ 65 Length1 = DevicePathNodeLength(CurrentPath1); 66 Length2 = DevicePathNodeLength(CurrentPath2); 67 if (Length1 != Length2) 68 { 69 /* Then they're not related */ 70 return NULL; 71 } 72 73 /* Check if the rest of the element data matches */ 74 if (RtlCompareMemory(CurrentPath1, CurrentPath2, Length1) != Length1) 75 { 76 /* Nope, not related */ 77 return NULL; 78 } 79 80 /* Move to the next element */ 81 CurrentPath1 = NextDevicePathNode(CurrentPath1); 82 CurrentPath2 = NextDevicePathNode(CurrentPath2); 83 } 84 85 /* If the last element in path 1 is empty, then path 2 is the child (deeper) */ 86 if (!IsDevicePathEndType(CurrentPath1)) 87 { 88 return DevicePath2; 89 } 90 91 /* If the last element in path 2 is empty, then path 1 is the child (deeper) */ 92 if (!IsDevicePathEndType(CurrentPath2)) 93 { 94 return DevicePath1; 95 } 96 97 /* They're both the end, so they're identical, so there's no parent */ 98 return NULL; 99 } 100 101 EFI_DEVICE_PATH* 102 EfiGetLeafNode ( 103 _In_ EFI_DEVICE_PATH *DevicePath 104 ) 105 { 106 EFI_DEVICE_PATH *NextDevicePath; 107 108 /* Make sure we're not already at the end */ 109 if (!IsDevicePathEndType(DevicePath)) 110 { 111 /* Grab the next node element, and keep going until the end */ 112 for (NextDevicePath = NextDevicePathNode(DevicePath); 113 !IsDevicePathEndType(NextDevicePath); 114 NextDevicePath = NextDevicePathNode(NextDevicePath)) 115 { 116 /* Save the current node we're at */ 117 DevicePath = NextDevicePath; 118 } 119 } 120 121 /* This now contains the deepest (leaf) node */ 122 return DevicePath; 123 } 124 125 VOID 126 EfiPrintf ( 127 _In_ PWCHAR Format, 128 ... 129 ) 130 { 131 va_list args; 132 va_start(args, Format); 133 134 /* Capture the buffer in our scratch pad, and NULL-terminate */ 135 vsnwprintf(BlScratchBuffer, RTL_NUMBER_OF(BlScratchBuffer) - 1, Format, args); 136 BlScratchBuffer[RTL_NUMBER_OF(BlScratchBuffer) - 1] = UNICODE_NULL; 137 138 /* Check which mode we're in */ 139 if (CurrentExecutionContext->Mode == BlRealMode) 140 { 141 /* Call EFI directly */ 142 EfiConOut->OutputString(EfiConOut, BlScratchBuffer); 143 } 144 else 145 { 146 /* Switch to real mode */ 147 BlpArchSwitchContext(BlRealMode); 148 149 /* Call EFI directly */ 150 if (EfiConOut != NULL) 151 { 152 EfiConOut->OutputString(EfiConOut, BlScratchBuffer); 153 } 154 155 /* Switch back to protected mode */ 156 BlpArchSwitchContext(BlProtectedMode); 157 } 158 159 /* All done */ 160 va_end(args); 161 } 162 163 BOOLEAN EfiProtHashTableInitialized; 164 ULONG EfiProtHashTableId; 165 166 typedef struct _BL_EFI_PROTOCOL 167 { 168 LIST_ENTRY ListEntry; 169 EFI_GUID* Protocol; 170 PVOID Interface; 171 LONG ReferenceCount; 172 BOOLEAN AddressMapped; 173 } BL_EFI_PROTOCOL, *PBL_EFI_PROTOCOL; 174 175 NTSTATUS 176 EfiVmOpenProtocol ( 177 _In_ EFI_HANDLE Handle, 178 _In_ EFI_GUID* Protocol, 179 _Outptr_ PVOID* Interface 180 ) 181 { 182 BOOLEAN AddressMapped; 183 PLIST_ENTRY HashList, NextEntry; 184 PHYSICAL_ADDRESS InterfaceAddress, TranslatedAddress; 185 NTSTATUS Status; 186 BL_HASH_ENTRY HashEntry; 187 PBL_HASH_VALUE HashValue; 188 PBL_EFI_PROTOCOL EfiProtocol; 189 BL_ARCH_MODE OldMode; 190 EFI_STATUS EfiStatus; 191 PVOID InterfaceVa; 192 193 /* Initialize failure paths */ 194 AddressMapped = FALSE; 195 HashList = NULL; 196 InterfaceAddress.QuadPart = 0; 197 198 /* Have we initialized the protocol table yet? */ 199 if (!EfiProtHashTableInitialized) 200 { 201 /* Nope -- create the hash table */ 202 Status = BlHtCreate(0, NULL, NULL, &EfiProtHashTableId); 203 if (!NT_SUCCESS(Status)) 204 { 205 return Status; 206 } 207 208 /* Remember for next time */ 209 EfiProtHashTableInitialized = TRUE; 210 } 211 212 /* Check if we already have a list of protocols for this handle */ 213 HashEntry.Flags = BL_HT_VALUE_IS_INLINE; 214 HashEntry.Size = sizeof(Handle); 215 HashEntry.Value = Handle; 216 Status = BlHtLookup(EfiProtHashTableId, &HashEntry, &HashValue); 217 if (NT_SUCCESS(Status)) 218 { 219 /* We do -- the hash value is the list itself */ 220 HashList = (PLIST_ENTRY)HashValue->Data; 221 NextEntry = HashList->Flink; 222 223 /* Iterate over it */ 224 while (NextEntry != HashList) 225 { 226 /* Get each protocol in the list, checking for a match */ 227 EfiProtocol = CONTAINING_RECORD(NextEntry, 228 BL_EFI_PROTOCOL, 229 ListEntry); 230 if (EfiProtocol->Protocol == Protocol) 231 { 232 /* Match found -- add a reference and return it */ 233 EfiProtocol->ReferenceCount++; 234 *Interface = EfiProtocol->Interface; 235 return STATUS_SUCCESS; 236 } 237 238 /* Try the next entry */ 239 NextEntry = NextEntry->Flink; 240 } 241 } 242 243 /* Switch to real mode for firmware call */ 244 OldMode = CurrentExecutionContext->Mode; 245 if (OldMode != BlRealMode) 246 { 247 BlpArchSwitchContext(BlRealMode); 248 } 249 250 /* Check if this is EFI 1.02 */ 251 if (EfiST->Hdr.Revision == EFI_1_02_SYSTEM_TABLE_REVISION) 252 { 253 /* Use the old call */ 254 EfiStatus = EfiBS->HandleProtocol(Handle, 255 Protocol, 256 (PVOID*)&InterfaceAddress); 257 } 258 else 259 { 260 /* Use the EFI 2.00 API instead */ 261 EfiStatus = EfiBS->OpenProtocol(Handle, 262 Protocol, 263 (PVOID*)&InterfaceAddress, 264 EfiImageHandle, 265 NULL, 266 EFI_OPEN_PROTOCOL_GET_PROTOCOL); 267 } 268 269 /* Switch back to protected mode if needed */ 270 if (OldMode != BlRealMode) 271 { 272 BlpArchSwitchContext(OldMode); 273 } 274 275 /* Check the result, and bail out on failure */ 276 Status = EfiGetNtStatusCode(EfiStatus); 277 if (!NT_SUCCESS(Status)) 278 { 279 return Status; 280 } 281 282 /* Check what address the interface lives at, and translate it */ 283 InterfaceVa = PhysicalAddressToPtr(InterfaceAddress); 284 if (BlMmTranslateVirtualAddress(InterfaceVa, &TranslatedAddress)) 285 { 286 /* We expect firmware to be 1:1 mapped, fail if not */ 287 if (InterfaceAddress.QuadPart != TranslatedAddress.QuadPart) 288 { 289 return STATUS_NOT_SUPPORTED; 290 } 291 } 292 else 293 { 294 /* Create a virtual (1:1) mapping for the interface */ 295 Status = BlMmMapPhysicalAddressEx(&InterfaceVa, 296 BlMemoryFixed, 297 PAGE_SIZE, 298 InterfaceAddress); 299 if (!NT_SUCCESS(Status)) 300 { 301 return Status; 302 } 303 304 /* Remember for cleanup */ 305 AddressMapped = TRUE; 306 } 307 308 /* The caller now has the interface */ 309 *Interface = InterfaceVa; 310 311 /* Did we already have some protocols on this handle? */ 312 if (!HashList) 313 { 314 /* Nope, this is the first time -- so allocate the list */ 315 HashList = BlMmAllocateHeap(sizeof(*HashList)); 316 if (!HashList) 317 { 318 Status = STATUS_NO_MEMORY; 319 goto Quickie; 320 } 321 322 /* Initialize it */ 323 InitializeListHead(HashList); 324 325 /* And then store it in the hash table for this handle */ 326 Status = BlHtStore(EfiProtHashTableId, 327 &HashEntry, 328 HashList, 329 sizeof(*HashList)); 330 if (!NT_SUCCESS(Status)) 331 { 332 BlMmFreeHeap(HashList); 333 goto Quickie; 334 } 335 } 336 337 /* Finally, allocate a protocol tracker structure */ 338 EfiProtocol = BlMmAllocateHeap(sizeof(*EfiProtocol)); 339 if (!EfiProtocol) 340 { 341 Status = STATUS_NO_MEMORY; 342 goto Quickie; 343 } 344 345 /* And store this information in case the protocol is needed again */ 346 EfiProtocol->Protocol = Protocol; 347 EfiProtocol->Interface = *Interface; 348 EfiProtocol->ReferenceCount = 1; 349 EfiProtocol->AddressMapped = AddressMapped; 350 InsertTailList(HashList, &EfiProtocol->ListEntry); 351 352 /* Passthru to success case */ 353 AddressMapped = FALSE; 354 355 Quickie: 356 /* Failure path -- did we map anything ?*/ 357 if (AddressMapped) 358 { 359 /* Get rid of it */ 360 BlMmUnmapVirtualAddressEx(InterfaceVa, PAGE_SIZE); 361 *Interface = NULL; 362 } 363 364 /* Return the failure */ 365 return Status; 366 } 367 368 NTSTATUS 369 EfiOpenProtocol ( 370 _In_ EFI_HANDLE Handle, 371 _In_ EFI_GUID *Protocol, 372 _Outptr_ PVOID* Interface 373 ) 374 { 375 EFI_STATUS EfiStatus; 376 NTSTATUS Status; 377 BL_ARCH_MODE OldMode; 378 379 /* Are we using virtual memory/ */ 380 if (MmTranslationType != BlNone) 381 { 382 /* We need complex tracking to make this work */ 383 Status = EfiVmOpenProtocol(Handle, Protocol, Interface); 384 } 385 else 386 { 387 /* Are we in protected mode? */ 388 OldMode = CurrentExecutionContext->Mode; 389 if (OldMode != BlRealMode) 390 { 391 /* Switch to real mode */ 392 BlpArchSwitchContext(BlRealMode); 393 } 394 395 /* Are we on legacy 1.02? */ 396 if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION) 397 { 398 /* Make the legacy call */ 399 EfiStatus = EfiBS->HandleProtocol(Handle, Protocol, Interface); 400 } 401 else 402 { 403 /* Use the UEFI version */ 404 EfiStatus = EfiBS->OpenProtocol(Handle, 405 Protocol, 406 Interface, 407 EfiImageHandle, 408 NULL, 409 EFI_OPEN_PROTOCOL_GET_PROTOCOL); 410 411 /* Switch back to protected mode if we came from there */ 412 if (OldMode != BlRealMode) 413 { 414 BlpArchSwitchContext(OldMode); 415 } 416 } 417 418 /* Convert the error to an NTSTATUS */ 419 Status = EfiGetNtStatusCode(EfiStatus); 420 } 421 422 /* Clear the interface on failure, and return the status */ 423 if (!NT_SUCCESS(Status)) 424 { 425 *Interface = NULL; 426 } 427 428 return Status; 429 } 430 431 NTSTATUS 432 EfiVmpCloseProtocol ( 433 _In_ EFI_HANDLE Handle, 434 _In_ EFI_GUID* Protocol 435 ) 436 { 437 EFI_STATUS EfiStatus; 438 BL_ARCH_MODE OldMode; 439 440 /* Are we in protected mode? */ 441 OldMode = CurrentExecutionContext->Mode; 442 if (OldMode != BlRealMode) 443 { 444 /* Switch to real mode */ 445 BlpArchSwitchContext(BlRealMode); 446 } 447 448 /* Are we on legacy 1.02? */ 449 if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION) 450 { 451 /* Nothing to close */ 452 EfiStatus = EFI_SUCCESS; 453 } 454 else 455 { 456 /* Use the UEFI version */ 457 EfiStatus = EfiBS->CloseProtocol(Handle, 458 Protocol, 459 EfiImageHandle, 460 NULL); 461 462 /* Normalize not found as success */ 463 if (EfiStatus == EFI_NOT_FOUND) 464 { 465 EfiStatus = EFI_SUCCESS; 466 } 467 } 468 469 /* Switch back to protected mode if we came from there */ 470 if (OldMode != BlRealMode) 471 { 472 BlpArchSwitchContext(OldMode); 473 } 474 475 /* Convert to NT status */ 476 return EfiGetNtStatusCode(EfiStatus); 477 } 478 479 NTSTATUS 480 EfiVmpFreeInterfaceEntry ( 481 _In_ EFI_HANDLE Handle, 482 _In_ PBL_EFI_PROTOCOL EfiProtocol 483 ) 484 { 485 NTSTATUS Status; 486 BL_HASH_ENTRY HashEntry; 487 488 /* Assume success */ 489 Status = STATUS_SUCCESS; 490 491 /* Is this the last protocol on this handle? */ 492 if (IsListEmpty(&EfiProtocol->ListEntry)) 493 { 494 /* Delete the hash table entry for this handle */ 495 HashEntry.Value = Handle; 496 HashEntry.Size = sizeof(Handle); 497 HashEntry.Flags = BL_HT_VALUE_IS_INLINE; 498 Status = BlHtDelete(EfiProtHashTableId, &HashEntry); 499 500 /* This will free the list head itself */ 501 BlMmFreeHeap(EfiProtocol->ListEntry.Flink); 502 } 503 else 504 { 505 /* Simply remove this entry */ 506 RemoveEntryList(&EfiProtocol->ListEntry); 507 } 508 509 /* Had we virtually mapped this protocol? */ 510 if (EfiProtocol->AddressMapped) 511 { 512 /* Unmap it */ 513 BlMmUnmapVirtualAddressEx(EfiProtocol->Interface, PAGE_SIZE); 514 } 515 516 /* Free the protocol entry, and return */ 517 BlMmFreeHeap(EfiProtocol); 518 return Status; 519 } 520 521 NTSTATUS 522 EfiVmCloseProtocol ( 523 _In_ EFI_HANDLE Handle, 524 _In_ EFI_GUID* Protocol 525 ) 526 { 527 BL_HASH_ENTRY HashEntry; 528 PLIST_ENTRY ListHead, NextEntry; 529 NTSTATUS Status, CloseStatus; 530 PBL_HASH_VALUE HashValue; 531 PBL_EFI_PROTOCOL EfiProtocol; 532 533 /* Lookup the list entry for this handle */ 534 HashEntry.Size = sizeof(Handle); 535 HashEntry.Flags = BL_HT_VALUE_IS_INLINE; 536 HashEntry.Value = Handle; 537 Status = BlHtLookup(EfiProtHashTableId, &HashEntry, &HashValue); 538 if (!NT_SUCCESS(Status)) 539 { 540 /* This handle was never used for any protocols */ 541 return STATUS_INVALID_PARAMETER; 542 } 543 544 /* Iterate through the list of opened protocols */ 545 ListHead = (PLIST_ENTRY)HashValue->Data; 546 NextEntry = ListHead->Flink; 547 while (NextEntry != ListHead) 548 { 549 /* Get this protocol entry and check for a match */ 550 EfiProtocol = CONTAINING_RECORD(NextEntry, BL_EFI_PROTOCOL, ListEntry); 551 if (EfiProtocol->Protocol == Protocol) 552 { 553 /* Drop a reference -- was it the last one? */ 554 if (EfiProtocol->ReferenceCount-- == 1) 555 { 556 /* Yep -- free this entry */ 557 Status = EfiVmpFreeInterfaceEntry(Handle, EfiProtocol); 558 559 /* Call firmware to close the protocol */ 560 CloseStatus = EfiVmpCloseProtocol(Handle, Protocol); 561 if (!NT_SUCCESS(CloseStatus)) 562 { 563 /* Override free status if close was a failure */ 564 Status = CloseStatus; 565 } 566 567 /* Return final status */ 568 return Status; 569 } 570 } 571 572 /* Next entry */ 573 NextEntry = NextEntry->Flink; 574 } 575 576 /* This protocol was never opened */ 577 return STATUS_INVALID_PARAMETER; 578 } 579 580 NTSTATUS 581 EfiCloseProtocol ( 582 _In_ EFI_HANDLE Handle, 583 _In_ EFI_GUID *Protocol 584 ) 585 { 586 EFI_STATUS EfiStatus; 587 NTSTATUS Status; 588 BL_ARCH_MODE OldMode; 589 590 /* Are we using virtual memory/ */ 591 if (MmTranslationType != BlNone) 592 { 593 /* We need complex tracking to make this work */ 594 Status = EfiVmCloseProtocol(Handle, Protocol); 595 } 596 else 597 { 598 /* Are we on legacy 1.02? */ 599 if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION) 600 { 601 /* Nothing to close */ 602 EfiStatus = EFI_SUCCESS; 603 } 604 else 605 { 606 /* Are we in protected mode? */ 607 OldMode = CurrentExecutionContext->Mode; 608 if (OldMode != BlRealMode) 609 { 610 /* Switch to real mode */ 611 BlpArchSwitchContext(BlRealMode); 612 } 613 614 /* Use the UEFI version */ 615 EfiStatus = EfiBS->CloseProtocol(Handle, Protocol, EfiImageHandle, NULL); 616 617 /* Switch back to protected mode if we came from there */ 618 if (OldMode != BlRealMode) 619 { 620 BlpArchSwitchContext(OldMode); 621 } 622 623 /* Normalize not found as success */ 624 if (EfiStatus == EFI_NOT_FOUND) 625 { 626 EfiStatus = EFI_SUCCESS; 627 } 628 } 629 630 /* Convert the error to an NTSTATUS */ 631 Status = EfiGetNtStatusCode(EfiStatus); 632 } 633 634 /* All done */ 635 return Status; 636 } 637 638 NTSTATUS 639 EfiGetVariable ( 640 _In_ PWCHAR VariableName, 641 _In_ EFI_GUID* VendorGuid, 642 _Out_opt_ PULONG Attributes, 643 _Inout_ PULONG DataSize, 644 _Out_ PVOID Data 645 ) 646 { 647 EFI_STATUS EfiStatus; 648 NTSTATUS Status; 649 BL_ARCH_MODE OldMode; 650 ULONG LocalAttributes; 651 652 /* Are we in protected mode? */ 653 OldMode = CurrentExecutionContext->Mode; 654 if (OldMode != BlRealMode) 655 { 656 /* FIXME: Not yet implemented */ 657 EfiPrintf(L"getvar vm path\r\n"); 658 EfiStall(10000000); 659 return STATUS_NOT_IMPLEMENTED; 660 } 661 662 /* Call the runtime API */ 663 EfiStatus = EfiRT->GetVariable(VariableName, 664 VendorGuid, 665 (UINT32*)&LocalAttributes, 666 (UINTN*)DataSize, 667 Data); 668 669 /* Switch back to protected mode if we came from there */ 670 if (OldMode != BlRealMode) 671 { 672 BlpArchSwitchContext(OldMode); 673 } 674 675 /* Return attributes back to the caller if asked to */ 676 if (Attributes) 677 { 678 *Attributes = LocalAttributes; 679 } 680 681 /* Convert the error to an NTSTATUS and return it */ 682 Status = EfiGetNtStatusCode(EfiStatus); 683 return Status; 684 } 685 686 NTSTATUS 687 BlpSecureBootEFIIsEnabled ( 688 VOID 689 ) 690 { 691 NTSTATUS Status; 692 BOOLEAN SetupMode, SecureBoot; 693 ULONG DataSize; 694 695 /* Assume setup mode enabled, and no secure boot */ 696 SecureBoot = FALSE; 697 SetupMode = TRUE; 698 699 /* Get the SetupMode variable */ 700 DataSize = sizeof(SetupMode); 701 Status = EfiGetVariable(L"SetupMode", 702 &EfiGlobalVariable, 703 NULL, 704 &DataSize, 705 &SetupMode); 706 if (NT_SUCCESS(Status)) 707 { 708 /* If it worked, get the SecureBoot variable */ 709 DataSize = sizeof(SecureBoot); 710 Status = EfiGetVariable(L"SecureBoot", 711 &EfiGlobalVariable, 712 NULL, 713 &DataSize, 714 &SecureBoot); 715 if (NT_SUCCESS(Status)) 716 { 717 /* In setup mode or without secureboot turned on, return failure */ 718 if ((SecureBoot != TRUE) || (SetupMode)) 719 { 720 Status = STATUS_INVALID_SIGNATURE; 721 } 722 723 // BlpSbdiStateFlags |= 8u; 724 } 725 } 726 727 /* Return secureboot status */ 728 return Status; 729 } 730 731 NTSTATUS 732 BlSecureBootIsEnabled ( 733 _Out_ PBOOLEAN SecureBootEnabled 734 ) 735 { 736 NTSTATUS Status; 737 738 /* Have we checked before ? */ 739 if (!BlpFirmwareChecked) 740 { 741 /* First time checking */ 742 Status = BlpSecureBootEFIIsEnabled(); 743 if NT_SUCCESS(Status) 744 { 745 /* Yep, it's on */ 746 BlpFirmwareEnabled = TRUE; 747 } 748 749 /* Don't check again */ 750 BlpFirmwareChecked = TRUE; 751 } 752 753 /* Return the firmware result */ 754 *SecureBootEnabled = BlpFirmwareEnabled; 755 return STATUS_SUCCESS; 756 } 757 758 NTSTATUS 759 BlSecureBootCheckForFactoryReset ( 760 VOID 761 ) 762 { 763 BOOLEAN SecureBootEnabled; 764 NTSTATUS Status; 765 ULONG DataSize; 766 767 /* Initialize locals */ 768 DataSize = 0; 769 SecureBootEnabled = FALSE; 770 771 /* Check if secureboot is enabled */ 772 Status = BlSecureBootIsEnabled(&SecureBootEnabled); 773 if (!(NT_SUCCESS(Status)) || !(SecureBootEnabled)) 774 { 775 /* It's not. Check if there's a revocation list */ 776 Status = EfiGetVariable(L"RevocationList", 777 &BlpEfiSecureBootPrivateNamespace, 778 NULL, 779 &DataSize, 780 NULL); 781 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL)) 782 { 783 /* We don't support this yet */ 784 EfiPrintf(L"Not yet supported\r\n"); 785 Status = STATUS_NOT_IMPLEMENTED; 786 } 787 } 788 789 /* Return back to the caller */ 790 return Status; 791 } 792 793 NTSTATUS 794 EfiConInReset ( 795 VOID 796 ) 797 { 798 BL_ARCH_MODE OldMode; 799 EFI_STATUS EfiStatus; 800 801 /* Are we in protected mode? */ 802 OldMode = CurrentExecutionContext->Mode; 803 if (OldMode != BlRealMode) 804 { 805 /* FIXME: Not yet implemented */ 806 EfiPrintf(L"coninreset vm path\r\n"); 807 EfiStall(10000000); 808 return STATUS_NOT_IMPLEMENTED; 809 } 810 811 /* Make the EFI call */ 812 EfiStatus = EfiConIn->Reset(EfiConIn, FALSE); 813 814 /* Switch back to protected mode if we came from there */ 815 if (OldMode != BlRealMode) 816 { 817 BlpArchSwitchContext(OldMode); 818 } 819 820 /* Convert the error to an NTSTATUS */ 821 return EfiGetNtStatusCode(EfiStatus); 822 } 823 824 NTSTATUS 825 EfiConInExReset ( 826 VOID 827 ) 828 { 829 BL_ARCH_MODE OldMode; 830 EFI_STATUS EfiStatus; 831 832 /* Are we in protected mode? */ 833 OldMode = CurrentExecutionContext->Mode; 834 if (OldMode != BlRealMode) 835 { 836 /* FIXME: Not yet implemented */ 837 EfiPrintf(L"conreset vm path\r\n"); 838 EfiStall(10000000); 839 return STATUS_NOT_IMPLEMENTED; 840 } 841 842 /* Make the EFI call */ 843 EfiStatus = EfiConInEx->Reset(EfiConInEx, FALSE); 844 845 /* Switch back to protected mode if we came from there */ 846 if (OldMode != BlRealMode) 847 { 848 BlpArchSwitchContext(OldMode); 849 } 850 851 /* Convert the error to an NTSTATUS */ 852 return EfiGetNtStatusCode(EfiStatus); 853 } 854 855 NTSTATUS 856 EfiConInExSetState ( 857 _In_ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *ConInEx, 858 _In_ EFI_KEY_TOGGLE_STATE* KeyToggleState 859 ) 860 { 861 BL_ARCH_MODE OldMode; 862 EFI_STATUS EfiStatus; 863 PHYSICAL_ADDRESS ConInExPhys, KeyTogglePhys; 864 865 /* Are we in protected mode? */ 866 OldMode = CurrentExecutionContext->Mode; 867 if (OldMode != BlRealMode) 868 { 869 /* Translate pointers from virtual to physical */ 870 BlMmTranslateVirtualAddress(ConInEx, &ConInExPhys); 871 ConInEx = (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL*)PhysicalAddressToPtr(ConInExPhys); 872 BlMmTranslateVirtualAddress(KeyToggleState, &KeyTogglePhys); 873 KeyToggleState = (EFI_KEY_TOGGLE_STATE*)PhysicalAddressToPtr(KeyTogglePhys); 874 875 /* Switch to real mode */ 876 BlpArchSwitchContext(BlRealMode); 877 } 878 879 /* Make the EFI call */ 880 EfiStatus = ConInEx->SetState(ConInEx, KeyToggleState); 881 882 /* Switch back to protected mode if we came from there */ 883 if (OldMode != BlRealMode) 884 { 885 BlpArchSwitchContext(OldMode); 886 } 887 888 /* Convert the error to an NTSTATUS */ 889 return EfiGetNtStatusCode(EfiStatus); 890 } 891 892 NTSTATUS 893 EfiSetWatchdogTimer ( 894 VOID 895 ) 896 { 897 BL_ARCH_MODE OldMode; 898 EFI_STATUS EfiStatus; 899 900 /* Are we in protected mode? */ 901 OldMode = CurrentExecutionContext->Mode; 902 if (OldMode != BlRealMode) 903 { 904 /* Switch to real mode */ 905 BlpArchSwitchContext(BlRealMode); 906 } 907 908 /* Make the EFI call */ 909 EfiStatus = EfiBS->SetWatchdogTimer(0, 0, 0, NULL); 910 911 /* Switch back to protected mode if we came from there */ 912 if (OldMode != BlRealMode) 913 { 914 BlpArchSwitchContext(OldMode); 915 } 916 917 /* Convert the error to an NTSTATUS */ 918 return EfiGetNtStatusCode(EfiStatus); 919 } 920 921 NTSTATUS 922 EfiGetMemoryMap ( 923 _Out_ UINTN* MemoryMapSize, 924 _Inout_ EFI_MEMORY_DESCRIPTOR *MemoryMap, 925 _Out_ UINTN* MapKey, 926 _Out_ UINTN* DescriptorSize, 927 _Out_ UINTN* DescriptorVersion 928 ) 929 { 930 BL_ARCH_MODE OldMode; 931 EFI_STATUS EfiStatus; 932 PHYSICAL_ADDRESS MemoryMapSizePhysical, MemoryMapPhysical, MapKeyPhysical; 933 PHYSICAL_ADDRESS DescriptorSizePhysical, DescriptorVersionPhysical; 934 935 /* Are we in protected mode? */ 936 OldMode = CurrentExecutionContext->Mode; 937 if (OldMode != BlRealMode) 938 { 939 /* Convert all of the addresses to physical */ 940 BlMmTranslateVirtualAddress(MemoryMapSize, &MemoryMapSizePhysical); 941 MemoryMapSize = (UINTN*)PhysicalAddressToPtr(MemoryMapSizePhysical); 942 BlMmTranslateVirtualAddress(MemoryMap, &MemoryMapPhysical); 943 MemoryMap = (EFI_MEMORY_DESCRIPTOR*)PhysicalAddressToPtr(MemoryMapPhysical); 944 BlMmTranslateVirtualAddress(MapKey, &MapKeyPhysical); 945 MapKey = (UINTN*)PhysicalAddressToPtr(MapKeyPhysical); 946 BlMmTranslateVirtualAddress(DescriptorSize, &DescriptorSizePhysical); 947 DescriptorSize = (UINTN*)PhysicalAddressToPtr(DescriptorSizePhysical); 948 BlMmTranslateVirtualAddress(DescriptorVersion, &DescriptorVersionPhysical); 949 DescriptorVersion = (UINTN*)PhysicalAddressToPtr(DescriptorVersionPhysical); 950 951 /* Switch to real mode */ 952 BlpArchSwitchContext(BlRealMode); 953 } 954 955 /* Make the EFI call */ 956 EfiStatus = EfiBS->GetMemoryMap(MemoryMapSize, 957 MemoryMap, 958 MapKey, 959 DescriptorSize, 960 DescriptorVersion); 961 962 /* Switch back to protected mode if we came from there */ 963 if (OldMode != BlRealMode) 964 { 965 BlpArchSwitchContext(OldMode); 966 } 967 968 /* Convert the error to an NTSTATUS */ 969 return EfiGetNtStatusCode(EfiStatus); 970 } 971 972 NTSTATUS 973 EfiFreePages ( 974 _In_ ULONG Pages, 975 _In_ EFI_PHYSICAL_ADDRESS PhysicalAddress 976 ) 977 { 978 BL_ARCH_MODE OldMode; 979 EFI_STATUS EfiStatus; 980 981 /* Are we in protected mode? */ 982 OldMode = CurrentExecutionContext->Mode; 983 if (OldMode != BlRealMode) 984 { 985 /* Switch to real mode */ 986 BlpArchSwitchContext(BlRealMode); 987 } 988 989 /* Make the EFI call */ 990 EfiStatus = EfiBS->FreePages(PhysicalAddress, Pages); 991 992 /* Switch back to protected mode if we came from there */ 993 if (OldMode != BlRealMode) 994 { 995 BlpArchSwitchContext(OldMode); 996 } 997 998 /* Convert the error to an NTSTATUS */ 999 return EfiGetNtStatusCode(EfiStatus); 1000 } 1001 1002 NTSTATUS 1003 EfiStall ( 1004 _In_ ULONG StallTime 1005 ) 1006 { 1007 BL_ARCH_MODE OldMode; 1008 EFI_STATUS EfiStatus; 1009 1010 /* Are we in protected mode? */ 1011 OldMode = CurrentExecutionContext->Mode; 1012 if (OldMode != BlRealMode) 1013 { 1014 /* Switch to real mode */ 1015 BlpArchSwitchContext(BlRealMode); 1016 } 1017 1018 /* Make the EFI call */ 1019 EfiStatus = EfiBS->Stall(StallTime); 1020 1021 /* Switch back to protected mode if we came from there */ 1022 if (OldMode != BlRealMode) 1023 { 1024 BlpArchSwitchContext(OldMode); 1025 } 1026 1027 /* Convert the error to an NTSTATUS */ 1028 return EfiGetNtStatusCode(EfiStatus); 1029 } 1030 1031 NTSTATUS 1032 EfiConOutQueryMode ( 1033 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface, 1034 _In_ ULONG Mode, 1035 _In_ UINTN* Columns, 1036 _In_ UINTN* Rows 1037 ) 1038 { 1039 BL_ARCH_MODE OldMode; 1040 EFI_STATUS EfiStatus; 1041 1042 /* Are we in protected mode? */ 1043 OldMode = CurrentExecutionContext->Mode; 1044 if (OldMode != BlRealMode) 1045 { 1046 /* FIXME: Not yet implemented */ 1047 EfiPrintf(L"conqmode vm path\r\n"); 1048 EfiStall(10000000); 1049 return STATUS_NOT_IMPLEMENTED; 1050 } 1051 1052 /* Make the EFI call */ 1053 EfiStatus = TextInterface->QueryMode(TextInterface, Mode, Columns, Rows); 1054 1055 /* Switch back to protected mode if we came from there */ 1056 if (OldMode != BlRealMode) 1057 { 1058 BlpArchSwitchContext(OldMode); 1059 } 1060 1061 /* Convert the error to an NTSTATUS */ 1062 return EfiGetNtStatusCode(EfiStatus); 1063 } 1064 1065 NTSTATUS 1066 EfiConOutSetMode ( 1067 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface, 1068 _In_ ULONG Mode 1069 ) 1070 { 1071 BL_ARCH_MODE OldMode; 1072 EFI_STATUS EfiStatus; 1073 1074 /* Are we in protected mode? */ 1075 OldMode = CurrentExecutionContext->Mode; 1076 if (OldMode != BlRealMode) 1077 { 1078 /* FIXME: Not yet implemented */ 1079 EfiPrintf(L"setmode vm path\r\n"); 1080 EfiStall(10000000); 1081 return STATUS_NOT_IMPLEMENTED; 1082 } 1083 1084 /* Make the EFI call */ 1085 EfiStatus = TextInterface->SetMode(TextInterface, Mode); 1086 1087 /* Switch back to protected mode if we came from there */ 1088 if (OldMode != BlRealMode) 1089 { 1090 BlpArchSwitchContext(OldMode); 1091 } 1092 1093 /* Convert the error to an NTSTATUS */ 1094 return EfiGetNtStatusCode(EfiStatus); 1095 } 1096 1097 NTSTATUS 1098 EfiConOutSetAttribute ( 1099 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface, 1100 _In_ ULONG Attribute 1101 ) 1102 { 1103 BL_ARCH_MODE OldMode; 1104 EFI_STATUS EfiStatus; 1105 1106 /* Are we in protected mode? */ 1107 OldMode = CurrentExecutionContext->Mode; 1108 if (OldMode != BlRealMode) 1109 { 1110 /* FIXME: Not yet implemented */ 1111 EfiPrintf(L"sattr vm path\r\n"); 1112 EfiStall(10000000); 1113 return STATUS_NOT_IMPLEMENTED; 1114 } 1115 1116 /* Make the EFI call */ 1117 EfiStatus = TextInterface->SetAttribute(TextInterface, Attribute); 1118 1119 /* Switch back to protected mode if we came from there */ 1120 if (OldMode != BlRealMode) 1121 { 1122 BlpArchSwitchContext(OldMode); 1123 } 1124 1125 /* Convert the error to an NTSTATUS */ 1126 return EfiGetNtStatusCode(EfiStatus); 1127 } 1128 1129 NTSTATUS 1130 EfiConOutSetCursorPosition ( 1131 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface, 1132 _In_ ULONG Column, 1133 _In_ ULONG Row 1134 ) 1135 { 1136 BL_ARCH_MODE OldMode; 1137 EFI_STATUS EfiStatus; 1138 1139 /* Are we in protected mode? */ 1140 OldMode = CurrentExecutionContext->Mode; 1141 if (OldMode != BlRealMode) 1142 { 1143 /* FIXME: Not yet implemented */ 1144 EfiPrintf(L"setcursor vm path\r\n"); 1145 EfiStall(10000000); 1146 return STATUS_NOT_IMPLEMENTED; 1147 } 1148 1149 /* Make the EFI call */ 1150 EfiStatus = TextInterface->SetCursorPosition(TextInterface, Column, Row); 1151 1152 /* Switch back to protected mode if we came from there */ 1153 if (OldMode != BlRealMode) 1154 { 1155 BlpArchSwitchContext(OldMode); 1156 } 1157 1158 /* Convert the error to an NTSTATUS */ 1159 return EfiGetNtStatusCode(EfiStatus); 1160 } 1161 1162 NTSTATUS 1163 EfiConOutEnableCursor ( 1164 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface, 1165 _In_ BOOLEAN Visible 1166 ) 1167 { 1168 BL_ARCH_MODE OldMode; 1169 EFI_STATUS EfiStatus; 1170 1171 /* Are we in protected mode? */ 1172 OldMode = CurrentExecutionContext->Mode; 1173 if (OldMode != BlRealMode) 1174 { 1175 /* FIXME: Not yet implemented */ 1176 EfiPrintf(L"enablecurso vm path\r\n"); 1177 EfiStall(10000000); 1178 return STATUS_NOT_IMPLEMENTED; 1179 } 1180 1181 /* Make the EFI call */ 1182 EfiStatus = TextInterface->EnableCursor(TextInterface, Visible); 1183 1184 /* Switch back to protected mode if we came from there */ 1185 if (OldMode != BlRealMode) 1186 { 1187 BlpArchSwitchContext(OldMode); 1188 } 1189 1190 /* Convert the error to an NTSTATUS */ 1191 return EfiGetNtStatusCode(EfiStatus); 1192 } 1193 1194 NTSTATUS 1195 EfiConOutOutputString ( 1196 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface, 1197 _In_ PWCHAR String 1198 ) 1199 { 1200 BL_ARCH_MODE OldMode; 1201 EFI_STATUS EfiStatus; 1202 1203 /* Are we in protected mode? */ 1204 OldMode = CurrentExecutionContext->Mode; 1205 if (OldMode != BlRealMode) 1206 { 1207 /* FIXME: Not yet implemented */ 1208 EfiPrintf(L"output string vm path\r\n"); 1209 EfiStall(10000000); 1210 return STATUS_NOT_IMPLEMENTED; 1211 } 1212 1213 /* Make the EFI call */ 1214 EfiStatus = TextInterface->OutputString(TextInterface, String); 1215 1216 /* Switch back to protected mode if we came from there */ 1217 if (OldMode != BlRealMode) 1218 { 1219 BlpArchSwitchContext(OldMode); 1220 } 1221 1222 /* Convert the error to an NTSTATUS */ 1223 return EfiGetNtStatusCode(EfiStatus); 1224 } 1225 1226 VOID 1227 EfiConOutReadCurrentMode ( 1228 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface, 1229 _Out_ EFI_SIMPLE_TEXT_OUTPUT_MODE* Mode 1230 ) 1231 { 1232 BL_ARCH_MODE OldMode; 1233 1234 /* Are we in protected mode? */ 1235 OldMode = CurrentExecutionContext->Mode; 1236 if (OldMode != BlRealMode) 1237 { 1238 /* FIXME: Not yet implemented */ 1239 EfiPrintf(L"readmode vm path\r\n"); 1240 EfiStall(10000000); 1241 return; 1242 } 1243 1244 /* Make the EFI call */ 1245 RtlCopyMemory(Mode, TextInterface->Mode, sizeof(*Mode)); 1246 1247 /* Switch back to protected mode if we came from there */ 1248 if (OldMode != BlRealMode) 1249 { 1250 BlpArchSwitchContext(OldMode); 1251 } 1252 } 1253 1254 VOID 1255 EfiGopGetFrameBuffer ( 1256 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, 1257 _Out_ PHYSICAL_ADDRESS* FrameBuffer, 1258 _Out_ UINTN *FrameBufferSize 1259 ) 1260 { 1261 BL_ARCH_MODE OldMode; 1262 PHYSICAL_ADDRESS GopInterfacePhys, FrameBufferPhys, FrameBufferSizePhys; 1263 1264 /* Are we in protected mode? */ 1265 OldMode = CurrentExecutionContext->Mode; 1266 if (OldMode != BlRealMode) 1267 { 1268 /* Translate pointer to physical */ 1269 BlMmTranslateVirtualAddress(GopInterface, &GopInterfacePhys); 1270 GopInterface = PhysicalAddressToPtr(GopInterfacePhys); 1271 1272 /* Translate pointer to physical */ 1273 BlMmTranslateVirtualAddress(FrameBuffer, &FrameBufferPhys); 1274 FrameBuffer = PhysicalAddressToPtr(FrameBufferPhys); 1275 1276 /* Translate pointer to physical */ 1277 BlMmTranslateVirtualAddress(FrameBufferSize, &FrameBufferSizePhys); 1278 FrameBufferSize = PhysicalAddressToPtr(FrameBufferSizePhys); 1279 1280 /* Switch to real mode */ 1281 BlpArchSwitchContext(BlRealMode); 1282 } 1283 1284 /* Make the EFI call */ 1285 FrameBuffer->QuadPart = GopInterface->Mode->FrameBufferBase; 1286 *FrameBufferSize = GopInterface->Mode->FrameBufferSize; 1287 1288 /* Switch back to protected mode if we came from there */ 1289 if (OldMode != BlRealMode) 1290 { 1291 BlpArchSwitchContext(OldMode); 1292 } 1293 } 1294 1295 NTSTATUS 1296 EfiGopGetCurrentMode ( 1297 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, 1298 _Out_ UINTN* Mode, 1299 _Out_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information 1300 ) 1301 { 1302 BL_ARCH_MODE OldMode; 1303 PHYSICAL_ADDRESS GopInterfacePhys, ModePhys, InformationPhys; 1304 1305 /* Are we in protected mode? */ 1306 OldMode = CurrentExecutionContext->Mode; 1307 if (OldMode != BlRealMode) 1308 { 1309 /* Translate pointer to physical */ 1310 if (!BlMmTranslateVirtualAddress(GopInterface, &GopInterfacePhys)) 1311 { 1312 return STATUS_UNSUCCESSFUL; 1313 } 1314 GopInterface = PhysicalAddressToPtr(GopInterfacePhys); 1315 1316 /* Translate pointer to physical */ 1317 if (!BlMmTranslateVirtualAddress(Mode, &ModePhys)) 1318 { 1319 return STATUS_UNSUCCESSFUL; 1320 } 1321 Mode = PhysicalAddressToPtr(ModePhys); 1322 1323 /* Translate pointer to physical */ 1324 if (!BlMmTranslateVirtualAddress(Information, &InformationPhys)) 1325 { 1326 return STATUS_UNSUCCESSFUL; 1327 } 1328 Information = PhysicalAddressToPtr(InformationPhys); 1329 1330 /* Switch to real mode */ 1331 BlpArchSwitchContext(BlRealMode); 1332 } 1333 1334 /* Make the EFI call */ 1335 *Mode = GopInterface->Mode->Mode; 1336 RtlCopyMemory(Information, GopInterface->Mode->Info, sizeof(*Information)); 1337 1338 /* Switch back to protected mode if we came from there */ 1339 if (OldMode != BlRealMode) 1340 { 1341 BlpArchSwitchContext(OldMode); 1342 } 1343 1344 /* Return back */ 1345 return STATUS_SUCCESS; 1346 } 1347 1348 NTSTATUS 1349 EfiGopSetMode ( 1350 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, 1351 _In_ ULONG Mode 1352 ) 1353 { 1354 BL_ARCH_MODE OldMode; 1355 EFI_STATUS EfiStatus; 1356 BOOLEAN ModeChanged; 1357 NTSTATUS Status; 1358 1359 /* Are we in protected mode? */ 1360 OldMode = CurrentExecutionContext->Mode; 1361 if (OldMode != BlRealMode) 1362 { 1363 /* FIXME: Not yet implemented */ 1364 EfiPrintf(L"gopsmode vm path\r\n"); 1365 EfiStall(10000000); 1366 return STATUS_NOT_IMPLEMENTED; 1367 } 1368 1369 /* Make the EFI call */ 1370 if (Mode == GopInterface->Mode->Mode) 1371 { 1372 EfiStatus = EFI_SUCCESS; 1373 ModeChanged = FALSE; 1374 } 1375 { 1376 EfiStatus = GopInterface->SetMode(GopInterface, Mode); 1377 ModeChanged = TRUE; 1378 } 1379 1380 /* Switch back to protected mode if we came from there */ 1381 if (OldMode != BlRealMode) 1382 { 1383 BlpArchSwitchContext(OldMode); 1384 } 1385 1386 /* Print out to the debugger if the mode was changed */ 1387 Status = EfiGetNtStatusCode(EfiStatus); 1388 if ((ModeChanged) && (NT_SUCCESS(Status))) 1389 { 1390 /* FIXME @TODO: Should be BlStatusPrint */ 1391 EfiPrintf(L"Console video mode set to 0x%x\r\n", Mode); 1392 } 1393 1394 /* Convert the error to an NTSTATUS */ 1395 return Status; 1396 } 1397 1398 NTSTATUS 1399 EfiLocateHandleBuffer ( 1400 _In_ EFI_LOCATE_SEARCH_TYPE SearchType, 1401 _In_ EFI_GUID *Protocol, 1402 _Inout_ PULONG HandleCount, 1403 _Inout_ EFI_HANDLE** Buffer 1404 ) 1405 { 1406 BL_ARCH_MODE OldMode; 1407 EFI_STATUS EfiStatus; 1408 UINTN BufferSize; 1409 PVOID InputBuffer; 1410 BOOLEAN TranslateResult; 1411 PHYSICAL_ADDRESS BufferPhys; 1412 1413 /* Bail out if we're missing parameters */ 1414 if (!(Buffer) || !(HandleCount)) 1415 { 1416 return STATUS_INVALID_PARAMETER; 1417 } 1418 1419 /* Check if a buffer was passed in*/ 1420 InputBuffer = *Buffer; 1421 if (InputBuffer) 1422 { 1423 /* Then we should already have a buffer size*/ 1424 BufferSize = sizeof(EFI_HANDLE) * *HandleCount; 1425 } 1426 else 1427 { 1428 /* Then no buffer size exists */ 1429 BufferSize = 0; 1430 } 1431 1432 /* Are we in protected mode? */ 1433 OldMode = CurrentExecutionContext->Mode; 1434 if (OldMode != BlRealMode) 1435 { 1436 /* Translate the input buffer from virtual to physical */ 1437 TranslateResult = BlMmTranslateVirtualAddress(InputBuffer, &BufferPhys); 1438 InputBuffer = TranslateResult ? PhysicalAddressToPtr(BufferPhys) : NULL; 1439 1440 /* Switch to real mode */ 1441 BlpArchSwitchContext(BlRealMode); 1442 } 1443 1444 /* Try the first time */ 1445 EfiStatus = EfiBS->LocateHandle(SearchType, 1446 Protocol, 1447 NULL, 1448 &BufferSize, 1449 InputBuffer); 1450 1451 /* Switch back to protected mode if we came from there */ 1452 if (OldMode != BlRealMode) 1453 { 1454 BlpArchSwitchContext(OldMode); 1455 } 1456 1457 /* Check result of first search */ 1458 if (EfiStatus == EFI_BUFFER_TOO_SMALL) 1459 { 1460 /* Did we have an existing buffer? */ 1461 if (*Buffer) 1462 { 1463 /* Free it */ 1464 BlMmFreeHeap(*Buffer); 1465 } 1466 1467 /* Allocate a new one */ 1468 InputBuffer = BlMmAllocateHeap(BufferSize); 1469 *Buffer = InputBuffer; 1470 if (!InputBuffer) 1471 { 1472 /* No space, fail */ 1473 return STATUS_NO_MEMORY; 1474 } 1475 1476 if (OldMode != BlRealMode) 1477 { 1478 /* Translate the input buffer from virtual to physical */ 1479 TranslateResult = BlMmTranslateVirtualAddress(InputBuffer, 1480 &BufferPhys); 1481 InputBuffer = TranslateResult ? PhysicalAddressToPtr(BufferPhys) : NULL; 1482 1483 /* Switch to real mode */ 1484 BlpArchSwitchContext(BlRealMode); 1485 } 1486 1487 /* Try again */ 1488 EfiStatus = EfiBS->LocateHandle(SearchType, 1489 Protocol, 1490 NULL, 1491 &BufferSize, 1492 InputBuffer); 1493 1494 /* Switch back to protected mode if we came from there */ 1495 if (OldMode != BlRealMode) 1496 { 1497 BlpArchSwitchContext(OldMode); 1498 } 1499 } 1500 1501 /* Return the number of handles */ 1502 *HandleCount = BufferSize / sizeof(EFI_HANDLE); 1503 1504 /* Convert the error to an NTSTATUS */ 1505 return EfiGetNtStatusCode(EfiStatus); 1506 } 1507 1508 VOID 1509 EfiResetSystem ( 1510 _In_ EFI_RESET_TYPE ResetType 1511 ) 1512 { 1513 BL_ARCH_MODE OldMode; 1514 1515 /* Are we in protected mode? */ 1516 OldMode = CurrentExecutionContext->Mode; 1517 if (OldMode != BlRealMode) 1518 { 1519 /* FIXME: Not yet implemented */ 1520 EfiPrintf(L"reset vm path\r\n"); 1521 EfiStall(10000000); 1522 return; 1523 } 1524 1525 /* Call the EFI runtime */ 1526 EfiRT->ResetSystem(ResetType, EFI_SUCCESS, 0, NULL); 1527 } 1528 1529 NTSTATUS 1530 EfiConnectController ( 1531 _In_ EFI_HANDLE ControllerHandle 1532 ) 1533 { 1534 BL_ARCH_MODE OldMode; 1535 EFI_STATUS EfiStatus; 1536 1537 /* Is this EFI 1.02? */ 1538 if (EfiST->Hdr.Revision == EFI_1_02_SYSTEM_TABLE_REVISION) 1539 { 1540 /* This function didn't exist back then */ 1541 return STATUS_NOT_SUPPORTED; 1542 } 1543 1544 /* Are we in protected mode? */ 1545 OldMode = CurrentExecutionContext->Mode; 1546 if (OldMode != BlRealMode) 1547 { 1548 /* FIXME: Not yet implemented */ 1549 EfiPrintf(L"connectctrl vm path\r\n"); 1550 EfiStall(10000000); 1551 return STATUS_NOT_IMPLEMENTED; 1552 } 1553 1554 /* Make the EFI call */ 1555 EfiStatus = EfiBS->ConnectController(ControllerHandle, NULL, NULL, TRUE); 1556 1557 /* Switch back to protected mode if we came from there */ 1558 if (OldMode != BlRealMode) 1559 { 1560 BlpArchSwitchContext(OldMode); 1561 } 1562 1563 /* Convert the error to an NTSTATUS */ 1564 return EfiGetNtStatusCode(EfiStatus); 1565 } 1566 1567 NTSTATUS 1568 EfiAllocatePages ( 1569 _In_ ULONG Type, 1570 _In_ ULONG Pages, 1571 _Inout_ EFI_PHYSICAL_ADDRESS* Memory 1572 ) 1573 { 1574 BL_ARCH_MODE OldMode; 1575 EFI_STATUS EfiStatus; 1576 PHYSICAL_ADDRESS MemoryPhysical; 1577 1578 /* Are we in protected mode? */ 1579 OldMode = CurrentExecutionContext->Mode; 1580 if (OldMode != BlRealMode) 1581 { 1582 /* Translate output address */ 1583 BlMmTranslateVirtualAddress(Memory, &MemoryPhysical); 1584 Memory = (EFI_PHYSICAL_ADDRESS*)PhysicalAddressToPtr(MemoryPhysical); 1585 1586 /* Switch to real mode */ 1587 BlpArchSwitchContext(BlRealMode); 1588 } 1589 1590 /* Make the EFI call */ 1591 EfiStatus = EfiBS->AllocatePages(Type, EfiLoaderData, Pages, Memory); 1592 1593 /* Switch back to protected mode if we came from there */ 1594 if (OldMode != BlRealMode) 1595 { 1596 BlpArchSwitchContext(OldMode); 1597 } 1598 1599 /* Convert the error to an NTSTATUS */ 1600 return EfiGetNtStatusCode(EfiStatus); 1601 } 1602 1603 NTSTATUS 1604 EfipGetSystemTable ( 1605 _In_ EFI_GUID *TableGuid, 1606 _Out_ PPHYSICAL_ADDRESS TableAddress 1607 ) 1608 { 1609 ULONG i; 1610 NTSTATUS Status; 1611 1612 /* Assume failure */ 1613 Status = STATUS_NOT_FOUND; 1614 1615 /* Loop through the configuration tables */ 1616 for (i = 0; i < EfiST->NumberOfTableEntries; i++) 1617 { 1618 /* Check if this one matches the one we want */ 1619 if (RtlEqualMemory(&EfiST->ConfigurationTable[i].VendorGuid, 1620 TableGuid, 1621 sizeof(*TableGuid))) 1622 { 1623 /* Return its address */ 1624 TableAddress->QuadPart = (ULONG_PTR)EfiST->ConfigurationTable[i].VendorTable; 1625 Status = STATUS_SUCCESS; 1626 break; 1627 } 1628 } 1629 1630 /* Return the search result */ 1631 return Status; 1632 } 1633 1634 NTSTATUS 1635 EfipGetRsdt ( 1636 _Out_ PPHYSICAL_ADDRESS FoundRsdt 1637 ) 1638 { 1639 NTSTATUS Status; 1640 ULONG Length; 1641 PHYSICAL_ADDRESS RsdpAddress, Rsdt; 1642 PRSDP Rsdp; 1643 1644 /* Assume failure */ 1645 Length = 0; 1646 Rsdp = NULL; 1647 1648 /* Check if we already know it */ 1649 if (EfiRsdt.QuadPart) 1650 { 1651 /* Return it */ 1652 *FoundRsdt = EfiRsdt; 1653 return STATUS_SUCCESS; 1654 } 1655 1656 /* Otherwise, look for the ACPI 2.0 RSDP (XSDT really) */ 1657 Status = EfipGetSystemTable(&EfiRootAcpiTableGuid, &RsdpAddress); 1658 if (!NT_SUCCESS(Status)) 1659 { 1660 /* Didn't fint it, look for the ACPI 1.0 RSDP (RSDT really) */ 1661 Status = EfipGetSystemTable(&EfiRootAcpiTable10Guid, &RsdpAddress); 1662 if (!NT_SUCCESS(Status)) 1663 { 1664 return Status; 1665 } 1666 } 1667 1668 /* Map it */ 1669 Length = sizeof(*Rsdp); 1670 Status = BlMmMapPhysicalAddressEx((PVOID*)&Rsdp, 1671 0, 1672 Length, 1673 RsdpAddress); 1674 if (NT_SUCCESS(Status)) 1675 { 1676 /* Check the revision (anything >= 2.0 is XSDT) */ 1677 if (Rsdp->Revision) 1678 { 1679 /* Check if the table is bigger than just its header */ 1680 if (Rsdp->Length > Length) 1681 { 1682 /* Capture the real length */ 1683 Length = Rsdp->Length; 1684 1685 /* Unmap our header mapping */ 1686 BlMmUnmapVirtualAddressEx(Rsdp, sizeof(*Rsdp)); 1687 1688 /* And map the whole thing now */ 1689 Status = BlMmMapPhysicalAddressEx((PVOID*)&Rsdp, 1690 0, 1691 Length, 1692 RsdpAddress); 1693 if (!NT_SUCCESS(Status)) 1694 { 1695 return Status; 1696 } 1697 } 1698 1699 /* Read the XSDT address from the table*/ 1700 Rsdt = Rsdp->XsdtAddress; 1701 } 1702 else 1703 { 1704 /* ACPI 1.0 so just read the RSDT */ 1705 Rsdt.QuadPart = Rsdp->RsdtAddress; 1706 } 1707 1708 /* Save it for later */ 1709 EfiRsdt = Rsdt; 1710 1711 /* And return it back */ 1712 *FoundRsdt = Rsdt; 1713 } 1714 1715 /* Check if we had mapped the RSDP */ 1716 if (Rsdp) 1717 { 1718 /* Unmap it */ 1719 BlMmUnmapVirtualAddressEx(Rsdp, Length); 1720 } 1721 1722 /* Return search result back to caller */ 1723 return Status; 1724 } 1725 1726 BL_MEMORY_ATTR 1727 MmFwpGetOsAttributeType ( 1728 _In_ ULONGLONG Attribute 1729 ) 1730 { 1731 BL_MEMORY_ATTR OsAttribute = 0; 1732 1733 if (Attribute & EFI_MEMORY_UC) 1734 { 1735 OsAttribute = BlMemoryUncached; 1736 } 1737 1738 if (Attribute & EFI_MEMORY_WC) 1739 { 1740 OsAttribute |= BlMemoryWriteCombined; 1741 } 1742 1743 if (Attribute & EFI_MEMORY_WT) 1744 { 1745 OsAttribute |= BlMemoryWriteThrough; 1746 } 1747 1748 if (Attribute & EFI_MEMORY_WB) 1749 { 1750 OsAttribute |= BlMemoryWriteBack; 1751 } 1752 1753 if (Attribute & EFI_MEMORY_UCE) 1754 { 1755 OsAttribute |= BlMemoryUncachedExported; 1756 } 1757 1758 if (Attribute & EFI_MEMORY_WP) 1759 { 1760 OsAttribute |= BlMemoryWriteProtected; 1761 } 1762 1763 if (Attribute & EFI_MEMORY_RP) 1764 { 1765 OsAttribute |= BlMemoryReadProtected; 1766 } 1767 1768 if (Attribute & EFI_MEMORY_XP) 1769 { 1770 OsAttribute |= BlMemoryExecuteProtected; 1771 } 1772 1773 if (Attribute & EFI_MEMORY_RUNTIME) 1774 { 1775 OsAttribute |= BlMemoryRuntime; 1776 } 1777 1778 return OsAttribute; 1779 } 1780 1781 BL_MEMORY_TYPE 1782 MmFwpGetOsMemoryType ( 1783 _In_ EFI_MEMORY_TYPE MemoryType 1784 ) 1785 { 1786 BL_MEMORY_TYPE OsType; 1787 1788 switch (MemoryType) 1789 { 1790 case EfiLoaderCode: 1791 case EfiLoaderData: 1792 OsType = BlLoaderMemory; 1793 break; 1794 1795 case EfiBootServicesCode: 1796 case EfiBootServicesData: 1797 OsType = BlEfiBootMemory; 1798 break; 1799 1800 case EfiRuntimeServicesCode: 1801 OsType = BlEfiRuntimeCodeMemory; 1802 break; 1803 1804 case EfiRuntimeServicesData: 1805 OsType = BlEfiRuntimeDataMemory; 1806 break; 1807 1808 case EfiConventionalMemory: 1809 OsType = BlConventionalMemory; 1810 break; 1811 1812 case EfiUnusableMemory: 1813 OsType = BlUnusableMemory; 1814 break; 1815 1816 case EfiACPIReclaimMemory: 1817 OsType = BlAcpiReclaimMemory; 1818 break; 1819 1820 case EfiACPIMemoryNVS: 1821 OsType = BlAcpiNvsMemory; 1822 break; 1823 1824 case EfiMemoryMappedIO: 1825 OsType = BlDeviceIoMemory; 1826 break; 1827 1828 case EfiMemoryMappedIOPortSpace: 1829 OsType = BlDevicePortMemory; 1830 break; 1831 1832 case EfiPalCode: 1833 OsType = BlPalMemory; 1834 break; 1835 1836 default: 1837 OsType = BlReservedMemory; 1838 break; 1839 } 1840 1841 return OsType; 1842 } 1843 1844 NTSTATUS 1845 MmFwGetMemoryMap ( 1846 _Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap, 1847 _In_ ULONG Flags 1848 ) 1849 { 1850 BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters; 1851 BOOLEAN UseEfiBuffer, HaveRamDisk; 1852 NTSTATUS Status; 1853 ULONGLONG Pages, StartPage, EndPage, EfiBufferPage; 1854 UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion; 1855 EFI_PHYSICAL_ADDRESS EfiBuffer = 0; 1856 EFI_MEMORY_DESCRIPTOR* EfiMemoryMap; 1857 EFI_STATUS EfiStatus; 1858 BL_ARCH_MODE OldMode; 1859 EFI_MEMORY_DESCRIPTOR EfiDescriptor; 1860 BL_MEMORY_TYPE MemoryType; 1861 PBL_MEMORY_DESCRIPTOR Descriptor; 1862 BL_MEMORY_ATTR Attribute; 1863 PVOID LibraryBuffer; 1864 1865 /* Initialize EFI memory map attributes */ 1866 EfiMemoryMapSize = MapKey = DescriptorSize = DescriptorVersion = 0; 1867 LibraryBuffer = NULL; 1868 1869 /* Increment the nesting depth */ 1870 MmDescriptorCallTreeCount++; 1871 1872 /* Determine if we should use EFI or our own allocator at this point */ 1873 UseEfiBuffer = Flags & BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS; 1874 if (!(LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED)) 1875 { 1876 UseEfiBuffer = TRUE; 1877 } 1878 1879 /* Bail out if we don't have a list to use */ 1880 if (MemoryMap == NULL) 1881 { 1882 Status = STATUS_INVALID_PARAMETER; 1883 goto Quickie; 1884 } 1885 1886 /* Free the current descriptor list */ 1887 MmMdFreeList(MemoryMap); 1888 1889 /* Call into EFI to get the size of the memory map */ 1890 Status = EfiGetMemoryMap(&EfiMemoryMapSize, 1891 NULL, 1892 &MapKey, 1893 &DescriptorSize, 1894 &DescriptorVersion); 1895 if (Status != STATUS_BUFFER_TOO_SMALL) 1896 { 1897 /* This should've failed because our buffer was too small, nothing else */ 1898 if (NT_SUCCESS(Status)) 1899 { 1900 Status = STATUS_UNSUCCESSFUL; 1901 } 1902 goto Quickie; 1903 } 1904 1905 /* Add 4 more descriptors just in case things changed */ 1906 EfiMemoryMapSize += (4 * DescriptorSize); 1907 Pages = BYTES_TO_PAGES(EfiMemoryMapSize); 1908 1909 /* Should we use EFI to grab memory? */ 1910 if (UseEfiBuffer) 1911 { 1912 /* Yes -- request one more page to align up correctly */ 1913 Pages++; 1914 1915 /* Grab the required pages */ 1916 Status = EfiAllocatePages(AllocateAnyPages, 1917 Pages, 1918 &EfiBuffer); 1919 if (!NT_SUCCESS(Status)) 1920 { 1921 EfiPrintf(L"EFI allocation failed: %lx\r\n", Status); 1922 goto Quickie; 1923 } 1924 1925 /* Free the pages for now */ 1926 Status = EfiFreePages(Pages, EfiBuffer); 1927 if (!NT_SUCCESS(Status)) 1928 { 1929 EfiBuffer = 0; 1930 goto Quickie; 1931 } 1932 1933 /* Now round to the actual buffer size, removing the extra page */ 1934 EfiBuffer = ROUND_TO_PAGES(EfiBuffer); 1935 Pages--; 1936 Status = EfiAllocatePages(AllocateAddress, 1937 Pages, 1938 &EfiBuffer); 1939 if (!NT_SUCCESS(Status)) 1940 { 1941 EfiBuffer = 0; 1942 goto Quickie; 1943 } 1944 1945 /* Get the final aligned size and proper buffer */ 1946 EfiMemoryMapSize = EFI_PAGES_TO_SIZE(Pages); 1947 EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR*)(ULONG_PTR)EfiBuffer; 1948 1949 /* Switch to real mode if not already in it */ 1950 OldMode = CurrentExecutionContext->Mode; 1951 if (OldMode != BlRealMode) 1952 { 1953 BlpArchSwitchContext(BlRealMode); 1954 } 1955 1956 /* Call EFI to get the memory map */ 1957 EfiStatus = EfiBS->GetMemoryMap(&EfiMemoryMapSize, 1958 EfiMemoryMap, 1959 &MapKey, 1960 &DescriptorSize, 1961 &DescriptorVersion); 1962 1963 /* Switch back into the previous mode */ 1964 if (OldMode != BlRealMode) 1965 { 1966 BlpArchSwitchContext(OldMode); 1967 } 1968 1969 /* Convert the result code */ 1970 Status = EfiGetNtStatusCode(EfiStatus); 1971 } 1972 else 1973 { 1974 /* Round the map to pages */ 1975 Pages = BYTES_TO_PAGES(EfiMemoryMapSize); 1976 1977 /* Allocate a large enough buffer */ 1978 Status = MmPapAllocatePagesInRange(&LibraryBuffer, 1979 BlLoaderData, 1980 Pages, 1981 0, 1982 0, 1983 0, 1984 0); 1985 if (!NT_SUCCESS(Status)) 1986 { 1987 EfiPrintf(L"Failed to allocate mapped VM for EFI map: %lx\r\n", Status); 1988 goto Quickie; 1989 } 1990 1991 /* Call EFI to get the memory map */ 1992 EfiMemoryMap = LibraryBuffer; 1993 Status = EfiGetMemoryMap(&EfiMemoryMapSize, 1994 LibraryBuffer, 1995 &MapKey, 1996 &DescriptorSize, 1997 &DescriptorVersion); 1998 } 1999 2000 /* So far so good? */ 2001 if (!NT_SUCCESS(Status)) 2002 { 2003 EfiPrintf(L"Failed to get EFI memory map: %lx\r\n", Status); 2004 goto Quickie; 2005 } 2006 2007 /* Did we get correct data from firmware? */ 2008 if (((EfiMemoryMapSize % DescriptorSize)) || 2009 (DescriptorSize < sizeof(EFI_MEMORY_DESCRIPTOR))) 2010 { 2011 EfiPrintf(L"Incorrect descriptor size\r\n"); 2012 Status = STATUS_UNSUCCESSFUL; 2013 goto Quickie; 2014 } 2015 2016 /* Did we boot from a RAM disk? */ 2017 if ((BlpBootDevice->DeviceType == LocalDevice) && 2018 (BlpBootDevice->Local.Type == RamDiskDevice)) 2019 { 2020 /* We don't handle this yet */ 2021 EfiPrintf(L"RAM boot not supported\r\n"); 2022 Status = STATUS_NOT_IMPLEMENTED; 2023 goto Quickie; 2024 } 2025 else 2026 { 2027 /* We didn't, so there won't be any need to find the memory descriptor */ 2028 HaveRamDisk = FALSE; 2029 } 2030 2031 /* Loop the EFI memory map */ 2032 #if 0 2033 EfiPrintf(L"UEFI MEMORY MAP\r\n\r\n"); 2034 EfiPrintf(L"TYPE START END ATTRIBUTES\r\n"); 2035 EfiPrintf(L"===============================================================\r\n"); 2036 #endif 2037 while (EfiMemoryMapSize != 0) 2038 { 2039 /* Check if this is an EFI buffer, but we're not in real mode */ 2040 if ((UseEfiBuffer) && (OldMode != BlRealMode)) 2041 { 2042 BlpArchSwitchContext(BlRealMode); 2043 } 2044 2045 /* Capture it so we can go back to protected mode (if possible) */ 2046 EfiDescriptor = *EfiMemoryMap; 2047 2048 /* Go back to protected mode, if we had switched */ 2049 if ((UseEfiBuffer) && (OldMode != BlRealMode)) 2050 { 2051 BlpArchSwitchContext(OldMode); 2052 } 2053 2054 /* Convert to OS memory type */ 2055 MemoryType = MmFwpGetOsMemoryType(EfiDescriptor.Type); 2056 2057 /* Round up or round down depending on where the memory is coming from */ 2058 if (MemoryType == BlConventionalMemory) 2059 { 2060 StartPage = BYTES_TO_PAGES(EfiDescriptor.PhysicalStart); 2061 } 2062 else 2063 { 2064 StartPage = EfiDescriptor.PhysicalStart >> PAGE_SHIFT; 2065 } 2066 2067 /* Calculate the ending page */ 2068 EndPage = StartPage + EfiDescriptor.NumberOfPages; 2069 2070 /* If after rounding, we ended up with 0 pages, skip this */ 2071 if (StartPage == EndPage) 2072 { 2073 goto LoopAgain; 2074 } 2075 #if 0 2076 EfiPrintf(L"%08X 0x%016I64X-0x%016I64X 0x%I64X\r\n", 2077 MemoryType, 2078 StartPage << PAGE_SHIFT, 2079 EndPage << PAGE_SHIFT, 2080 EfiDescriptor.Attribute); 2081 #endif 2082 /* Check for any range of memory below 1MB */ 2083 if (StartPage < 0x100) 2084 { 2085 /* Does this range actually contain NULL? */ 2086 if (StartPage == 0) 2087 { 2088 /* Manually create a reserved descriptof for this page */ 2089 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute); 2090 Descriptor = MmMdInitByteGranularDescriptor(Attribute, 2091 BlReservedMemory, 2092 0, 2093 0, 2094 1); 2095 if (!Descriptor) 2096 { 2097 Status = STATUS_INSUFFICIENT_RESOURCES; 2098 break; 2099 } 2100 2101 /* Add this descriptor into the list */ 2102 Status = MmMdAddDescriptorToList(MemoryMap, 2103 Descriptor, 2104 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG); 2105 if (!NT_SUCCESS(Status)) 2106 { 2107 EfiPrintf(L"Failed to add zero page descriptor: %lx\r\n", Status); 2108 break; 2109 } 2110 2111 /* Now handle the rest of the range, unless this was it */ 2112 StartPage = 1; 2113 if (EndPage == 1) 2114 { 2115 goto LoopAgain; 2116 } 2117 } 2118 2119 /* Does the range go beyond 1MB? */ 2120 if (EndPage > 0x100) 2121 { 2122 /* Then create the descriptor for everything up until the megabyte */ 2123 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute); 2124 Descriptor = MmMdInitByteGranularDescriptor(Attribute, 2125 MemoryType, 2126 StartPage, 2127 0, 2128 0x100 - StartPage); 2129 if (!Descriptor) 2130 { 2131 Status = STATUS_INSUFFICIENT_RESOURCES; 2132 break; 2133 } 2134 2135 /* Check if this region is currently free RAM */ 2136 if (Descriptor->Type == BlConventionalMemory) 2137 { 2138 /* Set the appropriate flag on the descriptor */ 2139 Descriptor->Flags |= BlMemoryBelow1MB; 2140 } 2141 2142 /* Add this descriptor into the list */ 2143 Status = MmMdAddDescriptorToList(MemoryMap, 2144 Descriptor, 2145 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG); 2146 if (!NT_SUCCESS(Status)) 2147 { 2148 EfiPrintf(L"Failed to add 1MB descriptor: %lx\r\n", Status); 2149 break; 2150 } 2151 2152 /* Now handle the rest of the range above 1MB */ 2153 StartPage = 0x100; 2154 } 2155 } 2156 2157 /* Check if we loaded from a RAM disk */ 2158 if (HaveRamDisk) 2159 { 2160 /* We don't handle this yet */ 2161 EfiPrintf(L"RAM boot not supported\r\n"); 2162 Status = STATUS_NOT_IMPLEMENTED; 2163 goto Quickie; 2164 } 2165 2166 /* Create a descriptor for the current range */ 2167 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute); 2168 Descriptor = MmMdInitByteGranularDescriptor(Attribute, 2169 MemoryType, 2170 StartPage, 2171 0, 2172 EndPage - StartPage); 2173 if (!Descriptor) 2174 { 2175 Status = STATUS_INSUFFICIENT_RESOURCES; 2176 break; 2177 } 2178 2179 /* Check if this region is currently free RAM below 1MB */ 2180 if ((Descriptor->Type == BlConventionalMemory) && (EndPage <= 0x100)) 2181 { 2182 /* Set the appropriate flag on the descriptor */ 2183 Descriptor->Flags |= BlMemoryBelow1MB; 2184 } 2185 2186 /* Add the descriptor to the list, requesting coalescing as asked */ 2187 Status = MmMdAddDescriptorToList(MemoryMap, 2188 Descriptor, 2189 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG | 2190 ((Flags & BL_MM_FLAG_REQUEST_COALESCING) ? 2191 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG : 0)); 2192 if (!NT_SUCCESS(Status)) 2193 { 2194 EfiPrintf(L"Failed to add full descriptor: %lx\r\n", Status); 2195 break; 2196 } 2197 2198 LoopAgain: 2199 /* Consume this descriptor, and move to the next one */ 2200 EfiMemoryMapSize -= DescriptorSize; 2201 EfiMemoryMap = (PVOID)((ULONG_PTR)EfiMemoryMap + DescriptorSize); 2202 } 2203 2204 /* Check if we are using the local UEFI buffer */ 2205 if (!UseEfiBuffer) 2206 { 2207 goto Quickie; 2208 } 2209 2210 /* Free the EFI buffer */ 2211 Status = EfiFreePages(Pages, EfiBuffer); 2212 if (!NT_SUCCESS(Status)) 2213 { 2214 /* Keep the pages marked 'in use' and fake success */ 2215 Status = STATUS_SUCCESS; 2216 goto Quickie; 2217 } 2218 2219 /* Get the base page of the EFI buffer */ 2220 EfiBufferPage = EfiBuffer >> PAGE_SHIFT; 2221 Pages = (EfiBufferPage + Pages) - EfiBufferPage; 2222 2223 /* Don't try freeing below */ 2224 EfiBuffer = 0; 2225 2226 /* Find the current descriptor for the allocation */ 2227 Descriptor = MmMdFindDescriptorFromMdl(MemoryMap, 2228 BL_MM_REMOVE_PHYSICAL_REGION_FLAG, 2229 EfiBufferPage); 2230 if (!Descriptor) 2231 { 2232 Status = STATUS_UNSUCCESSFUL; 2233 goto Quickie; 2234 } 2235 2236 /* Convert it to a free descriptor */ 2237 Descriptor = MmMdInitByteGranularDescriptor(Descriptor->Flags, 2238 BlConventionalMemory, 2239 EfiBufferPage, 2240 0, 2241 Pages); 2242 if (!Descriptor) 2243 { 2244 Status = STATUS_INSUFFICIENT_RESOURCES; 2245 goto Quickie; 2246 } 2247 2248 /* Remove the region from the memory map */ 2249 Status = MmMdRemoveRegionFromMdlEx(MemoryMap, 2250 BL_MM_REMOVE_PHYSICAL_REGION_FLAG, 2251 EfiBufferPage, 2252 Pages, 2253 NULL); 2254 if (!NT_SUCCESS(Status)) 2255 { 2256 MmMdFreeDescriptor(Descriptor); 2257 goto Quickie; 2258 } 2259 2260 /* Add it back as free memory */ 2261 Status = MmMdAddDescriptorToList(MemoryMap, 2262 Descriptor, 2263 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG); 2264 2265 Quickie: 2266 /* Free the EFI buffer, if we had one */ 2267 if (EfiBuffer != 0) 2268 { 2269 EfiFreePages(Pages, EfiBuffer); 2270 } 2271 2272 /* Free the library-allocated buffer, if we had one */ 2273 if (LibraryBuffer != 0) 2274 { 2275 MmPapFreePages(LibraryBuffer, BL_MM_INCLUDE_MAPPED_ALLOCATED); 2276 } 2277 2278 /* On failure, free the memory map if one was passed in */ 2279 if (!NT_SUCCESS(Status) && (MemoryMap != NULL)) 2280 { 2281 MmMdFreeList(MemoryMap); 2282 } 2283 2284 /* Decrement the nesting depth and return */ 2285 MmDescriptorCallTreeCount--; 2286 return Status; 2287 } 2288 2289 NTSTATUS 2290 BlpFwInitialize ( 2291 _In_ ULONG Phase, 2292 _In_ PBL_FIRMWARE_DESCRIPTOR FirmwareData 2293 ) 2294 { 2295 NTSTATUS Status = STATUS_SUCCESS; 2296 EFI_KEY_TOGGLE_STATE KeyToggleState; 2297 2298 /* Check if we have valid firmware data */ 2299 if (!(FirmwareData) || !(FirmwareData->Version)) 2300 { 2301 return STATUS_INVALID_PARAMETER; 2302 } 2303 2304 /* Check which boot phase we're in */ 2305 if (Phase != 0) 2306 { 2307 /* Memory manager is ready, open the extended input protocol */ 2308 Status = EfiOpenProtocol(EfiST->ConsoleInHandle, 2309 &EfiSimpleTextInputExProtocol, 2310 (PVOID*)&EfiConInEx); 2311 if (NT_SUCCESS(Status)) 2312 { 2313 /* Set the initial key toggle state */ 2314 KeyToggleState = EFI_TOGGLE_STATE_VALID | 40; 2315 EfiConInExSetState(EfiConInEx, &KeyToggleState); 2316 } 2317 2318 /* Setup the watchdog timer */ 2319 EfiSetWatchdogTimer(); 2320 } 2321 else 2322 { 2323 /* Make a copy of the parameters */ 2324 EfiFirmwareParameters = &EfiFirmwareData; 2325 2326 /* Check which version we received */ 2327 if (FirmwareData->Version == 1) 2328 { 2329 /* FIXME: Not supported */ 2330 Status = STATUS_NOT_SUPPORTED; 2331 } 2332 else if (FirmwareData->Version >= BL_FIRMWARE_DESCRIPTOR_VERSION) 2333 { 2334 /* Version 2 -- save the data */ 2335 EfiFirmwareData = *FirmwareData; 2336 EfiSystemTable = FirmwareData->SystemTable; 2337 EfiImageHandle = FirmwareData->ImageHandle; 2338 2339 /* Set the EDK-II style variables as well */ 2340 EfiST = EfiSystemTable; 2341 EfiBS = EfiSystemTable->BootServices; 2342 EfiRT = EfiSystemTable->RuntimeServices; 2343 EfiConOut = EfiSystemTable->ConOut; 2344 EfiConIn = EfiSystemTable->ConIn; 2345 EfiConInEx = NULL; 2346 } 2347 else 2348 { 2349 /* Unknown version */ 2350 Status = STATUS_NOT_SUPPORTED; 2351 } 2352 } 2353 2354 /* Return the initialization state */ 2355 return Status; 2356 } 2357 2358 NTSTATUS 2359 BlFwGetParameters ( 2360 _In_ PBL_FIRMWARE_DESCRIPTOR Parameters 2361 ) 2362 { 2363 /* Make sure we got an argument */ 2364 if (!Parameters) 2365 { 2366 return STATUS_INVALID_PARAMETER; 2367 } 2368 2369 /* Copy the static data */ 2370 *Parameters = *EfiFirmwareParameters; 2371 return STATUS_SUCCESS; 2372 } 2373 2374 NTSTATUS 2375 BlFwEnumerateDevice ( 2376 _In_ PBL_DEVICE_DESCRIPTOR Device 2377 ) 2378 { 2379 NTSTATUS Status; 2380 ULONG PathProtocols, BlockProtocols; 2381 EFI_HANDLE* PathArray; 2382 EFI_HANDLE* BlockArray; 2383 2384 /* Initialize locals */ 2385 BlockArray = NULL; 2386 PathArray = NULL; 2387 PathProtocols = 0; 2388 BlockProtocols = 0; 2389 2390 /* Enumeration only makes sense on disks or partitions */ 2391 if ((Device->DeviceType != DiskDevice) && 2392 (Device->DeviceType != LegacyPartitionDevice) && 2393 (Device->DeviceType != PartitionDevice)) 2394 { 2395 return STATUS_NOT_SUPPORTED; 2396 } 2397 2398 /* Enumerate the list of device paths */ 2399 Status = EfiLocateHandleBuffer(ByProtocol, 2400 &EfiDevicePathProtocol, 2401 &PathProtocols, 2402 &PathArray); 2403 if (NT_SUCCESS(Status)) 2404 { 2405 /* Loop through each one */ 2406 Status = STATUS_NOT_FOUND; 2407 while (PathProtocols) 2408 { 2409 /* Attempt to connect the driver for this device epath */ 2410 Status = EfiConnectController(PathArray[--PathProtocols]); 2411 if (NT_SUCCESS(Status)) 2412 { 2413 /* Now enumerate any block I/O devices the driver added */ 2414 Status = EfiLocateHandleBuffer(ByProtocol, 2415 &EfiBlockIoProtocol, 2416 &BlockProtocols, 2417 &BlockArray); 2418 if (!NT_SUCCESS(Status)) 2419 { 2420 break; 2421 } 2422 2423 /* Loop through each one */ 2424 while (BlockProtocols) 2425 { 2426 /* Check if one of the new devices is the one we want */ 2427 Status = BlockIoEfiCompareDevice(Device, 2428 BlockArray[--BlockProtocols]); 2429 if (NT_SUCCESS(Status)) 2430 { 2431 /* Yep, all done */ 2432 goto Quickie; 2433 } 2434 } 2435 2436 /* Move on to the next device path */ 2437 BlMmFreeHeap(BlockArray); 2438 BlockArray = NULL; 2439 } 2440 } 2441 } 2442 2443 Quickie: 2444 /* We're done -- free the array of device path protocols, if any */ 2445 if (PathArray) 2446 { 2447 BlMmFreeHeap(PathArray); 2448 } 2449 2450 /* We're done -- free the array of block I/O protocols, if any */ 2451 if (BlockArray) 2452 { 2453 BlMmFreeHeap(BlockArray); 2454 } 2455 2456 /* Return if we found the device or not */ 2457 return Status; 2458 } 2459 2460 /*++ 2461 * @name EfiGetEfiStatusCode 2462 * 2463 * The EfiGetEfiStatusCode routine converts an NT Status to an EFI status. 2464 * 2465 * @param Status 2466 * NT Status code to be converted. 2467 * 2468 * @remark Only certain, specific NT status codes are converted to EFI codes. 2469 * 2470 * @return The corresponding EFI Status code, EFI_NO_MAPPING otherwise. 2471 * 2472 *--*/ 2473 EFI_STATUS 2474 EfiGetEfiStatusCode( 2475 _In_ NTSTATUS Status 2476 ) 2477 { 2478 switch (Status) 2479 { 2480 case STATUS_NOT_SUPPORTED: 2481 return EFI_UNSUPPORTED; 2482 case STATUS_DISK_FULL: 2483 return EFI_VOLUME_FULL; 2484 case STATUS_INSUFFICIENT_RESOURCES: 2485 return EFI_OUT_OF_RESOURCES; 2486 case STATUS_MEDIA_WRITE_PROTECTED: 2487 return EFI_WRITE_PROTECTED; 2488 case STATUS_DEVICE_NOT_READY: 2489 return EFI_NOT_STARTED; 2490 case STATUS_DEVICE_ALREADY_ATTACHED: 2491 return EFI_ALREADY_STARTED; 2492 case STATUS_MEDIA_CHANGED: 2493 return EFI_MEDIA_CHANGED; 2494 case STATUS_INVALID_PARAMETER: 2495 return EFI_INVALID_PARAMETER; 2496 case STATUS_ACCESS_DENIED: 2497 return EFI_ACCESS_DENIED; 2498 case STATUS_BUFFER_TOO_SMALL: 2499 return EFI_BUFFER_TOO_SMALL; 2500 case STATUS_DISK_CORRUPT_ERROR: 2501 return EFI_VOLUME_CORRUPTED; 2502 case STATUS_REQUEST_ABORTED: 2503 return EFI_ABORTED; 2504 case STATUS_NO_MEDIA: 2505 return EFI_NO_MEDIA; 2506 case STATUS_IO_DEVICE_ERROR: 2507 return EFI_DEVICE_ERROR; 2508 case STATUS_INVALID_BUFFER_SIZE: 2509 return EFI_BAD_BUFFER_SIZE; 2510 case STATUS_NOT_FOUND: 2511 return EFI_NOT_FOUND; 2512 case STATUS_DRIVER_UNABLE_TO_LOAD: 2513 return EFI_LOAD_ERROR; 2514 case STATUS_NO_MATCH: 2515 return EFI_NO_MAPPING; 2516 case STATUS_SUCCESS: 2517 return EFI_SUCCESS; 2518 case STATUS_TIMEOUT: 2519 return EFI_TIMEOUT; 2520 default: 2521 return EFI_NO_MAPPING; 2522 } 2523 } 2524 2525 /*++ 2526 * @name EfiGetNtStatusCode 2527 * 2528 * The EfiGetNtStatusCode routine converts an EFI Status to an NT status. 2529 * 2530 * @param EfiStatus 2531 * EFI Status code to be converted. 2532 * 2533 * @remark Only certain, specific EFI status codes are converted to NT codes. 2534 * 2535 * @return The corresponding NT Status code, STATUS_UNSUCCESSFUL otherwise. 2536 * 2537 *--*/ 2538 NTSTATUS 2539 EfiGetNtStatusCode ( 2540 _In_ EFI_STATUS EfiStatus 2541 ) 2542 { 2543 switch (EfiStatus) 2544 { 2545 case EFI_NOT_READY: 2546 case EFI_NOT_FOUND: 2547 return STATUS_NOT_FOUND; 2548 case EFI_NO_MEDIA: 2549 return STATUS_NO_MEDIA; 2550 case EFI_MEDIA_CHANGED: 2551 return STATUS_MEDIA_CHANGED; 2552 case EFI_ACCESS_DENIED: 2553 case EFI_SECURITY_VIOLATION: 2554 return STATUS_ACCESS_DENIED; 2555 case EFI_TIMEOUT: 2556 case EFI_NO_RESPONSE: 2557 return STATUS_TIMEOUT; 2558 case EFI_NO_MAPPING: 2559 return STATUS_NO_MATCH; 2560 case EFI_NOT_STARTED: 2561 return STATUS_DEVICE_NOT_READY; 2562 case EFI_ALREADY_STARTED: 2563 return STATUS_DEVICE_ALREADY_ATTACHED; 2564 case EFI_ABORTED: 2565 return STATUS_REQUEST_ABORTED; 2566 case EFI_VOLUME_FULL: 2567 return STATUS_DISK_FULL; 2568 case EFI_DEVICE_ERROR: 2569 return STATUS_IO_DEVICE_ERROR; 2570 case EFI_WRITE_PROTECTED: 2571 return STATUS_MEDIA_WRITE_PROTECTED; 2572 /* @FIXME: ReactOS Headers don't yet have this */ 2573 //case EFI_OUT_OF_RESOURCES: 2574 //return STATUS_INSUFFICIENT_NVRAM_RESOURCES; 2575 case EFI_VOLUME_CORRUPTED: 2576 return STATUS_DISK_CORRUPT_ERROR; 2577 case EFI_BUFFER_TOO_SMALL: 2578 return STATUS_BUFFER_TOO_SMALL; 2579 case EFI_SUCCESS: 2580 return STATUS_SUCCESS; 2581 case EFI_LOAD_ERROR: 2582 return STATUS_DRIVER_UNABLE_TO_LOAD; 2583 case EFI_INVALID_PARAMETER: 2584 return STATUS_INVALID_PARAMETER; 2585 case EFI_UNSUPPORTED: 2586 return STATUS_NOT_SUPPORTED; 2587 case EFI_BAD_BUFFER_SIZE: 2588 return STATUS_INVALID_BUFFER_SIZE; 2589 default: 2590 return STATUS_UNSUCCESSFUL; 2591 } 2592 } 2593