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)
9 /* INCLUDES ******************************************************************/
13 /* DATA VARIABLES ************************************************************/
15 PBL_FIRMWARE_DESCRIPTOR EfiFirmwareParameters
;
16 BL_FIRMWARE_DESCRIPTOR EfiFirmwareData
;
17 EFI_HANDLE EfiImageHandle
;
18 EFI_SYSTEM_TABLE
* EfiSystemTable
;
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
;
27 EFI_GUID EfiGraphicsOutputProtocol
= EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID
;
28 EFI_GUID EfiUgaDrawProtocol
= EFI_UGA_DRAW_PROTOCOL_GUID
;
29 EFI_GUID EfiLoadedImageProtocol
= EFI_LOADED_IMAGE_PROTOCOL_GUID
;
30 EFI_GUID EfiDevicePathProtocol
= EFI_DEVICE_PATH_PROTOCOL_GUID
;
31 EFI_GUID EfiSimpleTextInputExProtocol
= EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
;
32 EFI_GUID EfiBlockIoProtocol
= EFI_BLOCK_IO_PROTOCOL_GUID
;
34 WCHAR BlScratchBuffer
[8192];
36 /* FUNCTIONS *****************************************************************/
39 EfiIsDevicePathParent (
40 _In_ EFI_DEVICE_PATH
*DevicePath1
,
41 _In_ EFI_DEVICE_PATH
*DevicePath2
44 USHORT Length1
, Length2
;
46 /* Loop each element of the device path */
47 while (!IsDevicePathEndType(DevicePath1
) && !IsDevicePathEndType(DevicePath2
))
49 /* Check if the element has a different length */
50 Length1
= DevicePathNodeLength(DevicePath1
);
51 Length2
= DevicePathNodeLength(DevicePath2
);
52 if (Length1
!= Length2
)
54 /* Then they're not related */
58 /* Check if the rest of the element data matches */
59 if (RtlCompareMemory(DevicePath1
, DevicePath2
, Length1
) != Length1
)
61 /* Nope, not related */
65 /* Move to the next element */
66 DevicePath1
= NextDevicePathNode(DevicePath1
);
67 DevicePath2
= NextDevicePathNode(DevicePath2
);
70 /* If the last element in path 1 is empty, then path 2 is the child (deeper) */
71 if (!IsDevicePathEndType(DevicePath1
))
76 /* If the last element in path 2 is empty, then path 1 is the child (deeper) */
77 if (!IsDevicePathEndType(DevicePath2
))
82 /* They're both the end, so they're identical, so there's no parent */
88 _In_ EFI_DEVICE_PATH
*DevicePath
91 EFI_DEVICE_PATH
*NextDevicePath
;
93 /* Make sure we're not already at the end */
94 if (!IsDevicePathEndType(DevicePath
))
96 /* Grab the next node element, and keep going until the end */
97 for (NextDevicePath
= NextDevicePathNode(DevicePath
);
98 !IsDevicePathEndType(NextDevicePath
);
99 NextDevicePath
= NextDevicePathNode(NextDevicePath
))
101 /* Save the current node we're at */
102 DevicePath
= NextDevicePath
;
106 /* This now contains the deepeest (leaf) node */
117 va_start(args
, Format
);
119 /* Capture the buffer in our scratch pad, and NULL-terminate */
120 vsnwprintf(BlScratchBuffer
, RTL_NUMBER_OF(BlScratchBuffer
) - 1, Format
, args
);
121 BlScratchBuffer
[RTL_NUMBER_OF(BlScratchBuffer
) - 1] = UNICODE_NULL
;
123 /* Check which mode we're in */
124 if (CurrentExecutionContext
->Mode
== BlRealMode
)
126 /* Call EFI directly */
127 EfiConOut
->OutputString(EfiConOut
, BlScratchBuffer
);
131 /* FIXME: @TODO: Not yet supported */
140 _In_ EFI_HANDLE Handle
,
141 _In_ EFI_GUID
*Protocol
,
142 _Out_ PVOID
* Interface
145 EFI_STATUS EfiStatus
;
147 BL_ARCH_MODE OldMode
;
149 /* Are we using virtual memory/ */
150 if (MmTranslationType
!= BlNone
)
152 /* We need complex tracking to make this work */
153 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
154 Status
= STATUS_NOT_SUPPORTED
;
158 /* Are we in protected mode? */
159 OldMode
= CurrentExecutionContext
->Mode
;
160 if (OldMode
!= BlRealMode
)
162 /* FIXME: Not yet implemented */
163 return STATUS_NOT_IMPLEMENTED
;
166 /* Are we on legacy 1.02? */
167 if (EfiST
->FirmwareRevision
== EFI_1_02_SYSTEM_TABLE_REVISION
)
169 /* Make the legacy call */
170 EfiStatus
= EfiBS
->HandleProtocol(Handle
, Protocol
, Interface
);
174 /* Use the UEFI version */
175 EfiStatus
= EfiBS
->OpenProtocol(Handle
,
180 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
182 /* Switch back to protected mode if we came from there */
183 if (OldMode
!= BlRealMode
)
185 BlpArchSwitchContext(OldMode
);
189 /* Convert the error to an NTSTATUS */
190 Status
= EfiGetNtStatusCode(EfiStatus
);
193 /* Clear the interface on failure, and return the status */
194 if (!NT_SUCCESS(Status
))
204 _In_ EFI_HANDLE Handle
,
205 _In_ EFI_GUID
*Protocol
208 EFI_STATUS EfiStatus
;
210 BL_ARCH_MODE OldMode
;
212 /* Are we using virtual memory/ */
213 if (MmTranslationType
!= BlNone
)
215 /* We need complex tracking to make this work */
216 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
217 Status
= STATUS_NOT_SUPPORTED
;
221 /* Are we on legacy 1.02? */
222 if (EfiST
->FirmwareRevision
== EFI_1_02_SYSTEM_TABLE_REVISION
)
224 /* Nothing to close */
225 EfiStatus
= STATUS_SUCCESS
;
229 /* Are we in protected mode? */
230 OldMode
= CurrentExecutionContext
->Mode
;
231 if (OldMode
!= BlRealMode
)
233 /* FIXME: Not yet implemented */
234 return STATUS_NOT_IMPLEMENTED
;
237 /* Use the UEFI version */
238 EfiStatus
= EfiBS
->CloseProtocol(Handle
, Protocol
, EfiImageHandle
, NULL
);
240 /* Switch back to protected mode if we came from there */
241 if (OldMode
!= BlRealMode
)
243 BlpArchSwitchContext(OldMode
);
246 /* Normalize not found as success */
247 if (EfiStatus
== EFI_NOT_FOUND
)
249 EfiStatus
= EFI_SUCCESS
;
253 /* Convert the error to an NTSTATUS */
254 Status
= EfiGetNtStatusCode(EfiStatus
);
266 BL_ARCH_MODE OldMode
;
267 EFI_STATUS EfiStatus
;
269 /* Are we in protected mode? */
270 OldMode
= CurrentExecutionContext
->Mode
;
271 if (OldMode
!= BlRealMode
)
273 /* FIXME: Not yet implemented */
274 return STATUS_NOT_IMPLEMENTED
;
277 /* Make the EFI call */
278 EfiStatus
= EfiConIn
->Reset(EfiConIn
, FALSE
);
280 /* Switch back to protected mode if we came from there */
281 if (OldMode
!= BlRealMode
)
283 BlpArchSwitchContext(OldMode
);
286 /* Convert the error to an NTSTATUS */
287 return EfiGetNtStatusCode(EfiStatus
);
295 BL_ARCH_MODE OldMode
;
296 EFI_STATUS EfiStatus
;
298 /* Are we in protected mode? */
299 OldMode
= CurrentExecutionContext
->Mode
;
300 if (OldMode
!= BlRealMode
)
302 /* FIXME: Not yet implemented */
303 return STATUS_NOT_IMPLEMENTED
;
306 /* Make the EFI call */
307 EfiStatus
= EfiConInEx
->Reset(EfiConInEx
, FALSE
);
309 /* Switch back to protected mode if we came from there */
310 if (OldMode
!= BlRealMode
)
312 BlpArchSwitchContext(OldMode
);
315 /* Convert the error to an NTSTATUS */
316 return EfiGetNtStatusCode(EfiStatus
);
321 _In_ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*ConInEx
,
322 _In_ EFI_KEY_TOGGLE_STATE
* KeyToggleState
325 BL_ARCH_MODE OldMode
;
326 EFI_STATUS EfiStatus
;
328 /* Are we in protected mode? */
329 OldMode
= CurrentExecutionContext
->Mode
;
330 if (OldMode
!= BlRealMode
)
332 /* FIXME: Not yet implemented */
333 return STATUS_NOT_IMPLEMENTED
;
336 /* Make the EFI call */
337 EfiStatus
= ConInEx
->SetState(ConInEx
, KeyToggleState
);
339 /* Switch back to protected mode if we came from there */
340 if (OldMode
!= BlRealMode
)
342 BlpArchSwitchContext(OldMode
);
345 /* Convert the error to an NTSTATUS */
346 return EfiGetNtStatusCode(EfiStatus
);
350 EfiSetWatchdogTimer (
354 BL_ARCH_MODE OldMode
;
355 EFI_STATUS EfiStatus
;
357 /* Are we in protected mode? */
358 OldMode
= CurrentExecutionContext
->Mode
;
359 if (OldMode
!= BlRealMode
)
361 /* FIXME: Not yet implemented */
362 return STATUS_NOT_IMPLEMENTED
;
365 /* Make the EFI call */
366 EfiStatus
= EfiBS
->SetWatchdogTimer(0, 0, 0, NULL
);
368 /* Switch back to protected mode if we came from there */
369 if (OldMode
!= BlRealMode
)
371 BlpArchSwitchContext(OldMode
);
374 /* Convert the error to an NTSTATUS */
375 return EfiGetNtStatusCode(EfiStatus
);
380 _Out_ UINTN
* MemoryMapSize
,
381 _Inout_ EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
383 _Out_ UINTN
* DescriptorSize
,
384 _Out_ UINTN
* DescriptorVersion
387 BL_ARCH_MODE OldMode
;
388 EFI_STATUS EfiStatus
;
390 /* Are we in protected mode? */
391 OldMode
= CurrentExecutionContext
->Mode
;
392 if (OldMode
!= BlRealMode
)
394 /* FIXME: Not yet implemented */
395 return STATUS_NOT_IMPLEMENTED
;
398 /* Make the EFI call */
399 EfiStatus
= EfiBS
->GetMemoryMap(MemoryMapSize
,
405 /* Switch back to protected mode if we came from there */
406 if (OldMode
!= BlRealMode
)
408 BlpArchSwitchContext(OldMode
);
411 /* Convert the error to an NTSTATUS */
412 return EfiGetNtStatusCode(EfiStatus
);
418 _In_ EFI_PHYSICAL_ADDRESS PhysicalAddress
421 BL_ARCH_MODE OldMode
;
422 EFI_STATUS EfiStatus
;
424 /* Are we in protected mode? */
425 OldMode
= CurrentExecutionContext
->Mode
;
426 if (OldMode
!= BlRealMode
)
428 /* FIXME: Not yet implemented */
429 return STATUS_NOT_IMPLEMENTED
;
432 /* Make the EFI call */
433 EfiStatus
= EfiBS
->FreePages(PhysicalAddress
, Pages
);
435 /* Switch back to protected mode if we came from there */
436 if (OldMode
!= BlRealMode
)
438 BlpArchSwitchContext(OldMode
);
441 /* Convert the error to an NTSTATUS */
442 return EfiGetNtStatusCode(EfiStatus
);
450 BL_ARCH_MODE OldMode
;
451 EFI_STATUS EfiStatus
;
453 /* Are we in protected mode? */
454 OldMode
= CurrentExecutionContext
->Mode
;
455 if (OldMode
!= BlRealMode
)
457 /* FIXME: Not yet implemented */
458 return STATUS_NOT_IMPLEMENTED
;
461 /* Make the EFI call */
462 EfiStatus
= EfiBS
->Stall(StallTime
);
464 /* Switch back to protected mode if we came from there */
465 if (OldMode
!= BlRealMode
)
467 BlpArchSwitchContext(OldMode
);
470 /* Convert the error to an NTSTATUS */
471 return EfiGetNtStatusCode(EfiStatus
);
476 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
482 BL_ARCH_MODE OldMode
;
483 EFI_STATUS EfiStatus
;
485 /* Are we in protected mode? */
486 OldMode
= CurrentExecutionContext
->Mode
;
487 if (OldMode
!= BlRealMode
)
489 /* FIXME: Not yet implemented */
490 return STATUS_NOT_IMPLEMENTED
;
493 /* Make the EFI call */
494 EfiStatus
= TextInterface
->QueryMode(TextInterface
, Mode
, Columns
, Rows
);
496 /* Switch back to protected mode if we came from there */
497 if (OldMode
!= BlRealMode
)
499 BlpArchSwitchContext(OldMode
);
502 /* Convert the error to an NTSTATUS */
503 return EfiGetNtStatusCode(EfiStatus
);
508 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
512 BL_ARCH_MODE OldMode
;
513 EFI_STATUS EfiStatus
;
515 /* Are we in protected mode? */
516 OldMode
= CurrentExecutionContext
->Mode
;
517 if (OldMode
!= BlRealMode
)
519 /* FIXME: Not yet implemented */
520 return STATUS_NOT_IMPLEMENTED
;
523 /* Make the EFI call */
524 EfiStatus
= TextInterface
->SetMode(TextInterface
, Mode
);
526 /* Switch back to protected mode if we came from there */
527 if (OldMode
!= BlRealMode
)
529 BlpArchSwitchContext(OldMode
);
532 /* Convert the error to an NTSTATUS */
533 return EfiGetNtStatusCode(EfiStatus
);
537 EfiConOutSetAttribute (
538 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
542 BL_ARCH_MODE OldMode
;
543 EFI_STATUS EfiStatus
;
545 /* Are we in protected mode? */
546 OldMode
= CurrentExecutionContext
->Mode
;
547 if (OldMode
!= BlRealMode
)
549 /* FIXME: Not yet implemented */
550 return STATUS_NOT_IMPLEMENTED
;
553 /* Make the EFI call */
554 EfiStatus
= TextInterface
->SetAttribute(TextInterface
, Attribute
);
556 /* Switch back to protected mode if we came from there */
557 if (OldMode
!= BlRealMode
)
559 BlpArchSwitchContext(OldMode
);
562 /* Convert the error to an NTSTATUS */
563 return EfiGetNtStatusCode(EfiStatus
);
567 EfiConOutSetCursorPosition (
568 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
573 BL_ARCH_MODE OldMode
;
574 EFI_STATUS EfiStatus
;
576 /* Are we in protected mode? */
577 OldMode
= CurrentExecutionContext
->Mode
;
578 if (OldMode
!= BlRealMode
)
580 /* FIXME: Not yet implemented */
581 return STATUS_NOT_IMPLEMENTED
;
584 /* Make the EFI call */
585 EfiStatus
= TextInterface
->SetCursorPosition(TextInterface
, Column
, Row
);
587 /* Switch back to protected mode if we came from there */
588 if (OldMode
!= BlRealMode
)
590 BlpArchSwitchContext(OldMode
);
593 /* Convert the error to an NTSTATUS */
594 return EfiGetNtStatusCode(EfiStatus
);
598 EfiConOutEnableCursor (
599 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
603 BL_ARCH_MODE OldMode
;
604 EFI_STATUS EfiStatus
;
606 /* Are we in protected mode? */
607 OldMode
= CurrentExecutionContext
->Mode
;
608 if (OldMode
!= BlRealMode
)
610 /* FIXME: Not yet implemented */
611 return STATUS_NOT_IMPLEMENTED
;
614 /* Make the EFI call */
615 EfiStatus
= TextInterface
->EnableCursor(TextInterface
, Visible
);
617 /* Switch back to protected mode if we came from there */
618 if (OldMode
!= BlRealMode
)
620 BlpArchSwitchContext(OldMode
);
623 /* Convert the error to an NTSTATUS */
624 return EfiGetNtStatusCode(EfiStatus
);
628 EfiConOutReadCurrentMode (
629 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
630 _Out_ EFI_SIMPLE_TEXT_OUTPUT_MODE
* Mode
633 BL_ARCH_MODE OldMode
;
635 /* Are we in protected mode? */
636 OldMode
= CurrentExecutionContext
->Mode
;
637 if (OldMode
!= BlRealMode
)
639 /* FIXME: Not yet implemented */
643 /* Make the EFI call */
644 RtlCopyMemory(Mode
, TextInterface
->Mode
, sizeof(*Mode
));
646 /* Switch back to protected mode if we came from there */
647 if (OldMode
!= BlRealMode
)
649 BlpArchSwitchContext(OldMode
);
654 EfiGopGetFrameBuffer (
655 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL
*GopInterface
,
656 _Out_ PHYSICAL_ADDRESS
* FrameBuffer
,
657 _Out_ UINTN
*FrameBufferSize
660 BL_ARCH_MODE OldMode
;
662 /* Are we in protected mode? */
663 OldMode
= CurrentExecutionContext
->Mode
;
664 if (OldMode
!= BlRealMode
)
666 /* FIXME: Not yet implemented */
670 /* Make the EFI call */
671 FrameBuffer
->QuadPart
= GopInterface
->Mode
->FrameBufferBase
;
672 *FrameBufferSize
= GopInterface
->Mode
->FrameBufferSize
;
674 /* Switch back to protected mode if we came from there */
675 if (OldMode
!= BlRealMode
)
677 BlpArchSwitchContext(OldMode
);
682 EfiGopGetCurrentMode (
683 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL
*GopInterface
,
685 _Out_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Information
688 BL_ARCH_MODE OldMode
;
690 /* Are we in protected mode? */
691 OldMode
= CurrentExecutionContext
->Mode
;
692 if (OldMode
!= BlRealMode
)
694 /* FIXME: Not yet implemented */
695 return STATUS_NOT_IMPLEMENTED
;
698 /* Make the EFI call */
699 *Mode
= GopInterface
->Mode
->Mode
;
700 RtlCopyMemory(Information
, GopInterface
->Mode
->Info
, sizeof(*Information
));
702 /* Switch back to protected mode if we came from there */
703 if (OldMode
!= BlRealMode
)
705 BlpArchSwitchContext(OldMode
);
709 return STATUS_SUCCESS
;
714 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL
*GopInterface
,
718 BL_ARCH_MODE OldMode
;
719 EFI_STATUS EfiStatus
;
723 /* Are we in protected mode? */
724 OldMode
= CurrentExecutionContext
->Mode
;
725 if (OldMode
!= BlRealMode
)
727 /* FIXME: Not yet implemented */
728 return STATUS_NOT_IMPLEMENTED
;
731 /* Make the EFI call */
732 if (Mode
== GopInterface
->Mode
->Mode
)
734 EfiStatus
= EFI_SUCCESS
;
738 EfiStatus
= GopInterface
->SetMode(GopInterface
, Mode
);
742 /* Switch back to protected mode if we came from there */
743 if (OldMode
!= BlRealMode
)
745 BlpArchSwitchContext(OldMode
);
748 /* Print out to the debugger if the mode was changed */
749 Status
= EfiGetNtStatusCode(EfiStatus
);
750 if ((ModeChanged
) && (NT_SUCCESS(Status
)))
752 /* FIXME @TODO: Should be BlStatusPrint */
753 EfiPrintf(L
"Console video mode set to 0x%x\r\r\n", Mode
);
756 /* Convert the error to an NTSTATUS */
761 EfiLocateHandleBuffer (
762 _In_ EFI_LOCATE_SEARCH_TYPE SearchType
,
763 _In_ EFI_GUID
*Protocol
,
764 _Inout_ PULONG HandleCount
,
765 _Inout_ EFI_HANDLE
** Buffer
768 BL_ARCH_MODE OldMode
;
769 EFI_STATUS EfiStatus
;
772 /* Bail out if we're missing parameters */
773 if (!(Buffer
) || !(HandleCount
))
775 return STATUS_INVALID_PARAMETER
;
778 /* Check if a buffer was passed in*/
781 /* Then we should already have a buffer size*/
782 BufferSize
= sizeof(EFI_HANDLE
) * *HandleCount
;
786 /* Then no buffer size exists */
790 /* Are we in protected mode? */
791 OldMode
= CurrentExecutionContext
->Mode
;
792 if (OldMode
!= BlRealMode
)
794 /* FIXME: Not yet implemented */
795 return STATUS_NOT_IMPLEMENTED
;
798 /* Try the first time */
799 EfiStatus
= EfiBS
->LocateHandle(SearchType
, Protocol
, NULL
, &BufferSize
, *Buffer
);
800 if (EfiStatus
== EFI_BUFFER_TOO_SMALL
)
802 /* Did we have an existing buffer? */
806 BlMmFreeHeap(*Buffer
);
809 /* Allocate a new one */
810 *Buffer
= BlMmAllocateHeap(BufferSize
);
814 return STATUS_NO_MEMORY
;
818 EfiStatus
= EfiBS
->LocateHandle(SearchType
, Protocol
, NULL
, &BufferSize
, *Buffer
);
820 /* Switch back to protected mode if we came from there */
821 if (OldMode
!= BlRealMode
)
823 BlpArchSwitchContext(OldMode
);
827 /* Return the number of handles */
828 *HandleCount
= BufferSize
/ sizeof(EFI_HANDLE
);
830 /* Convert the error to an NTSTATUS */
831 return EfiGetNtStatusCode(EfiStatus
);
836 _In_ EFI_RESET_TYPE ResetType
839 BL_ARCH_MODE OldMode
;
841 /* Are we in protected mode? */
842 OldMode
= CurrentExecutionContext
->Mode
;
843 if (OldMode
!= BlRealMode
)
845 /* FIXME: Not yet implemented */
849 /* Call the EFI runtime */
850 EfiRT
->ResetSystem(ResetType
, EFI_SUCCESS
, 0, NULL
);
857 _Inout_ EFI_PHYSICAL_ADDRESS
* Memory
860 BL_ARCH_MODE OldMode
;
861 EFI_STATUS EfiStatus
;
863 /* Are we in protected mode? */
864 OldMode
= CurrentExecutionContext
->Mode
;
865 if (OldMode
!= BlRealMode
)
867 /* FIXME: Not yet implemented */
868 return STATUS_NOT_IMPLEMENTED
;
871 /* Make the EFI call */
872 EfiStatus
= EfiBS
->AllocatePages(Type
, EfiLoaderData
, Pages
, Memory
);
874 /* Switch back to protected mode if we came from there */
875 if (OldMode
!= BlRealMode
)
877 BlpArchSwitchContext(OldMode
);
880 /* Convert the error to an NTSTATUS */
881 return EfiGetNtStatusCode(EfiStatus
);
885 MmFwpGetOsAttributeType (
886 _In_ ULONGLONG Attribute
889 BL_MEMORY_ATTR OsAttribute
= 0;
891 if (Attribute
& EFI_MEMORY_UC
)
893 OsAttribute
= BlMemoryUncached
;
896 if (Attribute
& EFI_MEMORY_WC
)
898 OsAttribute
|= BlMemoryWriteCombined
;
901 if (Attribute
& EFI_MEMORY_WT
)
903 OsAttribute
|= BlMemoryWriteThrough
;
906 if (Attribute
& EFI_MEMORY_WB
)
908 OsAttribute
|= BlMemoryWriteBack
;
911 if (Attribute
& EFI_MEMORY_UCE
)
913 OsAttribute
|= BlMemoryUncachedExported
;
916 if (Attribute
& EFI_MEMORY_WP
)
918 OsAttribute
|= BlMemoryWriteProtected
;
921 if (Attribute
& EFI_MEMORY_RP
)
923 OsAttribute
|= BlMemoryReadProtected
;
926 if (Attribute
& EFI_MEMORY_XP
)
928 OsAttribute
|= BlMemoryExecuteProtected
;
931 if (Attribute
& EFI_MEMORY_RUNTIME
)
933 OsAttribute
|= BlMemoryRuntime
;
940 MmFwpGetOsMemoryType (
941 _In_ EFI_MEMORY_TYPE MemoryType
944 BL_MEMORY_TYPE OsType
;
950 OsType
= BlLoaderMemory
;
953 case EfiBootServicesCode
:
954 case EfiBootServicesData
:
955 OsType
= BlEfiBootMemory
;
958 case EfiRuntimeServicesCode
:
959 case EfiRuntimeServicesData
:
960 OsType
= BlEfiRuntimeMemory
;
963 case EfiConventionalMemory
:
964 OsType
= BlConventionalMemory
;
967 case EfiUnusableMemory
:
968 OsType
= BlUnusableMemory
;
971 case EfiACPIReclaimMemory
:
972 OsType
= BlAcpiReclaimMemory
;
975 case EfiACPIMemoryNVS
:
976 OsType
= BlAcpiNvsMemory
;
979 case EfiMemoryMappedIO
:
980 OsType
= BlDeviceIoMemory
;
983 case EfiMemoryMappedIOPortSpace
:
984 OsType
= BlDevicePortMemory
;
988 OsType
= BlPalMemory
;
992 OsType
= BlReservedMemory
;
1001 _Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap
,
1005 BL_LIBRARY_PARAMETERS LibraryParameters
= BlpLibraryParameters
;
1006 BOOLEAN UseEfiBuffer
, HaveRamDisk
;
1008 ULONGLONG Pages
, StartPage
, EndPage
;
1009 UINTN EfiMemoryMapSize
, MapKey
, DescriptorSize
, DescriptorVersion
;
1010 EFI_PHYSICAL_ADDRESS EfiBuffer
;
1011 EFI_MEMORY_DESCRIPTOR
* EfiMemoryMap
;
1012 EFI_STATUS EfiStatus
;
1013 BL_ARCH_MODE OldMode
;
1014 EFI_MEMORY_DESCRIPTOR EfiDescriptor
;
1015 BL_MEMORY_TYPE MemoryType
;
1016 PBL_MEMORY_DESCRIPTOR Descriptor
;
1017 BL_MEMORY_ATTR Attribute
;
1019 /* Initialize EFI memory map attributes */
1020 EfiMemoryMapSize
= MapKey
= DescriptorSize
= DescriptorVersion
= 0;
1022 /* Increment the nesting depth */
1023 MmDescriptorCallTreeCount
++;
1025 /* Determine if we should use EFI or our own allocator at this point */
1026 UseEfiBuffer
= Flags
& BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS
;
1027 if (!(LibraryParameters
.LibraryFlags
& BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED
))
1029 UseEfiBuffer
= TRUE
;
1032 /* Bail out if we don't have a list to use */
1033 if (MemoryMap
== NULL
)
1035 Status
= STATUS_INVALID_PARAMETER
;
1039 /* Free the current descriptor list */
1040 MmMdFreeList(MemoryMap
);
1042 /* Call into EFI to get the size of the memory map */
1043 Status
= EfiGetMemoryMap(&EfiMemoryMapSize
,
1047 &DescriptorVersion
);
1048 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1050 /* This should've failed because our buffer was too small, nothing else */
1051 EfiPrintf(L
"Got strange EFI status for memory map: %lx\r\n", Status
);
1052 if (NT_SUCCESS(Status
))
1054 Status
= STATUS_UNSUCCESSFUL
;
1059 /* Add 4 more descriptors just in case things changed */
1060 EfiMemoryMapSize
+= (4 * DescriptorSize
);
1061 Pages
= BYTES_TO_PAGES(EfiMemoryMapSize
);
1062 EfiPrintf(L
"Memory map size: %lx bytes, %d pages\r\n", EfiMemoryMapSize
, Pages
);
1064 /* Should we use EFI to grab memory? */
1067 /* Yes -- request one more page to align up correctly */
1070 /* Grab the required pages */
1071 Status
= EfiAllocatePages(AllocateAnyPages
,
1074 if (!NT_SUCCESS(Status
))
1076 EfiPrintf(L
"EFI allocation failed: %lx\r\n", Status
);
1080 /* Free the pages for now */
1081 Status
= EfiFreePages(Pages
, EfiBuffer
);
1082 if (!NT_SUCCESS(Status
))
1088 /* Now round to the actual buffer size, removing the extra page */
1089 EfiBuffer
= ROUND_TO_PAGES(EfiBuffer
);
1091 Status
= EfiAllocatePages(AllocateAddress
,
1094 if (!NT_SUCCESS(Status
))
1100 /* Get the final aligned size and proper buffer */
1101 EfiMemoryMapSize
= EFI_PAGES_TO_SIZE(Pages
);
1102 EfiMemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)(ULONG_PTR
)EfiBuffer
;
1104 /* Switch to real mode if not already in it */
1105 OldMode
= CurrentExecutionContext
->Mode
;
1106 if (OldMode
!= BlRealMode
)
1108 BlpArchSwitchContext(BlRealMode
);
1111 /* Call EFI to get the memory map */
1112 EfiStatus
= EfiBS
->GetMemoryMap(&EfiMemoryMapSize
,
1116 &DescriptorVersion
);
1118 /* Switch back into the previous mode */
1119 if (OldMode
!= BlRealMode
)
1121 BlpArchSwitchContext(OldMode
);
1124 /* Convert the result code */
1125 Status
= EfiGetNtStatusCode(EfiStatus
);
1129 /* We don't support this path yet */
1130 Status
= STATUS_NOT_IMPLEMENTED
;
1133 /* So far so good? */
1134 if (!NT_SUCCESS(Status
))
1136 EfiPrintf(L
"Failed to get EFI memory map: %lx\r\n", Status
);
1140 /* Did we get correct data from firmware? */
1141 if (((EfiMemoryMapSize
% DescriptorSize
)) ||
1142 (DescriptorSize
< sizeof(EFI_MEMORY_DESCRIPTOR
)))
1144 EfiPrintf(L
"Incorrect descriptor size\r\n");
1145 Status
= STATUS_UNSUCCESSFUL
;
1149 /* Did we boot from a RAM disk? */
1150 if ((BlpBootDevice
->DeviceType
== LocalDevice
) &&
1151 (BlpBootDevice
->Local
.Type
== RamDiskDevice
))
1153 /* We don't handle this yet */
1154 EfiPrintf(L
"RAM boot not supported\r\n");
1155 Status
= STATUS_NOT_IMPLEMENTED
;
1160 /* We didn't, so there won't be any need to find the memory descriptor */
1161 HaveRamDisk
= FALSE
;
1164 /* Loop the EFI memory map */
1166 EfiPrintf(L
"UEFI MEMORY MAP\n\r\n");
1167 EfiPrintf(L
"TYPE START END ATTRIBUTES\r\n");
1168 EfiPrintf(L
"===============================================================\r\n");
1170 while (EfiMemoryMapSize
!= 0)
1172 /* Check if this is an EFI buffer, but we're not in real mode */
1173 if ((UseEfiBuffer
) && (OldMode
!= BlRealMode
))
1175 BlpArchSwitchContext(BlRealMode
);
1178 /* Capture it so we can go back to protected mode (if possible) */
1179 EfiDescriptor
= *EfiMemoryMap
;
1181 /* Go back to protected mode, if we had switched */
1182 if ((UseEfiBuffer
) && (OldMode
!= BlRealMode
))
1184 BlpArchSwitchContext(OldMode
);
1187 /* Convert to OS memory type */
1188 MemoryType
= MmFwpGetOsMemoryType(EfiDescriptor
.Type
);
1190 /* Round up or round down depending on where the memory is coming from */
1191 if (MemoryType
== BlConventionalMemory
)
1193 StartPage
= BYTES_TO_PAGES(EfiDescriptor
.PhysicalStart
);
1197 StartPage
= EfiDescriptor
.PhysicalStart
>> PAGE_SHIFT
;
1200 /* Calculate the ending page */
1201 EndPage
= StartPage
+ EfiDescriptor
.NumberOfPages
;
1203 /* If after rounding, we ended up with 0 pages, skip this */
1204 if (StartPage
== EndPage
)
1209 EfiPrintf(L
"%08X 0x%016I64X-0x%016I64X 0x%I64X\r\n",
1211 StartPage
<< PAGE_SHIFT
,
1212 EndPage
<< PAGE_SHIFT
,
1213 EfiDescriptor
.Attribute
);
1215 /* Check for any range of memory below 1MB */
1216 if (StartPage
< 0x100)
1218 /* Does this range actually contain NULL? */
1221 /* Manually create a reserved descriptof for this page */
1222 Attribute
= MmFwpGetOsAttributeType(EfiDescriptor
.Attribute
);
1223 Descriptor
= MmMdInitByteGranularDescriptor(Attribute
,
1230 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1234 /* Add this descriptor into the list */
1235 Status
= MmMdAddDescriptorToList(MemoryMap
,
1237 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
);
1238 if (!NT_SUCCESS(Status
))
1240 EfiPrintf(L
"Failed to add zero page descriptor: %lx\r\n", Status
);
1244 /* Now handle the rest of the range, unless this was it */
1252 /* Does the range go beyond 1MB? */
1253 if (EndPage
> 0x100)
1255 /* Then create the descriptor for everything up until the megabyte */
1256 Attribute
= MmFwpGetOsAttributeType(EfiDescriptor
.Attribute
);
1257 Descriptor
= MmMdInitByteGranularDescriptor(Attribute
,
1264 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1268 /* Check if this region is currently free RAM */
1269 if (Descriptor
->Type
== BlConventionalMemory
)
1271 /* Set the reserved flag on the descriptor */
1272 Descriptor
->Flags
|= BlReservedMemory
;
1275 /* Add this descriptor into the list */
1276 Status
= MmMdAddDescriptorToList(MemoryMap
,
1278 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
);
1279 if (!NT_SUCCESS(Status
))
1281 EfiPrintf(L
"Failed to add 1MB descriptor: %lx\r\n", Status
);
1285 /* Now handle the rest of the range above 1MB */
1290 /* Check if we loaded from a RAM disk */
1293 /* We don't handle this yet */
1294 EfiPrintf(L
"RAM boot not supported\r\n");
1295 Status
= STATUS_NOT_IMPLEMENTED
;
1299 /* Create a descriptor for the current range */
1300 Attribute
= MmFwpGetOsAttributeType(EfiDescriptor
.Attribute
);
1301 Descriptor
= MmMdInitByteGranularDescriptor(Attribute
,
1305 EndPage
- StartPage
);
1308 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1312 /* Check if this region is currently free RAM below 1MB */
1313 if ((Descriptor
->Type
== BlConventionalMemory
) && (EndPage
<= 0x100))
1315 /* Set the reserved flag on the descriptor */
1316 Descriptor
->Flags
|= BlReservedMemory
;
1319 /* Add the descriptor to the list, requesting coalescing as asked */
1320 Status
= MmMdAddDescriptorToList(MemoryMap
,
1322 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
|
1323 (Flags
& BL_MM_FLAG_REQUEST_COALESCING
) ?
1324 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
: 0);
1325 if (!NT_SUCCESS(Status
))
1327 EfiPrintf(L
"Failed to add full descriptor: %lx\r\n", Status
);
1332 /* Consume this descriptor, and move to the next one */
1333 EfiMemoryMapSize
-= DescriptorSize
;
1334 EfiMemoryMap
= (PVOID
)((ULONG_PTR
)EfiMemoryMap
+ DescriptorSize
);
1337 /* FIXME: @TODO: Mark the EfiBuffer as free, since we're about to free it */
1338 /* For now, just "leak" the 1-2 pages... */
1341 /* Free the EFI buffer, if we had one */
1344 EfiFreePages(Pages
, EfiBuffer
);
1347 /* On failure, free the memory map if one was passed in */
1348 if (!NT_SUCCESS(Status
) && (MemoryMap
!= NULL
))
1350 MmMdFreeList(MemoryMap
);
1353 /* Decrement the nesting depth and return */
1354 MmDescriptorCallTreeCount
--;
1361 _In_ PBL_FIRMWARE_DESCRIPTOR FirmwareData
1364 NTSTATUS Status
= STATUS_SUCCESS
;
1365 EFI_KEY_TOGGLE_STATE KeyToggleState
;
1367 /* Check if we have vaild firmware data */
1368 if (!(FirmwareData
) || !(FirmwareData
->Version
))
1370 return STATUS_INVALID_PARAMETER
;
1373 /* Check which boot phase we're in */
1376 /* Memory manager is ready, open the extended input protocol */
1377 Status
= EfiOpenProtocol(EfiST
->ConsoleInHandle
,
1378 &EfiSimpleTextInputExProtocol
,
1379 (PVOID
*)&EfiConInEx
);
1380 if (NT_SUCCESS(Status
))
1382 /* Set the initial key toggle state */
1383 KeyToggleState
= EFI_TOGGLE_STATE_VALID
| 40;
1384 EfiConInExSetState(EfiConInEx
, &KeyToggleState
);
1387 /* Setup the watchdog timer */
1388 EfiSetWatchdogTimer();
1392 /* Make a copy of the parameters */
1393 EfiFirmwareParameters
= &EfiFirmwareData
;
1395 /* Check which version we received */
1396 if (FirmwareData
->Version
== 1)
1398 /* FIXME: Not supported */
1399 Status
= STATUS_NOT_SUPPORTED
;
1401 else if (FirmwareData
->Version
>= 2)
1403 /* Version 2 -- save the data */
1404 EfiFirmwareData
= *FirmwareData
;
1405 EfiSystemTable
= FirmwareData
->SystemTable
;
1406 EfiImageHandle
= FirmwareData
->ImageHandle
;
1408 /* Set the EDK-II style variables as well */
1409 EfiST
= EfiSystemTable
;
1410 EfiBS
= EfiSystemTable
->BootServices
;
1411 EfiRT
= EfiSystemTable
->RuntimeServices
;
1412 EfiConOut
= EfiSystemTable
->ConOut
;
1413 EfiConIn
= EfiSystemTable
->ConIn
;
1418 /* Unknown version */
1419 Status
= STATUS_NOT_SUPPORTED
;
1423 /* Return the initialization state */
1429 * @name EfiGetEfiStatusCode
1431 * The EfiGetEfiStatusCode routine converts an NT Status to an EFI status.
1434 * NT Status code to be converted.
1436 * @remark Only certain, specific NT status codes are converted to EFI codes.
1438 * @return The corresponding EFI Status code, EFI_NO_MAPPING otherwise.
1442 EfiGetEfiStatusCode(
1443 _In_ NTSTATUS Status
1448 case STATUS_NOT_SUPPORTED
:
1449 return EFI_UNSUPPORTED
;
1450 case STATUS_DISK_FULL
:
1451 return EFI_VOLUME_FULL
;
1452 case STATUS_INSUFFICIENT_RESOURCES
:
1453 return EFI_OUT_OF_RESOURCES
;
1454 case STATUS_MEDIA_WRITE_PROTECTED
:
1455 return EFI_WRITE_PROTECTED
;
1456 case STATUS_DEVICE_NOT_READY
:
1457 return EFI_NOT_STARTED
;
1458 case STATUS_DEVICE_ALREADY_ATTACHED
:
1459 return EFI_ALREADY_STARTED
;
1460 case STATUS_MEDIA_CHANGED
:
1461 return EFI_MEDIA_CHANGED
;
1462 case STATUS_INVALID_PARAMETER
:
1463 return EFI_INVALID_PARAMETER
;
1464 case STATUS_ACCESS_DENIED
:
1465 return EFI_ACCESS_DENIED
;
1466 case STATUS_BUFFER_TOO_SMALL
:
1467 return EFI_BUFFER_TOO_SMALL
;
1468 case STATUS_DISK_CORRUPT_ERROR
:
1469 return EFI_VOLUME_CORRUPTED
;
1470 case STATUS_REQUEST_ABORTED
:
1472 case STATUS_NO_MEDIA
:
1473 return EFI_NO_MEDIA
;
1474 case STATUS_IO_DEVICE_ERROR
:
1475 return EFI_DEVICE_ERROR
;
1476 case STATUS_INVALID_BUFFER_SIZE
:
1477 return EFI_BAD_BUFFER_SIZE
;
1478 case STATUS_NOT_FOUND
:
1479 return EFI_NOT_FOUND
;
1480 case STATUS_DRIVER_UNABLE_TO_LOAD
:
1481 return EFI_LOAD_ERROR
;
1482 case STATUS_NO_MATCH
:
1483 return EFI_NO_MAPPING
;
1484 case STATUS_SUCCESS
:
1486 case STATUS_TIMEOUT
:
1489 return EFI_NO_MAPPING
;
1494 * @name EfiGetNtStatusCode
1496 * The EfiGetNtStatusCode routine converts an EFI Status to an NT status.
1499 * EFI Status code to be converted.
1501 * @remark Only certain, specific EFI status codes are converted to NT codes.
1503 * @return The corresponding NT Status code, STATUS_UNSUCCESSFUL otherwise.
1507 EfiGetNtStatusCode (
1508 _In_ EFI_STATUS EfiStatus
1515 return STATUS_NOT_FOUND
;
1517 return STATUS_NO_MEDIA
;
1518 case EFI_MEDIA_CHANGED
:
1519 return STATUS_MEDIA_CHANGED
;
1520 case EFI_ACCESS_DENIED
:
1521 case EFI_SECURITY_VIOLATION
:
1522 return STATUS_ACCESS_DENIED
;
1524 case EFI_NO_RESPONSE
:
1525 return STATUS_TIMEOUT
;
1526 case EFI_NO_MAPPING
:
1527 return STATUS_NO_MATCH
;
1528 case EFI_NOT_STARTED
:
1529 return STATUS_DEVICE_NOT_READY
;
1530 case EFI_ALREADY_STARTED
:
1531 return STATUS_DEVICE_ALREADY_ATTACHED
;
1533 return STATUS_REQUEST_ABORTED
;
1534 case EFI_VOLUME_FULL
:
1535 return STATUS_DISK_FULL
;
1536 case EFI_DEVICE_ERROR
:
1537 return STATUS_IO_DEVICE_ERROR
;
1538 case EFI_WRITE_PROTECTED
:
1539 return STATUS_MEDIA_WRITE_PROTECTED
;
1540 /* @FIXME: ReactOS Headers don't yet have this */
1541 //case EFI_OUT_OF_RESOURCES:
1542 //return STATUS_INSUFFICIENT_NVRAM_RESOURCES;
1543 case EFI_VOLUME_CORRUPTED
:
1544 return STATUS_DISK_CORRUPT_ERROR
;
1545 case EFI_BUFFER_TOO_SMALL
:
1546 return STATUS_BUFFER_TOO_SMALL
;
1548 return STATUS_SUCCESS
;
1549 case EFI_LOAD_ERROR
:
1550 return STATUS_DRIVER_UNABLE_TO_LOAD
;
1551 case EFI_INVALID_PARAMETER
:
1552 return STATUS_INVALID_PARAMETER
;
1553 case EFI_UNSUPPORTED
:
1554 return STATUS_NOT_SUPPORTED
;
1555 case EFI_BAD_BUFFER_SIZE
:
1556 return STATUS_INVALID_BUFFER_SIZE
;
1558 return STATUS_UNSUCCESSFUL
;