[BOOTLIB]: Implement MmArchTranslateVirtualAddress for non-paging mode. Stub Mmx86Tra...
[reactos.git] / reactos / 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 NTSTATUS
164 EfiOpenProtocol (
165 _In_ EFI_HANDLE Handle,
166 _In_ EFI_GUID *Protocol,
167 _Out_ PVOID* Interface
168 )
169 {
170 EFI_STATUS EfiStatus;
171 NTSTATUS Status;
172 BL_ARCH_MODE OldMode;
173
174 /* Are we using virtual memory/ */
175 if (MmTranslationType != BlNone)
176 {
177 /* We need complex tracking to make this work */
178 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
179 Status = STATUS_NOT_SUPPORTED;
180 }
181 else
182 {
183 /* Are we in protected mode? */
184 OldMode = CurrentExecutionContext->Mode;
185 if (OldMode != BlRealMode)
186 {
187 /* FIXME: Not yet implemented */
188 return STATUS_NOT_IMPLEMENTED;
189 }
190
191 /* Are we on legacy 1.02? */
192 if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION)
193 {
194 /* Make the legacy call */
195 EfiStatus = EfiBS->HandleProtocol(Handle, Protocol, Interface);
196 }
197 else
198 {
199 /* Use the UEFI version */
200 EfiStatus = EfiBS->OpenProtocol(Handle,
201 Protocol,
202 Interface,
203 EfiImageHandle,
204 NULL,
205 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
206
207 /* Switch back to protected mode if we came from there */
208 if (OldMode != BlRealMode)
209 {
210 BlpArchSwitchContext(OldMode);
211 }
212 }
213
214 /* Convert the error to an NTSTATUS */
215 Status = EfiGetNtStatusCode(EfiStatus);
216 }
217
218 /* Clear the interface on failure, and return the status */
219 if (!NT_SUCCESS(Status))
220 {
221 *Interface = NULL;
222 }
223
224 return Status;
225 }
226
227 NTSTATUS
228 EfiCloseProtocol (
229 _In_ EFI_HANDLE Handle,
230 _In_ EFI_GUID *Protocol
231 )
232 {
233 EFI_STATUS EfiStatus;
234 NTSTATUS Status;
235 BL_ARCH_MODE OldMode;
236
237 /* Are we using virtual memory/ */
238 if (MmTranslationType != BlNone)
239 {
240 /* We need complex tracking to make this work */
241 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
242 Status = STATUS_NOT_SUPPORTED;
243 }
244 else
245 {
246 /* Are we on legacy 1.02? */
247 if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION)
248 {
249 /* Nothing to close */
250 EfiStatus = STATUS_SUCCESS;
251 }
252 else
253 {
254 /* Are we in protected mode? */
255 OldMode = CurrentExecutionContext->Mode;
256 if (OldMode != BlRealMode)
257 {
258 /* FIXME: Not yet implemented */
259 return STATUS_NOT_IMPLEMENTED;
260 }
261
262 /* Use the UEFI version */
263 EfiStatus = EfiBS->CloseProtocol(Handle, Protocol, EfiImageHandle, NULL);
264
265 /* Switch back to protected mode if we came from there */
266 if (OldMode != BlRealMode)
267 {
268 BlpArchSwitchContext(OldMode);
269 }
270
271 /* Normalize not found as success */
272 if (EfiStatus == EFI_NOT_FOUND)
273 {
274 EfiStatus = EFI_SUCCESS;
275 }
276 }
277
278 /* Convert the error to an NTSTATUS */
279 Status = EfiGetNtStatusCode(EfiStatus);
280 }
281
282 /* All done */
283 return Status;
284 }
285
286 NTSTATUS
287 EfiGetVariable (
288 _In_ PWCHAR VariableName,
289 _In_ EFI_GUID* VendorGuid,
290 _Out_opt_ PULONG Attributes,
291 _Inout_ PULONG DataSize,
292 _Out_ PVOID Data
293 )
294 {
295 EFI_STATUS EfiStatus;
296 NTSTATUS Status;
297 BL_ARCH_MODE OldMode;
298 ULONG LocalAttributes;
299
300 /* Are we in protected mode? */
301 OldMode = CurrentExecutionContext->Mode;
302 if (OldMode != BlRealMode)
303 {
304 /* FIXME: Not yet implemented */
305 return STATUS_NOT_IMPLEMENTED;
306 }
307
308 /* Call the runtime API */
309 EfiStatus = EfiRT->GetVariable(VariableName,
310 VendorGuid,
311 (UINT32*)&LocalAttributes,
312 (UINTN*)DataSize,
313 Data);
314
315 /* Switch back to protected mode if we came from there */
316 if (OldMode != BlRealMode)
317 {
318 BlpArchSwitchContext(OldMode);
319 }
320
321 /* Return attributes back to the caller if asked to */
322 if (Attributes)
323 {
324 *Attributes = LocalAttributes;
325 }
326
327 /* Convert the error to an NTSTATUS and return it */
328 Status = EfiGetNtStatusCode(EfiStatus);
329 return Status;
330 }
331
332 NTSTATUS
333 BlpSecureBootEFIIsEnabled (
334 VOID
335 )
336 {
337 NTSTATUS Status;
338 BOOLEAN SetupMode, SecureBoot;
339 ULONG DataSize;
340
341 /* Assume setup mode enabled, and no secure boot */
342 SecureBoot = FALSE;
343 SetupMode = TRUE;
344
345 /* Get the SetupMode variable */
346 DataSize = sizeof(SetupMode);
347 Status = EfiGetVariable(L"SetupMode",
348 &EfiGlobalVariable,
349 NULL,
350 &DataSize,
351 &SetupMode);
352 if (NT_SUCCESS(Status))
353 {
354 /* If it worked, get the SecureBoot variable */
355 DataSize = sizeof(SecureBoot);
356 Status = EfiGetVariable(L"SecureBoot",
357 &EfiGlobalVariable,
358 NULL,
359 &DataSize,
360 &SecureBoot);
361 if (NT_SUCCESS(Status))
362 {
363 /* In setup mode or without secureboot turned on, return failure */
364 if ((SecureBoot != TRUE) || (SetupMode))
365 {
366 Status = STATUS_INVALID_SIGNATURE;
367 }
368
369 // BlpSbdiStateFlags |= 8u;
370 }
371 }
372
373 /* Return secureboot status */
374 return Status;
375 }
376
377 NTSTATUS
378 BlSecureBootIsEnabled (
379 _Out_ PBOOLEAN SecureBootEnabled
380 )
381 {
382 NTSTATUS Status;
383
384 /* Have we checked before ? */
385 if (!BlpFirmwareChecked)
386 {
387 /* First time checking */
388 Status = BlpSecureBootEFIIsEnabled();
389 if NT_SUCCESS(Status)
390 {
391 /* Yep, it's on */
392 BlpFirmwareEnabled = TRUE;
393 }
394
395 /* Don't check again */
396 BlpFirmwareChecked = TRUE;
397 }
398
399 /* Return the firmware result */
400 *SecureBootEnabled = BlpFirmwareEnabled;
401 return STATUS_SUCCESS;
402 }
403
404 NTSTATUS
405 BlSecureBootCheckForFactoryReset (
406 VOID
407 )
408 {
409 BOOLEAN SecureBootEnabled;
410 NTSTATUS Status;
411 ULONG DataSize;
412
413 /* Initialize locals */
414 DataSize = 0;
415 SecureBootEnabled = FALSE;
416
417 /* Check if secureboot is enabled */
418 Status = BlSecureBootIsEnabled(&SecureBootEnabled);
419 if (!(NT_SUCCESS(Status)) || !(SecureBootEnabled))
420 {
421 /* It's not. Check if there's a revocation list */
422 Status = EfiGetVariable(L"RevocationList",
423 &BlpEfiSecureBootPrivateNamespace,
424 NULL,
425 &DataSize,
426 NULL);
427 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL))
428 {
429 /* We don't support this yet */
430 EfiPrintf(L"Not yet supported\r\n");
431 Status = STATUS_NOT_IMPLEMENTED;
432 }
433 }
434
435 /* Return back to the caller */
436 return Status;
437 }
438
439 NTSTATUS
440 EfiConInReset (
441 VOID
442 )
443 {
444 BL_ARCH_MODE OldMode;
445 EFI_STATUS EfiStatus;
446
447 /* Are we in protected mode? */
448 OldMode = CurrentExecutionContext->Mode;
449 if (OldMode != BlRealMode)
450 {
451 /* FIXME: Not yet implemented */
452 return STATUS_NOT_IMPLEMENTED;
453 }
454
455 /* Make the EFI call */
456 EfiStatus = EfiConIn->Reset(EfiConIn, FALSE);
457
458 /* Switch back to protected mode if we came from there */
459 if (OldMode != BlRealMode)
460 {
461 BlpArchSwitchContext(OldMode);
462 }
463
464 /* Convert the error to an NTSTATUS */
465 return EfiGetNtStatusCode(EfiStatus);
466 }
467
468 NTSTATUS
469 EfiConInExReset (
470 VOID
471 )
472 {
473 BL_ARCH_MODE OldMode;
474 EFI_STATUS EfiStatus;
475
476 /* Are we in protected mode? */
477 OldMode = CurrentExecutionContext->Mode;
478 if (OldMode != BlRealMode)
479 {
480 /* FIXME: Not yet implemented */
481 return STATUS_NOT_IMPLEMENTED;
482 }
483
484 /* Make the EFI call */
485 EfiStatus = EfiConInEx->Reset(EfiConInEx, FALSE);
486
487 /* Switch back to protected mode if we came from there */
488 if (OldMode != BlRealMode)
489 {
490 BlpArchSwitchContext(OldMode);
491 }
492
493 /* Convert the error to an NTSTATUS */
494 return EfiGetNtStatusCode(EfiStatus);
495 }
496
497 NTSTATUS
498 EfiConInExSetState (
499 _In_ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *ConInEx,
500 _In_ EFI_KEY_TOGGLE_STATE* KeyToggleState
501 )
502 {
503 BL_ARCH_MODE OldMode;
504 EFI_STATUS EfiStatus;
505
506 /* Are we in protected mode? */
507 OldMode = CurrentExecutionContext->Mode;
508 if (OldMode != BlRealMode)
509 {
510 /* FIXME: Not yet implemented */
511 return STATUS_NOT_IMPLEMENTED;
512 }
513
514 /* Make the EFI call */
515 EfiStatus = ConInEx->SetState(ConInEx, KeyToggleState);
516
517 /* Switch back to protected mode if we came from there */
518 if (OldMode != BlRealMode)
519 {
520 BlpArchSwitchContext(OldMode);
521 }
522
523 /* Convert the error to an NTSTATUS */
524 return EfiGetNtStatusCode(EfiStatus);
525 }
526
527 NTSTATUS
528 EfiSetWatchdogTimer (
529 VOID
530 )
531 {
532 BL_ARCH_MODE OldMode;
533 EFI_STATUS EfiStatus;
534
535 /* Are we in protected mode? */
536 OldMode = CurrentExecutionContext->Mode;
537 if (OldMode != BlRealMode)
538 {
539 /* FIXME: Not yet implemented */
540 return STATUS_NOT_IMPLEMENTED;
541 }
542
543 /* Make the EFI call */
544 EfiStatus = EfiBS->SetWatchdogTimer(0, 0, 0, NULL);
545
546 /* Switch back to protected mode if we came from there */
547 if (OldMode != BlRealMode)
548 {
549 BlpArchSwitchContext(OldMode);
550 }
551
552 /* Convert the error to an NTSTATUS */
553 return EfiGetNtStatusCode(EfiStatus);
554 }
555
556 NTSTATUS
557 EfiGetMemoryMap (
558 _Out_ UINTN* MemoryMapSize,
559 _Inout_ EFI_MEMORY_DESCRIPTOR *MemoryMap,
560 _Out_ UINTN* MapKey,
561 _Out_ UINTN* DescriptorSize,
562 _Out_ UINTN* DescriptorVersion
563 )
564 {
565 BL_ARCH_MODE OldMode;
566 EFI_STATUS EfiStatus;
567 PHYSICAL_ADDRESS MemoryMapSizePhysical, MemoryMapPhysical, MapKeyPhysical;
568 PHYSICAL_ADDRESS DescriptorSizePhysical, DescriptorVersionPhysical;
569
570 /* Are we in protected mode? */
571 OldMode = CurrentExecutionContext->Mode;
572 if (OldMode != BlRealMode)
573 {
574 /* Convert all of the addresses to physical */
575 BlMmTranslateVirtualAddress(MemoryMapSize, &MemoryMapSizePhysical);
576 MemoryMapSize = (UINTN*)MemoryMapSizePhysical.LowPart;
577 BlMmTranslateVirtualAddress(MemoryMap, &MemoryMapPhysical);
578 MemoryMap = (EFI_MEMORY_DESCRIPTOR*)MemoryMapPhysical.LowPart;
579 BlMmTranslateVirtualAddress(MapKey, &MapKeyPhysical);
580 MapKey = (UINTN*)MapKeyPhysical.LowPart;
581 BlMmTranslateVirtualAddress(DescriptorSize, &DescriptorSizePhysical);
582 DescriptorSize = (UINTN*)DescriptorSizePhysical.LowPart;
583 BlMmTranslateVirtualAddress(DescriptorVersion, &DescriptorVersionPhysical);
584 DescriptorVersion = (UINTN*)DescriptorVersionPhysical.LowPart;
585
586 /* Switch to real mode */
587 BlpArchSwitchContext(BlProtectedMode);
588 }
589
590 /* Make the EFI call */
591 EfiStatus = EfiBS->GetMemoryMap(MemoryMapSize,
592 MemoryMap,
593 MapKey,
594 DescriptorSize,
595 DescriptorVersion);
596
597 /* Switch back to protected mode if we came from there */
598 if (OldMode != BlRealMode)
599 {
600 BlpArchSwitchContext(OldMode);
601 }
602
603 /* Convert the error to an NTSTATUS */
604 return EfiGetNtStatusCode(EfiStatus);
605 }
606
607 NTSTATUS
608 EfiFreePages (
609 _In_ ULONG Pages,
610 _In_ EFI_PHYSICAL_ADDRESS PhysicalAddress
611 )
612 {
613 BL_ARCH_MODE OldMode;
614 EFI_STATUS EfiStatus;
615
616 /* Are we in protected mode? */
617 OldMode = CurrentExecutionContext->Mode;
618 if (OldMode != BlRealMode)
619 {
620 /* FIXME: Not yet implemented */
621 return STATUS_NOT_IMPLEMENTED;
622 }
623
624 /* Make the EFI call */
625 EfiStatus = EfiBS->FreePages(PhysicalAddress, Pages);
626
627 /* Switch back to protected mode if we came from there */
628 if (OldMode != BlRealMode)
629 {
630 BlpArchSwitchContext(OldMode);
631 }
632
633 /* Convert the error to an NTSTATUS */
634 return EfiGetNtStatusCode(EfiStatus);
635 }
636
637 NTSTATUS
638 EfiStall (
639 _In_ ULONG StallTime
640 )
641 {
642 BL_ARCH_MODE OldMode;
643 EFI_STATUS EfiStatus;
644
645 /* Are we in protected mode? */
646 OldMode = CurrentExecutionContext->Mode;
647 if (OldMode != BlRealMode)
648 {
649 /* FIXME: Not yet implemented */
650 return STATUS_NOT_IMPLEMENTED;
651 }
652
653 /* Make the EFI call */
654 EfiStatus = EfiBS->Stall(StallTime);
655
656 /* Switch back to protected mode if we came from there */
657 if (OldMode != BlRealMode)
658 {
659 BlpArchSwitchContext(OldMode);
660 }
661
662 /* Convert the error to an NTSTATUS */
663 return EfiGetNtStatusCode(EfiStatus);
664 }
665
666 NTSTATUS
667 EfiConOutQueryMode (
668 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
669 _In_ ULONG Mode,
670 _In_ UINTN* Columns,
671 _In_ UINTN* Rows
672 )
673 {
674 BL_ARCH_MODE OldMode;
675 EFI_STATUS EfiStatus;
676
677 /* Are we in protected mode? */
678 OldMode = CurrentExecutionContext->Mode;
679 if (OldMode != BlRealMode)
680 {
681 /* FIXME: Not yet implemented */
682 return STATUS_NOT_IMPLEMENTED;
683 }
684
685 /* Make the EFI call */
686 EfiStatus = TextInterface->QueryMode(TextInterface, Mode, Columns, Rows);
687
688 /* Switch back to protected mode if we came from there */
689 if (OldMode != BlRealMode)
690 {
691 BlpArchSwitchContext(OldMode);
692 }
693
694 /* Convert the error to an NTSTATUS */
695 return EfiGetNtStatusCode(EfiStatus);
696 }
697
698 NTSTATUS
699 EfiConOutSetMode (
700 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
701 _In_ ULONG Mode
702 )
703 {
704 BL_ARCH_MODE OldMode;
705 EFI_STATUS EfiStatus;
706
707 /* Are we in protected mode? */
708 OldMode = CurrentExecutionContext->Mode;
709 if (OldMode != BlRealMode)
710 {
711 /* FIXME: Not yet implemented */
712 return STATUS_NOT_IMPLEMENTED;
713 }
714
715 /* Make the EFI call */
716 EfiStatus = TextInterface->SetMode(TextInterface, Mode);
717
718 /* Switch back to protected mode if we came from there */
719 if (OldMode != BlRealMode)
720 {
721 BlpArchSwitchContext(OldMode);
722 }
723
724 /* Convert the error to an NTSTATUS */
725 return EfiGetNtStatusCode(EfiStatus);
726 }
727
728 NTSTATUS
729 EfiConOutSetAttribute (
730 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
731 _In_ ULONG Attribute
732 )
733 {
734 BL_ARCH_MODE OldMode;
735 EFI_STATUS EfiStatus;
736
737 /* Are we in protected mode? */
738 OldMode = CurrentExecutionContext->Mode;
739 if (OldMode != BlRealMode)
740 {
741 /* FIXME: Not yet implemented */
742 return STATUS_NOT_IMPLEMENTED;
743 }
744
745 /* Make the EFI call */
746 EfiStatus = TextInterface->SetAttribute(TextInterface, Attribute);
747
748 /* Switch back to protected mode if we came from there */
749 if (OldMode != BlRealMode)
750 {
751 BlpArchSwitchContext(OldMode);
752 }
753
754 /* Convert the error to an NTSTATUS */
755 return EfiGetNtStatusCode(EfiStatus);
756 }
757
758 NTSTATUS
759 EfiConOutSetCursorPosition (
760 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
761 _In_ ULONG Column,
762 _In_ ULONG Row
763 )
764 {
765 BL_ARCH_MODE OldMode;
766 EFI_STATUS EfiStatus;
767
768 /* Are we in protected mode? */
769 OldMode = CurrentExecutionContext->Mode;
770 if (OldMode != BlRealMode)
771 {
772 /* FIXME: Not yet implemented */
773 return STATUS_NOT_IMPLEMENTED;
774 }
775
776 /* Make the EFI call */
777 EfiStatus = TextInterface->SetCursorPosition(TextInterface, Column, Row);
778
779 /* Switch back to protected mode if we came from there */
780 if (OldMode != BlRealMode)
781 {
782 BlpArchSwitchContext(OldMode);
783 }
784
785 /* Convert the error to an NTSTATUS */
786 return EfiGetNtStatusCode(EfiStatus);
787 }
788
789 NTSTATUS
790 EfiConOutEnableCursor (
791 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
792 _In_ BOOLEAN Visible
793 )
794 {
795 BL_ARCH_MODE OldMode;
796 EFI_STATUS EfiStatus;
797
798 /* Are we in protected mode? */
799 OldMode = CurrentExecutionContext->Mode;
800 if (OldMode != BlRealMode)
801 {
802 /* FIXME: Not yet implemented */
803 return STATUS_NOT_IMPLEMENTED;
804 }
805
806 /* Make the EFI call */
807 EfiStatus = TextInterface->EnableCursor(TextInterface, Visible);
808
809 /* Switch back to protected mode if we came from there */
810 if (OldMode != BlRealMode)
811 {
812 BlpArchSwitchContext(OldMode);
813 }
814
815 /* Convert the error to an NTSTATUS */
816 return EfiGetNtStatusCode(EfiStatus);
817 }
818
819 NTSTATUS
820 EfiConOutOutputString (
821 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
822 _In_ PWCHAR String
823 )
824 {
825 BL_ARCH_MODE OldMode;
826 EFI_STATUS EfiStatus;
827
828 /* Are we in protected mode? */
829 OldMode = CurrentExecutionContext->Mode;
830 if (OldMode != BlRealMode)
831 {
832 /* FIXME: Not yet implemented */
833 return STATUS_NOT_IMPLEMENTED;
834 }
835
836 /* Make the EFI call */
837 EfiStatus = TextInterface->OutputString(TextInterface, String);
838
839 /* Switch back to protected mode if we came from there */
840 if (OldMode != BlRealMode)
841 {
842 BlpArchSwitchContext(OldMode);
843 }
844
845 /* Convert the error to an NTSTATUS */
846 return EfiGetNtStatusCode(EfiStatus);
847 }
848
849
850 VOID
851 EfiConOutReadCurrentMode (
852 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
853 _Out_ EFI_SIMPLE_TEXT_OUTPUT_MODE* Mode
854 )
855 {
856 BL_ARCH_MODE OldMode;
857
858 /* Are we in protected mode? */
859 OldMode = CurrentExecutionContext->Mode;
860 if (OldMode != BlRealMode)
861 {
862 /* FIXME: Not yet implemented */
863 return;
864 }
865
866 /* Make the EFI call */
867 RtlCopyMemory(Mode, TextInterface->Mode, sizeof(*Mode));
868
869 /* Switch back to protected mode if we came from there */
870 if (OldMode != BlRealMode)
871 {
872 BlpArchSwitchContext(OldMode);
873 }
874 }
875
876 VOID
877 EfiGopGetFrameBuffer (
878 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
879 _Out_ PHYSICAL_ADDRESS* FrameBuffer,
880 _Out_ UINTN *FrameBufferSize
881 )
882 {
883 BL_ARCH_MODE OldMode;
884
885 /* Are we in protected mode? */
886 OldMode = CurrentExecutionContext->Mode;
887 if (OldMode != BlRealMode)
888 {
889 /* FIXME: Not yet implemented */
890 return;
891 }
892
893 /* Make the EFI call */
894 FrameBuffer->QuadPart = GopInterface->Mode->FrameBufferBase;
895 *FrameBufferSize = GopInterface->Mode->FrameBufferSize;
896
897 /* Switch back to protected mode if we came from there */
898 if (OldMode != BlRealMode)
899 {
900 BlpArchSwitchContext(OldMode);
901 }
902 }
903
904 NTSTATUS
905 EfiGopGetCurrentMode (
906 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
907 _Out_ UINTN* Mode,
908 _Out_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information
909 )
910 {
911 BL_ARCH_MODE OldMode;
912
913 /* Are we in protected mode? */
914 OldMode = CurrentExecutionContext->Mode;
915 if (OldMode != BlRealMode)
916 {
917 /* FIXME: Not yet implemented */
918 return STATUS_NOT_IMPLEMENTED;
919 }
920
921 /* Make the EFI call */
922 *Mode = GopInterface->Mode->Mode;
923 RtlCopyMemory(Information, GopInterface->Mode->Info, sizeof(*Information));
924
925 /* Switch back to protected mode if we came from there */
926 if (OldMode != BlRealMode)
927 {
928 BlpArchSwitchContext(OldMode);
929 }
930
931 /* Return back */
932 return STATUS_SUCCESS;
933 }
934
935 NTSTATUS
936 EfiGopSetMode (
937 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
938 _In_ ULONG Mode
939 )
940 {
941 BL_ARCH_MODE OldMode;
942 EFI_STATUS EfiStatus;
943 BOOLEAN ModeChanged;
944 NTSTATUS Status;
945
946 /* Are we in protected mode? */
947 OldMode = CurrentExecutionContext->Mode;
948 if (OldMode != BlRealMode)
949 {
950 /* FIXME: Not yet implemented */
951 return STATUS_NOT_IMPLEMENTED;
952 }
953
954 /* Make the EFI call */
955 if (Mode == GopInterface->Mode->Mode)
956 {
957 EfiStatus = EFI_SUCCESS;
958 ModeChanged = FALSE;
959 }
960 {
961 EfiStatus = GopInterface->SetMode(GopInterface, Mode);
962 ModeChanged = TRUE;
963 }
964
965 /* Switch back to protected mode if we came from there */
966 if (OldMode != BlRealMode)
967 {
968 BlpArchSwitchContext(OldMode);
969 }
970
971 /* Print out to the debugger if the mode was changed */
972 Status = EfiGetNtStatusCode(EfiStatus);
973 if ((ModeChanged) && (NT_SUCCESS(Status)))
974 {
975 /* FIXME @TODO: Should be BlStatusPrint */
976 EfiPrintf(L"Console video mode set to 0x%x\r\n", Mode);
977 }
978
979 /* Convert the error to an NTSTATUS */
980 return Status;
981 }
982
983 NTSTATUS
984 EfiLocateHandleBuffer (
985 _In_ EFI_LOCATE_SEARCH_TYPE SearchType,
986 _In_ EFI_GUID *Protocol,
987 _Inout_ PULONG HandleCount,
988 _Inout_ EFI_HANDLE** Buffer
989 )
990 {
991 BL_ARCH_MODE OldMode;
992 EFI_STATUS EfiStatus;
993 UINTN BufferSize;
994
995 /* Bail out if we're missing parameters */
996 if (!(Buffer) || !(HandleCount))
997 {
998 return STATUS_INVALID_PARAMETER;
999 }
1000
1001 /* Check if a buffer was passed in*/
1002 if (*Buffer)
1003 {
1004 /* Then we should already have a buffer size*/
1005 BufferSize = sizeof(EFI_HANDLE) * *HandleCount;
1006 }
1007 else
1008 {
1009 /* Then no buffer size exists */
1010 BufferSize = 0;
1011 }
1012
1013 /* Are we in protected mode? */
1014 OldMode = CurrentExecutionContext->Mode;
1015 if (OldMode != BlRealMode)
1016 {
1017 /* FIXME: Not yet implemented */
1018 return STATUS_NOT_IMPLEMENTED;
1019 }
1020
1021 /* Try the first time */
1022 EfiStatus = EfiBS->LocateHandle(SearchType, Protocol, NULL, &BufferSize, *Buffer);
1023 if (EfiStatus == EFI_BUFFER_TOO_SMALL)
1024 {
1025 /* Did we have an existing buffer? */
1026 if (*Buffer)
1027 {
1028 /* Free it */
1029 BlMmFreeHeap(*Buffer);
1030 }
1031
1032 /* Allocate a new one */
1033 *Buffer = BlMmAllocateHeap(BufferSize);
1034 if (!(*Buffer))
1035 {
1036 /* No space, fail */
1037 return STATUS_NO_MEMORY;
1038 }
1039
1040 /* Try again */
1041 EfiStatus = EfiBS->LocateHandle(SearchType, Protocol, NULL, &BufferSize, *Buffer);
1042
1043 /* Switch back to protected mode if we came from there */
1044 if (OldMode != BlRealMode)
1045 {
1046 BlpArchSwitchContext(OldMode);
1047 }
1048 }
1049
1050 /* Return the number of handles */
1051 *HandleCount = BufferSize / sizeof(EFI_HANDLE);
1052
1053 /* Convert the error to an NTSTATUS */
1054 return EfiGetNtStatusCode(EfiStatus);
1055 }
1056
1057 VOID
1058 EfiResetSystem (
1059 _In_ EFI_RESET_TYPE ResetType
1060 )
1061 {
1062 BL_ARCH_MODE OldMode;
1063
1064 /* Are we in protected mode? */
1065 OldMode = CurrentExecutionContext->Mode;
1066 if (OldMode != BlRealMode)
1067 {
1068 /* FIXME: Not yet implemented */
1069 return;
1070 }
1071
1072 /* Call the EFI runtime */
1073 EfiRT->ResetSystem(ResetType, EFI_SUCCESS, 0, NULL);
1074 }
1075
1076 NTSTATUS
1077 EfiConnectController (
1078 _In_ EFI_HANDLE ControllerHandle
1079 )
1080 {
1081 BL_ARCH_MODE OldMode;
1082 EFI_STATUS EfiStatus;
1083
1084 /* Is this EFI 1.02? */
1085 if (EfiST->Hdr.Revision == EFI_1_02_SYSTEM_TABLE_REVISION)
1086 {
1087 /* This function didn't exist back then */
1088 return STATUS_NOT_SUPPORTED;
1089 }
1090
1091 /* Are we in protected mode? */
1092 OldMode = CurrentExecutionContext->Mode;
1093 if (OldMode != BlRealMode)
1094 {
1095 /* FIXME: Not yet implemented */
1096 return STATUS_NOT_IMPLEMENTED;
1097 }
1098
1099 /* Make the EFI call */
1100 EfiStatus = EfiBS->ConnectController(ControllerHandle, NULL, NULL, TRUE);
1101
1102 /* Switch back to protected mode if we came from there */
1103 if (OldMode != BlRealMode)
1104 {
1105 BlpArchSwitchContext(OldMode);
1106 }
1107
1108 /* Convert the error to an NTSTATUS */
1109 return EfiGetNtStatusCode(EfiStatus);
1110 }
1111
1112 NTSTATUS
1113 EfiAllocatePages (
1114 _In_ ULONG Type,
1115 _In_ ULONG Pages,
1116 _Inout_ EFI_PHYSICAL_ADDRESS* Memory
1117 )
1118 {
1119 BL_ARCH_MODE OldMode;
1120 EFI_STATUS EfiStatus;
1121
1122 /* Are we in protected mode? */
1123 OldMode = CurrentExecutionContext->Mode;
1124 if (OldMode != BlRealMode)
1125 {
1126 /* FIXME: Not yet implemented */
1127 return STATUS_NOT_IMPLEMENTED;
1128 }
1129
1130 /* Make the EFI call */
1131 EfiStatus = EfiBS->AllocatePages(Type, EfiLoaderData, Pages, Memory);
1132
1133 /* Switch back to protected mode if we came from there */
1134 if (OldMode != BlRealMode)
1135 {
1136 BlpArchSwitchContext(OldMode);
1137 }
1138
1139 /* Convert the error to an NTSTATUS */
1140 return EfiGetNtStatusCode(EfiStatus);
1141 }
1142
1143 NTSTATUS
1144 EfipGetSystemTable (
1145 _In_ EFI_GUID *TableGuid,
1146 _Out_ PPHYSICAL_ADDRESS TableAddress
1147 )
1148 {
1149 ULONG i;
1150 NTSTATUS Status;
1151
1152 /* Assume failure */
1153 Status = STATUS_NOT_FOUND;
1154
1155 /* Loop through the configuration tables */
1156 for (i = 0; i < EfiST->NumberOfTableEntries; i++)
1157 {
1158 /* Check if this one matches the one we want */
1159 if (RtlEqualMemory(&EfiST->ConfigurationTable[i].VendorGuid,
1160 TableGuid,
1161 sizeof(*TableGuid)))
1162 {
1163 /* Return its address */
1164 TableAddress->QuadPart = (ULONG_PTR)EfiST->ConfigurationTable[i].VendorTable;
1165 Status = STATUS_SUCCESS;
1166 break;
1167 }
1168 }
1169
1170 /* Return the search result */
1171 return Status;
1172 }
1173
1174 NTSTATUS
1175 EfipGetRsdt (
1176 _Out_ PPHYSICAL_ADDRESS FoundRsdt
1177 )
1178 {
1179 NTSTATUS Status;
1180 ULONG Length;
1181 PHYSICAL_ADDRESS RsdpAddress, Rsdt;
1182 PRSDP Rsdp;
1183
1184 /* Assume failure */
1185 Length = 0;
1186 Rsdp = NULL;
1187
1188 /* Check if we already know it */
1189 if (EfiRsdt.QuadPart)
1190 {
1191 /* Return it */
1192 *FoundRsdt = EfiRsdt;
1193 return STATUS_SUCCESS;
1194 }
1195
1196 /* Otherwise, look for the ACPI 2.0 RSDP (XSDT really) */
1197 Status = EfipGetSystemTable(&EfiRootAcpiTableGuid, &RsdpAddress);
1198 if (!NT_SUCCESS(Status))
1199 {
1200 /* Didn't fint it, look for the ACPI 1.0 RSDP (RSDT really) */
1201 Status = EfipGetSystemTable(&EfiRootAcpiTable10Guid, &RsdpAddress);
1202 if (!NT_SUCCESS(Status))
1203 {
1204 return Status;
1205 }
1206 }
1207
1208 /* Map it */
1209 Length = sizeof(*Rsdp);
1210 Status = BlMmMapPhysicalAddressEx((PVOID*)&Rsdp,
1211 0,
1212 Length,
1213 RsdpAddress);
1214 if (NT_SUCCESS(Status))
1215 {
1216 /* Check the revision (anything >= 2.0 is XSDT) */
1217 if (Rsdp->Revision)
1218 {
1219 /* Check if the table is bigger than just its header */
1220 if (Rsdp->Length > Length)
1221 {
1222 /* Capture the real length */
1223 Length = Rsdp->Length;
1224
1225 /* Unmap our header mapping */
1226 BlMmUnmapVirtualAddressEx(Rsdp, sizeof(*Rsdp));
1227
1228 /* And map the whole thing now */
1229 Status = BlMmMapPhysicalAddressEx((PVOID*)&Rsdp,
1230 0,
1231 Length,
1232 RsdpAddress);
1233 if (!NT_SUCCESS(Status))
1234 {
1235 return Status;
1236 }
1237 }
1238
1239 /* Read the XSDT address from the table*/
1240 Rsdt = Rsdp->XsdtAddress;
1241 }
1242 else
1243 {
1244 /* ACPI 1.0 so just read the RSDT */
1245 Rsdt.QuadPart = Rsdp->RsdtAddress;
1246 }
1247
1248 /* Save it for later */
1249 EfiRsdt = Rsdt;
1250
1251 /* And return it back */
1252 *FoundRsdt = Rsdt;
1253 }
1254
1255 /* Check if we had mapped the RSDP */
1256 if (Rsdp)
1257 {
1258 /* Unmap it */
1259 BlMmUnmapVirtualAddressEx(Rsdp, Length);
1260 }
1261
1262 /* Return search result back to caller */
1263 return Status;
1264 }
1265
1266 BL_MEMORY_ATTR
1267 MmFwpGetOsAttributeType (
1268 _In_ ULONGLONG Attribute
1269 )
1270 {
1271 BL_MEMORY_ATTR OsAttribute = 0;
1272
1273 if (Attribute & EFI_MEMORY_UC)
1274 {
1275 OsAttribute = BlMemoryUncached;
1276 }
1277
1278 if (Attribute & EFI_MEMORY_WC)
1279 {
1280 OsAttribute |= BlMemoryWriteCombined;
1281 }
1282
1283 if (Attribute & EFI_MEMORY_WT)
1284 {
1285 OsAttribute |= BlMemoryWriteThrough;
1286 }
1287
1288 if (Attribute & EFI_MEMORY_WB)
1289 {
1290 OsAttribute |= BlMemoryWriteBack;
1291 }
1292
1293 if (Attribute & EFI_MEMORY_UCE)
1294 {
1295 OsAttribute |= BlMemoryUncachedExported;
1296 }
1297
1298 if (Attribute & EFI_MEMORY_WP)
1299 {
1300 OsAttribute |= BlMemoryWriteProtected;
1301 }
1302
1303 if (Attribute & EFI_MEMORY_RP)
1304 {
1305 OsAttribute |= BlMemoryReadProtected;
1306 }
1307
1308 if (Attribute & EFI_MEMORY_XP)
1309 {
1310 OsAttribute |= BlMemoryExecuteProtected;
1311 }
1312
1313 if (Attribute & EFI_MEMORY_RUNTIME)
1314 {
1315 OsAttribute |= BlMemoryRuntime;
1316 }
1317
1318 return OsAttribute;
1319 }
1320
1321 BL_MEMORY_TYPE
1322 MmFwpGetOsMemoryType (
1323 _In_ EFI_MEMORY_TYPE MemoryType
1324 )
1325 {
1326 BL_MEMORY_TYPE OsType;
1327
1328 switch (MemoryType)
1329 {
1330 case EfiLoaderCode:
1331 case EfiLoaderData:
1332 OsType = BlLoaderMemory;
1333 break;
1334
1335 case EfiBootServicesCode:
1336 case EfiBootServicesData:
1337 OsType = BlEfiBootMemory;
1338 break;
1339
1340 case EfiRuntimeServicesCode:
1341 case EfiRuntimeServicesData:
1342 OsType = BlEfiRuntimeMemory;
1343 break;
1344
1345 case EfiConventionalMemory:
1346 OsType = BlConventionalMemory;
1347 break;
1348
1349 case EfiUnusableMemory:
1350 OsType = BlUnusableMemory;
1351 break;
1352
1353 case EfiACPIReclaimMemory:
1354 OsType = BlAcpiReclaimMemory;
1355 break;
1356
1357 case EfiACPIMemoryNVS:
1358 OsType = BlAcpiNvsMemory;
1359 break;
1360
1361 case EfiMemoryMappedIO:
1362 OsType = BlDeviceIoMemory;
1363 break;
1364
1365 case EfiMemoryMappedIOPortSpace:
1366 OsType = BlDevicePortMemory;
1367 break;
1368
1369 case EfiPalCode:
1370 OsType = BlPalMemory;
1371 break;
1372
1373 default:
1374 OsType = BlReservedMemory;
1375 break;
1376 }
1377
1378 return OsType;
1379 }
1380
1381 NTSTATUS
1382 MmFwGetMemoryMap (
1383 _Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap,
1384 _In_ ULONG Flags
1385 )
1386 {
1387 BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
1388 BOOLEAN UseEfiBuffer, HaveRamDisk;
1389 NTSTATUS Status;
1390 ULONGLONG Pages, StartPage, EndPage;
1391 UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion;
1392 EFI_PHYSICAL_ADDRESS EfiBuffer = 0;
1393 EFI_MEMORY_DESCRIPTOR* EfiMemoryMap;
1394 EFI_STATUS EfiStatus;
1395 BL_ARCH_MODE OldMode;
1396 EFI_MEMORY_DESCRIPTOR EfiDescriptor;
1397 BL_MEMORY_TYPE MemoryType;
1398 PBL_MEMORY_DESCRIPTOR Descriptor;
1399 BL_MEMORY_ATTR Attribute;
1400
1401 /* Initialize EFI memory map attributes */
1402 EfiMemoryMapSize = MapKey = DescriptorSize = DescriptorVersion = 0;
1403
1404 /* Increment the nesting depth */
1405 MmDescriptorCallTreeCount++;
1406
1407 /* Determine if we should use EFI or our own allocator at this point */
1408 UseEfiBuffer = Flags & BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS;
1409 if (!(LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED))
1410 {
1411 UseEfiBuffer = TRUE;
1412 }
1413
1414 /* Bail out if we don't have a list to use */
1415 if (MemoryMap == NULL)
1416 {
1417 Status = STATUS_INVALID_PARAMETER;
1418 goto Quickie;
1419 }
1420
1421 /* Free the current descriptor list */
1422 MmMdFreeList(MemoryMap);
1423
1424 /* Call into EFI to get the size of the memory map */
1425 Status = EfiGetMemoryMap(&EfiMemoryMapSize,
1426 NULL,
1427 &MapKey,
1428 &DescriptorSize,
1429 &DescriptorVersion);
1430 if (Status != STATUS_BUFFER_TOO_SMALL)
1431 {
1432 /* This should've failed because our buffer was too small, nothing else */
1433 EfiPrintf(L"Got strange EFI status for memory map: %lx\r\n", Status);
1434 if (NT_SUCCESS(Status))
1435 {
1436 Status = STATUS_UNSUCCESSFUL;
1437 }
1438 goto Quickie;
1439 }
1440
1441 /* Add 4 more descriptors just in case things changed */
1442 EfiMemoryMapSize += (4 * DescriptorSize);
1443 Pages = BYTES_TO_PAGES(EfiMemoryMapSize);
1444 EfiPrintf(L"Memory map size: %lx bytes, %d pages\r\n", EfiMemoryMapSize, Pages);
1445
1446 /* Should we use EFI to grab memory? */
1447 if (UseEfiBuffer)
1448 {
1449 /* Yes -- request one more page to align up correctly */
1450 Pages++;
1451
1452 /* Grab the required pages */
1453 Status = EfiAllocatePages(AllocateAnyPages,
1454 Pages,
1455 &EfiBuffer);
1456 if (!NT_SUCCESS(Status))
1457 {
1458 EfiPrintf(L"EFI allocation failed: %lx\r\n", Status);
1459 goto Quickie;
1460 }
1461
1462 /* Free the pages for now */
1463 Status = EfiFreePages(Pages, EfiBuffer);
1464 if (!NT_SUCCESS(Status))
1465 {
1466 EfiBuffer = 0;
1467 goto Quickie;
1468 }
1469
1470 /* Now round to the actual buffer size, removing the extra page */
1471 EfiBuffer = ROUND_TO_PAGES(EfiBuffer);
1472 Pages--;
1473 Status = EfiAllocatePages(AllocateAddress,
1474 Pages,
1475 &EfiBuffer);
1476 if (!NT_SUCCESS(Status))
1477 {
1478 EfiBuffer = 0;
1479 goto Quickie;
1480 }
1481
1482 /* Get the final aligned size and proper buffer */
1483 EfiMemoryMapSize = EFI_PAGES_TO_SIZE(Pages);
1484 EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR*)(ULONG_PTR)EfiBuffer;
1485
1486 /* Switch to real mode if not already in it */
1487 OldMode = CurrentExecutionContext->Mode;
1488 if (OldMode != BlRealMode)
1489 {
1490 BlpArchSwitchContext(BlRealMode);
1491 }
1492
1493 /* Call EFI to get the memory map */
1494 EfiStatus = EfiBS->GetMemoryMap(&EfiMemoryMapSize,
1495 EfiMemoryMap,
1496 &MapKey,
1497 &DescriptorSize,
1498 &DescriptorVersion);
1499
1500 /* Switch back into the previous mode */
1501 if (OldMode != BlRealMode)
1502 {
1503 BlpArchSwitchContext(OldMode);
1504 }
1505
1506 /* Convert the result code */
1507 Status = EfiGetNtStatusCode(EfiStatus);
1508 }
1509 else
1510 {
1511 /* We don't support this path yet */
1512 Status = STATUS_NOT_IMPLEMENTED;
1513 }
1514
1515 /* So far so good? */
1516 if (!NT_SUCCESS(Status))
1517 {
1518 EfiPrintf(L"Failed to get EFI memory map: %lx\r\n", Status);
1519 goto Quickie;
1520 }
1521
1522 /* Did we get correct data from firmware? */
1523 if (((EfiMemoryMapSize % DescriptorSize)) ||
1524 (DescriptorSize < sizeof(EFI_MEMORY_DESCRIPTOR)))
1525 {
1526 EfiPrintf(L"Incorrect descriptor size\r\n");
1527 Status = STATUS_UNSUCCESSFUL;
1528 goto Quickie;
1529 }
1530
1531 /* Did we boot from a RAM disk? */
1532 if ((BlpBootDevice->DeviceType == LocalDevice) &&
1533 (BlpBootDevice->Local.Type == RamDiskDevice))
1534 {
1535 /* We don't handle this yet */
1536 EfiPrintf(L"RAM boot not supported\r\n");
1537 Status = STATUS_NOT_IMPLEMENTED;
1538 goto Quickie;
1539 }
1540 else
1541 {
1542 /* We didn't, so there won't be any need to find the memory descriptor */
1543 HaveRamDisk = FALSE;
1544 }
1545
1546 /* Loop the EFI memory map */
1547 #if 0
1548 EfiPrintf(L"UEFI MEMORY MAP\r\n\r\n");
1549 EfiPrintf(L"TYPE START END ATTRIBUTES\r\n");
1550 EfiPrintf(L"===============================================================\r\n");
1551 #endif
1552 while (EfiMemoryMapSize != 0)
1553 {
1554 /* Check if this is an EFI buffer, but we're not in real mode */
1555 if ((UseEfiBuffer) && (OldMode != BlRealMode))
1556 {
1557 BlpArchSwitchContext(BlRealMode);
1558 }
1559
1560 /* Capture it so we can go back to protected mode (if possible) */
1561 EfiDescriptor = *EfiMemoryMap;
1562
1563 /* Go back to protected mode, if we had switched */
1564 if ((UseEfiBuffer) && (OldMode != BlRealMode))
1565 {
1566 BlpArchSwitchContext(OldMode);
1567 }
1568
1569 /* Convert to OS memory type */
1570 MemoryType = MmFwpGetOsMemoryType(EfiDescriptor.Type);
1571
1572 /* Round up or round down depending on where the memory is coming from */
1573 if (MemoryType == BlConventionalMemory)
1574 {
1575 StartPage = BYTES_TO_PAGES(EfiDescriptor.PhysicalStart);
1576 }
1577 else
1578 {
1579 StartPage = EfiDescriptor.PhysicalStart >> PAGE_SHIFT;
1580 }
1581
1582 /* Calculate the ending page */
1583 EndPage = StartPage + EfiDescriptor.NumberOfPages;
1584
1585 /* If after rounding, we ended up with 0 pages, skip this */
1586 if (StartPage == EndPage)
1587 {
1588 goto LoopAgain;
1589 }
1590 #if 0
1591 EfiPrintf(L"%08X 0x%016I64X-0x%016I64X 0x%I64X\r\n",
1592 MemoryType,
1593 StartPage << PAGE_SHIFT,
1594 EndPage << PAGE_SHIFT,
1595 EfiDescriptor.Attribute);
1596 #endif
1597 /* Check for any range of memory below 1MB */
1598 if (StartPage < 0x100)
1599 {
1600 /* Does this range actually contain NULL? */
1601 if (StartPage == 0)
1602 {
1603 /* Manually create a reserved descriptof for this page */
1604 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
1605 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
1606 BlReservedMemory,
1607 0,
1608 0,
1609 1);
1610 if (!Descriptor)
1611 {
1612 Status = STATUS_INSUFFICIENT_RESOURCES;
1613 break;
1614 }
1615
1616 /* Add this descriptor into the list */
1617 Status = MmMdAddDescriptorToList(MemoryMap,
1618 Descriptor,
1619 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
1620 if (!NT_SUCCESS(Status))
1621 {
1622 EfiPrintf(L"Failed to add zero page descriptor: %lx\r\n", Status);
1623 break;
1624 }
1625
1626 /* Now handle the rest of the range, unless this was it */
1627 StartPage = 1;
1628 if (EndPage == 1)
1629 {
1630 goto LoopAgain;
1631 }
1632 }
1633
1634 /* Does the range go beyond 1MB? */
1635 if (EndPage > 0x100)
1636 {
1637 /* Then create the descriptor for everything up until the megabyte */
1638 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
1639 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
1640 MemoryType,
1641 StartPage,
1642 0,
1643 0x100 - StartPage);
1644 if (!Descriptor)
1645 {
1646 Status = STATUS_INSUFFICIENT_RESOURCES;
1647 break;
1648 }
1649
1650 /* Check if this region is currently free RAM */
1651 if (Descriptor->Type == BlConventionalMemory)
1652 {
1653 /* Set the reserved flag on the descriptor */
1654 EfiPrintf(L"Adding magic flag\r\n");
1655 Descriptor->Flags |= BlMemoryReserved;
1656 }
1657
1658 /* Add this descriptor into the list */
1659 Status = MmMdAddDescriptorToList(MemoryMap,
1660 Descriptor,
1661 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
1662 if (!NT_SUCCESS(Status))
1663 {
1664 EfiPrintf(L"Failed to add 1MB descriptor: %lx\r\n", Status);
1665 break;
1666 }
1667
1668 /* Now handle the rest of the range above 1MB */
1669 StartPage = 0x100;
1670 }
1671 }
1672
1673 /* Check if we loaded from a RAM disk */
1674 if (HaveRamDisk)
1675 {
1676 /* We don't handle this yet */
1677 EfiPrintf(L"RAM boot not supported\r\n");
1678 Status = STATUS_NOT_IMPLEMENTED;
1679 goto Quickie;
1680 }
1681
1682 /* Create a descriptor for the current range */
1683 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
1684 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
1685 MemoryType,
1686 StartPage,
1687 0,
1688 EndPage - StartPage);
1689 if (!Descriptor)
1690 {
1691 Status = STATUS_INSUFFICIENT_RESOURCES;
1692 break;
1693 }
1694
1695 /* Check if this region is currently free RAM below 1MB */
1696 if ((Descriptor->Type == BlConventionalMemory) && (EndPage <= 0x100))
1697 {
1698 /* Set the reserved flag on the descriptor */
1699 EfiPrintf(L"Adding magic flag\r\n");
1700 Descriptor->Flags |= BlMemoryReserved;
1701 }
1702
1703 /* Add the descriptor to the list, requesting coalescing as asked */
1704 Status = MmMdAddDescriptorToList(MemoryMap,
1705 Descriptor,
1706 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG |
1707 ((Flags & BL_MM_FLAG_REQUEST_COALESCING) ?
1708 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG : 0));
1709 if (!NT_SUCCESS(Status))
1710 {
1711 EfiPrintf(L"Failed to add full descriptor: %lx\r\n", Status);
1712 break;
1713 }
1714
1715 LoopAgain:
1716 /* Consume this descriptor, and move to the next one */
1717 EfiMemoryMapSize -= DescriptorSize;
1718 EfiMemoryMap = (PVOID)((ULONG_PTR)EfiMemoryMap + DescriptorSize);
1719 }
1720
1721 /* FIXME: @TODO: Mark the EfiBuffer as free, since we're about to free it */
1722 /* For now, just "leak" the 1-2 pages... */
1723
1724 Quickie:
1725 /* Free the EFI buffer, if we had one */
1726 if (EfiBuffer != 0)
1727 {
1728 EfiFreePages(Pages, EfiBuffer);
1729 }
1730
1731 /* On failure, free the memory map if one was passed in */
1732 if (!NT_SUCCESS(Status) && (MemoryMap != NULL))
1733 {
1734 MmMdFreeList(MemoryMap);
1735 }
1736
1737 /* Decrement the nesting depth and return */
1738 MmDescriptorCallTreeCount--;
1739 return Status;
1740 }
1741
1742 NTSTATUS
1743 BlpFwInitialize (
1744 _In_ ULONG Phase,
1745 _In_ PBL_FIRMWARE_DESCRIPTOR FirmwareData
1746 )
1747 {
1748 NTSTATUS Status = STATUS_SUCCESS;
1749 EFI_KEY_TOGGLE_STATE KeyToggleState;
1750
1751 /* Check if we have valid firmware data */
1752 if (!(FirmwareData) || !(FirmwareData->Version))
1753 {
1754 return STATUS_INVALID_PARAMETER;
1755 }
1756
1757 /* Check which boot phase we're in */
1758 if (Phase != 0)
1759 {
1760 /* Memory manager is ready, open the extended input protocol */
1761 Status = EfiOpenProtocol(EfiST->ConsoleInHandle,
1762 &EfiSimpleTextInputExProtocol,
1763 (PVOID*)&EfiConInEx);
1764 if (NT_SUCCESS(Status))
1765 {
1766 /* Set the initial key toggle state */
1767 KeyToggleState = EFI_TOGGLE_STATE_VALID | 40;
1768 EfiConInExSetState(EfiConInEx, &KeyToggleState);
1769 }
1770
1771 /* Setup the watchdog timer */
1772 EfiSetWatchdogTimer();
1773 }
1774 else
1775 {
1776 /* Make a copy of the parameters */
1777 EfiFirmwareParameters = &EfiFirmwareData;
1778
1779 /* Check which version we received */
1780 if (FirmwareData->Version == 1)
1781 {
1782 /* FIXME: Not supported */
1783 Status = STATUS_NOT_SUPPORTED;
1784 }
1785 else if (FirmwareData->Version >= BL_FIRMWARE_DESCRIPTOR_VERSION)
1786 {
1787 /* Version 2 -- save the data */
1788 EfiFirmwareData = *FirmwareData;
1789 EfiSystemTable = FirmwareData->SystemTable;
1790 EfiImageHandle = FirmwareData->ImageHandle;
1791
1792 /* Set the EDK-II style variables as well */
1793 EfiST = EfiSystemTable;
1794 EfiBS = EfiSystemTable->BootServices;
1795 EfiRT = EfiSystemTable->RuntimeServices;
1796 EfiConOut = EfiSystemTable->ConOut;
1797 EfiConIn = EfiSystemTable->ConIn;
1798 EfiConInEx = NULL;
1799 }
1800 else
1801 {
1802 /* Unknown version */
1803 Status = STATUS_NOT_SUPPORTED;
1804 }
1805 }
1806
1807 /* Return the initialization state */
1808 return Status;
1809 }
1810
1811 NTSTATUS
1812 BlFwGetParameters (
1813 _In_ PBL_FIRMWARE_DESCRIPTOR Parameters
1814 )
1815 {
1816 /* Make sure we got an argument */
1817 if (!Parameters)
1818 {
1819 return STATUS_INVALID_PARAMETER;
1820 }
1821
1822 /* Copy the static data */
1823 *Parameters = *EfiFirmwareParameters;
1824 return STATUS_SUCCESS;
1825 }
1826
1827 NTSTATUS
1828 BlFwEnumerateDevice (
1829 _In_ PBL_DEVICE_DESCRIPTOR Device
1830 )
1831 {
1832 NTSTATUS Status;
1833 ULONG PathProtocols, BlockProtocols;
1834 EFI_HANDLE* PathArray;
1835 EFI_HANDLE* BlockArray;
1836
1837 /* Initialize locals */
1838 BlockArray = NULL;
1839 PathArray = NULL;
1840 PathProtocols = 0;
1841 BlockProtocols = 0;
1842
1843 /* Enumeration only makes sense on disks or partitions */
1844 if ((Device->DeviceType != DiskDevice) &&
1845 (Device->DeviceType != LegacyPartitionDevice) &&
1846 (Device->DeviceType != PartitionDevice))
1847 {
1848 return STATUS_NOT_SUPPORTED;
1849 }
1850
1851 /* Enumerate the list of device paths */
1852 Status = EfiLocateHandleBuffer(ByProtocol,
1853 &EfiDevicePathProtocol,
1854 &PathProtocols,
1855 &PathArray);
1856 if (NT_SUCCESS(Status))
1857 {
1858 /* Loop through each one */
1859 Status = STATUS_NOT_FOUND;
1860 while (PathProtocols)
1861 {
1862 /* Attempt to connect the driver for this device epath */
1863 Status = EfiConnectController(PathArray[--PathProtocols]);
1864 if (NT_SUCCESS(Status))
1865 {
1866 /* Now enumerate any block I/O devices the driver added */
1867 Status = EfiLocateHandleBuffer(ByProtocol,
1868 &EfiBlockIoProtocol,
1869 &BlockProtocols,
1870 &BlockArray);
1871 if (!NT_SUCCESS(Status))
1872 {
1873 break;
1874 }
1875
1876 /* Loop through each one */
1877 while (BlockProtocols)
1878 {
1879 /* Check if one of the new devices is the one we want */
1880 Status = BlockIoEfiCompareDevice(Device,
1881 BlockArray[--BlockProtocols]);
1882 if (NT_SUCCESS(Status))
1883 {
1884 /* Yep, all done */
1885 goto Quickie;
1886 }
1887 }
1888
1889 /* Move on to the next device path */
1890 BlMmFreeHeap(BlockArray);
1891 BlockArray = NULL;
1892 }
1893 }
1894 }
1895
1896 Quickie:
1897 /* We're done -- free the array of device path protocols, if any */
1898 if (PathArray)
1899 {
1900 BlMmFreeHeap(PathArray);
1901 }
1902
1903 /* We're done -- free the array of block I/O protocols, if any */
1904 if (BlockArray)
1905 {
1906 BlMmFreeHeap(BlockArray);
1907 }
1908
1909 /* Return if we found the device or not */
1910 return Status;
1911 }
1912
1913 /*++
1914 * @name EfiGetEfiStatusCode
1915 *
1916 * The EfiGetEfiStatusCode routine converts an NT Status to an EFI status.
1917 *
1918 * @param Status
1919 * NT Status code to be converted.
1920 *
1921 * @remark Only certain, specific NT status codes are converted to EFI codes.
1922 *
1923 * @return The corresponding EFI Status code, EFI_NO_MAPPING otherwise.
1924 *
1925 *--*/
1926 EFI_STATUS
1927 EfiGetEfiStatusCode(
1928 _In_ NTSTATUS Status
1929 )
1930 {
1931 switch (Status)
1932 {
1933 case STATUS_NOT_SUPPORTED:
1934 return EFI_UNSUPPORTED;
1935 case STATUS_DISK_FULL:
1936 return EFI_VOLUME_FULL;
1937 case STATUS_INSUFFICIENT_RESOURCES:
1938 return EFI_OUT_OF_RESOURCES;
1939 case STATUS_MEDIA_WRITE_PROTECTED:
1940 return EFI_WRITE_PROTECTED;
1941 case STATUS_DEVICE_NOT_READY:
1942 return EFI_NOT_STARTED;
1943 case STATUS_DEVICE_ALREADY_ATTACHED:
1944 return EFI_ALREADY_STARTED;
1945 case STATUS_MEDIA_CHANGED:
1946 return EFI_MEDIA_CHANGED;
1947 case STATUS_INVALID_PARAMETER:
1948 return EFI_INVALID_PARAMETER;
1949 case STATUS_ACCESS_DENIED:
1950 return EFI_ACCESS_DENIED;
1951 case STATUS_BUFFER_TOO_SMALL:
1952 return EFI_BUFFER_TOO_SMALL;
1953 case STATUS_DISK_CORRUPT_ERROR:
1954 return EFI_VOLUME_CORRUPTED;
1955 case STATUS_REQUEST_ABORTED:
1956 return EFI_ABORTED;
1957 case STATUS_NO_MEDIA:
1958 return EFI_NO_MEDIA;
1959 case STATUS_IO_DEVICE_ERROR:
1960 return EFI_DEVICE_ERROR;
1961 case STATUS_INVALID_BUFFER_SIZE:
1962 return EFI_BAD_BUFFER_SIZE;
1963 case STATUS_NOT_FOUND:
1964 return EFI_NOT_FOUND;
1965 case STATUS_DRIVER_UNABLE_TO_LOAD:
1966 return EFI_LOAD_ERROR;
1967 case STATUS_NO_MATCH:
1968 return EFI_NO_MAPPING;
1969 case STATUS_SUCCESS:
1970 return EFI_SUCCESS;
1971 case STATUS_TIMEOUT:
1972 return EFI_TIMEOUT;
1973 default:
1974 return EFI_NO_MAPPING;
1975 }
1976 }
1977
1978 /*++
1979 * @name EfiGetNtStatusCode
1980 *
1981 * The EfiGetNtStatusCode routine converts an EFI Status to an NT status.
1982 *
1983 * @param EfiStatus
1984 * EFI Status code to be converted.
1985 *
1986 * @remark Only certain, specific EFI status codes are converted to NT codes.
1987 *
1988 * @return The corresponding NT Status code, STATUS_UNSUCCESSFUL otherwise.
1989 *
1990 *--*/
1991 NTSTATUS
1992 EfiGetNtStatusCode (
1993 _In_ EFI_STATUS EfiStatus
1994 )
1995 {
1996 switch (EfiStatus)
1997 {
1998 case EFI_NOT_READY:
1999 case EFI_NOT_FOUND:
2000 return STATUS_NOT_FOUND;
2001 case EFI_NO_MEDIA:
2002 return STATUS_NO_MEDIA;
2003 case EFI_MEDIA_CHANGED:
2004 return STATUS_MEDIA_CHANGED;
2005 case EFI_ACCESS_DENIED:
2006 case EFI_SECURITY_VIOLATION:
2007 return STATUS_ACCESS_DENIED;
2008 case EFI_TIMEOUT:
2009 case EFI_NO_RESPONSE:
2010 return STATUS_TIMEOUT;
2011 case EFI_NO_MAPPING:
2012 return STATUS_NO_MATCH;
2013 case EFI_NOT_STARTED:
2014 return STATUS_DEVICE_NOT_READY;
2015 case EFI_ALREADY_STARTED:
2016 return STATUS_DEVICE_ALREADY_ATTACHED;
2017 case EFI_ABORTED:
2018 return STATUS_REQUEST_ABORTED;
2019 case EFI_VOLUME_FULL:
2020 return STATUS_DISK_FULL;
2021 case EFI_DEVICE_ERROR:
2022 return STATUS_IO_DEVICE_ERROR;
2023 case EFI_WRITE_PROTECTED:
2024 return STATUS_MEDIA_WRITE_PROTECTED;
2025 /* @FIXME: ReactOS Headers don't yet have this */
2026 //case EFI_OUT_OF_RESOURCES:
2027 //return STATUS_INSUFFICIENT_NVRAM_RESOURCES;
2028 case EFI_VOLUME_CORRUPTED:
2029 return STATUS_DISK_CORRUPT_ERROR;
2030 case EFI_BUFFER_TOO_SMALL:
2031 return STATUS_BUFFER_TOO_SMALL;
2032 case EFI_SUCCESS:
2033 return STATUS_SUCCESS;
2034 case EFI_LOAD_ERROR:
2035 return STATUS_DRIVER_UNABLE_TO_LOAD;
2036 case EFI_INVALID_PARAMETER:
2037 return STATUS_INVALID_PARAMETER;
2038 case EFI_UNSUPPORTED:
2039 return STATUS_NOT_SUPPORTED;
2040 case EFI_BAD_BUFFER_SIZE:
2041 return STATUS_INVALID_BUFFER_SIZE;
2042 default:
2043 return STATUS_UNSUCCESSFUL;
2044 }
2045 }