[BOOTMGFW]
[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
27 EFI_GUID EfiGraphicsOutputProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
28 EFI_GUID EfiUgaDrawProtocol = EFI_UGA_DRAW_PROTOCOL_GUID;
29 EFI_GUID EfiLoadedImageProtocol = EFI_LOADED_IMAGE_PROTOCOL_GUID;
30 EFI_GUID EfiDevicePathProtocol = EFI_DEVICE_PATH_PROTOCOL_GUID;
31 EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
32
33 /* FUNCTIONS *****************************************************************/
34
35 NTSTATUS
36 EfiOpenProtocol (
37 _In_ EFI_HANDLE Handle,
38 _In_ EFI_GUID *Protocol,
39 _Out_ PVOID* Interface
40 )
41 {
42 EFI_STATUS EfiStatus;
43 NTSTATUS Status;
44 BL_ARCH_MODE OldMode;
45
46 /* Are we using virtual memory/ */
47 if (MmTranslationType != BlNone)
48 {
49 /* We need complex tracking to make this work */
50 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
51 Status = STATUS_NOT_SUPPORTED;
52 }
53 else
54 {
55 /* Are we in protected mode? */
56 OldMode = CurrentExecutionContext->Mode;
57 if (OldMode != BlRealMode)
58 {
59 /* FIXME: Not yet implemented */
60 return STATUS_NOT_IMPLEMENTED;
61 }
62
63 /* Are we on legacy 1.02? */
64 if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION)
65 {
66 /* Make the legacy call */
67 EfiStatus = EfiBS->HandleProtocol(Handle, Protocol, Interface);
68 }
69 else
70 {
71 /* Use the UEFI version */
72 EfiStatus = EfiBS->OpenProtocol(Handle,
73 Protocol,
74 Interface,
75 EfiImageHandle,
76 NULL,
77 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
78
79 /* Switch back to protected mode if we came from there */
80 if (OldMode != BlRealMode)
81 {
82 BlpArchSwitchContext(OldMode);
83 }
84 }
85
86 /* Convert the error to an NTSTATUS */
87 Status = EfiGetNtStatusCode(EfiStatus);
88 }
89
90 /* Clear the interface on failure, and return the status */
91 if (!NT_SUCCESS(Status))
92 {
93 *Interface = NULL;
94 }
95
96 return Status;
97 }
98
99 NTSTATUS
100 EfiCloseProtocol (
101 _In_ EFI_HANDLE Handle,
102 _In_ EFI_GUID *Protocol
103 )
104 {
105 EFI_STATUS EfiStatus;
106 NTSTATUS Status;
107 BL_ARCH_MODE OldMode;
108
109 /* Are we using virtual memory/ */
110 if (MmTranslationType != BlNone)
111 {
112 /* We need complex tracking to make this work */
113 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
114 Status = STATUS_NOT_SUPPORTED;
115 }
116 else
117 {
118 /* Are we on legacy 1.02? */
119 if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION)
120 {
121 /* Nothing to close */
122 EfiStatus = STATUS_SUCCESS;
123 }
124 else
125 {
126 /* Are we in protected mode? */
127 OldMode = CurrentExecutionContext->Mode;
128 if (OldMode != BlRealMode)
129 {
130 /* FIXME: Not yet implemented */
131 return STATUS_NOT_IMPLEMENTED;
132 }
133
134 /* Use the UEFI version */
135 EfiStatus = EfiBS->CloseProtocol(Handle, Protocol, EfiImageHandle, NULL);
136
137 /* Switch back to protected mode if we came from there */
138 if (OldMode != BlRealMode)
139 {
140 BlpArchSwitchContext(OldMode);
141 }
142
143 /* Normalize not found as success */
144 if (EfiStatus == EFI_NOT_FOUND)
145 {
146 EfiStatus = EFI_SUCCESS;
147 }
148 }
149
150 /* Convert the error to an NTSTATUS */
151 Status = EfiGetNtStatusCode(EfiStatus);
152 }
153
154 /* All done */
155 return Status;
156 }
157
158 NTSTATUS
159 EfiConInExSetState (
160 _In_ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *ConInEx,
161 _In_ EFI_KEY_TOGGLE_STATE* KeyToggleState
162 )
163 {
164 BL_ARCH_MODE OldMode;
165 EFI_STATUS EfiStatus;
166
167 /* Are we in protected mode? */
168 OldMode = CurrentExecutionContext->Mode;
169 if (OldMode != BlRealMode)
170 {
171 /* FIXME: Not yet implemented */
172 return STATUS_NOT_IMPLEMENTED;
173 }
174
175 /* Make the EFI call */
176 EfiStatus = ConInEx->SetState(ConInEx, KeyToggleState);
177
178 /* Switch back to protected mode if we came from there */
179 if (OldMode != BlRealMode)
180 {
181 BlpArchSwitchContext(OldMode);
182 }
183
184 /* Convert the error to an NTSTATUS */
185 return EfiGetNtStatusCode(EfiStatus);
186 }
187
188 NTSTATUS
189 EfiSetWatchdogTimer (
190 VOID
191 )
192 {
193 BL_ARCH_MODE OldMode;
194 EFI_STATUS EfiStatus;
195
196 /* Are we in protected mode? */
197 OldMode = CurrentExecutionContext->Mode;
198 if (OldMode != BlRealMode)
199 {
200 /* FIXME: Not yet implemented */
201 return STATUS_NOT_IMPLEMENTED;
202 }
203
204 /* Make the EFI call */
205 EfiStatus = EfiBS->SetWatchdogTimer(0, 0, 0, NULL);
206
207 /* Switch back to protected mode if we came from there */
208 if (OldMode != BlRealMode)
209 {
210 BlpArchSwitchContext(OldMode);
211 }
212
213 /* Convert the error to an NTSTATUS */
214 return EfiGetNtStatusCode(EfiStatus);
215 }
216
217 NTSTATUS
218 EfiGetMemoryMap (
219 _Out_ UINTN* MemoryMapSize,
220 _Inout_ EFI_MEMORY_DESCRIPTOR *MemoryMap,
221 _Out_ UINTN* MapKey,
222 _Out_ UINTN* DescriptorSize,
223 _Out_ UINTN* DescriptorVersion
224 )
225 {
226 BL_ARCH_MODE OldMode;
227 EFI_STATUS EfiStatus;
228
229 /* Are we in protected mode? */
230 OldMode = CurrentExecutionContext->Mode;
231 if (OldMode != BlRealMode)
232 {
233 /* FIXME: Not yet implemented */
234 return STATUS_NOT_IMPLEMENTED;
235 }
236
237 /* Make the EFI call */
238 EfiStatus = EfiBS->GetMemoryMap(MemoryMapSize,
239 MemoryMap,
240 MapKey,
241 DescriptorSize,
242 DescriptorVersion);
243
244 /* Switch back to protected mode if we came from there */
245 if (OldMode != BlRealMode)
246 {
247 BlpArchSwitchContext(OldMode);
248 }
249
250 /* Convert the error to an NTSTATUS */
251 return EfiGetNtStatusCode(EfiStatus);
252 }
253
254 NTSTATUS
255 EfiFreePages (
256 _In_ ULONG Pages,
257 _In_ EFI_PHYSICAL_ADDRESS PhysicalAddress
258 )
259 {
260 BL_ARCH_MODE OldMode;
261 EFI_STATUS EfiStatus;
262
263 /* Are we in protected mode? */
264 OldMode = CurrentExecutionContext->Mode;
265 if (OldMode != BlRealMode)
266 {
267 /* FIXME: Not yet implemented */
268 return STATUS_NOT_IMPLEMENTED;
269 }
270
271 /* Make the EFI call */
272 EfiStatus = EfiBS->FreePages(PhysicalAddress, Pages);
273
274 /* Switch back to protected mode if we came from there */
275 if (OldMode != BlRealMode)
276 {
277 BlpArchSwitchContext(OldMode);
278 }
279
280 /* Convert the error to an NTSTATUS */
281 return EfiGetNtStatusCode(EfiStatus);
282 }
283
284 NTSTATUS
285 EfiStall (
286 _In_ ULONG StallTime
287 )
288 {
289 BL_ARCH_MODE OldMode;
290 EFI_STATUS EfiStatus;
291
292 /* Are we in protected mode? */
293 OldMode = CurrentExecutionContext->Mode;
294 if (OldMode != BlRealMode)
295 {
296 /* FIXME: Not yet implemented */
297 return STATUS_NOT_IMPLEMENTED;
298 }
299
300 /* Make the EFI call */
301 EfiStatus = EfiBS->Stall(StallTime);
302
303 /* Switch back to protected mode if we came from there */
304 if (OldMode != BlRealMode)
305 {
306 BlpArchSwitchContext(OldMode);
307 }
308
309 /* Convert the error to an NTSTATUS */
310 return EfiGetNtStatusCode(EfiStatus);
311 }
312
313 NTSTATUS
314 EfiConOutQueryMode (
315 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
316 _In_ ULONG Mode,
317 _In_ UINTN* Columns,
318 _In_ UINTN* Rows
319 )
320 {
321 BL_ARCH_MODE OldMode;
322 EFI_STATUS EfiStatus;
323
324 /* Are we in protected mode? */
325 OldMode = CurrentExecutionContext->Mode;
326 if (OldMode != BlRealMode)
327 {
328 /* FIXME: Not yet implemented */
329 return STATUS_NOT_IMPLEMENTED;
330 }
331
332 /* Make the EFI call */
333 EfiStatus = TextInterface->QueryMode(TextInterface, Mode, Columns, Rows);
334
335 /* Switch back to protected mode if we came from there */
336 if (OldMode != BlRealMode)
337 {
338 BlpArchSwitchContext(OldMode);
339 }
340
341 /* Convert the error to an NTSTATUS */
342 return EfiGetNtStatusCode(EfiStatus);
343 }
344
345 NTSTATUS
346 EfiConOutSetMode (
347 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
348 _In_ ULONG Mode
349 )
350 {
351 BL_ARCH_MODE OldMode;
352 EFI_STATUS EfiStatus;
353
354 /* Are we in protected mode? */
355 OldMode = CurrentExecutionContext->Mode;
356 if (OldMode != BlRealMode)
357 {
358 /* FIXME: Not yet implemented */
359 return STATUS_NOT_IMPLEMENTED;
360 }
361
362 /* Make the EFI call */
363 EfiStatus = TextInterface->SetMode(TextInterface, Mode);
364
365 /* Switch back to protected mode if we came from there */
366 if (OldMode != BlRealMode)
367 {
368 BlpArchSwitchContext(OldMode);
369 }
370
371 /* Convert the error to an NTSTATUS */
372 return EfiGetNtStatusCode(EfiStatus);
373 }
374
375 NTSTATUS
376 EfiConOutSetAttribute (
377 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
378 _In_ ULONG Attribute
379 )
380 {
381 BL_ARCH_MODE OldMode;
382 EFI_STATUS EfiStatus;
383
384 /* Are we in protected mode? */
385 OldMode = CurrentExecutionContext->Mode;
386 if (OldMode != BlRealMode)
387 {
388 /* FIXME: Not yet implemented */
389 return STATUS_NOT_IMPLEMENTED;
390 }
391
392 /* Make the EFI call */
393 EfiStatus = TextInterface->SetAttribute(TextInterface, Attribute);
394
395 /* Switch back to protected mode if we came from there */
396 if (OldMode != BlRealMode)
397 {
398 BlpArchSwitchContext(OldMode);
399 }
400
401 /* Convert the error to an NTSTATUS */
402 return EfiGetNtStatusCode(EfiStatus);
403 }
404
405 NTSTATUS
406 EfiConOutSetCursorPosition (
407 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
408 _In_ ULONG Column,
409 _In_ ULONG Row
410 )
411 {
412 BL_ARCH_MODE OldMode;
413 EFI_STATUS EfiStatus;
414
415 /* Are we in protected mode? */
416 OldMode = CurrentExecutionContext->Mode;
417 if (OldMode != BlRealMode)
418 {
419 /* FIXME: Not yet implemented */
420 return STATUS_NOT_IMPLEMENTED;
421 }
422
423 /* Make the EFI call */
424 EfiStatus = TextInterface->SetCursorPosition(TextInterface, Column, Row);
425
426 /* Switch back to protected mode if we came from there */
427 if (OldMode != BlRealMode)
428 {
429 BlpArchSwitchContext(OldMode);
430 }
431
432 /* Convert the error to an NTSTATUS */
433 return EfiGetNtStatusCode(EfiStatus);
434 }
435
436 NTSTATUS
437 EfiConOutEnableCursor (
438 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
439 _In_ BOOLEAN Visible
440 )
441 {
442 BL_ARCH_MODE OldMode;
443 EFI_STATUS EfiStatus;
444
445 /* Are we in protected mode? */
446 OldMode = CurrentExecutionContext->Mode;
447 if (OldMode != BlRealMode)
448 {
449 /* FIXME: Not yet implemented */
450 return STATUS_NOT_IMPLEMENTED;
451 }
452
453 /* Make the EFI call */
454 EfiStatus = TextInterface->EnableCursor(TextInterface, Visible);
455
456 /* Switch back to protected mode if we came from there */
457 if (OldMode != BlRealMode)
458 {
459 BlpArchSwitchContext(OldMode);
460 }
461
462 /* Convert the error to an NTSTATUS */
463 return EfiGetNtStatusCode(EfiStatus);
464 }
465
466 VOID
467 EfiConOutReadCurrentMode (
468 _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
469 _Out_ EFI_SIMPLE_TEXT_OUTPUT_MODE* Mode
470 )
471 {
472 BL_ARCH_MODE OldMode;
473
474 /* Are we in protected mode? */
475 OldMode = CurrentExecutionContext->Mode;
476 if (OldMode != BlRealMode)
477 {
478 /* FIXME: Not yet implemented */
479 return;
480 }
481
482 /* Make the EFI call */
483 RtlCopyMemory(Mode, TextInterface->Mode, sizeof(*Mode));
484
485 /* Switch back to protected mode if we came from there */
486 if (OldMode != BlRealMode)
487 {
488 BlpArchSwitchContext(OldMode);
489 }
490 }
491
492 VOID
493 EfiGopGetFrameBuffer (
494 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
495 _Out_ PHYSICAL_ADDRESS* FrameBuffer,
496 _Out_ UINTN *FrameBufferSize
497 )
498 {
499 BL_ARCH_MODE OldMode;
500
501 /* Are we in protected mode? */
502 OldMode = CurrentExecutionContext->Mode;
503 if (OldMode != BlRealMode)
504 {
505 /* FIXME: Not yet implemented */
506 return;
507 }
508
509 /* Make the EFI call */
510 FrameBuffer->QuadPart = GopInterface->Mode->FrameBufferBase;
511 *FrameBufferSize = GopInterface->Mode->FrameBufferSize;
512
513 /* Switch back to protected mode if we came from there */
514 if (OldMode != BlRealMode)
515 {
516 BlpArchSwitchContext(OldMode);
517 }
518 }
519
520 NTSTATUS
521 EfiGopGetCurrentMode (
522 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
523 _Out_ UINTN* Mode,
524 _Out_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information
525 )
526 {
527 BL_ARCH_MODE OldMode;
528
529 /* Are we in protected mode? */
530 OldMode = CurrentExecutionContext->Mode;
531 if (OldMode != BlRealMode)
532 {
533 /* FIXME: Not yet implemented */
534 return STATUS_NOT_IMPLEMENTED;
535 }
536
537 /* Make the EFI call */
538 *Mode = GopInterface->Mode->Mode;
539 RtlCopyMemory(Information, GopInterface->Mode->Info, sizeof(*Information));
540
541 /* Switch back to protected mode if we came from there */
542 if (OldMode != BlRealMode)
543 {
544 BlpArchSwitchContext(OldMode);
545 }
546
547 /* Return back */
548 return STATUS_SUCCESS;
549 }
550
551 NTSTATUS
552 EfiGopSetMode (
553 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface,
554 _In_ ULONG Mode
555 )
556 {
557 BL_ARCH_MODE OldMode;
558 EFI_STATUS EfiStatus;
559 BOOLEAN ModeChanged;
560 NTSTATUS Status;
561
562 /* Are we in protected mode? */
563 OldMode = CurrentExecutionContext->Mode;
564 if (OldMode != BlRealMode)
565 {
566 /* FIXME: Not yet implemented */
567 return STATUS_NOT_IMPLEMENTED;
568 }
569
570 /* Make the EFI call */
571 if (Mode == GopInterface->Mode->Mode)
572 {
573 EfiStatus = EFI_SUCCESS;
574 ModeChanged = FALSE;
575 }
576 {
577 EfiStatus = GopInterface->SetMode(GopInterface, Mode);
578 ModeChanged = TRUE;
579 }
580
581 /* Switch back to protected mode if we came from there */
582 if (OldMode != BlRealMode)
583 {
584 BlpArchSwitchContext(OldMode);
585 }
586
587 /* Print out to the debugger if the mode was changed */
588 Status = EfiGetNtStatusCode(EfiStatus);
589 if ((ModeChanged) && (NT_SUCCESS(Status)))
590 {
591 /* FIXME @TODO: Should be BlStatusPrint */
592 EarlyPrint(L"Console video mode set to 0x%x\r\n", Mode);
593 }
594
595 /* Convert the error to an NTSTATUS */
596 return Status;
597 }
598
599 NTSTATUS
600 EfiLocateHandleBuffer (
601 _In_ EFI_LOCATE_SEARCH_TYPE SearchType,
602 _In_ EFI_GUID *Protocol,
603 _Inout_ PULONG HandleCount,
604 _Inout_ EFI_HANDLE** Buffer
605 )
606 {
607 BL_ARCH_MODE OldMode;
608 EFI_STATUS EfiStatus;
609 UINTN BufferSize;
610
611 /* Bail out if we're missing parameters */
612 if (!(Buffer) || !(HandleCount))
613 {
614 return STATUS_INVALID_PARAMETER;
615 }
616
617 /* Check if a buffer was passed in*/
618 if (*Buffer)
619 {
620 /* Then we should already have a buffer size*/
621 BufferSize = sizeof(EFI_HANDLE) * *HandleCount;
622 }
623 else
624 {
625 /* Then no buffer size exists */
626 BufferSize = 0;
627 }
628
629 /* Are we in protected mode? */
630 OldMode = CurrentExecutionContext->Mode;
631 if (OldMode != BlRealMode)
632 {
633 /* FIXME: Not yet implemented */
634 return STATUS_NOT_IMPLEMENTED;
635 }
636
637 /* Try the first time */
638 EfiStatus = EfiBS->LocateHandle(SearchType, Protocol, NULL, &BufferSize, *Buffer);
639 if (EfiStatus == EFI_BUFFER_TOO_SMALL)
640 {
641 /* Did we have an existing buffer? */
642 if (*Buffer)
643 {
644 /* Free it */
645 BlMmFreeHeap(*Buffer);
646 }
647
648 /* Allocate a new one */
649 *Buffer = BlMmAllocateHeap(BufferSize);
650 if (!(*Buffer))
651 {
652 /* No space, fail */
653 return STATUS_NO_MEMORY;
654 }
655
656 /* Try again */
657 EfiStatus = EfiBS->LocateHandle(SearchType, Protocol, NULL, &BufferSize, *Buffer);
658
659 /* Switch back to protected mode if we came from there */
660 if (OldMode != BlRealMode)
661 {
662 BlpArchSwitchContext(OldMode);
663 }
664 }
665
666 /* Return the number of handles */
667 *HandleCount = BufferSize / sizeof(EFI_HANDLE);
668
669 /* Convert the error to an NTSTATUS */
670 return EfiGetNtStatusCode(EfiStatus);
671 }
672
673 NTSTATUS
674 EfiAllocatePages (
675 _In_ ULONG Type,
676 _In_ ULONG Pages,
677 _Inout_ EFI_PHYSICAL_ADDRESS* Memory
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 = EfiBS->AllocatePages(Type, EfiLoaderData, Pages, Memory);
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 BL_MEMORY_ATTR
705 MmFwpGetOsAttributeType (
706 _In_ ULONGLONG Attribute
707 )
708 {
709 BL_MEMORY_ATTR OsAttribute = 0;
710
711 if (Attribute & EFI_MEMORY_UC)
712 {
713 OsAttribute = BlMemoryUncached;
714 }
715
716 if (Attribute & EFI_MEMORY_WC)
717 {
718 OsAttribute |= BlMemoryWriteCombined;
719 }
720
721 if (Attribute & EFI_MEMORY_WT)
722 {
723 OsAttribute |= BlMemoryWriteThrough;
724 }
725
726 if (Attribute & EFI_MEMORY_WB)
727 {
728 OsAttribute |= BlMemoryWriteBack;
729 }
730
731 if (Attribute & EFI_MEMORY_UCE)
732 {
733 OsAttribute |= BlMemoryUncachedExported;
734 }
735
736 if (Attribute & EFI_MEMORY_WP)
737 {
738 OsAttribute |= BlMemoryWriteProtected;
739 }
740
741 if (Attribute & EFI_MEMORY_RP)
742 {
743 OsAttribute |= BlMemoryReadProtected;
744 }
745
746 if (Attribute & EFI_MEMORY_XP)
747 {
748 OsAttribute |= BlMemoryExecuteProtected;
749 }
750
751 if (Attribute & EFI_MEMORY_RUNTIME)
752 {
753 OsAttribute |= BlMemoryRuntime;
754 }
755
756 return OsAttribute;
757 }
758
759 BL_MEMORY_TYPE
760 MmFwpGetOsMemoryType (
761 _In_ EFI_MEMORY_TYPE MemoryType
762 )
763 {
764 BL_MEMORY_TYPE OsType;
765
766 switch (MemoryType)
767 {
768 case EfiLoaderCode:
769 case EfiLoaderData:
770 OsType = BlLoaderMemory;
771 break;
772
773 case EfiBootServicesCode:
774 case EfiBootServicesData:
775 OsType = BlEfiBootMemory;
776 break;
777
778 case EfiRuntimeServicesCode:
779 case EfiRuntimeServicesData:
780 OsType = BlEfiRuntimeMemory;
781 break;
782
783 case EfiConventionalMemory:
784 OsType = BlConventionalMemory;
785 break;
786
787 case EfiUnusableMemory:
788 OsType = BlUnusableMemory;
789 break;
790
791 case EfiACPIReclaimMemory:
792 OsType = BlAcpiReclaimMemory;
793 break;
794
795 case EfiACPIMemoryNVS:
796 OsType = BlAcpiNvsMemory;
797 break;
798
799 case EfiMemoryMappedIO:
800 OsType = BlDeviceIoMemory;
801 break;
802
803 case EfiMemoryMappedIOPortSpace:
804 OsType = BlDevicePortMemory;
805 break;
806
807 case EfiPalCode:
808 OsType = BlPalMemory;
809 break;
810
811 default:
812 OsType = BlReservedMemory;
813 break;
814 }
815
816 return OsType;
817 }
818
819 NTSTATUS
820 MmFwGetMemoryMap (
821 _Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap,
822 _In_ ULONG Flags
823 )
824 {
825 BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
826 BOOLEAN UseEfiBuffer, HaveRamDisk;
827 NTSTATUS Status;
828 ULONGLONG Pages, StartPage, EndPage;
829 UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion;
830 EFI_PHYSICAL_ADDRESS EfiBuffer;
831 EFI_MEMORY_DESCRIPTOR* EfiMemoryMap;
832 EFI_STATUS EfiStatus;
833 BL_ARCH_MODE OldMode;
834 EFI_MEMORY_DESCRIPTOR EfiDescriptor;
835 BL_MEMORY_TYPE MemoryType;
836 PBL_MEMORY_DESCRIPTOR Descriptor;
837 BL_MEMORY_ATTR Attribute;
838
839 /* Initialize EFI memory map attributes */
840 EfiMemoryMapSize = MapKey = DescriptorSize = DescriptorVersion = 0;
841
842 /* Increment the nesting depth */
843 MmDescriptorCallTreeCount++;
844
845 /* Determine if we should use EFI or our own allocator at this point */
846 UseEfiBuffer = Flags & BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS;
847 if (!(LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED))
848 {
849 UseEfiBuffer = TRUE;
850 }
851
852 /* Bail out if we don't have a list to use */
853 if (MemoryMap == NULL)
854 {
855 Status = STATUS_INVALID_PARAMETER;
856 goto Quickie;
857 }
858
859 /* Free the current descriptor list */
860 MmMdFreeList(MemoryMap);
861
862 /* Call into EFI to get the size of the memory map */
863 Status = EfiGetMemoryMap(&EfiMemoryMapSize,
864 NULL,
865 &MapKey,
866 &DescriptorSize,
867 &DescriptorVersion);
868 if (Status != STATUS_BUFFER_TOO_SMALL)
869 {
870 /* This should've failed because our buffer was too small, nothing else */
871 EarlyPrint(L"Got strange EFI status for memory map: %lx\n", Status);
872 if (NT_SUCCESS(Status))
873 {
874 Status = STATUS_UNSUCCESSFUL;
875 }
876 goto Quickie;
877 }
878
879 /* Add 4 more descriptors just in case things changed */
880 EfiMemoryMapSize += (4 * DescriptorSize);
881 Pages = BYTES_TO_PAGES(EfiMemoryMapSize);
882 EarlyPrint(L"Memory map size: %lx bytes, %d pages\n", EfiMemoryMapSize, Pages);
883
884 /* Should we use EFI to grab memory? */
885 if (UseEfiBuffer)
886 {
887 /* Yes -- request one more page to align up correctly */
888 Pages++;
889
890 /* Grab the required pages */
891 Status = EfiAllocatePages(AllocateAnyPages,
892 Pages,
893 &EfiBuffer);
894 if (!NT_SUCCESS(Status))
895 {
896 EarlyPrint(L"EFI allocation failed: %lx\n", Status);
897 goto Quickie;
898 }
899
900 /* Free the pages for now */
901 Status = EfiFreePages(Pages, EfiBuffer);
902 if (!NT_SUCCESS(Status))
903 {
904 EfiBuffer = 0;
905 goto Quickie;
906 }
907
908 /* Now round to the actual buffer size, removing the extra page */
909 EfiBuffer = ROUND_TO_PAGES(EfiBuffer);
910 Pages--;
911 Status = EfiAllocatePages(AllocateAddress,
912 Pages,
913 &EfiBuffer);
914 if (!NT_SUCCESS(Status))
915 {
916 EfiBuffer = 0;
917 goto Quickie;
918 }
919
920 /* Get the final aligned size and proper buffer */
921 EfiMemoryMapSize = EFI_PAGES_TO_SIZE(Pages);
922 EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR*)(ULONG_PTR)EfiBuffer;
923
924 /* Switch to real mode if not already in it */
925 OldMode = CurrentExecutionContext->Mode;
926 if (OldMode != BlRealMode)
927 {
928 BlpArchSwitchContext(BlRealMode);
929 }
930
931 /* Call EFI to get the memory map */
932 EfiStatus = EfiBS->GetMemoryMap(&EfiMemoryMapSize,
933 EfiMemoryMap,
934 &MapKey,
935 &DescriptorSize,
936 &DescriptorVersion);
937
938 /* Switch back into the previous mode */
939 if (OldMode != BlRealMode)
940 {
941 BlpArchSwitchContext(OldMode);
942 }
943
944 /* Convert the result code */
945 Status = EfiGetNtStatusCode(EfiStatus);
946 }
947 else
948 {
949 /* We don't support this path yet */
950 Status = STATUS_NOT_IMPLEMENTED;
951 }
952
953 /* So far so good? */
954 if (!NT_SUCCESS(Status))
955 {
956 EarlyPrint(L"Failed to get EFI memory map: %lx\n", Status);
957 goto Quickie;
958 }
959
960 /* Did we get correct data from firmware? */
961 if (((EfiMemoryMapSize % DescriptorSize)) ||
962 (DescriptorSize < sizeof(EFI_MEMORY_DESCRIPTOR)))
963 {
964 EarlyPrint(L"Incorrect descriptor size\n");
965 Status = STATUS_UNSUCCESSFUL;
966 goto Quickie;
967 }
968
969 /* Did we boot from a RAM disk? */
970 if ((BlpBootDevice->DeviceType == LocalDevice) &&
971 (BlpBootDevice->Local.Type == RamDiskDevice))
972 {
973 /* We don't handle this yet */
974 EarlyPrint(L"RAM boot not supported\n");
975 Status = STATUS_NOT_IMPLEMENTED;
976 goto Quickie;
977 }
978 else
979 {
980 /* We didn't, so there won't be any need to find the memory descriptor */
981 HaveRamDisk = FALSE;
982 }
983
984 /* Loop the EFI memory map */
985 #if 0
986 EarlyPrint(L"UEFI MEMORY MAP\n\n");
987 EarlyPrint(L"TYPE START END ATTRIBUTES\n");
988 EarlyPrint(L"===============================================================\n");
989 #endif
990 while (EfiMemoryMapSize != 0)
991 {
992 /* Check if this is an EFI buffer, but we're not in real mode */
993 if ((UseEfiBuffer) && (OldMode != BlRealMode))
994 {
995 BlpArchSwitchContext(BlRealMode);
996 }
997
998 /* Capture it so we can go back to protected mode (if possible) */
999 EfiDescriptor = *EfiMemoryMap;
1000
1001 /* Go back to protected mode, if we had switched */
1002 if ((UseEfiBuffer) && (OldMode != BlRealMode))
1003 {
1004 BlpArchSwitchContext(OldMode);
1005 }
1006
1007 /* Convert to OS memory type */
1008 MemoryType = MmFwpGetOsMemoryType(EfiDescriptor.Type);
1009
1010 /* Round up or round down depending on where the memory is coming from */
1011 if (MemoryType == BlConventionalMemory)
1012 {
1013 StartPage = BYTES_TO_PAGES(EfiDescriptor.PhysicalStart);
1014 }
1015 else
1016 {
1017 StartPage = EfiDescriptor.PhysicalStart >> PAGE_SHIFT;
1018 }
1019
1020 /* Calculate the ending page */
1021 EndPage = StartPage + EfiDescriptor.NumberOfPages;
1022
1023 /* If after rounding, we ended up with 0 pages, skip this */
1024 if (StartPage == EndPage)
1025 {
1026 goto LoopAgain;
1027 }
1028 #if 0
1029 EarlyPrint(L"%08X 0x%016I64X-0x%016I64X 0x%I64X\n",
1030 MemoryType,
1031 StartPage << PAGE_SHIFT,
1032 EndPage << PAGE_SHIFT,
1033 EfiDescriptor.Attribute);
1034 #endif
1035 /* Check for any range of memory below 1MB */
1036 if (StartPage < 0x100)
1037 {
1038 /* Does this range actually contain NULL? */
1039 if (StartPage == 0)
1040 {
1041 /* Manually create a reserved descriptof for this page */
1042 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
1043 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
1044 BlReservedMemory,
1045 0,
1046 0,
1047 1);
1048 if (!Descriptor)
1049 {
1050 Status = STATUS_INSUFFICIENT_RESOURCES;
1051 break;
1052 }
1053
1054 /* Add this descriptor into the list */
1055 Status = MmMdAddDescriptorToList(MemoryMap,
1056 Descriptor,
1057 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
1058 if (!NT_SUCCESS(Status))
1059 {
1060 EarlyPrint(L"Failed to add zero page descriptor: %lx\n", Status);
1061 break;
1062 }
1063
1064 /* Now handle the rest of the range, unless this was it */
1065 StartPage = 1;
1066 if (EndPage == 1)
1067 {
1068 goto LoopAgain;
1069 }
1070 }
1071
1072 /* Does the range go beyond 1MB? */
1073 if (EndPage > 0x100)
1074 {
1075 /* Then create the descriptor for everything up until the megabyte */
1076 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
1077 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
1078 MemoryType,
1079 StartPage,
1080 0,
1081 0x100 - StartPage);
1082 if (!Descriptor)
1083 {
1084 Status = STATUS_INSUFFICIENT_RESOURCES;
1085 break;
1086 }
1087
1088 /* Check if this region is currently free RAM */
1089 if (Descriptor->Type == BlConventionalMemory)
1090 {
1091 /* Set an unknown flag on the descriptor */
1092 Descriptor->Flags |= 0x80000;
1093 }
1094
1095 /* Add this descriptor into the list */
1096 Status = MmMdAddDescriptorToList(MemoryMap,
1097 Descriptor,
1098 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
1099 if (!NT_SUCCESS(Status))
1100 {
1101 EarlyPrint(L"Failed to add 1MB descriptor: %lx\n", Status);
1102 break;
1103 }
1104
1105 /* Now handle the rest of the range above 1MB */
1106 StartPage = 0x100;
1107 }
1108 }
1109
1110 /* Check if we loaded from a RAM disk */
1111 if (HaveRamDisk)
1112 {
1113 /* We don't handle this yet */
1114 EarlyPrint(L"RAM boot not supported\n");
1115 Status = STATUS_NOT_IMPLEMENTED;
1116 goto Quickie;
1117 }
1118
1119 /* Create a descriptor for the current range */
1120 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
1121 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
1122 MemoryType,
1123 StartPage,
1124 0,
1125 EndPage - StartPage);
1126 if (!Descriptor)
1127 {
1128 Status = STATUS_INSUFFICIENT_RESOURCES;
1129 break;
1130 }
1131
1132 /* Check if this region is currently free RAM below 1MB */
1133 if ((Descriptor->Type == BlConventionalMemory) && (EndPage <= 0x100))
1134 {
1135 /* Set an unknown flag on the descriptor */
1136 Descriptor->Flags |= 0x80000;
1137 }
1138
1139 /* Add the descriptor to the list, requesting coalescing as asked */
1140 Status = MmMdAddDescriptorToList(MemoryMap,
1141 Descriptor,
1142 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG |
1143 (Flags & BL_MM_FLAG_REQUEST_COALESCING) ?
1144 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG : 0);
1145 if (!NT_SUCCESS(Status))
1146 {
1147 EarlyPrint(L"Failed to add full descriptor: %lx\n", Status);
1148 break;
1149 }
1150
1151 LoopAgain:
1152 /* Consume this descriptor, and move to the next one */
1153 EfiMemoryMapSize -= DescriptorSize;
1154 EfiMemoryMap = (PVOID)((ULONG_PTR)EfiMemoryMap + DescriptorSize);
1155 }
1156
1157 /* FIXME: @TODO: Mark the EfiBuffer as free, since we're about to free it */
1158 /* For now, just "leak" the 1-2 pages... */
1159
1160 Quickie:
1161 /* Free the EFI buffer, if we had one */
1162 if (EfiBuffer != 0)
1163 {
1164 EfiFreePages(Pages, EfiBuffer);
1165 }
1166
1167 /* On failure, free the memory map if one was passed in */
1168 if (!NT_SUCCESS(Status) && (MemoryMap != NULL))
1169 {
1170 MmMdFreeList(MemoryMap);
1171 }
1172
1173 /* Decrement the nesting depth and return */
1174 MmDescriptorCallTreeCount--;
1175 return Status;
1176 }
1177
1178 NTSTATUS
1179 BlpFwInitialize (
1180 _In_ ULONG Phase,
1181 _In_ PBL_FIRMWARE_DESCRIPTOR FirmwareData
1182 )
1183 {
1184 NTSTATUS Status = STATUS_SUCCESS;
1185 EFI_KEY_TOGGLE_STATE KeyToggleState;
1186
1187 /* Check if we have vaild firmware data */
1188 if (!(FirmwareData) || !(FirmwareData->Version))
1189 {
1190 return STATUS_INVALID_PARAMETER;
1191 }
1192
1193 /* Check which boot phase we're in */
1194 if (Phase != 0)
1195 {
1196 /* Memory manager is ready, open the extended input protocol */
1197 Status = EfiOpenProtocol(EfiST->ConsoleInHandle,
1198 &EfiSimpleTextInputExProtocol,
1199 (PVOID*)&EfiConInEx);
1200 if (NT_SUCCESS(Status))
1201 {
1202 /* Set the initial key toggle state */
1203 KeyToggleState = EFI_TOGGLE_STATE_VALID | 40;
1204 EfiConInExSetState(EfiConInEx, &KeyToggleState);
1205 }
1206
1207 /* Setup the watchdog timer */
1208 EfiSetWatchdogTimer();
1209 }
1210 else
1211 {
1212 /* Make a copy of the parameters */
1213 EfiFirmwareParameters = &EfiFirmwareData;
1214
1215 /* Check which version we received */
1216 if (FirmwareData->Version == 1)
1217 {
1218 /* FIXME: Not supported */
1219 Status = STATUS_NOT_SUPPORTED;
1220 }
1221 else if (FirmwareData->Version >= 2)
1222 {
1223 /* Version 2 -- save the data */
1224 EfiFirmwareData = *FirmwareData;
1225 EfiSystemTable = FirmwareData->SystemTable;
1226 EfiImageHandle = FirmwareData->ImageHandle;
1227
1228 /* Set the EDK-II style variables as well */
1229 EfiST = EfiSystemTable;
1230 EfiBS = EfiSystemTable->BootServices;
1231 EfiRT = EfiSystemTable->RuntimeServices;
1232 EfiConOut = EfiSystemTable->ConOut;
1233 EfiConIn = EfiSystemTable->ConIn;
1234 EfiConInEx = NULL;
1235 }
1236 else
1237 {
1238 /* Unknown version */
1239 Status = STATUS_NOT_SUPPORTED;
1240 }
1241 }
1242
1243 /* Return the initialization state */
1244 return Status;
1245 }
1246