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
;
33 WCHAR BlScratchBuffer
[8192];
35 /* FUNCTIONS *****************************************************************/
44 va_start(args
, Format
);
46 /* Capture the buffer in our scratch pad, and NULL-terminate */
47 vsnwprintf(BlScratchBuffer
, RTL_NUMBER_OF(BlScratchBuffer
) - 1, Format
, args
);
48 BlScratchBuffer
[RTL_NUMBER_OF(BlScratchBuffer
) - 1] = UNICODE_NULL
;
50 /* Check which mode we're in */
51 if (CurrentExecutionContext
->Mode
== BlRealMode
)
53 /* Call EFI directly */
54 EfiConOut
->OutputString(EfiConOut
, BlScratchBuffer
);
58 /* FIXME: @TODO: Not yet supported */
67 _In_ EFI_HANDLE Handle
,
68 _In_ EFI_GUID
*Protocol
,
69 _Out_ PVOID
* Interface
76 /* Are we using virtual memory/ */
77 if (MmTranslationType
!= BlNone
)
79 /* We need complex tracking to make this work */
80 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
81 Status
= STATUS_NOT_SUPPORTED
;
85 /* Are we in protected mode? */
86 OldMode
= CurrentExecutionContext
->Mode
;
87 if (OldMode
!= BlRealMode
)
89 /* FIXME: Not yet implemented */
90 return STATUS_NOT_IMPLEMENTED
;
93 /* Are we on legacy 1.02? */
94 if (EfiST
->FirmwareRevision
== EFI_1_02_SYSTEM_TABLE_REVISION
)
96 /* Make the legacy call */
97 EfiStatus
= EfiBS
->HandleProtocol(Handle
, Protocol
, Interface
);
101 /* Use the UEFI version */
102 EfiStatus
= EfiBS
->OpenProtocol(Handle
,
107 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
109 /* Switch back to protected mode if we came from there */
110 if (OldMode
!= BlRealMode
)
112 BlpArchSwitchContext(OldMode
);
116 /* Convert the error to an NTSTATUS */
117 Status
= EfiGetNtStatusCode(EfiStatus
);
120 /* Clear the interface on failure, and return the status */
121 if (!NT_SUCCESS(Status
))
131 _In_ EFI_HANDLE Handle
,
132 _In_ EFI_GUID
*Protocol
135 EFI_STATUS EfiStatus
;
137 BL_ARCH_MODE OldMode
;
139 /* Are we using virtual memory/ */
140 if (MmTranslationType
!= BlNone
)
142 /* We need complex tracking to make this work */
143 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
144 Status
= STATUS_NOT_SUPPORTED
;
148 /* Are we on legacy 1.02? */
149 if (EfiST
->FirmwareRevision
== EFI_1_02_SYSTEM_TABLE_REVISION
)
151 /* Nothing to close */
152 EfiStatus
= STATUS_SUCCESS
;
156 /* Are we in protected mode? */
157 OldMode
= CurrentExecutionContext
->Mode
;
158 if (OldMode
!= BlRealMode
)
160 /* FIXME: Not yet implemented */
161 return STATUS_NOT_IMPLEMENTED
;
164 /* Use the UEFI version */
165 EfiStatus
= EfiBS
->CloseProtocol(Handle
, Protocol
, EfiImageHandle
, NULL
);
167 /* Switch back to protected mode if we came from there */
168 if (OldMode
!= BlRealMode
)
170 BlpArchSwitchContext(OldMode
);
173 /* Normalize not found as success */
174 if (EfiStatus
== EFI_NOT_FOUND
)
176 EfiStatus
= EFI_SUCCESS
;
180 /* Convert the error to an NTSTATUS */
181 Status
= EfiGetNtStatusCode(EfiStatus
);
190 _In_ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*ConInEx
,
191 _In_ EFI_KEY_TOGGLE_STATE
* KeyToggleState
194 BL_ARCH_MODE OldMode
;
195 EFI_STATUS EfiStatus
;
197 /* Are we in protected mode? */
198 OldMode
= CurrentExecutionContext
->Mode
;
199 if (OldMode
!= BlRealMode
)
201 /* FIXME: Not yet implemented */
202 return STATUS_NOT_IMPLEMENTED
;
205 /* Make the EFI call */
206 EfiStatus
= ConInEx
->SetState(ConInEx
, KeyToggleState
);
208 /* Switch back to protected mode if we came from there */
209 if (OldMode
!= BlRealMode
)
211 BlpArchSwitchContext(OldMode
);
214 /* Convert the error to an NTSTATUS */
215 return EfiGetNtStatusCode(EfiStatus
);
219 EfiSetWatchdogTimer (
223 BL_ARCH_MODE OldMode
;
224 EFI_STATUS EfiStatus
;
226 /* Are we in protected mode? */
227 OldMode
= CurrentExecutionContext
->Mode
;
228 if (OldMode
!= BlRealMode
)
230 /* FIXME: Not yet implemented */
231 return STATUS_NOT_IMPLEMENTED
;
234 /* Make the EFI call */
235 EfiStatus
= EfiBS
->SetWatchdogTimer(0, 0, 0, NULL
);
237 /* Switch back to protected mode if we came from there */
238 if (OldMode
!= BlRealMode
)
240 BlpArchSwitchContext(OldMode
);
243 /* Convert the error to an NTSTATUS */
244 return EfiGetNtStatusCode(EfiStatus
);
249 _Out_ UINTN
* MemoryMapSize
,
250 _Inout_ EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
252 _Out_ UINTN
* DescriptorSize
,
253 _Out_ UINTN
* DescriptorVersion
256 BL_ARCH_MODE OldMode
;
257 EFI_STATUS EfiStatus
;
259 /* Are we in protected mode? */
260 OldMode
= CurrentExecutionContext
->Mode
;
261 if (OldMode
!= BlRealMode
)
263 /* FIXME: Not yet implemented */
264 return STATUS_NOT_IMPLEMENTED
;
267 /* Make the EFI call */
268 EfiStatus
= EfiBS
->GetMemoryMap(MemoryMapSize
,
274 /* Switch back to protected mode if we came from there */
275 if (OldMode
!= BlRealMode
)
277 BlpArchSwitchContext(OldMode
);
280 /* Convert the error to an NTSTATUS */
281 return EfiGetNtStatusCode(EfiStatus
);
287 _In_ EFI_PHYSICAL_ADDRESS PhysicalAddress
290 BL_ARCH_MODE OldMode
;
291 EFI_STATUS EfiStatus
;
293 /* Are we in protected mode? */
294 OldMode
= CurrentExecutionContext
->Mode
;
295 if (OldMode
!= BlRealMode
)
297 /* FIXME: Not yet implemented */
298 return STATUS_NOT_IMPLEMENTED
;
301 /* Make the EFI call */
302 EfiStatus
= EfiBS
->FreePages(PhysicalAddress
, Pages
);
304 /* Switch back to protected mode if we came from there */
305 if (OldMode
!= BlRealMode
)
307 BlpArchSwitchContext(OldMode
);
310 /* Convert the error to an NTSTATUS */
311 return EfiGetNtStatusCode(EfiStatus
);
319 BL_ARCH_MODE OldMode
;
320 EFI_STATUS EfiStatus
;
322 /* Are we in protected mode? */
323 OldMode
= CurrentExecutionContext
->Mode
;
324 if (OldMode
!= BlRealMode
)
326 /* FIXME: Not yet implemented */
327 return STATUS_NOT_IMPLEMENTED
;
330 /* Make the EFI call */
331 EfiStatus
= EfiBS
->Stall(StallTime
);
333 /* Switch back to protected mode if we came from there */
334 if (OldMode
!= BlRealMode
)
336 BlpArchSwitchContext(OldMode
);
339 /* Convert the error to an NTSTATUS */
340 return EfiGetNtStatusCode(EfiStatus
);
345 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
351 BL_ARCH_MODE OldMode
;
352 EFI_STATUS EfiStatus
;
354 /* Are we in protected mode? */
355 OldMode
= CurrentExecutionContext
->Mode
;
356 if (OldMode
!= BlRealMode
)
358 /* FIXME: Not yet implemented */
359 return STATUS_NOT_IMPLEMENTED
;
362 /* Make the EFI call */
363 EfiStatus
= TextInterface
->QueryMode(TextInterface
, Mode
, Columns
, Rows
);
365 /* Switch back to protected mode if we came from there */
366 if (OldMode
!= BlRealMode
)
368 BlpArchSwitchContext(OldMode
);
371 /* Convert the error to an NTSTATUS */
372 return EfiGetNtStatusCode(EfiStatus
);
377 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
381 BL_ARCH_MODE OldMode
;
382 EFI_STATUS EfiStatus
;
384 /* Are we in protected mode? */
385 OldMode
= CurrentExecutionContext
->Mode
;
386 if (OldMode
!= BlRealMode
)
388 /* FIXME: Not yet implemented */
389 return STATUS_NOT_IMPLEMENTED
;
392 /* Make the EFI call */
393 EfiStatus
= TextInterface
->SetMode(TextInterface
, Mode
);
395 /* Switch back to protected mode if we came from there */
396 if (OldMode
!= BlRealMode
)
398 BlpArchSwitchContext(OldMode
);
401 /* Convert the error to an NTSTATUS */
402 return EfiGetNtStatusCode(EfiStatus
);
406 EfiConOutSetAttribute (
407 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
411 BL_ARCH_MODE OldMode
;
412 EFI_STATUS EfiStatus
;
414 /* Are we in protected mode? */
415 OldMode
= CurrentExecutionContext
->Mode
;
416 if (OldMode
!= BlRealMode
)
418 /* FIXME: Not yet implemented */
419 return STATUS_NOT_IMPLEMENTED
;
422 /* Make the EFI call */
423 EfiStatus
= TextInterface
->SetAttribute(TextInterface
, Attribute
);
425 /* Switch back to protected mode if we came from there */
426 if (OldMode
!= BlRealMode
)
428 BlpArchSwitchContext(OldMode
);
431 /* Convert the error to an NTSTATUS */
432 return EfiGetNtStatusCode(EfiStatus
);
436 EfiConOutSetCursorPosition (
437 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
442 BL_ARCH_MODE OldMode
;
443 EFI_STATUS EfiStatus
;
445 /* Are we in protected mode? */
446 OldMode
= CurrentExecutionContext
->Mode
;
447 if (OldMode
!= BlRealMode
)
449 /* FIXME: Not yet implemented */
450 return STATUS_NOT_IMPLEMENTED
;
453 /* Make the EFI call */
454 EfiStatus
= TextInterface
->SetCursorPosition(TextInterface
, Column
, Row
);
456 /* Switch back to protected mode if we came from there */
457 if (OldMode
!= BlRealMode
)
459 BlpArchSwitchContext(OldMode
);
462 /* Convert the error to an NTSTATUS */
463 return EfiGetNtStatusCode(EfiStatus
);
467 EfiConOutEnableCursor (
468 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
472 BL_ARCH_MODE OldMode
;
473 EFI_STATUS EfiStatus
;
475 /* Are we in protected mode? */
476 OldMode
= CurrentExecutionContext
->Mode
;
477 if (OldMode
!= BlRealMode
)
479 /* FIXME: Not yet implemented */
480 return STATUS_NOT_IMPLEMENTED
;
483 /* Make the EFI call */
484 EfiStatus
= TextInterface
->EnableCursor(TextInterface
, Visible
);
486 /* Switch back to protected mode if we came from there */
487 if (OldMode
!= BlRealMode
)
489 BlpArchSwitchContext(OldMode
);
492 /* Convert the error to an NTSTATUS */
493 return EfiGetNtStatusCode(EfiStatus
);
497 EfiConOutReadCurrentMode (
498 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE
*TextInterface
,
499 _Out_ EFI_SIMPLE_TEXT_OUTPUT_MODE
* Mode
502 BL_ARCH_MODE OldMode
;
504 /* Are we in protected mode? */
505 OldMode
= CurrentExecutionContext
->Mode
;
506 if (OldMode
!= BlRealMode
)
508 /* FIXME: Not yet implemented */
512 /* Make the EFI call */
513 RtlCopyMemory(Mode
, TextInterface
->Mode
, sizeof(*Mode
));
515 /* Switch back to protected mode if we came from there */
516 if (OldMode
!= BlRealMode
)
518 BlpArchSwitchContext(OldMode
);
523 EfiGopGetFrameBuffer (
524 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL
*GopInterface
,
525 _Out_ PHYSICAL_ADDRESS
* FrameBuffer
,
526 _Out_ UINTN
*FrameBufferSize
529 BL_ARCH_MODE OldMode
;
531 /* Are we in protected mode? */
532 OldMode
= CurrentExecutionContext
->Mode
;
533 if (OldMode
!= BlRealMode
)
535 /* FIXME: Not yet implemented */
539 /* Make the EFI call */
540 FrameBuffer
->QuadPart
= GopInterface
->Mode
->FrameBufferBase
;
541 *FrameBufferSize
= GopInterface
->Mode
->FrameBufferSize
;
543 /* Switch back to protected mode if we came from there */
544 if (OldMode
!= BlRealMode
)
546 BlpArchSwitchContext(OldMode
);
551 EfiGopGetCurrentMode (
552 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL
*GopInterface
,
554 _Out_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Information
557 BL_ARCH_MODE OldMode
;
559 /* Are we in protected mode? */
560 OldMode
= CurrentExecutionContext
->Mode
;
561 if (OldMode
!= BlRealMode
)
563 /* FIXME: Not yet implemented */
564 return STATUS_NOT_IMPLEMENTED
;
567 /* Make the EFI call */
568 *Mode
= GopInterface
->Mode
->Mode
;
569 RtlCopyMemory(Information
, GopInterface
->Mode
->Info
, sizeof(*Information
));
571 /* Switch back to protected mode if we came from there */
572 if (OldMode
!= BlRealMode
)
574 BlpArchSwitchContext(OldMode
);
578 return STATUS_SUCCESS
;
583 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL
*GopInterface
,
587 BL_ARCH_MODE OldMode
;
588 EFI_STATUS EfiStatus
;
592 /* Are we in protected mode? */
593 OldMode
= CurrentExecutionContext
->Mode
;
594 if (OldMode
!= BlRealMode
)
596 /* FIXME: Not yet implemented */
597 return STATUS_NOT_IMPLEMENTED
;
600 /* Make the EFI call */
601 if (Mode
== GopInterface
->Mode
->Mode
)
603 EfiStatus
= EFI_SUCCESS
;
607 EfiStatus
= GopInterface
->SetMode(GopInterface
, Mode
);
611 /* Switch back to protected mode if we came from there */
612 if (OldMode
!= BlRealMode
)
614 BlpArchSwitchContext(OldMode
);
617 /* Print out to the debugger if the mode was changed */
618 Status
= EfiGetNtStatusCode(EfiStatus
);
619 if ((ModeChanged
) && (NT_SUCCESS(Status
)))
621 /* FIXME @TODO: Should be BlStatusPrint */
622 EfiPrintf(L
"Console video mode set to 0x%x\r\r\n", Mode
);
625 /* Convert the error to an NTSTATUS */
630 EfiLocateHandleBuffer (
631 _In_ EFI_LOCATE_SEARCH_TYPE SearchType
,
632 _In_ EFI_GUID
*Protocol
,
633 _Inout_ PULONG HandleCount
,
634 _Inout_ EFI_HANDLE
** Buffer
637 BL_ARCH_MODE OldMode
;
638 EFI_STATUS EfiStatus
;
641 /* Bail out if we're missing parameters */
642 if (!(Buffer
) || !(HandleCount
))
644 return STATUS_INVALID_PARAMETER
;
647 /* Check if a buffer was passed in*/
650 /* Then we should already have a buffer size*/
651 BufferSize
= sizeof(EFI_HANDLE
) * *HandleCount
;
655 /* Then no buffer size exists */
659 /* Are we in protected mode? */
660 OldMode
= CurrentExecutionContext
->Mode
;
661 if (OldMode
!= BlRealMode
)
663 /* FIXME: Not yet implemented */
664 return STATUS_NOT_IMPLEMENTED
;
667 /* Try the first time */
668 EfiStatus
= EfiBS
->LocateHandle(SearchType
, Protocol
, NULL
, &BufferSize
, *Buffer
);
669 if (EfiStatus
== EFI_BUFFER_TOO_SMALL
)
671 /* Did we have an existing buffer? */
675 BlMmFreeHeap(*Buffer
);
678 /* Allocate a new one */
679 *Buffer
= BlMmAllocateHeap(BufferSize
);
683 return STATUS_NO_MEMORY
;
687 EfiStatus
= EfiBS
->LocateHandle(SearchType
, Protocol
, NULL
, &BufferSize
, *Buffer
);
689 /* Switch back to protected mode if we came from there */
690 if (OldMode
!= BlRealMode
)
692 BlpArchSwitchContext(OldMode
);
696 /* Return the number of handles */
697 *HandleCount
= BufferSize
/ sizeof(EFI_HANDLE
);
699 /* Convert the error to an NTSTATUS */
700 return EfiGetNtStatusCode(EfiStatus
);
705 _In_ EFI_RESET_TYPE ResetType
708 BL_ARCH_MODE OldMode
;
710 /* Are we in protected mode? */
711 OldMode
= CurrentExecutionContext
->Mode
;
712 if (OldMode
!= BlRealMode
)
714 /* FIXME: Not yet implemented */
718 /* Call the EFI runtime */
719 EfiRT
->ResetSystem(ResetType
, EFI_SUCCESS
, 0, NULL
);
726 _Inout_ EFI_PHYSICAL_ADDRESS
* Memory
729 BL_ARCH_MODE OldMode
;
730 EFI_STATUS EfiStatus
;
732 /* Are we in protected mode? */
733 OldMode
= CurrentExecutionContext
->Mode
;
734 if (OldMode
!= BlRealMode
)
736 /* FIXME: Not yet implemented */
737 return STATUS_NOT_IMPLEMENTED
;
740 /* Make the EFI call */
741 EfiStatus
= EfiBS
->AllocatePages(Type
, EfiLoaderData
, Pages
, Memory
);
743 /* Switch back to protected mode if we came from there */
744 if (OldMode
!= BlRealMode
)
746 BlpArchSwitchContext(OldMode
);
749 /* Convert the error to an NTSTATUS */
750 return EfiGetNtStatusCode(EfiStatus
);
754 MmFwpGetOsAttributeType (
755 _In_ ULONGLONG Attribute
758 BL_MEMORY_ATTR OsAttribute
= 0;
760 if (Attribute
& EFI_MEMORY_UC
)
762 OsAttribute
= BlMemoryUncached
;
765 if (Attribute
& EFI_MEMORY_WC
)
767 OsAttribute
|= BlMemoryWriteCombined
;
770 if (Attribute
& EFI_MEMORY_WT
)
772 OsAttribute
|= BlMemoryWriteThrough
;
775 if (Attribute
& EFI_MEMORY_WB
)
777 OsAttribute
|= BlMemoryWriteBack
;
780 if (Attribute
& EFI_MEMORY_UCE
)
782 OsAttribute
|= BlMemoryUncachedExported
;
785 if (Attribute
& EFI_MEMORY_WP
)
787 OsAttribute
|= BlMemoryWriteProtected
;
790 if (Attribute
& EFI_MEMORY_RP
)
792 OsAttribute
|= BlMemoryReadProtected
;
795 if (Attribute
& EFI_MEMORY_XP
)
797 OsAttribute
|= BlMemoryExecuteProtected
;
800 if (Attribute
& EFI_MEMORY_RUNTIME
)
802 OsAttribute
|= BlMemoryRuntime
;
809 MmFwpGetOsMemoryType (
810 _In_ EFI_MEMORY_TYPE MemoryType
813 BL_MEMORY_TYPE OsType
;
819 OsType
= BlLoaderMemory
;
822 case EfiBootServicesCode
:
823 case EfiBootServicesData
:
824 OsType
= BlEfiBootMemory
;
827 case EfiRuntimeServicesCode
:
828 case EfiRuntimeServicesData
:
829 OsType
= BlEfiRuntimeMemory
;
832 case EfiConventionalMemory
:
833 OsType
= BlConventionalMemory
;
836 case EfiUnusableMemory
:
837 OsType
= BlUnusableMemory
;
840 case EfiACPIReclaimMemory
:
841 OsType
= BlAcpiReclaimMemory
;
844 case EfiACPIMemoryNVS
:
845 OsType
= BlAcpiNvsMemory
;
848 case EfiMemoryMappedIO
:
849 OsType
= BlDeviceIoMemory
;
852 case EfiMemoryMappedIOPortSpace
:
853 OsType
= BlDevicePortMemory
;
857 OsType
= BlPalMemory
;
861 OsType
= BlReservedMemory
;
870 _Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap
,
874 BL_LIBRARY_PARAMETERS LibraryParameters
= BlpLibraryParameters
;
875 BOOLEAN UseEfiBuffer
, HaveRamDisk
;
877 ULONGLONG Pages
, StartPage
, EndPage
;
878 UINTN EfiMemoryMapSize
, MapKey
, DescriptorSize
, DescriptorVersion
;
879 EFI_PHYSICAL_ADDRESS EfiBuffer
;
880 EFI_MEMORY_DESCRIPTOR
* EfiMemoryMap
;
881 EFI_STATUS EfiStatus
;
882 BL_ARCH_MODE OldMode
;
883 EFI_MEMORY_DESCRIPTOR EfiDescriptor
;
884 BL_MEMORY_TYPE MemoryType
;
885 PBL_MEMORY_DESCRIPTOR Descriptor
;
886 BL_MEMORY_ATTR Attribute
;
888 /* Initialize EFI memory map attributes */
889 EfiMemoryMapSize
= MapKey
= DescriptorSize
= DescriptorVersion
= 0;
891 /* Increment the nesting depth */
892 MmDescriptorCallTreeCount
++;
894 /* Determine if we should use EFI or our own allocator at this point */
895 UseEfiBuffer
= Flags
& BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS
;
896 if (!(LibraryParameters
.LibraryFlags
& BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED
))
901 /* Bail out if we don't have a list to use */
902 if (MemoryMap
== NULL
)
904 Status
= STATUS_INVALID_PARAMETER
;
908 /* Free the current descriptor list */
909 MmMdFreeList(MemoryMap
);
911 /* Call into EFI to get the size of the memory map */
912 Status
= EfiGetMemoryMap(&EfiMemoryMapSize
,
917 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
919 /* This should've failed because our buffer was too small, nothing else */
920 EfiPrintf(L
"Got strange EFI status for memory map: %lx\r\n", Status
);
921 if (NT_SUCCESS(Status
))
923 Status
= STATUS_UNSUCCESSFUL
;
928 /* Add 4 more descriptors just in case things changed */
929 EfiMemoryMapSize
+= (4 * DescriptorSize
);
930 Pages
= BYTES_TO_PAGES(EfiMemoryMapSize
);
931 EfiPrintf(L
"Memory map size: %lx bytes, %d pages\r\n", EfiMemoryMapSize
, Pages
);
933 /* Should we use EFI to grab memory? */
936 /* Yes -- request one more page to align up correctly */
939 /* Grab the required pages */
940 Status
= EfiAllocatePages(AllocateAnyPages
,
943 if (!NT_SUCCESS(Status
))
945 EfiPrintf(L
"EFI allocation failed: %lx\r\n", Status
);
949 /* Free the pages for now */
950 Status
= EfiFreePages(Pages
, EfiBuffer
);
951 if (!NT_SUCCESS(Status
))
957 /* Now round to the actual buffer size, removing the extra page */
958 EfiBuffer
= ROUND_TO_PAGES(EfiBuffer
);
960 Status
= EfiAllocatePages(AllocateAddress
,
963 if (!NT_SUCCESS(Status
))
969 /* Get the final aligned size and proper buffer */
970 EfiMemoryMapSize
= EFI_PAGES_TO_SIZE(Pages
);
971 EfiMemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)(ULONG_PTR
)EfiBuffer
;
973 /* Switch to real mode if not already in it */
974 OldMode
= CurrentExecutionContext
->Mode
;
975 if (OldMode
!= BlRealMode
)
977 BlpArchSwitchContext(BlRealMode
);
980 /* Call EFI to get the memory map */
981 EfiStatus
= EfiBS
->GetMemoryMap(&EfiMemoryMapSize
,
987 /* Switch back into the previous mode */
988 if (OldMode
!= BlRealMode
)
990 BlpArchSwitchContext(OldMode
);
993 /* Convert the result code */
994 Status
= EfiGetNtStatusCode(EfiStatus
);
998 /* We don't support this path yet */
999 Status
= STATUS_NOT_IMPLEMENTED
;
1002 /* So far so good? */
1003 if (!NT_SUCCESS(Status
))
1005 EfiPrintf(L
"Failed to get EFI memory map: %lx\r\n", Status
);
1009 /* Did we get correct data from firmware? */
1010 if (((EfiMemoryMapSize
% DescriptorSize
)) ||
1011 (DescriptorSize
< sizeof(EFI_MEMORY_DESCRIPTOR
)))
1013 EfiPrintf(L
"Incorrect descriptor size\r\n");
1014 Status
= STATUS_UNSUCCESSFUL
;
1018 /* Did we boot from a RAM disk? */
1019 if ((BlpBootDevice
->DeviceType
== LocalDevice
) &&
1020 (BlpBootDevice
->Local
.Type
== RamDiskDevice
))
1022 /* We don't handle this yet */
1023 EfiPrintf(L
"RAM boot not supported\r\n");
1024 Status
= STATUS_NOT_IMPLEMENTED
;
1029 /* We didn't, so there won't be any need to find the memory descriptor */
1030 HaveRamDisk
= FALSE
;
1033 /* Loop the EFI memory map */
1035 EfiPrintf(L
"UEFI MEMORY MAP\n\r\n");
1036 EfiPrintf(L
"TYPE START END ATTRIBUTES\r\n");
1037 EfiPrintf(L
"===============================================================\r\n");
1039 while (EfiMemoryMapSize
!= 0)
1041 /* Check if this is an EFI buffer, but we're not in real mode */
1042 if ((UseEfiBuffer
) && (OldMode
!= BlRealMode
))
1044 BlpArchSwitchContext(BlRealMode
);
1047 /* Capture it so we can go back to protected mode (if possible) */
1048 EfiDescriptor
= *EfiMemoryMap
;
1050 /* Go back to protected mode, if we had switched */
1051 if ((UseEfiBuffer
) && (OldMode
!= BlRealMode
))
1053 BlpArchSwitchContext(OldMode
);
1056 /* Convert to OS memory type */
1057 MemoryType
= MmFwpGetOsMemoryType(EfiDescriptor
.Type
);
1059 /* Round up or round down depending on where the memory is coming from */
1060 if (MemoryType
== BlConventionalMemory
)
1062 StartPage
= BYTES_TO_PAGES(EfiDescriptor
.PhysicalStart
);
1066 StartPage
= EfiDescriptor
.PhysicalStart
>> PAGE_SHIFT
;
1069 /* Calculate the ending page */
1070 EndPage
= StartPage
+ EfiDescriptor
.NumberOfPages
;
1072 /* If after rounding, we ended up with 0 pages, skip this */
1073 if (StartPage
== EndPage
)
1078 EfiPrintf(L
"%08X 0x%016I64X-0x%016I64X 0x%I64X\r\n",
1080 StartPage
<< PAGE_SHIFT
,
1081 EndPage
<< PAGE_SHIFT
,
1082 EfiDescriptor
.Attribute
);
1084 /* Check for any range of memory below 1MB */
1085 if (StartPage
< 0x100)
1087 /* Does this range actually contain NULL? */
1090 /* Manually create a reserved descriptof for this page */
1091 Attribute
= MmFwpGetOsAttributeType(EfiDescriptor
.Attribute
);
1092 Descriptor
= MmMdInitByteGranularDescriptor(Attribute
,
1099 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1103 /* Add this descriptor into the list */
1104 Status
= MmMdAddDescriptorToList(MemoryMap
,
1106 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
);
1107 if (!NT_SUCCESS(Status
))
1109 EfiPrintf(L
"Failed to add zero page descriptor: %lx\r\n", Status
);
1113 /* Now handle the rest of the range, unless this was it */
1121 /* Does the range go beyond 1MB? */
1122 if (EndPage
> 0x100)
1124 /* Then create the descriptor for everything up until the megabyte */
1125 Attribute
= MmFwpGetOsAttributeType(EfiDescriptor
.Attribute
);
1126 Descriptor
= MmMdInitByteGranularDescriptor(Attribute
,
1133 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1137 /* Check if this region is currently free RAM */
1138 if (Descriptor
->Type
== BlConventionalMemory
)
1140 /* Set an unknown flag on the descriptor */
1141 Descriptor
->Flags
|= 0x80000;
1144 /* Add this descriptor into the list */
1145 Status
= MmMdAddDescriptorToList(MemoryMap
,
1147 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
);
1148 if (!NT_SUCCESS(Status
))
1150 EfiPrintf(L
"Failed to add 1MB descriptor: %lx\r\n", Status
);
1154 /* Now handle the rest of the range above 1MB */
1159 /* Check if we loaded from a RAM disk */
1162 /* We don't handle this yet */
1163 EfiPrintf(L
"RAM boot not supported\r\n");
1164 Status
= STATUS_NOT_IMPLEMENTED
;
1168 /* Create a descriptor for the current range */
1169 Attribute
= MmFwpGetOsAttributeType(EfiDescriptor
.Attribute
);
1170 Descriptor
= MmMdInitByteGranularDescriptor(Attribute
,
1174 EndPage
- StartPage
);
1177 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1181 /* Check if this region is currently free RAM below 1MB */
1182 if ((Descriptor
->Type
== BlConventionalMemory
) && (EndPage
<= 0x100))
1184 /* Set an unknown flag on the descriptor */
1185 Descriptor
->Flags
|= 0x80000;
1188 /* Add the descriptor to the list, requesting coalescing as asked */
1189 Status
= MmMdAddDescriptorToList(MemoryMap
,
1191 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
|
1192 (Flags
& BL_MM_FLAG_REQUEST_COALESCING
) ?
1193 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
: 0);
1194 if (!NT_SUCCESS(Status
))
1196 EfiPrintf(L
"Failed to add full descriptor: %lx\r\n", Status
);
1201 /* Consume this descriptor, and move to the next one */
1202 EfiMemoryMapSize
-= DescriptorSize
;
1203 EfiMemoryMap
= (PVOID
)((ULONG_PTR
)EfiMemoryMap
+ DescriptorSize
);
1206 /* FIXME: @TODO: Mark the EfiBuffer as free, since we're about to free it */
1207 /* For now, just "leak" the 1-2 pages... */
1210 /* Free the EFI buffer, if we had one */
1213 EfiFreePages(Pages
, EfiBuffer
);
1216 /* On failure, free the memory map if one was passed in */
1217 if (!NT_SUCCESS(Status
) && (MemoryMap
!= NULL
))
1219 MmMdFreeList(MemoryMap
);
1222 /* Decrement the nesting depth and return */
1223 MmDescriptorCallTreeCount
--;
1230 _In_ PBL_FIRMWARE_DESCRIPTOR FirmwareData
1233 NTSTATUS Status
= STATUS_SUCCESS
;
1234 EFI_KEY_TOGGLE_STATE KeyToggleState
;
1236 /* Check if we have vaild firmware data */
1237 if (!(FirmwareData
) || !(FirmwareData
->Version
))
1239 return STATUS_INVALID_PARAMETER
;
1242 /* Check which boot phase we're in */
1245 /* Memory manager is ready, open the extended input protocol */
1246 Status
= EfiOpenProtocol(EfiST
->ConsoleInHandle
,
1247 &EfiSimpleTextInputExProtocol
,
1248 (PVOID
*)&EfiConInEx
);
1249 if (NT_SUCCESS(Status
))
1251 /* Set the initial key toggle state */
1252 KeyToggleState
= EFI_TOGGLE_STATE_VALID
| 40;
1253 EfiConInExSetState(EfiConInEx
, &KeyToggleState
);
1256 /* Setup the watchdog timer */
1257 EfiSetWatchdogTimer();
1261 /* Make a copy of the parameters */
1262 EfiFirmwareParameters
= &EfiFirmwareData
;
1264 /* Check which version we received */
1265 if (FirmwareData
->Version
== 1)
1267 /* FIXME: Not supported */
1268 Status
= STATUS_NOT_SUPPORTED
;
1270 else if (FirmwareData
->Version
>= 2)
1272 /* Version 2 -- save the data */
1273 EfiFirmwareData
= *FirmwareData
;
1274 EfiSystemTable
= FirmwareData
->SystemTable
;
1275 EfiImageHandle
= FirmwareData
->ImageHandle
;
1277 /* Set the EDK-II style variables as well */
1278 EfiST
= EfiSystemTable
;
1279 EfiBS
= EfiSystemTable
->BootServices
;
1280 EfiRT
= EfiSystemTable
->RuntimeServices
;
1281 EfiConOut
= EfiSystemTable
->ConOut
;
1282 EfiConIn
= EfiSystemTable
->ConIn
;
1287 /* Unknown version */
1288 Status
= STATUS_NOT_SUPPORTED
;
1292 /* Return the initialization state */