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