1 /** @file
2   DXE Core Main Entry Point
3 
4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "DxeMain.h"
16 
17 //
18 // DXE Core Global Variables for Protocols from PEI
19 //
20 EFI_HANDLE                                mDecompressHandle = NULL;
21 
22 //
23 // DXE Core globals for Architecture Protocols
24 //
25 EFI_SECURITY_ARCH_PROTOCOL        *gSecurity      = NULL;
26 EFI_SECURITY2_ARCH_PROTOCOL       *gSecurity2     = NULL;
27 EFI_CPU_ARCH_PROTOCOL             *gCpu           = NULL;
28 EFI_METRONOME_ARCH_PROTOCOL       *gMetronome     = NULL;
29 EFI_TIMER_ARCH_PROTOCOL           *gTimer         = NULL;
30 EFI_BDS_ARCH_PROTOCOL             *gBds           = NULL;
31 EFI_WATCHDOG_TIMER_ARCH_PROTOCOL  *gWatchdogTimer = NULL;
32 
33 //
34 // DXE Core globals for optional protocol dependencies
35 //
36 EFI_SMM_BASE2_PROTOCOL            *gSmmBase2      = NULL;
37 
38 //
39 // DXE Core Global used to update core loaded image protocol handle
40 //
41 EFI_GUID                           *gDxeCoreFileName;
42 EFI_LOADED_IMAGE_PROTOCOL          *gDxeCoreLoadedImage;
43 
44 //
45 // DXE Core Module Variables
46 //
47 EFI_BOOT_SERVICES mBootServices = {
48   {
49     EFI_BOOT_SERVICES_SIGNATURE,                                                          // Signature
50     EFI_BOOT_SERVICES_REVISION,                                                           // Revision
51     sizeof (EFI_BOOT_SERVICES),                                                           // HeaderSize
52     0,                                                                                    // CRC32
53     0                                                                                     // Reserved
54   },
55   (EFI_RAISE_TPL)                               CoreRaiseTpl,                             // RaiseTPL
56   (EFI_RESTORE_TPL)                             CoreRestoreTpl,                           // RestoreTPL
57   (EFI_ALLOCATE_PAGES)                          CoreAllocatePages,                        // AllocatePages
58   (EFI_FREE_PAGES)                              CoreFreePages,                            // FreePages
59   (EFI_GET_MEMORY_MAP)                          CoreGetMemoryMap,                         // GetMemoryMap
60   (EFI_ALLOCATE_POOL)                           CoreAllocatePool,                         // AllocatePool
61   (EFI_FREE_POOL)                               CoreFreePool,                             // FreePool
62   (EFI_CREATE_EVENT)                            CoreCreateEvent,                          // CreateEvent
63   (EFI_SET_TIMER)                               CoreSetTimer,                             // SetTimer
64   (EFI_WAIT_FOR_EVENT)                          CoreWaitForEvent,                         // WaitForEvent
65   (EFI_SIGNAL_EVENT)                            CoreSignalEvent,                          // SignalEvent
66   (EFI_CLOSE_EVENT)                             CoreCloseEvent,                           // CloseEvent
67   (EFI_CHECK_EVENT)                             CoreCheckEvent,                           // CheckEvent
68   (EFI_INSTALL_PROTOCOL_INTERFACE)              CoreInstallProtocolInterface,             // InstallProtocolInterface
69   (EFI_REINSTALL_PROTOCOL_INTERFACE)            CoreReinstallProtocolInterface,           // ReinstallProtocolInterface
70   (EFI_UNINSTALL_PROTOCOL_INTERFACE)            CoreUninstallProtocolInterface,           // UninstallProtocolInterface
71   (EFI_HANDLE_PROTOCOL)                         CoreHandleProtocol,                       // HandleProtocol
72   (VOID *)                                      NULL,                                     // Reserved
73   (EFI_REGISTER_PROTOCOL_NOTIFY)                CoreRegisterProtocolNotify,               // RegisterProtocolNotify
74   (EFI_LOCATE_HANDLE)                           CoreLocateHandle,                         // LocateHandle
75   (EFI_LOCATE_DEVICE_PATH)                      CoreLocateDevicePath,                     // LocateDevicePath
76   (EFI_INSTALL_CONFIGURATION_TABLE)             CoreInstallConfigurationTable,            // InstallConfigurationTable
77   (EFI_IMAGE_LOAD)                              CoreLoadImage,                            // LoadImage
78   (EFI_IMAGE_START)                             CoreStartImage,                           // StartImage
79   (EFI_EXIT)                                    CoreExit,                                 // Exit
80   (EFI_IMAGE_UNLOAD)                            CoreUnloadImage,                          // UnloadImage
81   (EFI_EXIT_BOOT_SERVICES)                      CoreExitBootServices,                     // ExitBootServices
82   (EFI_GET_NEXT_MONOTONIC_COUNT)                CoreEfiNotAvailableYetArg1,               // GetNextMonotonicCount
83   (EFI_STALL)                                   CoreStall,                                // Stall
84   (EFI_SET_WATCHDOG_TIMER)                      CoreSetWatchdogTimer,                     // SetWatchdogTimer
85   (EFI_CONNECT_CONTROLLER)                      CoreConnectController,                    // ConnectController
86   (EFI_DISCONNECT_CONTROLLER)                   CoreDisconnectController,                 // DisconnectController
87   (EFI_OPEN_PROTOCOL)                           CoreOpenProtocol,                         // OpenProtocol
88   (EFI_CLOSE_PROTOCOL)                          CoreCloseProtocol,                        // CloseProtocol
89   (EFI_OPEN_PROTOCOL_INFORMATION)               CoreOpenProtocolInformation,              // OpenProtocolInformation
90   (EFI_PROTOCOLS_PER_HANDLE)                    CoreProtocolsPerHandle,                   // ProtocolsPerHandle
91   (EFI_LOCATE_HANDLE_BUFFER)                    CoreLocateHandleBuffer,                   // LocateHandleBuffer
92   (EFI_LOCATE_PROTOCOL)                         CoreLocateProtocol,                       // LocateProtocol
93   (EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES)    CoreInstallMultipleProtocolInterfaces,    // InstallMultipleProtocolInterfaces
94   (EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES)  CoreUninstallMultipleProtocolInterfaces,  // UninstallMultipleProtocolInterfaces
95   (EFI_CALCULATE_CRC32)                         CoreEfiNotAvailableYetArg3,               // CalculateCrc32
96   (EFI_COPY_MEM)                                CopyMem,                                  // CopyMem
97   (EFI_SET_MEM)                                 SetMem,                                   // SetMem
98   (EFI_CREATE_EVENT_EX)                         CoreCreateEventEx                         // CreateEventEx
99 };
100 
101 EFI_DXE_SERVICES mDxeServices = {
102   {
103     DXE_SERVICES_SIGNATURE,                                           // Signature
104     DXE_SERVICES_REVISION,                                            // Revision
105     sizeof (DXE_SERVICES),                                            // HeaderSize
106     0,                                                                    // CRC32
107     0                                                                     // Reserved
108   },
109   (EFI_ADD_MEMORY_SPACE)             CoreAddMemorySpace,                  // AddMemorySpace
110   (EFI_ALLOCATE_MEMORY_SPACE)        CoreAllocateMemorySpace,             // AllocateMemorySpace
111   (EFI_FREE_MEMORY_SPACE)            CoreFreeMemorySpace,                 // FreeMemorySpace
112   (EFI_REMOVE_MEMORY_SPACE)          CoreRemoveMemorySpace,               // RemoveMemorySpace
113   (EFI_GET_MEMORY_SPACE_DESCRIPTOR)  CoreGetMemorySpaceDescriptor,        // GetMemorySpaceDescriptor
114   (EFI_SET_MEMORY_SPACE_ATTRIBUTES)  CoreSetMemorySpaceAttributes,        // SetMemorySpaceAttributes
115   (EFI_GET_MEMORY_SPACE_MAP)         CoreGetMemorySpaceMap,               // GetMemorySpaceMap
116   (EFI_ADD_IO_SPACE)                 CoreAddIoSpace,                      // AddIoSpace
117   (EFI_ALLOCATE_IO_SPACE)            CoreAllocateIoSpace,                 // AllocateIoSpace
118   (EFI_FREE_IO_SPACE)                CoreFreeIoSpace,                     // FreeIoSpace
119   (EFI_REMOVE_IO_SPACE)              CoreRemoveIoSpace,                   // RemoveIoSpace
120   (EFI_GET_IO_SPACE_DESCRIPTOR)      CoreGetIoSpaceDescriptor,            // GetIoSpaceDescriptor
121   (EFI_GET_IO_SPACE_MAP)             CoreGetIoSpaceMap,                   // GetIoSpaceMap
122   (EFI_DISPATCH)                     CoreDispatcher,                      // Dispatch
123   (EFI_SCHEDULE)                     CoreSchedule,                        // Schedule
124   (EFI_TRUST)                        CoreTrust,                           // Trust
125   (EFI_PROCESS_FIRMWARE_VOLUME)      CoreProcessFirmwareVolume,           // ProcessFirmwareVolume
126   (EFI_SET_MEMORY_SPACE_CAPABILITIES)CoreSetMemorySpaceCapabilities,      // SetMemorySpaceCapabilities
127 };
128 
129 EFI_SYSTEM_TABLE mEfiSystemTableTemplate = {
130   {
131     EFI_SYSTEM_TABLE_SIGNATURE,                                           // Signature
132     EFI_SYSTEM_TABLE_REVISION,                                            // Revision
133     sizeof (EFI_SYSTEM_TABLE),                                            // HeaderSize
134     0,                                                                    // CRC32
135     0                                                                     // Reserved
136   },
137   NULL,                                                                   // FirmwareVendor
138   0,                                                                      // FirmwareRevision
139   NULL,                                                                   // ConsoleInHandle
140   NULL,                                                                   // ConIn
141   NULL,                                                                   // ConsoleOutHandle
142   NULL,                                                                   // ConOut
143   NULL,                                                                   // StandardErrorHandle
144   NULL,                                                                   // StdErr
145   NULL,                                                                   // RuntimeServices
146   &mBootServices,                                                         // BootServices
147   0,                                                                      // NumberOfConfigurationTableEntries
148   NULL                                                                    // ConfigurationTable
149 };
150 
151 EFI_RUNTIME_SERVICES mEfiRuntimeServicesTableTemplate = {
152   {
153     EFI_RUNTIME_SERVICES_SIGNATURE,                               // Signature
154     EFI_RUNTIME_SERVICES_REVISION,                                // Revision
155     sizeof (EFI_RUNTIME_SERVICES),                                // HeaderSize
156     0,                                                            // CRC32
157     0                                                             // Reserved
158   },
159   (EFI_GET_TIME)                    CoreEfiNotAvailableYetArg2,   // GetTime
160   (EFI_SET_TIME)                    CoreEfiNotAvailableYetArg1,   // SetTime
161   (EFI_GET_WAKEUP_TIME)             CoreEfiNotAvailableYetArg3,   // GetWakeupTime
162   (EFI_SET_WAKEUP_TIME)             CoreEfiNotAvailableYetArg2,   // SetWakeupTime
163   (EFI_SET_VIRTUAL_ADDRESS_MAP)     CoreEfiNotAvailableYetArg4,   // SetVirtualAddressMap
164   (EFI_CONVERT_POINTER)             CoreEfiNotAvailableYetArg2,   // ConvertPointer
165   (EFI_GET_VARIABLE)                CoreEfiNotAvailableYetArg5,   // GetVariable
166   (EFI_GET_NEXT_VARIABLE_NAME)      CoreEfiNotAvailableYetArg3,   // GetNextVariableName
167   (EFI_SET_VARIABLE)                CoreEfiNotAvailableYetArg5,   // SetVariable
168   (EFI_GET_NEXT_HIGH_MONO_COUNT)    CoreEfiNotAvailableYetArg1,   // GetNextHighMonotonicCount
169   (EFI_RESET_SYSTEM)                CoreEfiNotAvailableYetArg4,   // ResetSystem
170   (EFI_UPDATE_CAPSULE)              CoreEfiNotAvailableYetArg3,   // UpdateCapsule
171   (EFI_QUERY_CAPSULE_CAPABILITIES)  CoreEfiNotAvailableYetArg4,   // QueryCapsuleCapabilities
172   (EFI_QUERY_VARIABLE_INFO)         CoreEfiNotAvailableYetArg4    // QueryVariableInfo
173 };
174 
175 EFI_RUNTIME_ARCH_PROTOCOL gRuntimeTemplate = {
176   INITIALIZE_LIST_HEAD_VARIABLE (gRuntimeTemplate.ImageHead),
177   INITIALIZE_LIST_HEAD_VARIABLE (gRuntimeTemplate.EventHead),
178 
179   //
180   // Make sure Size != sizeof (EFI_MEMORY_DESCRIPTOR). This will
181   // prevent people from having pointer math bugs in their code.
182   // now you have to use *DescriptorSize to make things work.
183   //
184   sizeof (EFI_MEMORY_DESCRIPTOR) + sizeof (UINT64) - (sizeof (EFI_MEMORY_DESCRIPTOR) % sizeof (UINT64)),
185   EFI_MEMORY_DESCRIPTOR_VERSION,
186   0,
187   NULL,
188   NULL,
189   FALSE,
190   FALSE
191 };
192 
193 EFI_RUNTIME_ARCH_PROTOCOL *gRuntime = &gRuntimeTemplate;
194 
195 //
196 // DXE Core Global Variables for the EFI System Table, Boot Services Table,
197 // DXE Services Table, and Runtime Services Table
198 //
199 EFI_DXE_SERVICES      *gDxeCoreDS = &mDxeServices;
200 EFI_SYSTEM_TABLE      *gDxeCoreST = NULL;
201 
202 //
203 // For debug initialize gDxeCoreRT to template. gDxeCoreRT must be allocated from RT memory
204 //  but gDxeCoreRT is used for ASSERT () and DEBUG () type macros so lets give it
205 //  a value that will not cause debug infrastructure to crash early on.
206 //
207 EFI_RUNTIME_SERVICES  *gDxeCoreRT = &mEfiRuntimeServicesTableTemplate;
208 EFI_HANDLE            gDxeCoreImageHandle = NULL;
209 
210 
211 //
212 // EFI Decompress Protocol
213 //
214 EFI_DECOMPRESS_PROTOCOL  gEfiDecompress = {
215   DxeMainUefiDecompressGetInfo,
216   DxeMainUefiDecompress
217 };
218 
219 //
220 // For Loading modules at fixed address feature, the configuration table is to cache the top address below which to load
221 // Runtime code&boot time code
222 //
223 GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE    gLoadModuleAtFixAddressConfigurationTable = {0, 0};
224 
225 // Main entry point to the DXE Core
226 //
227 
228 /**
229   Main entry point to DXE Core.
230 
231   @param  HobStart               Pointer to the beginning of the HOB List from PEI.
232 
233   @return This function should never return.
234 
235 **/
236 VOID
237 EFIAPI
DxeMain(IN VOID * HobStart)238 DxeMain (
239   IN  VOID *HobStart
240   )
241 {
242   EFI_STATUS                    Status;
243   EFI_PHYSICAL_ADDRESS          MemoryBaseAddress;
244   UINT64                        MemoryLength;
245   PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
246   UINTN                         Index;
247   EFI_HOB_GUID_TYPE             *GuidHob;
248   EFI_VECTOR_HANDOFF_INFO       *VectorInfoList;
249   EFI_VECTOR_HANDOFF_INFO       *VectorInfo;
250 
251   //
252   // Setup the default exception handlers
253   //
254   VectorInfoList = NULL;
255   GuidHob = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
256   if (GuidHob != NULL) {
257     VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *) (GET_GUID_HOB_DATA(GuidHob));
258   }
259   Status = InitializeCpuExceptionHandlers (VectorInfoList);
260   ASSERT_EFI_ERROR (Status);
261 
262   //
263   // Initialize Debug Agent to support source level debug in DXE phase
264   //
265   InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_CORE, HobStart, NULL);
266 
267   //
268   // Initialize Memory Services
269   //
270   CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
271 
272   MemoryProfileInit (HobStart);
273 
274   //
275   // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData
276   // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table
277   //
278   gDxeCoreST = AllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate);
279   ASSERT (gDxeCoreST != NULL);
280 
281   gDxeCoreRT = AllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate);
282   ASSERT (gDxeCoreRT != NULL);
283 
284   gDxeCoreST->RuntimeServices = gDxeCoreRT;
285 
286   //
287   // Start the Image Services.
288   //
289   Status = CoreInitializeImageServices (HobStart);
290   ASSERT_EFI_ERROR (Status);
291 
292   //
293   // Report DXE Core image information to the PE/COFF Extra Action Library
294   //
295   ZeroMem (&ImageContext, sizeof (ImageContext));
296   ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreLoadedImage->ImageBase;
297   ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
298   PeCoffLoaderRelocateImageExtraAction (&ImageContext);
299 
300   //
301   // Initialize the Global Coherency Domain Services
302   //
303   Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength);
304   ASSERT_EFI_ERROR (Status);
305 
306   //
307   // Call constructor for all libraries
308   //
309   ProcessLibraryConstructorList (gDxeCoreImageHandle, gDxeCoreST);
310   PERF_END   (NULL,"PEI", NULL, 0) ;
311   PERF_START (NULL,"DXE", NULL, 0) ;
312 
313   //
314   // Install the DXE Services Table into the EFI System Tables's Configuration Table
315   //
316   Status = CoreInstallConfigurationTable (&gEfiDxeServicesTableGuid, gDxeCoreDS);
317   ASSERT_EFI_ERROR (Status);
318 
319   //
320   // Install the HOB List into the EFI System Tables's Configuration Table
321   //
322   Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart);
323   ASSERT_EFI_ERROR (Status);
324 
325   //
326   // Install Memory Type Information Table into the EFI System Tables's Configuration Table
327   //
328   Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);
329   ASSERT_EFI_ERROR (Status);
330 
331   //
332   // If Loading modules At fixed address feature is enabled, install Load moduels at fixed address
333   // Configuration Table so that user could easily to retrieve the top address to load Dxe and PEI
334   // Code and Tseg base to load SMM driver.
335   //
336   if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
337     Status = CoreInstallConfigurationTable (&gLoadFixedAddressConfigurationTableGuid, &gLoadModuleAtFixAddressConfigurationTable);
338     ASSERT_EFI_ERROR (Status);
339   }
340   //
341   // Report Status Code here for DXE_ENTRY_POINT once it is available
342   //
343   REPORT_STATUS_CODE (
344     EFI_PROGRESS_CODE,
345     (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT)
346     );
347 
348   //
349   // Create the aligned system table pointer structure that is used by external
350   // debuggers to locate the system table...  Also, install debug image info
351   // configuration table.
352   //
353   CoreInitializeDebugImageInfoTable ();
354   CoreNewDebugImageInfoEntry (
355     EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
356     gDxeCoreLoadedImage,
357     gDxeCoreImageHandle
358     );
359 
360   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "HOBLIST address in DXE = 0x%p\n", HobStart));
361 
362   DEBUG_CODE_BEGIN ();
363     EFI_PEI_HOB_POINTERS               Hob;
364 
365     for (Hob.Raw = HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
366       if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
367         DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \
368           Hob.MemoryAllocation->AllocDescriptor.MemoryType,                      \
369           Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress,               \
370           Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1));
371       }
372     }
373     for (Hob.Raw = HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
374       if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) {
375         DEBUG ((DEBUG_INFO | DEBUG_LOAD, "FV2 Hob           0x%0lx - 0x%0lx\n", Hob.FirmwareVolume2->BaseAddress, Hob.FirmwareVolume2->BaseAddress + Hob.FirmwareVolume2->Length - 1));
376       } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
377         DEBUG ((DEBUG_INFO | DEBUG_LOAD, "FV Hob            0x%0lx - 0x%0lx\n", Hob.FirmwareVolume->BaseAddress, Hob.FirmwareVolume->BaseAddress + Hob.FirmwareVolume->Length - 1));
378       }
379     }
380   DEBUG_CODE_END ();
381 
382   //
383   // Initialize the Event Services
384   //
385   Status = CoreInitializeEventServices ();
386   ASSERT_EFI_ERROR (Status);
387 
388   MemoryProfileInstallProtocol ();
389 
390   CoreInitializePropertiesTable ();
391 
392   //
393   // Get persisted vector hand-off info from GUIDeed HOB again due to HobStart may be updated,
394   // and install configuration table
395   //
396   GuidHob = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
397   if (GuidHob != NULL) {
398     VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *) (GET_GUID_HOB_DATA(GuidHob));
399     VectorInfo = VectorInfoList;
400     Index = 1;
401     while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
402       VectorInfo ++;
403       Index ++;
404     }
405     VectorInfo = AllocateCopyPool (sizeof (EFI_VECTOR_HANDOFF_INFO) * Index, (VOID *) VectorInfoList);
406     ASSERT (VectorInfo != NULL);
407     Status = CoreInstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *) VectorInfo);
408     ASSERT_EFI_ERROR (Status);
409   }
410 
411   //
412   // Get the Protocols that were passed in from PEI to DXE through GUIDed HOBs
413   //
414   // These Protocols are not architectural. This implementation is sharing code between
415   // PEI and DXE in order to save FLASH space. These Protocols could also be implemented
416   // as part of the DXE Core. However, that would also require the DXE Core to be ported
417   // each time a different CPU is used, a different Decompression algorithm is used, or a
418   // different Image type is used. By placing these Protocols in PEI, the DXE Core remains
419   // generic, and only PEI and the Arch Protocols need to be ported from Platform to Platform,
420   // and from CPU to CPU.
421   //
422 
423   //
424   // Publish the EFI, Tiano, and Custom Decompress protocols for use by other DXE components
425   //
426   Status = CoreInstallMultipleProtocolInterfaces (
427              &mDecompressHandle,
428              &gEfiDecompressProtocolGuid,           &gEfiDecompress,
429              NULL
430              );
431   ASSERT_EFI_ERROR (Status);
432 
433   //
434   // Register for the GUIDs of the Architectural Protocols, so the rest of the
435   // EFI Boot Services and EFI Runtime Services tables can be filled in.
436   // Also register for the GUIDs of optional protocols.
437   //
438   CoreNotifyOnProtocolInstallation ();
439 
440   //
441   // Produce Firmware Volume Protocols, one for each FV in the HOB list.
442   //
443   Status = FwVolBlockDriverInit (gDxeCoreImageHandle, gDxeCoreST);
444   ASSERT_EFI_ERROR (Status);
445 
446   Status = FwVolDriverInit (gDxeCoreImageHandle, gDxeCoreST);
447   ASSERT_EFI_ERROR (Status);
448 
449   //
450   // Produce the Section Extraction Protocol
451   //
452   Status = InitializeSectionExtraction (gDxeCoreImageHandle, gDxeCoreST);
453   ASSERT_EFI_ERROR (Status);
454 
455   //
456   // Initialize the DXE Dispatcher
457   //
458   PERF_START (NULL,"CoreInitializeDispatcher", "DxeMain", 0) ;
459   CoreInitializeDispatcher ();
460   PERF_END (NULL,"CoreInitializeDispatcher", "DxeMain", 0) ;
461 
462   //
463   // Invoke the DXE Dispatcher
464   //
465   PERF_START (NULL, "CoreDispatcher", "DxeMain", 0);
466   CoreDispatcher ();
467   PERF_END (NULL, "CoreDispatcher", "DxeMain", 0);
468 
469   //
470   // Display Architectural protocols that were not loaded if this is DEBUG build
471   //
472   DEBUG_CODE_BEGIN ();
473     CoreDisplayMissingArchProtocols ();
474   DEBUG_CODE_END ();
475 
476   //
477   // Display any drivers that were not dispatched because dependency expression
478   // evaluated to false if this is a debug build
479   //
480   DEBUG_CODE_BEGIN ();
481     CoreDisplayDiscoveredNotDispatched ();
482   DEBUG_CODE_END ();
483 
484   //
485   // Assert if the Architectural Protocols are not present.
486   //
487   Status = CoreAllEfiServicesAvailable ();
488   if (EFI_ERROR(Status)) {
489     //
490     // Report Status code that some Architectural Protocols are not present.
491     //
492     REPORT_STATUS_CODE (
493       EFI_ERROR_CODE | EFI_ERROR_MAJOR,
494       (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_EC_NO_ARCH)
495       );
496   }
497   ASSERT_EFI_ERROR (Status);
498 
499   //
500   // Report Status code before transfer control to BDS
501   //
502   REPORT_STATUS_CODE (
503     EFI_PROGRESS_CODE,
504     (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT)
505     );
506 
507   //
508   // Transfer control to the BDS Architectural Protocol
509   //
510   gBds->Entry (gBds);
511 
512   //
513   // BDS should never return
514   //
515   ASSERT (FALSE);
516   CpuDeadLoop ();
517 }
518 
519 
520 
521 /**
522   Place holder function until all the Boot Services and Runtime Services are
523   available.
524 
525   @return EFI_NOT_AVAILABLE_YET
526 
527 **/
528 EFI_STATUS
529 EFIAPI
CoreEfiNotAvailableYetArg0(VOID)530 CoreEfiNotAvailableYetArg0 (
531   VOID
532   )
533 {
534   //
535   // This function should never be executed.  If it does, then the architectural protocols
536   // have not been designed correctly.  The CpuBreakpoint () is commented out for now until the
537   // DXE Core and all the Architectural Protocols are complete.
538   //
539 
540   return EFI_NOT_AVAILABLE_YET;
541 }
542 
543 
544 /**
545   Place holder function until all the Boot Services and Runtime Services are
546   available.
547 
548   @param  Arg1                   Undefined
549 
550   @return EFI_NOT_AVAILABLE_YET
551 
552 **/
553 EFI_STATUS
554 EFIAPI
CoreEfiNotAvailableYetArg1(UINTN Arg1)555 CoreEfiNotAvailableYetArg1 (
556   UINTN Arg1
557   )
558 {
559   //
560   // This function should never be executed.  If it does, then the architectural protocols
561   // have not been designed correctly.  The CpuBreakpoint () is commented out for now until the
562   // DXE Core and all the Architectural Protocols are complete.
563   //
564 
565   return EFI_NOT_AVAILABLE_YET;
566 }
567 
568 
569 /**
570   Place holder function until all the Boot Services and Runtime Services are available.
571 
572   @param  Arg1                   Undefined
573   @param  Arg2                   Undefined
574 
575   @return EFI_NOT_AVAILABLE_YET
576 
577 **/
578 EFI_STATUS
579 EFIAPI
CoreEfiNotAvailableYetArg2(UINTN Arg1,UINTN Arg2)580 CoreEfiNotAvailableYetArg2 (
581   UINTN Arg1,
582   UINTN Arg2
583   )
584 {
585   //
586   // This function should never be executed.  If it does, then the architectural protocols
587   // have not been designed correctly.  The CpuBreakpoint () is commented out for now until the
588   // DXE Core and all the Architectural Protocols are complete.
589   //
590 
591   return EFI_NOT_AVAILABLE_YET;
592 }
593 
594 
595 /**
596   Place holder function until all the Boot Services and Runtime Services are available.
597 
598   @param  Arg1                   Undefined
599   @param  Arg2                   Undefined
600   @param  Arg3                   Undefined
601 
602   @return EFI_NOT_AVAILABLE_YET
603 
604 **/
605 EFI_STATUS
606 EFIAPI
CoreEfiNotAvailableYetArg3(UINTN Arg1,UINTN Arg2,UINTN Arg3)607 CoreEfiNotAvailableYetArg3 (
608   UINTN Arg1,
609   UINTN Arg2,
610   UINTN Arg3
611   )
612 {
613   //
614   // This function should never be executed.  If it does, then the architectural protocols
615   // have not been designed correctly.  The CpuBreakpoint () is commented out for now until the
616   // DXE Core and all the Architectural Protocols are complete.
617   //
618 
619   return EFI_NOT_AVAILABLE_YET;
620 }
621 
622 
623 /**
624   Place holder function until all the Boot Services and Runtime Services are available.
625 
626   @param  Arg1                   Undefined
627   @param  Arg2                   Undefined
628   @param  Arg3                   Undefined
629   @param  Arg4                   Undefined
630 
631   @return EFI_NOT_AVAILABLE_YET
632 
633 **/
634 EFI_STATUS
635 EFIAPI
CoreEfiNotAvailableYetArg4(UINTN Arg1,UINTN Arg2,UINTN Arg3,UINTN Arg4)636 CoreEfiNotAvailableYetArg4 (
637   UINTN Arg1,
638   UINTN Arg2,
639   UINTN Arg3,
640   UINTN Arg4
641   )
642 {
643   //
644   // This function should never be executed.  If it does, then the architectural protocols
645   // have not been designed correctly.  The CpuBreakpoint () is commented out for now until the
646   // DXE Core and all the Architectural Protocols are complete.
647   //
648 
649   return EFI_NOT_AVAILABLE_YET;
650 }
651 
652 
653 /**
654   Place holder function until all the Boot Services and Runtime Services are available.
655 
656   @param  Arg1                   Undefined
657   @param  Arg2                   Undefined
658   @param  Arg3                   Undefined
659   @param  Arg4                   Undefined
660   @param  Arg5                   Undefined
661 
662   @return EFI_NOT_AVAILABLE_YET
663 
664 **/
665 EFI_STATUS
666 EFIAPI
CoreEfiNotAvailableYetArg5(UINTN Arg1,UINTN Arg2,UINTN Arg3,UINTN Arg4,UINTN Arg5)667 CoreEfiNotAvailableYetArg5 (
668   UINTN Arg1,
669   UINTN Arg2,
670   UINTN Arg3,
671   UINTN Arg4,
672   UINTN Arg5
673   )
674 {
675   //
676   // This function should never be executed.  If it does, then the architectural protocols
677   // have not been designed correctly.  The CpuBreakpoint () is commented out for now until the
678   // DXE Core and all the Architectural Protocols are complete.
679   //
680 
681   return EFI_NOT_AVAILABLE_YET;
682 }
683 
684 
685 /**
686   Calcualte the 32-bit CRC in a EFI table using the service provided by the
687   gRuntime service.
688 
689   @param  Hdr                    Pointer to an EFI standard header
690 
691 **/
692 VOID
CalculateEfiHdrCrc(IN OUT EFI_TABLE_HEADER * Hdr)693 CalculateEfiHdrCrc (
694   IN  OUT EFI_TABLE_HEADER    *Hdr
695   )
696 {
697   UINT32 Crc;
698 
699   Hdr->CRC32 = 0;
700 
701   //
702   // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
703   //  Crc will come back as zero if we set it to zero here
704   //
705   Crc = 0;
706   gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);
707   Hdr->CRC32 = Crc;
708 }
709 
710 
711 /**
712   Terminates all boot services.
713 
714   @param  ImageHandle            Handle that identifies the exiting image.
715   @param  MapKey                 Key to the latest memory map.
716 
717   @retval EFI_SUCCESS            Boot Services terminated
718   @retval EFI_INVALID_PARAMETER  MapKey is incorrect.
719 
720 **/
721 EFI_STATUS
722 EFIAPI
CoreExitBootServices(IN EFI_HANDLE ImageHandle,IN UINTN MapKey)723 CoreExitBootServices (
724   IN EFI_HANDLE   ImageHandle,
725   IN UINTN        MapKey
726   )
727 {
728   EFI_STATUS                Status;
729 
730   //
731   // Disable Timer
732   //
733   gTimer->SetTimerPeriod (gTimer, 0);
734 
735   //
736   // Terminate memory services if the MapKey matches
737   //
738   Status = CoreTerminateMemoryMap (MapKey);
739   if (EFI_ERROR (Status)) {
740     //
741     // Notify other drivers that ExitBootServices fail
742     //
743     CoreNotifySignalList (&gEventExitBootServicesFailedGuid);
744     return Status;
745   }
746 
747   //
748   // Notify other drivers that we are exiting boot services.
749   //
750   CoreNotifySignalList (&gEfiEventExitBootServicesGuid);
751 
752   //
753   // Report that ExitBootServices() has been called
754   //
755   REPORT_STATUS_CODE (
756     EFI_PROGRESS_CODE,
757     (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)
758     );
759 
760   //
761   // Disable interrupt of Debug timer.
762   //
763   SaveAndSetDebugTimerInterrupt (FALSE);
764 
765   //
766   // Disable CPU Interrupts
767   //
768   gCpu->DisableInterrupt (gCpu);
769 
770   //
771   // Clear the non-runtime values of the EFI System Table
772   //
773   gDxeCoreST->BootServices        = NULL;
774   gDxeCoreST->ConIn               = NULL;
775   gDxeCoreST->ConsoleInHandle     = NULL;
776   gDxeCoreST->ConOut              = NULL;
777   gDxeCoreST->ConsoleOutHandle    = NULL;
778   gDxeCoreST->StdErr              = NULL;
779   gDxeCoreST->StandardErrorHandle = NULL;
780 
781   //
782   // Recompute the 32-bit CRC of the EFI System Table
783   //
784   CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
785 
786   //
787   // Zero out the Boot Service Table
788   //
789   ZeroMem (gBS, sizeof (EFI_BOOT_SERVICES));
790   gBS = NULL;
791 
792   //
793   // Update the AtRuntime field in Runtiem AP.
794   //
795   gRuntime->AtRuntime = TRUE;
796 
797   return Status;
798 }
799 
800 
801 /**
802   Given a compressed source buffer, this function retrieves the size of the
803   uncompressed buffer and the size of the scratch buffer required to decompress
804   the compressed source buffer.
805 
806   The GetInfo() function retrieves the size of the uncompressed buffer and the
807   temporary scratch buffer required to decompress the buffer specified by Source
808   and SourceSize. If the size of the uncompressed buffer or the size of the
809   scratch buffer cannot be determined from the compressed data specified by
810   Source and SourceData, then EFI_INVALID_PARAMETER is returned. Otherwise, the
811   size of the uncompressed buffer is returned in DestinationSize, the size of
812   the scratch buffer is returned in ScratchSize, and EFI_SUCCESS is returned.
813   The GetInfo() function does not have scratch buffer available to perform a
814   thorough checking of the validity of the source data. It just retrieves the
815   "Original Size" field from the beginning bytes of the source data and output
816   it as DestinationSize. And ScratchSize is specific to the decompression
817   implementation.
818 
819   @param  This               A pointer to the EFI_DECOMPRESS_PROTOCOL instance.
820   @param  Source             The source buffer containing the compressed data.
821   @param  SourceSize         The size, in bytes, of the source buffer.
822   @param  DestinationSize    A pointer to the size, in bytes, of the
823                              uncompressed buffer that will be generated when the
824                              compressed buffer specified by Source and
825                              SourceSize is decompressed.
826   @param  ScratchSize        A pointer to the size, in bytes, of the scratch
827                              buffer that is required to decompress the
828                              compressed buffer specified by Source and
829                              SourceSize.
830 
831   @retval EFI_SUCCESS        The size of the uncompressed data was returned in
832                              DestinationSize and the size of the scratch buffer
833                              was returned in ScratchSize.
834   @retval EFI_INVALID_PARAMETER The size of the uncompressed data or the size of
835                                 the scratch buffer cannot be determined from the
836                                 compressed data specified by Source and
837                                 SourceSize.
838 
839 **/
840 EFI_STATUS
841 EFIAPI
DxeMainUefiDecompressGetInfo(IN EFI_DECOMPRESS_PROTOCOL * This,IN VOID * Source,IN UINT32 SourceSize,OUT UINT32 * DestinationSize,OUT UINT32 * ScratchSize)842 DxeMainUefiDecompressGetInfo (
843   IN EFI_DECOMPRESS_PROTOCOL            *This,
844   IN   VOID                             *Source,
845   IN   UINT32                           SourceSize,
846   OUT  UINT32                           *DestinationSize,
847   OUT  UINT32                           *ScratchSize
848   )
849 {
850   if (Source == NULL || DestinationSize == NULL || ScratchSize == NULL) {
851     return EFI_INVALID_PARAMETER;
852   }
853   return UefiDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize);
854 }
855 
856 
857 /**
858   Decompresses a compressed source buffer.
859 
860   The Decompress() function extracts decompressed data to its original form.
861   This protocol is designed so that the decompression algorithm can be
862   implemented without using any memory services. As a result, the Decompress()
863   Function is not allowed to call AllocatePool() or AllocatePages() in its
864   implementation. It is the caller's responsibility to allocate and free the
865   Destination and Scratch buffers.
866   If the compressed source data specified by Source and SourceSize is
867   successfully decompressed into Destination, then EFI_SUCCESS is returned. If
868   the compressed source data specified by Source and SourceSize is not in a
869   valid compressed data format, then EFI_INVALID_PARAMETER is returned.
870 
871   @param  This                A pointer to the EFI_DECOMPRESS_PROTOCOL instance.
872   @param  Source              The source buffer containing the compressed data.
873   @param  SourceSize          SourceSizeThe size of source data.
874   @param  Destination         On output, the destination buffer that contains
875                               the uncompressed data.
876   @param  DestinationSize     The size of the destination buffer.  The size of
877                               the destination buffer needed is obtained from
878                               EFI_DECOMPRESS_PROTOCOL.GetInfo().
879   @param  Scratch             A temporary scratch buffer that is used to perform
880                               the decompression.
881   @param  ScratchSize         The size of scratch buffer. The size of the
882                               scratch buffer needed is obtained from GetInfo().
883 
884   @retval EFI_SUCCESS         Decompression completed successfully, and the
885                               uncompressed buffer is returned in Destination.
886   @retval EFI_INVALID_PARAMETER  The source buffer specified by Source and
887                                  SourceSize is corrupted (not in a valid
888                                  compressed format).
889 
890 **/
891 EFI_STATUS
892 EFIAPI
DxeMainUefiDecompress(IN EFI_DECOMPRESS_PROTOCOL * This,IN VOID * Source,IN UINT32 SourceSize,IN OUT VOID * Destination,IN UINT32 DestinationSize,IN OUT VOID * Scratch,IN UINT32 ScratchSize)893 DxeMainUefiDecompress (
894   IN     EFI_DECOMPRESS_PROTOCOL          *This,
895   IN     VOID                             *Source,
896   IN     UINT32                           SourceSize,
897   IN OUT VOID                             *Destination,
898   IN     UINT32                           DestinationSize,
899   IN OUT VOID                             *Scratch,
900   IN     UINT32                           ScratchSize
901   )
902 {
903   EFI_STATUS  Status;
904   UINT32      TestDestinationSize;
905   UINT32      TestScratchSize;
906 
907   if (Source == NULL || Destination== NULL || Scratch == NULL) {
908     return EFI_INVALID_PARAMETER;
909   }
910 
911   Status = UefiDecompressGetInfo (Source, SourceSize, &TestDestinationSize, &TestScratchSize);
912   if (EFI_ERROR (Status)) {
913     return Status;
914   }
915 
916   if (ScratchSize < TestScratchSize || DestinationSize < TestDestinationSize) {
917     return RETURN_INVALID_PARAMETER;
918   }
919 
920   return UefiDecompress (Source, Destination, Scratch);
921 }
922