915de6d43ec15908eead8aba00ee96f8a27954eb
[reactos.git] / boot / environ / lib / firmware / efi / firmware.c
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 = (PVOID)InterfaceAddress.LowPart;
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*)ConInExPhys.LowPart;
872 BlMmTranslateVirtualAddress(KeyToggleState, &KeyTogglePhys);
873 KeyToggleState = (EFI_KEY_TOGGLE_STATE*)KeyTogglePhys.LowPart;
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*)MemoryMapSizePhysical.LowPart;
942 BlMmTranslateVirtualAddress(MemoryMap, &MemoryMapPhysical);
943 MemoryMap = (EFI_MEMORY_DESCRIPTOR*)MemoryMapPhysical.LowPart;
944 BlMmTranslateVirtualAddress(MapKey, &MapKeyPhysical);
945 MapKey = (UINTN*)MapKeyPhysical.LowPart;
946 BlMmTranslateVirtualAddress(DescriptorSize, &DescriptorSizePhysical);
947 DescriptorSize = (UINTN*)DescriptorSizePhysical.LowPart;
948 BlMmTranslateVirtualAddress(DescriptorVersion, &DescriptorVersionPhysical);
949 DescriptorVersion = (UINTN*)DescriptorVersionPhysical.LowPart;
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 = (PVOID)GopInterfacePhys.LowPart;
1271
1272 /* Translate pointer to physical */
1273 BlMmTranslateVirtualAddress(FrameBuffer, &FrameBufferPhys);
1274 FrameBuffer = (PVOID)FrameBufferPhys.LowPart;
1275
1276 /* Translate pointer to physical */
1277 BlMmTranslateVirtualAddress(FrameBufferSize, &FrameBufferSizePhys);
1278 FrameBufferSize = (PVOID)FrameBufferSizePhys.LowPart;
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 = (PVOID)GopInterfacePhys.LowPart;
1315
1316 /* Translate pointer to physical */
1317 if (!BlMmTranslateVirtualAddress(Mode, &ModePhys))
1318 {
1319 return STATUS_UNSUCCESSFUL;
1320 }
1321 Mode = (PVOID)ModePhys.LowPart;
1322
1323 /* Translate pointer to physical */
1324 if (!BlMmTranslateVirtualAddress(Information, &InformationPhys))
1325 {
1326 return STATUS_UNSUCCESSFUL;
1327 }
1328 Information = (PVOID)InformationPhys.LowPart;
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 ? (PVOID)BufferPhys.LowPart : 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 ? (PVOID)BufferPhys.LowPart : 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*)MemoryPhysical.LowPart;
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 }