[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 GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
16
17 PBL_FIRMWARE_DESCRIPTOR EfiFirmwareParameters;
18 BL_FIRMWARE_DESCRIPTOR EfiFirmwareData;
19 EFI_HANDLE EfiImageHandle;
20 EFI_SYSTEM_TABLE* EfiSystemTable;
21
22 EFI_SYSTEM_TABLE *EfiST;
23 EFI_BOOT_SERVICES *EfiBS;
24 EFI_RUNTIME_SERVICES *EfiRT;
25 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *EfiConOut;
26 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *EfiConIn;
27 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx;
28
29 /* FUNCTIONS *****************************************************************/
30
31 NTSTATUS
32 EfiOpenProtocol (
33 _In_ EFI_HANDLE Handle,
34 _In_ EFI_GUID *Protocol,
35 _Out_ PVOID* Interface
36 )
37 {
38 EFI_STATUS EfiStatus;
39 NTSTATUS Status;
40 BL_ARCH_MODE OldMode;
41
42 /* Are we using virtual memory/ */
43 if (MmTranslationType != BlNone)
44 {
45 /* We need complex tracking to make this work */
46 //Status = EfiVmOpenProtocol(Handle, Protocol, Interface);
47 Status = STATUS_NOT_SUPPORTED;
48 }
49 else
50 {
51 /* Are we in protected mode? */
52 OldMode = CurrentExecutionContext->Mode;
53 if (OldMode != BlRealMode)
54 {
55 /* FIXME: Not yet implemented */
56 return STATUS_NOT_IMPLEMENTED;
57 }
58
59 /* Are we on legacy 1.02? */
60 if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION)
61 {
62 /* Make the legacy call */
63 EfiStatus = EfiBS->HandleProtocol(Handle, Protocol, Interface);
64 }
65 else
66 {
67 /* Use the UEFI version */
68 EfiStatus = EfiBS->OpenProtocol(Handle,
69 Protocol,
70 Interface,
71 EfiImageHandle,
72 NULL,
73 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
74
75 /* Switch back to protected mode if we came from there */
76 if (OldMode != BlRealMode)
77 {
78 BlpArchSwitchContext(OldMode);
79 }
80 }
81
82 /* Convert the error to an NTSTATUS */
83 Status = EfiGetNtStatusCode(EfiStatus);
84 }
85
86 /* Clear the interface on failure, and return the status */
87 if (!NT_SUCCESS(Status))
88 {
89 *Interface = NULL;
90 }
91
92 return Status;
93 }
94
95 NTSTATUS
96 EfiConInExSetState (
97 _In_ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *ConInEx,
98 _In_ EFI_KEY_TOGGLE_STATE* KeyToggleState
99 )
100 {
101 BL_ARCH_MODE OldMode;
102 EFI_STATUS EfiStatus;
103
104 /* Are we in protected mode? */
105 OldMode = CurrentExecutionContext->Mode;
106 if (OldMode != BlRealMode)
107 {
108 /* FIXME: Not yet implemented */
109 return STATUS_NOT_IMPLEMENTED;
110 }
111
112 /* Make the EFI call */
113 EfiStatus = ConInEx->SetState(ConInEx, KeyToggleState);
114
115 /* Switch back to protected mode if we came from there */
116 if (OldMode != BlRealMode)
117 {
118 BlpArchSwitchContext(OldMode);
119 }
120
121 /* Convert the error to an NTSTATUS */
122 return EfiGetNtStatusCode(EfiStatus);
123 }
124
125 NTSTATUS
126 EfiSetWatchdogTimer (
127 VOID
128 )
129 {
130 BL_ARCH_MODE OldMode;
131 EFI_STATUS EfiStatus;
132
133 /* Are we in protected mode? */
134 OldMode = CurrentExecutionContext->Mode;
135 if (OldMode != BlRealMode)
136 {
137 /* FIXME: Not yet implemented */
138 return STATUS_NOT_IMPLEMENTED;
139 }
140
141 /* Make the EFI call */
142 EfiStatus = EfiBS->SetWatchdogTimer(0, 0, 0, NULL);
143
144 /* Switch back to protected mode if we came from there */
145 if (OldMode != BlRealMode)
146 {
147 BlpArchSwitchContext(OldMode);
148 }
149
150 /* Convert the error to an NTSTATUS */
151 return EfiGetNtStatusCode(EfiStatus);
152 }
153
154 NTSTATUS
155 EfiGetMemoryMap (
156 _Out_ UINTN* MemoryMapSize,
157 _Inout_ EFI_MEMORY_DESCRIPTOR *MemoryMap,
158 _Out_ UINTN* MapKey,
159 _Out_ UINTN* DescriptorSize,
160 _Out_ UINTN* DescriptorVersion
161 )
162 {
163 BL_ARCH_MODE OldMode;
164 EFI_STATUS EfiStatus;
165
166 /* Are we in protected mode? */
167 OldMode = CurrentExecutionContext->Mode;
168 if (OldMode != BlRealMode)
169 {
170 /* FIXME: Not yet implemented */
171 return STATUS_NOT_IMPLEMENTED;
172 }
173
174 /* Make the EFI call */
175 EfiStatus = EfiBS->GetMemoryMap(MemoryMapSize,
176 MemoryMap,
177 MapKey,
178 DescriptorSize,
179 DescriptorVersion);
180
181 /* Switch back to protected mode if we came from there */
182 if (OldMode != BlRealMode)
183 {
184 BlpArchSwitchContext(OldMode);
185 }
186
187 /* Convert the error to an NTSTATUS */
188 return EfiGetNtStatusCode(EfiStatus);
189 }
190
191 NTSTATUS
192 EfiFreePages (
193 _In_ ULONG Pages,
194 _In_ EFI_PHYSICAL_ADDRESS PhysicalAddress
195 )
196 {
197 BL_ARCH_MODE OldMode;
198 EFI_STATUS EfiStatus;
199
200 /* Are we in protected mode? */
201 OldMode = CurrentExecutionContext->Mode;
202 if (OldMode != BlRealMode)
203 {
204 /* FIXME: Not yet implemented */
205 return STATUS_NOT_IMPLEMENTED;
206 }
207
208 /* Make the EFI call */
209 EfiStatus = EfiBS->FreePages(PhysicalAddress, Pages);
210
211 /* Switch back to protected mode if we came from there */
212 if (OldMode != BlRealMode)
213 {
214 BlpArchSwitchContext(OldMode);
215 }
216
217 /* Convert the error to an NTSTATUS */
218 return EfiGetNtStatusCode(EfiStatus);
219 }
220
221 NTSTATUS
222 EfiStall (
223 _In_ ULONG StallTime
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->Stall(StallTime);
239
240 /* Switch back to protected mode if we came from there */
241 if (OldMode != BlRealMode)
242 {
243 BlpArchSwitchContext(OldMode);
244 }
245
246 /* Convert the error to an NTSTATUS */
247 return EfiGetNtStatusCode(EfiStatus);
248 }
249
250 NTSTATUS
251 EfiAllocatePages (
252 _In_ ULONG Type,
253 _In_ ULONG Pages,
254 _Inout_ EFI_PHYSICAL_ADDRESS* Memory
255 )
256 {
257 BL_ARCH_MODE OldMode;
258 EFI_STATUS EfiStatus;
259
260 /* Are we in protected mode? */
261 OldMode = CurrentExecutionContext->Mode;
262 if (OldMode != BlRealMode)
263 {
264 /* FIXME: Not yet implemented */
265 return STATUS_NOT_IMPLEMENTED;
266 }
267
268 /* Make the EFI call */
269 EfiStatus = EfiBS->AllocatePages(Type, EfiLoaderData, Pages, Memory);
270
271 /* Switch back to protected mode if we came from there */
272 if (OldMode != BlRealMode)
273 {
274 BlpArchSwitchContext(OldMode);
275 }
276
277 /* Convert the error to an NTSTATUS */
278 return EfiGetNtStatusCode(EfiStatus);
279 }
280
281 BL_MEMORY_ATTR
282 MmFwpGetOsAttributeType (
283 _In_ ULONGLONG Attribute
284 )
285 {
286 BL_MEMORY_ATTR OsAttribute = 0;
287
288 if (Attribute & EFI_MEMORY_UC)
289 {
290 OsAttribute = BlMemoryUncached;
291 }
292
293 if (Attribute & EFI_MEMORY_WC)
294 {
295 OsAttribute |= BlMemoryWriteCombined;
296 }
297
298 if (Attribute & EFI_MEMORY_WT)
299 {
300 OsAttribute |= BlMemoryWriteThrough;
301 }
302
303 if (Attribute & EFI_MEMORY_WB)
304 {
305 OsAttribute |= BlMemoryWriteBack;
306 }
307
308 if (Attribute & EFI_MEMORY_UCE)
309 {
310 OsAttribute |= BlMemoryUncachedExported;
311 }
312
313 if (Attribute & EFI_MEMORY_WP)
314 {
315 OsAttribute |= BlMemoryWriteProtected;
316 }
317
318 if (Attribute & EFI_MEMORY_RP)
319 {
320 OsAttribute |= BlMemoryReadProtected;
321 }
322
323 if (Attribute & EFI_MEMORY_XP)
324 {
325 OsAttribute |= BlMemoryExecuteProtected;
326 }
327
328 if (Attribute & EFI_MEMORY_RUNTIME)
329 {
330 OsAttribute |= BlMemoryRuntime;
331 }
332
333 return OsAttribute;
334 }
335
336 BL_MEMORY_TYPE
337 MmFwpGetOsMemoryType (
338 _In_ EFI_MEMORY_TYPE MemoryType
339 )
340 {
341 BL_MEMORY_TYPE OsType;
342
343 switch (MemoryType)
344 {
345 case EfiLoaderCode:
346 case EfiLoaderData:
347 OsType = BlLoaderMemory;
348 break;
349
350 case EfiBootServicesCode:
351 case EfiBootServicesData:
352 OsType = BlEfiBootMemory;
353 break;
354
355 case EfiRuntimeServicesCode:
356 case EfiRuntimeServicesData:
357 OsType = BlEfiRuntimeMemory;
358 break;
359
360 case EfiConventionalMemory:
361 OsType = BlConventionalMemory;
362 break;
363
364 case EfiUnusableMemory:
365 OsType = BlUnusableMemory;
366 break;
367
368 case EfiACPIReclaimMemory:
369 OsType = BlAcpiReclaimMemory;
370 break;
371
372 case EfiACPIMemoryNVS:
373 OsType = BlAcpiNvsMemory;
374 break;
375
376 case EfiMemoryMappedIO:
377 OsType = BlDeviceIoMemory;
378 break;
379
380 case EfiMemoryMappedIOPortSpace:
381 OsType = BlDevicePortMemory;
382 break;
383
384 case EfiPalCode:
385 OsType = BlPalMemory;
386 break;
387
388 default:
389 OsType = BlReservedMemory;
390 break;
391 }
392
393 return OsType;
394 }
395
396 NTSTATUS
397 MmFwGetMemoryMap (
398 _Out_ PBL_MEMORY_DESCRIPTOR_LIST MemoryMap,
399 _In_ ULONG Flags
400 )
401 {
402 BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
403 BOOLEAN UseEfiBuffer, HaveRamDisk;
404 NTSTATUS Status;
405 ULONGLONG Pages, StartPage, EndPage;
406 UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion;
407 EFI_PHYSICAL_ADDRESS EfiBuffer;
408 EFI_MEMORY_DESCRIPTOR* EfiMemoryMap;
409 EFI_STATUS EfiStatus;
410 BL_ARCH_MODE OldMode;
411 EFI_MEMORY_DESCRIPTOR EfiDescriptor;
412 BL_MEMORY_TYPE MemoryType;
413 PBL_MEMORY_DESCRIPTOR Descriptor;
414 BL_MEMORY_ATTR Attribute;
415
416 /* Initialize EFI memory map attributes */
417 EfiMemoryMapSize = MapKey = DescriptorSize = DescriptorVersion = 0;
418
419 /* Increment the nesting depth */
420 MmDescriptorCallTreeCount++;
421
422 /* Determine if we should use EFI or our own allocator at this point */
423 UseEfiBuffer = Flags & BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS;
424 if (!(LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_INITIALIZATION_COMPLETED))
425 {
426 UseEfiBuffer = TRUE;
427 }
428
429 /* Bail out if we don't have a list to use */
430 if (MemoryMap == NULL)
431 {
432 Status = STATUS_INVALID_PARAMETER;
433 goto Quickie;
434 }
435
436 /* Free the current descriptor list */
437 MmMdFreeList(MemoryMap);
438
439 /* Call into EFI to get the size of the memory map */
440 Status = EfiGetMemoryMap(&EfiMemoryMapSize,
441 NULL,
442 &MapKey,
443 &DescriptorSize,
444 &DescriptorVersion);
445 if (Status != STATUS_BUFFER_TOO_SMALL)
446 {
447 /* This should've failed because our buffer was too small, nothing else */
448 EarlyPrint(L"Got strange EFI status for memory map: %lx\n", Status);
449 if (NT_SUCCESS(Status))
450 {
451 Status = STATUS_UNSUCCESSFUL;
452 }
453 goto Quickie;
454 }
455
456 /* Add 4 more descriptors just in case things changed */
457 EfiMemoryMapSize += (4 * DescriptorSize);
458 Pages = BYTES_TO_PAGES(EfiMemoryMapSize);
459 EarlyPrint(L"Memory map size: %lx bytes, %d pages\n", EfiMemoryMapSize, Pages);
460
461 /* Should we use EFI to grab memory? */
462 if (UseEfiBuffer)
463 {
464 /* Yes -- request one more page to align up correctly */
465 Pages++;
466
467 /* Grab the required pages */
468 Status = EfiAllocatePages(AllocateAnyPages,
469 Pages,
470 &EfiBuffer);
471 if (!NT_SUCCESS(Status))
472 {
473 EarlyPrint(L"EFI allocation failed: %lx\n", Status);
474 goto Quickie;
475 }
476
477 /* Free the pages for now */
478 Status = EfiFreePages(Pages, EfiBuffer);
479 if (!NT_SUCCESS(Status))
480 {
481 EfiBuffer = 0;
482 goto Quickie;
483 }
484
485 /* Now round to the actual buffer size, removing the extra page */
486 EfiBuffer = ROUND_TO_PAGES(EfiBuffer);
487 Pages--;
488 Status = EfiAllocatePages(AllocateAddress,
489 Pages,
490 &EfiBuffer);
491 if (!NT_SUCCESS(Status))
492 {
493 EfiBuffer = 0;
494 goto Quickie;
495 }
496
497 /* Get the final aligned size and proper buffer */
498 EfiMemoryMapSize = EFI_PAGES_TO_SIZE(Pages);
499 EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR*)(ULONG_PTR)EfiBuffer;
500
501 /* Switch to real mode if not already in it */
502 OldMode = CurrentExecutionContext->Mode;
503 if (OldMode != BlRealMode)
504 {
505 BlpArchSwitchContext(BlRealMode);
506 }
507
508 /* Call EFI to get the memory map */
509 EfiStatus = EfiBS->GetMemoryMap(&EfiMemoryMapSize,
510 EfiMemoryMap,
511 &MapKey,
512 &DescriptorSize,
513 &DescriptorVersion);
514
515 /* Switch back into the previous mode */
516 if (OldMode != BlRealMode)
517 {
518 BlpArchSwitchContext(OldMode);
519 }
520
521 /* Convert the result code */
522 Status = EfiGetNtStatusCode(EfiStatus);
523 }
524 else
525 {
526 /* We don't support this path yet */
527 Status = STATUS_NOT_IMPLEMENTED;
528 }
529
530 /* So far so good? */
531 if (!NT_SUCCESS(Status))
532 {
533 EarlyPrint(L"Failed to get EFI memory map: %lx\n", Status);
534 goto Quickie;
535 }
536
537 /* Did we get correct data from firmware? */
538 if (((EfiMemoryMapSize % DescriptorSize)) ||
539 (DescriptorSize < sizeof(EFI_MEMORY_DESCRIPTOR)))
540 {
541 EarlyPrint(L"Incorrect descriptor size\n");
542 Status = STATUS_UNSUCCESSFUL;
543 goto Quickie;
544 }
545
546 /* Did we boot from a RAM disk? */
547 if ((BlpBootDevice->DeviceType == LocalDevice) &&
548 (BlpBootDevice->Local.Type == RamDiskDevice))
549 {
550 /* We don't handle this yet */
551 EarlyPrint(L"RAM boot not supported\n");
552 Status = STATUS_NOT_IMPLEMENTED;
553 goto Quickie;
554 }
555 else
556 {
557 /* We didn't, so there won't be any need to find the memory descriptor */
558 HaveRamDisk = FALSE;
559 }
560
561 /* Loop the EFI memory map */
562 #if 0
563 EarlyPrint(L"UEFI MEMORY MAP\n\n");
564 EarlyPrint(L"TYPE START END ATTRIBUTES\n");
565 EarlyPrint(L"===============================================================\n");
566 #endif
567 while (EfiMemoryMapSize != 0)
568 {
569 /* Check if this is an EFI buffer, but we're not in real mode */
570 if ((UseEfiBuffer) && (OldMode != BlRealMode))
571 {
572 BlpArchSwitchContext(BlRealMode);
573 }
574
575 /* Capture it so we can go back to protected mode (if possible) */
576 EfiDescriptor = *EfiMemoryMap;
577
578 /* Go back to protected mode, if we had switched */
579 if ((UseEfiBuffer) && (OldMode != BlRealMode))
580 {
581 BlpArchSwitchContext(OldMode);
582 }
583
584 /* Convert to OS memory type */
585 MemoryType = MmFwpGetOsMemoryType(EfiDescriptor.Type);
586
587 /* Round up or round down depending on where the memory is coming from */
588 if (MemoryType == BlConventionalMemory)
589 {
590 StartPage = BYTES_TO_PAGES(EfiDescriptor.PhysicalStart);
591 }
592 else
593 {
594 StartPage = EfiDescriptor.PhysicalStart >> PAGE_SHIFT;
595 }
596
597 /* Calculate the ending page */
598 EndPage = StartPage + EfiDescriptor.NumberOfPages;
599
600 /* If after rounding, we ended up with 0 pages, skip this */
601 if (StartPage == EndPage)
602 {
603 goto LoopAgain;
604 }
605 #if 0
606 EarlyPrint(L"%08X 0x%016I64X-0x%016I64X 0x%I64X\n",
607 MemoryType,
608 StartPage << PAGE_SHIFT,
609 EndPage << PAGE_SHIFT,
610 EfiDescriptor.Attribute);
611 #endif
612 /* Check for any range of memory below 1MB */
613 if (StartPage < 0x100)
614 {
615 /* Does this range actually contain NULL? */
616 if (StartPage == 0)
617 {
618 /* Manually create a reserved descriptof for this page */
619 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
620 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
621 BlReservedMemory,
622 0,
623 0,
624 1);
625 if (!Descriptor)
626 {
627 Status = STATUS_INSUFFICIENT_RESOURCES;
628 break;
629 }
630
631 /* Add this descriptor into the list */
632 Status = MmMdAddDescriptorToList(MemoryMap,
633 Descriptor,
634 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
635 if (!NT_SUCCESS(Status))
636 {
637 EarlyPrint(L"Failed to add zero page descriptor: %lx\n", Status);
638 break;
639 }
640
641 /* Now handle the rest of the range, unless this was it */
642 StartPage = 1;
643 if (EndPage == 1)
644 {
645 goto LoopAgain;
646 }
647 }
648
649 /* Does the range go beyond 1MB? */
650 if (EndPage > 0x100)
651 {
652 /* Then create the descriptor for everything up until the megabyte */
653 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
654 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
655 MemoryType,
656 StartPage,
657 0,
658 0x100 - StartPage);
659 if (!Descriptor)
660 {
661 Status = STATUS_INSUFFICIENT_RESOURCES;
662 break;
663 }
664
665 /* Check if this region is currently free RAM */
666 if (Descriptor->Type == BlConventionalMemory)
667 {
668 /* Set an unknown flag on the descriptor */
669 Descriptor->Flags |= 0x80000;
670 }
671
672 /* Add this descriptor into the list */
673 Status = MmMdAddDescriptorToList(MemoryMap,
674 Descriptor,
675 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
676 if (!NT_SUCCESS(Status))
677 {
678 EarlyPrint(L"Failed to add 1MB descriptor: %lx\n", Status);
679 break;
680 }
681
682 /* Now handle the rest of the range above 1MB */
683 StartPage = 0x100;
684 }
685 }
686
687 /* Check if we loaded from a RAM disk */
688 if (HaveRamDisk)
689 {
690 /* We don't handle this yet */
691 EarlyPrint(L"RAM boot not supported\n");
692 Status = STATUS_NOT_IMPLEMENTED;
693 goto Quickie;
694 }
695
696 /* Create a descriptor for the current range */
697 Attribute = MmFwpGetOsAttributeType(EfiDescriptor.Attribute);
698 Descriptor = MmMdInitByteGranularDescriptor(Attribute,
699 MemoryType,
700 StartPage,
701 0,
702 EndPage - StartPage);
703 if (!Descriptor)
704 {
705 Status = STATUS_INSUFFICIENT_RESOURCES;
706 break;
707 }
708
709 /* Check if this region is currently free RAM below 1MB */
710 if ((Descriptor->Type == BlConventionalMemory) && (EndPage <= 0x100))
711 {
712 /* Set an unknown flag on the descriptor */
713 Descriptor->Flags |= 0x80000;
714 }
715
716 /* Add the descriptor to the list, requesting coalescing as asked */
717 Status = MmMdAddDescriptorToList(MemoryMap,
718 Descriptor,
719 BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG |
720 (Flags & BL_MM_FLAG_REQUEST_COALESCING) ?
721 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG : 0);
722 if (!NT_SUCCESS(Status))
723 {
724 EarlyPrint(L"Failed to add full descriptor: %lx\n", Status);
725 break;
726 }
727
728 LoopAgain:
729 /* Consume this descriptor, and move to the next one */
730 EfiMemoryMapSize -= DescriptorSize;
731 EfiMemoryMap = (PVOID)((ULONG_PTR)EfiMemoryMap + DescriptorSize);
732 }
733
734 /* FIXME: @TODO: Mark the EfiBuffer as free, since we're about to free it */
735 /* For now, just "leak" the 1-2 pages... */
736
737 Quickie:
738 /* Free the EFI buffer, if we had one */
739 if (EfiBuffer != 0)
740 {
741 EfiFreePages(Pages, EfiBuffer);
742 }
743
744 /* On failure, free the memory map if one was passed in */
745 if (!NT_SUCCESS(Status) && (MemoryMap != NULL))
746 {
747 MmMdFreeList(MemoryMap);
748 }
749
750 /* Decrement the nesting depth and return */
751 MmDescriptorCallTreeCount--;
752 return Status;
753 }
754
755 NTSTATUS
756 BlpFwInitialize (
757 _In_ ULONG Phase,
758 _In_ PBL_FIRMWARE_DESCRIPTOR FirmwareData
759 )
760 {
761 NTSTATUS Status = STATUS_SUCCESS;
762 EFI_KEY_TOGGLE_STATE KeyToggleState;
763
764 /* Check if we have vaild firmware data */
765 if (!(FirmwareData) || !(FirmwareData->Version))
766 {
767 return STATUS_INVALID_PARAMETER;
768 }
769
770 /* Check which boot phase we're in */
771 if (Phase != 0)
772 {
773 /* Memory manager is ready, open the extended input protocol */
774 Status = EfiOpenProtocol(EfiST->ConsoleInHandle,
775 &EfiSimpleTextInputExProtocol,
776 (PVOID*)&EfiConInEx);
777 if (NT_SUCCESS(Status))
778 {
779 /* Set the initial key toggle state */
780 KeyToggleState = EFI_TOGGLE_STATE_VALID | 40;
781 EfiConInExSetState(EfiConInEx, &KeyToggleState);
782 }
783
784 /* Setup the watchdog timer */
785 EfiSetWatchdogTimer();
786 }
787 else
788 {
789 /* Make a copy of the parameters */
790 EfiFirmwareParameters = &EfiFirmwareData;
791
792 /* Check which version we received */
793 if (FirmwareData->Version == 1)
794 {
795 /* FIXME: Not supported */
796 Status = STATUS_NOT_SUPPORTED;
797 }
798 else if (FirmwareData->Version >= 2)
799 {
800 /* Version 2 -- save the data */
801 EfiFirmwareData = *FirmwareData;
802 EfiSystemTable = FirmwareData->SystemTable;
803 EfiImageHandle = FirmwareData->ImageHandle;
804
805 /* Set the EDK-II style variables as well */
806 EfiST = EfiSystemTable;
807 EfiBS = EfiSystemTable->BootServices;
808 EfiRT = EfiSystemTable->RuntimeServices;
809 EfiConOut = EfiSystemTable->ConOut;
810 EfiConIn = EfiSystemTable->ConIn;
811 EfiConInEx = NULL;
812 }
813 else
814 {
815 /* Unknown version */
816 Status = STATUS_NOT_SUPPORTED;
817 }
818 }
819
820 /* Return the initialization state */
821 return Status;
822 }
823