]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/Dispatcher.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Dispatcher.c
CommitLineData
e42e9404 1/** @file\r
2 SMM Driver Dispatcher.\r
3\r
4 Step #1 - When a FV protocol is added to the system every driver in the FV\r
fa542a1e 5 is added to the mDiscoveredList. The Before, and After Depex are\r
e42e9404 6 pre-processed as drivers are added to the mDiscoveredList. If an Apriori\r
7 file exists in the FV those drivers are addeded to the\r
8 mScheduledQueue. The mFvHandleList is used to make sure a\r
9 FV is only processed once.\r
10\r
11 Step #2 - Dispatch. Remove driver from the mScheduledQueue and load and\r
12 start it. After mScheduledQueue is drained check the\r
13 mDiscoveredList to see if any item has a Depex that is ready to\r
14 be placed on the mScheduledQueue.\r
15\r
16 Step #3 - Adding to the mScheduledQueue requires that you process Before\r
17 and After dependencies. This is done recursively as the call to add\r
18 to the mScheduledQueue checks for Before and recursively adds\r
19 all Befores. It then addes the item that was passed in and then\r
4be497df 20 processes the After dependencies by recursively calling the routine.\r
e42e9404 21\r
22 Dispatcher Rules:\r
23 The rules for the dispatcher are similar to the DXE dispatcher.\r
24\r
25 The rules for DXE dispatcher are in chapter 10 of the DXE CIS. Figure 10-3\r
26 is the state diagram for the DXE dispatcher\r
27\r
4be497df 28 Depex - Dependency Expression.\r
e42e9404 29\r
891d8445 30 Copyright (c) 2014, Hewlett-Packard Development Company, L.P.\r
d1102dba 31 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 32 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e42e9404 33\r
34**/\r
35\r
36#include "PiSmmCore.h"\r
37\r
38//\r
39// SMM Dispatcher Data structures\r
40//\r
41#define KNOWN_HANDLE_SIGNATURE SIGNATURE_32('k','n','o','w')\r
42typedef struct {\r
1436aea4
MK
43 UINTN Signature;\r
44 LIST_ENTRY Link; // mFvHandleList\r
45 EFI_HANDLE Handle;\r
e42e9404 46} KNOWN_HANDLE;\r
47\r
48//\r
49// Function Prototypes\r
50//\r
51\r
52/**\r
53 Insert InsertedDriverEntry onto the mScheduledQueue. To do this you\r
54 must add any driver with a before dependency on InsertedDriverEntry first.\r
55 You do this by recursively calling this routine. After all the Befores are\r
56 processed you can add InsertedDriverEntry to the mScheduledQueue.\r
57 Then you can add any driver with an After dependency on InsertedDriverEntry\r
58 by recursively calling this routine.\r
59\r
60 @param InsertedDriverEntry The driver to insert on the ScheduledLink Queue\r
61\r
62**/\r
63VOID\r
64SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (\r
1436aea4 65 IN EFI_SMM_DRIVER_ENTRY *InsertedDriverEntry\r
e42e9404 66 );\r
67\r
68//\r
69// The Driver List contains one copy of every driver that has been discovered.\r
70// Items are never removed from the driver list. List of EFI_SMM_DRIVER_ENTRY\r
71//\r
72LIST_ENTRY mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList);\r
73\r
74//\r
75// Queue of drivers that are ready to dispatch. This queue is a subset of the\r
76// mDiscoveredList.list of EFI_SMM_DRIVER_ENTRY.\r
77//\r
78LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);\r
79\r
80//\r
81// List of handles who's Fv's have been parsed and added to the mFwDriverList.\r
82//\r
83LIST_ENTRY mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList);\r
84\r
85//\r
4be497df 86// Flag for the SMM Dispatcher. TRUE if dispatcher is executing.\r
e42e9404 87//\r
88BOOLEAN gDispatcherRunning = FALSE;\r
89\r
90//\r
4be497df 91// Flag for the SMM Dispatcher. TRUE if there is one or more SMM drivers ready to be dispatched\r
e42e9404 92//\r
93BOOLEAN gRequestDispatch = FALSE;\r
94\r
95//\r
96// List of file types supported by dispatcher\r
97//\r
1436aea4 98EFI_FV_FILETYPE mSmmFileTypes[] = {\r
e42e9404 99 EFI_FV_FILETYPE_SMM,\r
0b256fb1
JY
100 EFI_FV_FILETYPE_COMBINED_SMM_DXE,\r
101 EFI_FV_FILETYPE_SMM_CORE,\r
e42e9404 102 //\r
103 // Note: DXE core will process the FV image file, so skip it in SMM core\r
104 // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\r
105 //\r
106};\r
107\r
108typedef struct {\r
1436aea4
MK
109 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File;\r
110 EFI_DEVICE_PATH_PROTOCOL End;\r
e42e9404 111} FV_FILEPATH_DEVICE_PATH;\r
112\r
113FV_FILEPATH_DEVICE_PATH mFvDevicePath;\r
114\r
115//\r
116// DXE Architecture Protocols\r
117//\r
1436aea4
MK
118EFI_SECURITY_ARCH_PROTOCOL *mSecurity = NULL;\r
119EFI_SECURITY2_ARCH_PROTOCOL *mSecurity2 = NULL;\r
e42e9404 120\r
3c447c27 121//\r
122// The global variable is defined for Loading modules at fixed address feature to track the SMM code\r
2048c585 123// memory range usage. It is a bit mapped array in which every bit indicates the corresponding\r
d1102dba 124// memory page available or not.\r
3c447c27 125//\r
1436aea4 126GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mSmmCodeMemoryRangeUsageBitMap = NULL;\r
3c447c27 127\r
128/**\r
2048c585
GM
129 To check memory usage bit map array to figure out if the memory range in which the image will be loaded is available or not. If\r
130 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.\r
d1102dba
LG
131 The function is only invoked when load modules at fixed address feature is enabled.\r
132\r
2048c585 133 @param ImageBase The base address the image will be loaded at.\r
3c447c27 134 @param ImageSize The size of the image\r
d1102dba 135\r
3c447c27 136 @retval EFI_SUCCESS The memory range the image will be loaded in is available\r
137 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available\r
138**/\r
139EFI_STATUS\r
140CheckAndMarkFixLoadingMemoryUsageBitMap (\r
1436aea4
MK
141 IN EFI_PHYSICAL_ADDRESS ImageBase,\r
142 IN UINTN ImageSize\r
3c447c27 143 )\r
144{\r
1436aea4
MK
145 UINT32 SmmCodePageNumber;\r
146 UINT64 SmmCodeSize;\r
147 EFI_PHYSICAL_ADDRESS SmmCodeBase;\r
148 UINTN BaseOffsetPageNumber;\r
149 UINTN TopOffsetPageNumber;\r
150 UINTN Index;\r
151\r
152 //\r
153 // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber\r
154 //\r
155 SmmCodePageNumber = PcdGet32 (PcdLoadFixAddressSmmCodePageNumber);\r
156 SmmCodeSize = EFI_PAGES_TO_SIZE (SmmCodePageNumber);\r
157 SmmCodeBase = gLoadModuleAtFixAddressSmramBase;\r
158\r
159 //\r
160 // If the memory usage bit map is not initialized, do it. Every bit in the array\r
161 // indicate the status of the corresponding memory page, available or not\r
162 //\r
163 if (mSmmCodeMemoryRangeUsageBitMap == NULL) {\r
164 mSmmCodeMemoryRangeUsageBitMap = AllocateZeroPool (((SmmCodePageNumber / 64) + 1)*sizeof (UINT64));\r
165 }\r
166\r
167 //\r
168 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND\r
169 //\r
170 if (mSmmCodeMemoryRangeUsageBitMap == NULL) {\r
171 return EFI_NOT_FOUND;\r
172 }\r
173\r
174 //\r
175 // see if the memory range for loading the image is in the SMM code range.\r
176 //\r
177 if ((SmmCodeBase + SmmCodeSize < ImageBase + ImageSize) || (SmmCodeBase > ImageBase)) {\r
178 return EFI_NOT_FOUND;\r
179 }\r
180\r
181 //\r
182 // Test if the memory is available or not.\r
183 //\r
184 BaseOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase - SmmCodeBase));\r
185 TopOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase + ImageSize - SmmCodeBase));\r
186 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) {\r
187 if ((mSmmCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64 (1, (Index % 64))) != 0) {\r
188 //\r
189 // This page is already used.\r
190 //\r
191 return EFI_NOT_FOUND;\r
192 }\r
193 }\r
194\r
195 //\r
196 // Being here means the memory range is available. So mark the bits for the memory range\r
197 //\r
198 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) {\r
199 mSmmCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64 (1, (Index % 64));\r
200 }\r
201\r
202 return EFI_SUCCESS;\r
3c447c27 203}\r
1436aea4 204\r
3c447c27 205/**\r
2048c585 206 Get the fixed loading address from image header assigned by build tool. This function only be called\r
3c447c27 207 when Loading module at Fixed address feature enabled.\r
d1102dba 208\r
3c447c27 209 @param ImageContext Pointer to the image context structure that describes the PE/COFF\r
210 image that needs to be examined by this function.\r
211 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .\r
2048c585 212 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.\r
3c447c27 213\r
214**/\r
215EFI_STATUS\r
1436aea4 216GetPeCoffImageFixLoadingAssignedAddress (\r
3c447c27 217 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
218 )\r
219{\r
1436aea4
MK
220 UINTN SectionHeaderOffset;\r
221 EFI_STATUS Status;\r
222 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
223 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
224 EFI_PHYSICAL_ADDRESS FixLoadingAddress;\r
225 UINT16 Index;\r
226 UINTN Size;\r
227 UINT16 NumberOfSections;\r
228 UINT64 ValueInSectionHeader;\r
2048c585
GM
229\r
230 FixLoadingAddress = 0;\r
1436aea4 231 Status = EFI_NOT_FOUND;\r
2048c585
GM
232\r
233 //\r
234 // Get PeHeader pointer\r
235 //\r
1436aea4 236 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
16f69227
HW
237 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +\r
238 sizeof (UINT32) +\r
239 sizeof (EFI_IMAGE_FILE_HEADER) +\r
240 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\r
2048c585
GM
241 NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
242\r
243 //\r
244 // Get base address from the first section header that doesn't point to code section.\r
245 //\r
246 for (Index = 0; Index < NumberOfSections; Index++) {\r
247 //\r
248 // Read section header from file\r
249 //\r
1436aea4 250 Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
2048c585 251 Status = ImageContext->ImageRead (\r
1436aea4
MK
252 ImageContext->Handle,\r
253 SectionHeaderOffset,\r
254 &Size,\r
255 &SectionHeader\r
256 );\r
2048c585
GM
257 if (EFI_ERROR (Status)) {\r
258 return Status;\r
259 }\r
260\r
261 Status = EFI_NOT_FOUND;\r
262\r
263 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
264 //\r
265 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header\r
266 // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled,\r
267 // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields\r
268 // should not be Zero, or else, these 2 fields should be set to Zero\r
269 //\r
1436aea4 270 ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations);\r
2048c585
GM
271 if (ValueInSectionHeader != 0) {\r
272 //\r
273 // Found first section header that doesn't point to code section in which build tool saves the\r
274 // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields\r
275 //\r
276 FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader);\r
277 //\r
278 // Check if the memory range is available.\r
279 //\r
280 Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
1436aea4 281 if (!EFI_ERROR (Status)) {\r
2048c585
GM
282 //\r
283 // The assigned address is valid. Return the specified loading address\r
284 //\r
285 ImageContext->ImageAddress = FixLoadingAddress;\r
286 }\r
287 }\r
1436aea4 288\r
2048c585
GM
289 break;\r
290 }\r
1436aea4 291\r
2048c585
GM
292 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
293 }\r
1436aea4 294\r
87000d77 295 DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoadingAddress, Status));\r
2048c585 296 return Status;\r
3c447c27 297}\r
1436aea4 298\r
e42e9404 299/**\r
300 Loads an EFI image into SMRAM.\r
301\r
302 @param DriverEntry EFI_SMM_DRIVER_ENTRY instance\r
303\r
304 @return EFI_STATUS\r
305\r
306**/\r
307EFI_STATUS\r
308EFIAPI\r
309SmmLoadImage (\r
310 IN OUT EFI_SMM_DRIVER_ENTRY *DriverEntry\r
311 )\r
312{\r
313 UINT32 AuthenticationStatus;\r
314 UINTN FilePathSize;\r
315 VOID *Buffer;\r
316 UINTN Size;\r
317 UINTN PageCount;\r
318 EFI_GUID *NameGuid;\r
319 EFI_STATUS Status;\r
320 EFI_STATUS SecurityStatus;\r
321 EFI_HANDLE DeviceHandle;\r
322 EFI_PHYSICAL_ADDRESS DstBuffer;\r
323 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
324 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
325 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
326 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
327 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
c2cb08df 328\r
67e9ab84
BD
329 PERF_LOAD_IMAGE_BEGIN (DriverEntry->ImageHandle);\r
330\r
1436aea4
MK
331 Buffer = NULL;\r
332 Size = 0;\r
333 Fv = DriverEntry->Fv;\r
334 NameGuid = &DriverEntry->FileName;\r
335 FilePath = DriverEntry->FvFileDevicePath;\r
e42e9404 336\r
337 OriginalFilePath = FilePath;\r
338 HandleFilePath = FilePath;\r
339 DeviceHandle = NULL;\r
340 SecurityStatus = EFI_SUCCESS;\r
341 Status = EFI_SUCCESS;\r
342 AuthenticationStatus = 0;\r
343\r
344 //\r
345 // Try to get the image device handle by checking the match protocol.\r
346 //\r
347 Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
1436aea4 348 if (EFI_ERROR (Status)) {\r
e42e9404 349 return Status;\r
350 }\r
351\r
352 //\r
bc2dfdbc 353 // If the Security2 and Security Architectural Protocol has not been located yet, then attempt to locate it\r
e42e9404 354 //\r
bc2dfdbc 355 if (mSecurity2 == NULL) {\r
1436aea4 356 gBS->LocateProtocol (&gEfiSecurity2ArchProtocolGuid, NULL, (VOID **)&mSecurity2);\r
bc2dfdbc 357 }\r
1436aea4 358\r
e42e9404 359 if (mSecurity == NULL) {\r
1436aea4 360 gBS->LocateProtocol (&gEfiSecurityArchProtocolGuid, NULL, (VOID **)&mSecurity);\r
e42e9404 361 }\r
1436aea4 362\r
e42e9404 363 //\r
bc2dfdbc 364 // When Security2 is installed, Security Architectural Protocol must be published.\r
e42e9404 365 //\r
bc2dfdbc
LG
366 ASSERT (mSecurity2 == NULL || mSecurity != NULL);\r
367\r
e42e9404 368 //\r
369 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
370 //\r
371 FilePath = OriginalFilePath;\r
1436aea4 372 Status = gBS->HandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
e42e9404 373 if (!EFI_ERROR (Status)) {\r
1436aea4
MK
374 FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
375 FilePath = (EFI_DEVICE_PATH_PROTOCOL *)(((UINT8 *)FilePath) + FilePathSize);\r
e42e9404 376 }\r
377\r
378 //\r
379 // Try reading PE32 section firstly\r
380 //\r
381 Status = Fv->ReadSection (\r
382 Fv,\r
383 NameGuid,\r
384 EFI_SECTION_PE32,\r
385 0,\r
386 &Buffer,\r
387 &Size,\r
388 &AuthenticationStatus\r
389 );\r
390\r
391 if (EFI_ERROR (Status)) {\r
392 //\r
393 // Try reading TE section secondly\r
394 //\r
395 Buffer = NULL;\r
396 Size = 0;\r
397 Status = Fv->ReadSection (\r
1436aea4
MK
398 Fv,\r
399 NameGuid,\r
400 EFI_SECTION_TE,\r
401 0,\r
402 &Buffer,\r
403 &Size,\r
404 &AuthenticationStatus\r
405 );\r
e42e9404 406 }\r
d1102dba 407\r
e42e9404 408 if (EFI_ERROR (Status)) {\r
409 if (Buffer != NULL) {\r
b08b7ba4 410 gBS->FreePool (Buffer);\r
e42e9404 411 }\r
1436aea4 412\r
e42e9404 413 return Status;\r
414 }\r
415\r
bc2dfdbc
LG
416 //\r
417 // Verify File Authentication through the Security2 Architectural Protocol\r
418 //\r
419 if (mSecurity2 != NULL) {\r
420 SecurityStatus = mSecurity2->FileAuthentication (\r
1436aea4
MK
421 mSecurity2,\r
422 OriginalFilePath,\r
423 Buffer,\r
424 Size,\r
425 FALSE\r
426 );\r
bc2dfdbc
LG
427 }\r
428\r
429 //\r
430 // Verify the Authentication Status through the Security Architectural Protocol\r
431 // Only on images that have been read using Firmware Volume protocol.\r
d1102dba 432 // All SMM images are from FV protocol.\r
bc2dfdbc
LG
433 //\r
434 if (!EFI_ERROR (SecurityStatus) && (mSecurity != NULL)) {\r
435 SecurityStatus = mSecurity->FileAuthenticationState (\r
436 mSecurity,\r
437 AuthenticationStatus,\r
438 OriginalFilePath\r
439 );\r
440 }\r
441\r
1436aea4 442 if (EFI_ERROR (SecurityStatus) && (SecurityStatus != EFI_SECURITY_VIOLATION)) {\r
bc2dfdbc
LG
443 Status = SecurityStatus;\r
444 return Status;\r
445 }\r
d1102dba 446\r
e42e9404 447 //\r
448 // Initialize ImageContext\r
449 //\r
1436aea4 450 ImageContext.Handle = Buffer;\r
e42e9404 451 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
452\r
453 //\r
454 // Get information about the image being loaded\r
455 //\r
456 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
457 if (EFI_ERROR (Status)) {\r
458 if (Buffer != NULL) {\r
b08b7ba4 459 gBS->FreePool (Buffer);\r
e42e9404 460 }\r
1436aea4 461\r
e42e9404 462 return Status;\r
463 }\r
1436aea4 464\r
3c447c27 465 //\r
466 // if Loading module at Fixed Address feature is enabled, then cut out a memory range started from TESG BASE\r
467 // to hold the Smm driver code\r
468 //\r
1436aea4 469 if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {\r
3c447c27 470 //\r
471 // Get the fixed loading address assigned by Build tool\r
472 //\r
473 Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);\r
474 if (!EFI_ERROR (Status)) {\r
475 //\r
4be497df 476 // Since the memory range to load Smm core already been cut out, so no need to allocate and free this range\r
3c447c27 477 // following statements is to bypass SmmFreePages\r
478 //\r
479 PageCount = 0;\r
d1102dba 480 DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase;\r
3c447c27 481 } else {\r
1436aea4
MK
482 DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));\r
483 //\r
484 // allocate the memory to load the SMM driver\r
485 //\r
486 PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);\r
487 DstBuffer = (UINTN)(-1);\r
488\r
489 Status = SmmAllocatePages (\r
490 AllocateMaxAddress,\r
491 EfiRuntimeServicesCode,\r
492 PageCount,\r
493 &DstBuffer\r
494 );\r
495 if (EFI_ERROR (Status)) {\r
496 if (Buffer != NULL) {\r
497 gBS->FreePool (Buffer);\r
498 }\r
499\r
500 return Status;\r
501 }\r
502\r
3c447c27 503 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
e42e9404 504 }\r
3c447c27 505 } else {\r
1436aea4
MK
506 PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);\r
507 DstBuffer = (UINTN)(-1);\r
508\r
509 Status = SmmAllocatePages (\r
510 AllocateMaxAddress,\r
511 EfiRuntimeServicesCode,\r
512 PageCount,\r
513 &DstBuffer\r
514 );\r
515 if (EFI_ERROR (Status)) {\r
516 if (Buffer != NULL) {\r
517 gBS->FreePool (Buffer);\r
518 }\r
519\r
520 return Status;\r
521 }\r
522\r
523 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
e42e9404 524 }\r
1436aea4 525\r
e42e9404 526 //\r
6393d9c8 527 // Align buffer on section boundary\r
e42e9404 528 //\r
529 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
16f69227 530 ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);\r
e42e9404 531\r
532 //\r
533 // Load the image to our new buffer\r
534 //\r
535 Status = PeCoffLoaderLoadImage (&ImageContext);\r
536 if (EFI_ERROR (Status)) {\r
537 if (Buffer != NULL) {\r
b08b7ba4 538 gBS->FreePool (Buffer);\r
e42e9404 539 }\r
1436aea4 540\r
e42e9404 541 SmmFreePages (DstBuffer, PageCount);\r
542 return Status;\r
543 }\r
544\r
545 //\r
546 // Relocate the image in our new buffer\r
547 //\r
548 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
549 if (EFI_ERROR (Status)) {\r
550 if (Buffer != NULL) {\r
b08b7ba4 551 gBS->FreePool (Buffer);\r
e42e9404 552 }\r
1436aea4 553\r
e42e9404 554 SmmFreePages (DstBuffer, PageCount);\r
555 return Status;\r
556 }\r
557\r
558 //\r
559 // Flush the instruction cache so the image data are written before we execute it\r
560 //\r
1436aea4 561 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
e42e9404 562\r
563 //\r
564 // Save Image EntryPoint in DriverEntry\r
565 //\r
1436aea4
MK
566 DriverEntry->ImageEntryPoint = ImageContext.EntryPoint;\r
567 DriverEntry->ImageBuffer = DstBuffer;\r
568 DriverEntry->NumberOfPage = PageCount;\r
e42e9404 569\r
570 //\r
571 // Allocate a Loaded Image Protocol in EfiBootServicesData\r
572 //\r
573 Status = gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&DriverEntry->LoadedImage);\r
574 if (EFI_ERROR (Status)) {\r
575 if (Buffer != NULL) {\r
b08b7ba4 576 gBS->FreePool (Buffer);\r
e42e9404 577 }\r
1436aea4 578\r
e42e9404 579 SmmFreePages (DstBuffer, PageCount);\r
580 return Status;\r
581 }\r
582\r
891d8445 583 ZeroMem (DriverEntry->LoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));\r
e42e9404 584 //\r
585 // Fill in the remaining fields of the Loaded Image Protocol instance.\r
586 // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.\r
587 //\r
1436aea4
MK
588 DriverEntry->LoadedImage->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
589 DriverEntry->LoadedImage->ParentHandle = gSmmCorePrivate->SmmIplImageHandle;\r
590 DriverEntry->LoadedImage->SystemTable = gST;\r
591 DriverEntry->LoadedImage->DeviceHandle = DeviceHandle;\r
e42e9404 592\r
285a682c
JY
593 DriverEntry->SmmLoadedImage.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
594 DriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle;\r
595 DriverEntry->SmmLoadedImage.SystemTable = gST;\r
596 DriverEntry->SmmLoadedImage.DeviceHandle = DeviceHandle;\r
597\r
e42e9404 598 //\r
599 // Make an EfiBootServicesData buffer copy of FilePath\r
600 //\r
601 Status = gBS->AllocatePool (EfiBootServicesData, GetDevicePathSize (FilePath), (VOID **)&DriverEntry->LoadedImage->FilePath);\r
602 if (EFI_ERROR (Status)) {\r
603 if (Buffer != NULL) {\r
b08b7ba4 604 gBS->FreePool (Buffer);\r
e42e9404 605 }\r
1436aea4 606\r
e42e9404 607 SmmFreePages (DstBuffer, PageCount);\r
608 return Status;\r
609 }\r
1436aea4 610\r
e42e9404 611 CopyMem (DriverEntry->LoadedImage->FilePath, FilePath, GetDevicePathSize (FilePath));\r
612\r
1436aea4 613 DriverEntry->LoadedImage->ImageBase = (VOID *)(UINTN)ImageContext.ImageAddress;\r
e42e9404 614 DriverEntry->LoadedImage->ImageSize = ImageContext.ImageSize;\r
615 DriverEntry->LoadedImage->ImageCodeType = EfiRuntimeServicesCode;\r
616 DriverEntry->LoadedImage->ImageDataType = EfiRuntimeServicesData;\r
617\r
285a682c
JY
618 //\r
619 // Make a buffer copy of FilePath\r
620 //\r
1436aea4 621 Status = SmmAllocatePool (EfiRuntimeServicesData, GetDevicePathSize (FilePath), (VOID **)&DriverEntry->SmmLoadedImage.FilePath);\r
285a682c
JY
622 if (EFI_ERROR (Status)) {\r
623 if (Buffer != NULL) {\r
624 gBS->FreePool (Buffer);\r
625 }\r
1436aea4 626\r
285a682c
JY
627 gBS->FreePool (DriverEntry->LoadedImage->FilePath);\r
628 SmmFreePages (DstBuffer, PageCount);\r
629 return Status;\r
630 }\r
285a682c 631\r
1436aea4
MK
632 CopyMem (DriverEntry->SmmLoadedImage.FilePath, FilePath, GetDevicePathSize (FilePath));\r
633\r
634 DriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN)ImageContext.ImageAddress;\r
635 DriverEntry->SmmLoadedImage.ImageSize = ImageContext.ImageSize;\r
285a682c
JY
636 DriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;\r
637 DriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;\r
638\r
e42e9404 639 //\r
640 // Create a new image handle in the UEFI handle database for the SMM Driver\r
641 //\r
642 DriverEntry->ImageHandle = NULL;\r
1436aea4
MK
643 Status = gBS->InstallMultipleProtocolInterfaces (\r
644 &DriverEntry->ImageHandle,\r
645 &gEfiLoadedImageProtocolGuid,\r
646 DriverEntry->LoadedImage,\r
647 NULL\r
648 );\r
e42e9404 649\r
285a682c
JY
650 //\r
651 // Create a new image handle in the SMM handle database for the SMM Driver\r
652 //\r
653 DriverEntry->SmmImageHandle = NULL;\r
1436aea4
MK
654 Status = SmmInstallProtocolInterface (\r
655 &DriverEntry->SmmImageHandle,\r
656 &gEfiLoadedImageProtocolGuid,\r
657 EFI_NATIVE_INTERFACE,\r
658 &DriverEntry->SmmLoadedImage\r
659 );\r
285a682c 660\r
67e9ab84 661 PERF_LOAD_IMAGE_END (DriverEntry->ImageHandle);\r
c2cb08df 662\r
e42e9404 663 //\r
664 // Print the load address and the PDB file name if it is available\r
665 //\r
666\r
667 DEBUG_CODE_BEGIN ();\r
668\r
1436aea4
MK
669 UINTN Index;\r
670 UINTN StartIndex;\r
671 CHAR8 EfiFileName[256];\r
e42e9404 672\r
1436aea4
MK
673 DEBUG ((\r
674 DEBUG_INFO | DEBUG_LOAD,\r
675 "Loading SMM driver at 0x%11p EntryPoint=0x%11p ",\r
676 (VOID *)(UINTN)ImageContext.ImageAddress,\r
677 FUNCTION_ENTRY_POINT (ImageContext.EntryPoint)\r
678 ));\r
e42e9404 679\r
1436aea4
MK
680 //\r
681 // Print Module Name by Pdb file path.\r
682 // Windows and Unix style file path are all trimmed correctly.\r
683 //\r
684 if (ImageContext.PdbPointer != NULL) {\r
685 StartIndex = 0;\r
686 for (Index = 0; ImageContext.PdbPointer[Index] != 0; Index++) {\r
687 if ((ImageContext.PdbPointer[Index] == '\\') || (ImageContext.PdbPointer[Index] == '/')) {\r
688 StartIndex = Index + 1;\r
689 }\r
690 }\r
e42e9404 691\r
692 //\r
1436aea4
MK
693 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
694 // The PDB file name is limited in the range of 0~255.\r
695 // If the length is bigger than 255, trim the redundant characters to avoid overflow in array boundary.\r
e42e9404 696 //\r
1436aea4
MK
697 for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {\r
698 EfiFileName[Index] = ImageContext.PdbPointer[Index + StartIndex];\r
699 if (EfiFileName[Index] == 0) {\r
700 EfiFileName[Index] = '.';\r
e42e9404 701 }\r
702\r
1436aea4
MK
703 if (EfiFileName[Index] == '.') {\r
704 EfiFileName[Index + 1] = 'e';\r
705 EfiFileName[Index + 2] = 'f';\r
706 EfiFileName[Index + 3] = 'i';\r
707 EfiFileName[Index + 4] = 0;\r
708 break;\r
e42e9404 709 }\r
e42e9404 710 }\r
1436aea4
MK
711\r
712 if (Index == sizeof (EfiFileName) - 4) {\r
713 EfiFileName[Index] = 0;\r
714 }\r
715\r
716 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
717 }\r
718\r
719 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));\r
e42e9404 720\r
721 DEBUG_CODE_END ();\r
722\r
723 //\r
724 // Free buffer allocated by Fv->ReadSection.\r
725 //\r
d1102dba 726 // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection\r
e42e9404 727 // used the UEFI Boot Services AllocatePool() function\r
728 //\r
1436aea4 729 Status = gBS->FreePool (Buffer);\r
022ff6bb
SZ
730 if (!EFI_ERROR (Status) && EFI_ERROR (SecurityStatus)) {\r
731 Status = SecurityStatus;\r
732 }\r
1436aea4 733\r
d1102dba 734 return Status;\r
e42e9404 735}\r
736\r
737/**\r
738 Preprocess dependency expression and update DriverEntry to reflect the\r
fa542a1e 739 state of Before and After dependencies. If DriverEntry->Before\r
d1102dba 740 or DriverEntry->After is set it will never be cleared.\r
e42e9404 741\r
742 @param DriverEntry DriverEntry element to update .\r
743\r
744 @retval EFI_SUCCESS It always works.\r
745\r
746**/\r
747EFI_STATUS\r
748SmmPreProcessDepex (\r
749 IN EFI_SMM_DRIVER_ENTRY *DriverEntry\r
750 )\r
751{\r
752 UINT8 *Iterator;\r
753\r
1436aea4 754 Iterator = DriverEntry->Depex;\r
fa542a1e 755 DriverEntry->Dependent = TRUE;\r
e42e9404 756\r
757 if (*Iterator == EFI_DEP_BEFORE) {\r
758 DriverEntry->Before = TRUE;\r
759 } else if (*Iterator == EFI_DEP_AFTER) {\r
760 DriverEntry->After = TRUE;\r
761 }\r
762\r
763 if (DriverEntry->Before || DriverEntry->After) {\r
764 CopyMem (&DriverEntry->BeforeAfterGuid, Iterator + 1, sizeof (EFI_GUID));\r
765 }\r
766\r
767 return EFI_SUCCESS;\r
768}\r
769\r
770/**\r
771 Read Depex and pre-process the Depex for Before and After. If Section Extraction\r
772 protocol returns an error via ReadSection defer the reading of the Depex.\r
773\r
774 @param DriverEntry Driver to work on.\r
775\r
4be497df 776 @retval EFI_SUCCESS Depex read and preprocessed\r
e42e9404 777 @retval EFI_PROTOCOL_ERROR The section extraction protocol returned an error\r
778 and Depex reading needs to be retried.\r
779 @retval Error DEPEX not found.\r
780\r
781**/\r
782EFI_STATUS\r
783SmmGetDepexSectionAndPreProccess (\r
784 IN EFI_SMM_DRIVER_ENTRY *DriverEntry\r
785 )\r
786{\r
787 EFI_STATUS Status;\r
788 EFI_SECTION_TYPE SectionType;\r
789 UINT32 AuthenticationStatus;\r
790 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
791\r
792 Fv = DriverEntry->Fv;\r
793\r
794 //\r
795 // Grab Depex info, it will never be free'ed.\r
796 // (Note: DriverEntry->Depex is in DXE memory)\r
797 //\r
1436aea4
MK
798 SectionType = EFI_SECTION_SMM_DEPEX;\r
799 Status = Fv->ReadSection (\r
800 DriverEntry->Fv,\r
801 &DriverEntry->FileName,\r
802 SectionType,\r
803 0,\r
804 &DriverEntry->Depex,\r
805 (UINTN *)&DriverEntry->DepexSize,\r
806 &AuthenticationStatus\r
807 );\r
e42e9404 808 if (EFI_ERROR (Status)) {\r
809 if (Status == EFI_PROTOCOL_ERROR) {\r
810 //\r
811 // The section extraction protocol failed so set protocol error flag\r
812 //\r
813 DriverEntry->DepexProtocolError = TRUE;\r
814 } else {\r
815 //\r
816 // If no Depex assume depend on all architectural protocols\r
817 //\r
1436aea4
MK
818 DriverEntry->Depex = NULL;\r
819 DriverEntry->Dependent = TRUE;\r
e42e9404 820 DriverEntry->DepexProtocolError = FALSE;\r
821 }\r
822 } else {\r
823 //\r
fa542a1e 824 // Set Before and After state information based on Depex\r
825 // Driver will be put in Dependent state\r
e42e9404 826 //\r
827 SmmPreProcessDepex (DriverEntry);\r
828 DriverEntry->DepexProtocolError = FALSE;\r
829 }\r
830\r
831 return Status;\r
832}\r
833\r
e42e9404 834/**\r
835 This is the main Dispatcher for SMM and it exits when there are no more\r
836 drivers to run. Drain the mScheduledQueue and load and start a PE\r
837 image for each driver. Search the mDiscoveredList to see if any driver can\r
838 be placed on the mScheduledQueue. If no drivers are placed on the\r
d1102dba 839 mScheduledQueue exit the function.\r
5657b268 840\r
841 @retval EFI_SUCCESS All of the SMM Drivers that could be dispatched\r
842 have been run and the SMM Entry Point has been\r
843 registered.\r
844 @retval EFI_NOT_READY The SMM Driver that registered the SMM Entry Point\r
845 was just dispatched.\r
846 @retval EFI_NOT_FOUND There are no SMM Drivers available to be dispatched.\r
e42e9404 847 @retval EFI_ALREADY_STARTED The SMM Dispatcher is already running\r
e42e9404 848\r
849**/\r
850EFI_STATUS\r
851SmmDispatcher (\r
852 VOID\r
853 )\r
854{\r
855 EFI_STATUS Status;\r
e42e9404 856 LIST_ENTRY *Link;\r
857 EFI_SMM_DRIVER_ENTRY *DriverEntry;\r
858 BOOLEAN ReadyToRun;\r
5657b268 859 BOOLEAN PreviousSmmEntryPointRegistered;\r
e42e9404 860\r
861 if (!gRequestDispatch) {\r
862 return EFI_NOT_FOUND;\r
863 }\r
864\r
865 if (gDispatcherRunning) {\r
866 //\r
867 // If the dispatcher is running don't let it be restarted.\r
868 //\r
869 return EFI_ALREADY_STARTED;\r
870 }\r
871\r
872 gDispatcherRunning = TRUE;\r
873\r
e42e9404 874 do {\r
875 //\r
876 // Drain the Scheduled Queue\r
877 //\r
878 while (!IsListEmpty (&mScheduledQueue)) {\r
879 DriverEntry = CR (\r
880 mScheduledQueue.ForwardLink,\r
881 EFI_SMM_DRIVER_ENTRY,\r
882 ScheduledLink,\r
883 EFI_SMM_DRIVER_ENTRY_SIGNATURE\r
884 );\r
885\r
886 //\r
887 // Load the SMM Driver image into memory. If the Driver was transitioned from\r
888 // Untrused to Scheduled it would have already been loaded so we may need to\r
889 // skip the LoadImage\r
890 //\r
891 if (DriverEntry->ImageHandle == NULL) {\r
892 Status = SmmLoadImage (DriverEntry);\r
893\r
894 //\r
895 // Update the driver state to reflect that it's been loaded\r
896 //\r
897 if (EFI_ERROR (Status)) {\r
fa542a1e 898 //\r
899 // The SMM Driver could not be loaded, and do not attempt to load or start it again.\r
900 // Take driver from Scheduled to Initialized.\r
901 //\r
1436aea4
MK
902 DriverEntry->Initialized = TRUE;\r
903 DriverEntry->Scheduled = FALSE;\r
e42e9404 904 RemoveEntryList (&DriverEntry->ScheduledLink);\r
905\r
906 //\r
907 // If it's an error don't try the StartImage\r
908 //\r
909 continue;\r
910 }\r
911 }\r
912\r
1436aea4
MK
913 DriverEntry->Scheduled = FALSE;\r
914 DriverEntry->Initialized = TRUE;\r
e42e9404 915 RemoveEntryList (&DriverEntry->ScheduledLink);\r
916\r
917 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
918 EFI_PROGRESS_CODE,\r
919 EFI_SOFTWARE_SMM_DRIVER | EFI_SW_PC_INIT_BEGIN,\r
920 &DriverEntry->ImageHandle,\r
921 sizeof (DriverEntry->ImageHandle)\r
922 );\r
923\r
5657b268 924 //\r
925 // Cache state of SmmEntryPointRegistered before calling entry point\r
926 //\r
927 PreviousSmmEntryPointRegistered = gSmmCorePrivate->SmmEntryPointRegistered;\r
928\r
e42e9404 929 //\r
930 // For each SMM driver, pass NULL as ImageHandle\r
931 //\r
84edd20b 932 RegisterSmramProfileImage (DriverEntry, TRUE);\r
67e9ab84 933 PERF_START_IMAGE_BEGIN (DriverEntry->ImageHandle);\r
e42e9404 934 Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, gST);\r
67e9ab84 935 PERF_START_IMAGE_END (DriverEntry->ImageHandle);\r
1436aea4 936 if (EFI_ERROR (Status)) {\r
a1ddad95
LE
937 DEBUG ((\r
938 DEBUG_ERROR,\r
939 "Error: SMM image at %11p start failed: %r\n",\r
940 DriverEntry->SmmLoadedImage.ImageBase,\r
941 Status\r
942 ));\r
84edd20b 943 UnregisterSmramProfileImage (DriverEntry, TRUE);\r
1436aea4 944 SmmFreePages (DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);\r
02f02b16
JY
945 //\r
946 // Uninstall LoadedImage\r
947 //\r
948 Status = gBS->UninstallProtocolInterface (\r
949 DriverEntry->ImageHandle,\r
950 &gEfiLoadedImageProtocolGuid,\r
951 DriverEntry->LoadedImage\r
952 );\r
953 if (!EFI_ERROR (Status)) {\r
954 if (DriverEntry->LoadedImage->FilePath != NULL) {\r
955 gBS->FreePool (DriverEntry->LoadedImage->FilePath);\r
956 }\r
1436aea4 957\r
02f02b16
JY
958 gBS->FreePool (DriverEntry->LoadedImage);\r
959 }\r
1436aea4 960\r
285a682c
JY
961 Status = SmmUninstallProtocolInterface (\r
962 DriverEntry->SmmImageHandle,\r
963 &gEfiLoadedImageProtocolGuid,\r
964 &DriverEntry->SmmLoadedImage\r
965 );\r
1436aea4 966 if (!EFI_ERROR (Status)) {\r
285a682c
JY
967 if (DriverEntry->SmmLoadedImage.FilePath != NULL) {\r
968 SmmFreePool (DriverEntry->SmmLoadedImage.FilePath);\r
969 }\r
970 }\r
e42e9404 971 }\r
972\r
973 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
974 EFI_PROGRESS_CODE,\r
975 EFI_SOFTWARE_SMM_DRIVER | EFI_SW_PC_INIT_END,\r
976 &DriverEntry->ImageHandle,\r
977 sizeof (DriverEntry->ImageHandle)\r
978 );\r
979\r
5657b268 980 if (!PreviousSmmEntryPointRegistered && gSmmCorePrivate->SmmEntryPointRegistered) {\r
981 //\r
d1102dba 982 // Return immediately if the SMM Entry Point was registered by the SMM\r
5657b268 983 // Driver that was just dispatched. The SMM IPL will reinvoke the SMM\r
d1102dba
LG
984 // Core Dispatcher. This is required so SMM Mode may be enabled as soon\r
985 // as all the dependent SMM Drivers for SMM Mode have been dispatched.\r
986 // Once the SMM Entry Point has been registered, then SMM Mode will be\r
5657b268 987 // used.\r
988 //\r
1436aea4 989 gRequestDispatch = TRUE;\r
5657b268 990 gDispatcherRunning = FALSE;\r
991 return EFI_NOT_READY;\r
992 }\r
e42e9404 993 }\r
994\r
995 //\r
996 // Search DriverList for items to place on Scheduled Queue\r
997 //\r
998 ReadyToRun = FALSE;\r
999 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
1000 DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);\r
1001\r
1436aea4 1002 if (DriverEntry->DepexProtocolError) {\r
e42e9404 1003 //\r
1004 // If Section Extraction Protocol did not let the Depex be read before retry the read\r
1005 //\r
1006 Status = SmmGetDepexSectionAndPreProccess (DriverEntry);\r
1007 }\r
1008\r
1009 if (DriverEntry->Dependent) {\r
1010 if (SmmIsSchedulable (DriverEntry)) {\r
1011 SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
1012 ReadyToRun = TRUE;\r
1013 }\r
1014 }\r
1015 }\r
1016 } while (ReadyToRun);\r
1017\r
1018 //\r
1019 // If there is no more SMM driver to dispatch, stop the dispatch request\r
1020 //\r
1021 gRequestDispatch = FALSE;\r
1022 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
1023 DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);\r
1024\r
1436aea4 1025 if (!DriverEntry->Initialized) {\r
e42e9404 1026 //\r
1027 // We have SMM driver pending to dispatch\r
1028 //\r
1029 gRequestDispatch = TRUE;\r
1030 break;\r
1031 }\r
1032 }\r
1033\r
1034 gDispatcherRunning = FALSE;\r
1035\r
5657b268 1036 return EFI_SUCCESS;\r
e42e9404 1037}\r
1038\r
1039/**\r
1040 Insert InsertedDriverEntry onto the mScheduledQueue. To do this you\r
1041 must add any driver with a before dependency on InsertedDriverEntry first.\r
1042 You do this by recursively calling this routine. After all the Befores are\r
1043 processed you can add InsertedDriverEntry to the mScheduledQueue.\r
1044 Then you can add any driver with an After dependency on InsertedDriverEntry\r
1045 by recursively calling this routine.\r
1046\r
1047 @param InsertedDriverEntry The driver to insert on the ScheduledLink Queue\r
1048\r
1049**/\r
1050VOID\r
1051SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (\r
1436aea4 1052 IN EFI_SMM_DRIVER_ENTRY *InsertedDriverEntry\r
e42e9404 1053 )\r
1054{\r
1055 LIST_ENTRY *Link;\r
1436aea4 1056 EFI_SMM_DRIVER_ENTRY *DriverEntry;\r
e42e9404 1057\r
1058 //\r
1059 // Process Before Dependency\r
1060 //\r
1061 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
1436aea4
MK
1062 DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);\r
1063 if (DriverEntry->Before && DriverEntry->Dependent && (DriverEntry != InsertedDriverEntry)) {\r
6a55eea3 1064 DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
1065 DEBUG ((DEBUG_DISPATCH, " BEFORE FFS(%g) = ", &DriverEntry->BeforeAfterGuid));\r
e42e9404 1066 if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
1067 //\r
1068 // Recursively process BEFORE\r
1069 //\r
6a55eea3 1070 DEBUG ((DEBUG_DISPATCH, "TRUE\n END\n RESULT = TRUE\n"));\r
e42e9404 1071 SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
6a55eea3 1072 } else {\r
1073 DEBUG ((DEBUG_DISPATCH, "FALSE\n END\n RESULT = FALSE\n"));\r
e42e9404 1074 }\r
1075 }\r
1076 }\r
1077\r
1078 //\r
1079 // Convert driver from Dependent to Scheduled state\r
1080 //\r
1081\r
1082 InsertedDriverEntry->Dependent = FALSE;\r
1083 InsertedDriverEntry->Scheduled = TRUE;\r
1084 InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);\r
1085\r
e42e9404 1086 //\r
1087 // Process After Dependency\r
1088 //\r
1089 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
1436aea4
MK
1090 DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);\r
1091 if (DriverEntry->After && DriverEntry->Dependent && (DriverEntry != InsertedDriverEntry)) {\r
6a55eea3 1092 DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
1093 DEBUG ((DEBUG_DISPATCH, " AFTER FFS(%g) = ", &DriverEntry->BeforeAfterGuid));\r
e42e9404 1094 if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
1095 //\r
1096 // Recursively process AFTER\r
1097 //\r
6a55eea3 1098 DEBUG ((DEBUG_DISPATCH, "TRUE\n END\n RESULT = TRUE\n"));\r
e42e9404 1099 SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
6a55eea3 1100 } else {\r
1101 DEBUG ((DEBUG_DISPATCH, "FALSE\n END\n RESULT = FALSE\n"));\r
e42e9404 1102 }\r
1103 }\r
1104 }\r
1105}\r
1106\r
1107/**\r
1108 Return TRUE if the Fv has been processed, FALSE if not.\r
1109\r
1110 @param FvHandle The handle of a FV that's being tested\r
1111\r
1112 @retval TRUE Fv protocol on FvHandle has been processed\r
1113 @retval FALSE Fv protocol on FvHandle has not yet been\r
1114 processed\r
1115\r
1116**/\r
1117BOOLEAN\r
1118FvHasBeenProcessed (\r
1119 IN EFI_HANDLE FvHandle\r
1120 )\r
1121{\r
1122 LIST_ENTRY *Link;\r
1123 KNOWN_HANDLE *KnownHandle;\r
1124\r
1125 for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {\r
1436aea4 1126 KnownHandle = CR (Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);\r
e42e9404 1127 if (KnownHandle->Handle == FvHandle) {\r
1128 return TRUE;\r
1129 }\r
1130 }\r
1436aea4 1131\r
e42e9404 1132 return FALSE;\r
1133}\r
1134\r
1135/**\r
4be497df
AC
1136 Remember that Fv protocol on FvHandle has had its drivers placed on the\r
1137 mDiscoveredList. This function adds entries on the mFvHandleList. Items are\r
e42e9404 1138 never removed/freed from the mFvHandleList.\r
1139\r
1140 @param FvHandle The handle of a FV that has been processed\r
1141\r
1142**/\r
1143VOID\r
d4fa02a8 1144FvIsBeingProcessed (\r
e42e9404 1145 IN EFI_HANDLE FvHandle\r
1146 )\r
1147{\r
1148 KNOWN_HANDLE *KnownHandle;\r
1149\r
1150 KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE));\r
1151 ASSERT (KnownHandle != NULL);\r
1152\r
1153 KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;\r
1436aea4 1154 KnownHandle->Handle = FvHandle;\r
e42e9404 1155 InsertTailList (&mFvHandleList, &KnownHandle->Link);\r
1156}\r
1157\r
1158/**\r
1159 Convert FvHandle and DriverName into an EFI device path\r
1160\r
1161 @param Fv Fv protocol, needed to read Depex info out of\r
1162 FLASH.\r
1163 @param FvHandle Handle for Fv, needed in the\r
1164 EFI_SMM_DRIVER_ENTRY so that the PE image can be\r
1165 read out of the FV at a later time.\r
1166 @param DriverName Name of driver to add to mDiscoveredList.\r
1167\r
1168 @return Pointer to device path constructed from FvHandle and DriverName\r
1169\r
1170**/\r
1171EFI_DEVICE_PATH_PROTOCOL *\r
1172SmmFvToDevicePath (\r
1436aea4
MK
1173 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,\r
1174 IN EFI_HANDLE FvHandle,\r
1175 IN EFI_GUID *DriverName\r
e42e9404 1176 )\r
1177{\r
1436aea4
MK
1178 EFI_STATUS Status;\r
1179 EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;\r
1180 EFI_DEVICE_PATH_PROTOCOL *FileNameDevicePath;\r
e42e9404 1181\r
1182 //\r
1183 // Remember the device path of the FV\r
1184 //\r
1185 Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);\r
1186 if (EFI_ERROR (Status)) {\r
1187 FileNameDevicePath = NULL;\r
1188 } else {\r
1189 //\r
1190 // Build a device path to the file in the FV to pass into gBS->LoadImage\r
1191 //\r
1192 EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);\r
1193 SetDevicePathEndNode (&mFvDevicePath.End);\r
1194\r
1195 //\r
1196 // Note: FileNameDevicePath is in DXE memory\r
1197 //\r
1198 FileNameDevicePath = AppendDevicePath (\r
1436aea4
MK
1199 FvDevicePath,\r
1200 (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath\r
1201 );\r
e42e9404 1202 }\r
1436aea4 1203\r
e42e9404 1204 return FileNameDevicePath;\r
1205}\r
1206\r
1207/**\r
1208 Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,\r
4be497df 1209 and initialize any state variables. Read the Depex from the FV and store it\r
fa542a1e 1210 in DriverEntry. Pre-process the Depex to set the Before and After state.\r
e42e9404 1211 The Discovered list is never free'ed and contains booleans that represent the\r
1212 other possible SMM driver states.\r
1213\r
1214 @param Fv Fv protocol, needed to read Depex info out of\r
1215 FLASH.\r
1216 @param FvHandle Handle for Fv, needed in the\r
1217 EFI_SMM_DRIVER_ENTRY so that the PE image can be\r
1218 read out of the FV at a later time.\r
1219 @param DriverName Name of driver to add to mDiscoveredList.\r
1220\r
1221 @retval EFI_SUCCESS If driver was added to the mDiscoveredList.\r
1222 @retval EFI_ALREADY_STARTED The driver has already been started. Only one\r
1223 DriverName may be active in the system at any one\r
1224 time.\r
1225\r
1226**/\r
1227EFI_STATUS\r
1228SmmAddToDriverList (\r
1229 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,\r
1230 IN EFI_HANDLE FvHandle,\r
1231 IN EFI_GUID *DriverName\r
1232 )\r
1233{\r
1234 EFI_SMM_DRIVER_ENTRY *DriverEntry;\r
1235\r
1236 //\r
1237 // Create the Driver Entry for the list. ZeroPool initializes lots of variables to\r
1238 // NULL or FALSE.\r
1239 //\r
1240 DriverEntry = AllocateZeroPool (sizeof (EFI_SMM_DRIVER_ENTRY));\r
1241 ASSERT (DriverEntry != NULL);\r
1242\r
1436aea4 1243 DriverEntry->Signature = EFI_SMM_DRIVER_ENTRY_SIGNATURE;\r
e42e9404 1244 CopyGuid (&DriverEntry->FileName, DriverName);\r
1245 DriverEntry->FvHandle = FvHandle;\r
1246 DriverEntry->Fv = Fv;\r
1247 DriverEntry->FvFileDevicePath = SmmFvToDevicePath (Fv, FvHandle, DriverName);\r
1248\r
1249 SmmGetDepexSectionAndPreProccess (DriverEntry);\r
1250\r
1251 InsertTailList (&mDiscoveredList, &DriverEntry->Link);\r
1252 gRequestDispatch = TRUE;\r
1253\r
1254 return EFI_SUCCESS;\r
1255}\r
1256\r
1257/**\r
1258 This function is the main entry point for an SMM handler dispatch\r
1259 or communicate-based callback.\r
1260\r
1261 Event notification that is fired every time a FV dispatch protocol is added.\r
1262 More than one protocol may have been added when this event is fired, so you\r
1263 must loop on SmmLocateHandle () to see how many protocols were added and\r
1264 do the following to each FV:\r
1265 If the Fv has already been processed, skip it. If the Fv has not been\r
1266 processed then mark it as being processed, as we are about to process it.\r
1267 Read the Fv and add any driver in the Fv to the mDiscoveredList.The\r
1268 mDiscoveredList is never free'ed and contains variables that define\r
1269 the other states the SMM driver transitions to..\r
1270 While you are at it read the A Priori file into memory.\r
1271 Place drivers in the A Priori list onto the mScheduledQueue.\r
1272\r
1273 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
1274 @param Context Points to an optional handler context which was specified when the handler was registered.\r
1275 @param CommBuffer A pointer to a collection of data in memory that will\r
1276 be conveyed from a non-SMM environment into an SMM environment.\r
1277 @param CommBufferSize The size of the CommBuffer.\r
1278\r
1279 @return Status Code\r
1280\r
1281**/\r
1282EFI_STATUS\r
1283EFIAPI\r
1284SmmDriverDispatchHandler (\r
1285 IN EFI_HANDLE DispatchHandle,\r
e3917e22
MK
1286 IN CONST VOID *Context OPTIONAL,\r
1287 IN OUT VOID *CommBuffer OPTIONAL,\r
e42e9404 1288 IN OUT UINTN *CommBufferSize OPTIONAL\r
1289 )\r
1290{\r
1436aea4
MK
1291 EFI_STATUS Status;\r
1292 UINTN HandleCount;\r
1293 EFI_HANDLE *HandleBuffer;\r
1294 EFI_STATUS GetNextFileStatus;\r
1295 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
1296 EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;\r
1297 EFI_HANDLE FvHandle;\r
1298 EFI_GUID NameGuid;\r
1299 UINTN Key;\r
1300 EFI_FV_FILETYPE Type;\r
1301 EFI_FV_FILE_ATTRIBUTES Attributes;\r
1302 UINTN Size;\r
1303 EFI_SMM_DRIVER_ENTRY *DriverEntry;\r
1304 EFI_GUID *AprioriFile;\r
1305 UINTN AprioriEntryCount;\r
1306 UINTN HandleIndex;\r
1307 UINTN SmmTypeIndex;\r
1308 UINTN AprioriIndex;\r
1309 LIST_ENTRY *Link;\r
1310 UINT32 AuthenticationStatus;\r
1311 UINTN SizeOfBuffer;\r
e42e9404 1312\r
1313 HandleBuffer = NULL;\r
1436aea4
MK
1314 Status = gBS->LocateHandleBuffer (\r
1315 ByProtocol,\r
1316 &gEfiFirmwareVolume2ProtocolGuid,\r
1317 NULL,\r
1318 &HandleCount,\r
1319 &HandleBuffer\r
1320 );\r
e42e9404 1321 if (EFI_ERROR (Status)) {\r
1322 return EFI_NOT_FOUND;\r
1323 }\r
1324\r
5d832d62
ZB
1325 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
1326 FvHandle = HandleBuffer[HandleIndex];\r
e42e9404 1327\r
1328 if (FvHasBeenProcessed (FvHandle)) {\r
1329 //\r
1330 // This Fv has already been processed so lets skip it!\r
1331 //\r
1332 continue;\r
1333 }\r
1334\r
1335 //\r
1336 // Since we are about to process this Fv mark it as processed.\r
1337 //\r
d4fa02a8 1338 FvIsBeingProcessed (FvHandle);\r
e42e9404 1339\r
1340 Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);\r
1341 if (EFI_ERROR (Status)) {\r
1342 //\r
1343 // FvHandle must have a Firmware Volume2 Protocol thus we should never get here.\r
1344 //\r
1345 ASSERT (FALSE);\r
1346 continue;\r
1347 }\r
1348\r
1349 Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);\r
1350 if (EFI_ERROR (Status)) {\r
1351 //\r
1352 // The Firmware volume doesn't have device path, can't be dispatched.\r
1353 //\r
1354 continue;\r
1355 }\r
1356\r
e42e9404 1357 //\r
1358 // Discover Drivers in FV and add them to the Discovered Driver List.\r
1359 // Process EFI_FV_FILETYPE_SMM type and then EFI_FV_FILETYPE_COMBINED_SMM_DXE\r
0b256fb1 1360 // EFI_FV_FILETYPE_SMM_CORE is processed to produce a Loaded Image protocol for the core\r
e42e9404 1361 //\r
5d832d62 1362 for (SmmTypeIndex = 0; SmmTypeIndex < sizeof (mSmmFileTypes)/sizeof (EFI_FV_FILETYPE); SmmTypeIndex++) {\r
e42e9404 1363 //\r
1364 // Initialize the search key\r
1365 //\r
1366 Key = 0;\r
1367 do {\r
1436aea4 1368 Type = mSmmFileTypes[SmmTypeIndex];\r
e42e9404 1369 GetNextFileStatus = Fv->GetNextFile (\r
1370 Fv,\r
1371 &Key,\r
1372 &Type,\r
1373 &NameGuid,\r
1374 &Attributes,\r
1375 &Size\r
1376 );\r
1377 if (!EFI_ERROR (GetNextFileStatus)) {\r
0b256fb1
JY
1378 if (Type == EFI_FV_FILETYPE_SMM_CORE) {\r
1379 //\r
1380 // If this is the SMM core fill in it's DevicePath & DeviceHandle\r
1381 //\r
1382 if (mSmmCoreLoadedImage->FilePath == NULL) {\r
1383 //\r
1384 // Maybe one special FV contains only one SMM_CORE module, so its device path must\r
1385 // be initialized completely.\r
1386 //\r
1387 EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);\r
1388 SetDevicePathEndNode (&mFvDevicePath.End);\r
1389\r
1390 //\r
1391 // Make an EfiBootServicesData buffer copy of FilePath\r
1392 //\r
1393 Status = gBS->AllocatePool (\r
1394 EfiBootServicesData,\r
1395 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath),\r
1396 (VOID **)&mSmmCoreLoadedImage->FilePath\r
1397 );\r
1398 ASSERT_EFI_ERROR (Status);\r
1399 CopyMem (mSmmCoreLoadedImage->FilePath, &mFvDevicePath, GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath));\r
1400\r
1401 mSmmCoreLoadedImage->DeviceHandle = FvHandle;\r
1402 }\r
1436aea4 1403\r
285a682c
JY
1404 if (mSmmCoreDriverEntry->SmmLoadedImage.FilePath == NULL) {\r
1405 //\r
1406 // Maybe one special FV contains only one SMM_CORE module, so its device path must\r
1407 // be initialized completely.\r
1408 //\r
1409 EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);\r
1410 SetDevicePathEndNode (&mFvDevicePath.End);\r
1411\r
1412 //\r
1413 // Make a buffer copy FilePath\r
1414 //\r
1415 Status = SmmAllocatePool (\r
1416 EfiRuntimeServicesData,\r
1417 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath),\r
1418 (VOID **)&mSmmCoreDriverEntry->SmmLoadedImage.FilePath\r
1419 );\r
1420 ASSERT_EFI_ERROR (Status);\r
1436aea4 1421 CopyMem (mSmmCoreDriverEntry->SmmLoadedImage.FilePath, &mFvDevicePath, GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath));\r
285a682c
JY
1422\r
1423 mSmmCoreDriverEntry->SmmLoadedImage.DeviceHandle = FvHandle;\r
1424 }\r
0b256fb1
JY
1425 } else {\r
1426 SmmAddToDriverList (Fv, FvHandle, &NameGuid);\r
1427 }\r
e42e9404 1428 }\r
1429 } while (!EFI_ERROR (GetNextFileStatus));\r
1430 }\r
1431\r
1432 //\r
1433 // Read the array of GUIDs from the Apriori file if it is present in the firmware volume\r
1434 // (Note: AprioriFile is in DXE memory)\r
1435 //\r
1436 AprioriFile = NULL;\r
1436aea4
MK
1437 Status = Fv->ReadSection (\r
1438 Fv,\r
1439 &gAprioriGuid,\r
1440 EFI_SECTION_RAW,\r
1441 0,\r
1442 (VOID **)&AprioriFile,\r
1443 &SizeOfBuffer,\r
1444 &AuthenticationStatus\r
1445 );\r
e42e9404 1446 if (!EFI_ERROR (Status)) {\r
1447 AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);\r
1448 } else {\r
1449 AprioriEntryCount = 0;\r
1450 }\r
1451\r
1452 //\r
1453 // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes\r
1454 // drivers not in the current FV and these must be skipped since the a priori list\r
1455 // is only valid for the FV that it resided in.\r
1456 //\r
1457\r
5d832d62 1458 for (AprioriIndex = 0; AprioriIndex < AprioriEntryCount; AprioriIndex++) {\r
e42e9404 1459 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
1436aea4 1460 DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);\r
5d832d62 1461 if (CompareGuid (&DriverEntry->FileName, &AprioriFile[AprioriIndex]) &&\r
1436aea4
MK
1462 (FvHandle == DriverEntry->FvHandle))\r
1463 {\r
e42e9404 1464 DriverEntry->Dependent = FALSE;\r
1465 DriverEntry->Scheduled = TRUE;\r
1466 InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);\r
6a55eea3 1467 DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
1468 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));\r
e42e9404 1469 break;\r
1470 }\r
1471 }\r
1472 }\r
1473\r
1474 //\r
1475 // Free data allocated by Fv->ReadSection ()\r
1476 //\r
d1102dba 1477 // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection\r
e42e9404 1478 // used the UEFI Boot Services AllocatePool() function\r
1479 //\r
1480 gBS->FreePool (AprioriFile);\r
1481 }\r
1482\r
1483 //\r
d1102dba 1484 // Execute the SMM Dispatcher on any newly discovered FVs and previously\r
e42e9404 1485 // discovered SMM drivers that have been discovered but not dispatched.\r
1486 //\r
5657b268 1487 Status = SmmDispatcher ();\r
1488\r
1489 //\r
1490 // Check to see if CommBuffer and CommBufferSize are valid\r
1491 //\r
1436aea4 1492 if ((CommBuffer != NULL) && (CommBufferSize != NULL)) {\r
5657b268 1493 if (*CommBufferSize > 0) {\r
1494 if (Status == EFI_NOT_READY) {\r
1495 //\r
d1102dba 1496 // If a the SMM Core Entry Point was just registered, then set flag to\r
5657b268 1497 // request the SMM Dispatcher to be restarted.\r
1498 //\r
1499 *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_RESTART;\r
1500 } else if (!EFI_ERROR (Status)) {\r
1501 //\r
1502 // Set the flag to show that the SMM Dispatcher executed without errors\r
1503 //\r
1504 *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_SUCCESS;\r
1505 } else {\r
1506 //\r
1507 // Set the flag to show that the SMM Dispatcher encountered an error\r
1508 //\r
1509 *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_ERROR;\r
1510 }\r
1511 }\r
1512 }\r
1513\r
1514 return EFI_SUCCESS;\r
e42e9404 1515}\r
1516\r
1517/**\r
1518 Traverse the discovered list for any drivers that were discovered but not loaded\r
4be497df 1519 because the dependency expressions evaluated to false.\r
e42e9404 1520\r
1521**/\r
1522VOID\r
1523SmmDisplayDiscoveredNotDispatched (\r
1524 VOID\r
1525 )\r
1526{\r
1436aea4
MK
1527 LIST_ENTRY *Link;\r
1528 EFI_SMM_DRIVER_ENTRY *DriverEntry;\r
e42e9404 1529\r
1436aea4
MK
1530 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
1531 DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);\r
e42e9404 1532 if (DriverEntry->Dependent) {\r
1533 DEBUG ((DEBUG_LOAD, "SMM Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));\r
1534 }\r
1535 }\r
1536}\r