]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c
MdeModulePkg: Change OPTIONAL keyword usage style
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmiHandlerProfile.c
CommitLineData
ca41f3f4
JY
1/** @file\r
2 SMI handler profile support.\r
3\r
4Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
ca41f3f4
JY
6\r
7**/\r
8\r
9#include <PiSmm.h>\r
10#include <Library/BaseLib.h>\r
11#include <Library/BaseMemoryLib.h>\r
12#include <Library/MemoryAllocationLib.h>\r
13#include <Library/UefiBootServicesTableLib.h>\r
14#include <Library/SmmServicesTableLib.h>\r
15#include <Library/DebugLib.h>\r
16#include <Library/PrintLib.h>\r
17#include <Library/UefiLib.h>\r
18#include <Library/DevicePathLib.h>\r
19#include <Library/PeCoffGetEntryPointLib.h>\r
ca41f3f4
JY
20#include <Protocol/LoadedImage.h>\r
21#include <Protocol/SmmAccess2.h>\r
22#include <Protocol/SmmReadyToLock.h>\r
23#include <Protocol/SmmEndOfDxe.h>\r
24\r
25#include <Guid/SmiHandlerProfile.h>\r
26\r
27#include "PiSmmCore.h"\r
28\r
f2485395
SZ
29#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \\r
30 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))\r
31\r
ca41f3f4 32typedef struct {\r
f2485395
SZ
33 EFI_GUID FileGuid;\r
34 PHYSICAL_ADDRESS EntryPoint;\r
35 PHYSICAL_ADDRESS ImageBase;\r
36 UINT64 ImageSize;\r
37 UINT32 ImageRef;\r
38 UINT16 PdbStringSize;\r
39 CHAR8 *PdbString;\r
ca41f3f4
JY
40} IMAGE_STRUCT;\r
41\r
42/**\r
43 Register SMI handler profile handler.\r
44**/\r
45VOID\r
46RegisterSmiHandlerProfileHandler(\r
47 VOID\r
48 );\r
49\r
50/**\r
51 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded\r
52 into system memory with the PE/COFF Loader Library functions.\r
53\r
54 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry\r
55 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then\r
56 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.\r
57 If Pe32Data is NULL, then ASSERT().\r
58 If EntryPoint is NULL, then ASSERT().\r
59\r
60 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.\r
61 @param EntryPoint The pointer to entry point to the PE/COFF image to return.\r
62\r
63 @retval RETURN_SUCCESS EntryPoint was returned.\r
64 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.\r
65\r
66**/\r
67RETURN_STATUS\r
68InternalPeCoffGetEntryPoint (\r
69 IN VOID *Pe32Data,\r
70 OUT VOID **EntryPoint\r
71 );\r
72\r
73extern LIST_ENTRY mSmiEntryList;\r
74extern LIST_ENTRY mHardwareSmiEntryList;\r
75extern SMI_ENTRY mRootSmiEntry;\r
76\r
77extern SMI_HANDLER_PROFILE_PROTOCOL mSmiHandlerProfile;\r
78\r
79GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mHardwareSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mHardwareSmiEntryList);\r
80\r
81GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mRootSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiEntryList);\r
82\r
83GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY *mSmmCoreRootSmiEntryList = &mRootSmiEntryList;\r
84GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY *mSmmCoreSmiEntryList = &mSmiEntryList;\r
85GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY *mSmmCoreHardwareSmiEntryList = &mHardwareSmiEntryList;\r
86\r
87GLOBAL_REMOVE_IF_UNREFERENCED IMAGE_STRUCT *mImageStruct;\r
f2485395
SZ
88GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mImageStructCountMax;\r
89GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mImageStructCount;\r
ca41f3f4
JY
90\r
91GLOBAL_REMOVE_IF_UNREFERENCED VOID *mSmiHandlerProfileDatabase;\r
92GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmiHandlerProfileDatabaseSize;\r
93\r
94GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmImageDatabaseSize;\r
95GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmRootSmiDatabaseSize;\r
96GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmSmiDatabaseSize;\r
97GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmmHardwareSmiDatabaseSize;\r
98\r
99GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmiHandlerProfileRecordingStatus;\r
100\r
101GLOBAL_REMOVE_IF_UNREFERENCED SMI_HANDLER_PROFILE_PROTOCOL mSmiHandlerProfile = {\r
102 SmiHandlerProfileRegisterHandler,\r
103 SmiHandlerProfileUnregisterHandler,\r
104};\r
105\r
106/**\r
107 This function dump raw data.\r
108\r
109 @param Data raw data\r
110 @param Size raw data size\r
111**/\r
112VOID\r
113InternalDumpData (\r
114 IN UINT8 *Data,\r
115 IN UINTN Size\r
116 )\r
117{\r
118 UINTN Index;\r
119 for (Index = 0; Index < Size; Index++) {\r
120 DEBUG ((DEBUG_INFO, "%02x ", (UINTN)Data[Index]));\r
121 }\r
122}\r
123\r
124/**\r
125 Get GUID name for an image.\r
126\r
127 @param[in] LoadedImage LoadedImage protocol.\r
128 @param[out] Guid Guid of the FFS\r
129**/\r
130VOID\r
131GetDriverGuid (\r
132 IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,\r
133 OUT EFI_GUID *Guid\r
134 )\r
135{\r
136 EFI_GUID *FileName;\r
137\r
138 FileName = NULL;\r
139 if ((DevicePathType(LoadedImage->FilePath) == MEDIA_DEVICE_PATH) &&\r
140 (DevicePathSubType(LoadedImage->FilePath) == MEDIA_PIWG_FW_FILE_DP)) {\r
141 FileName = &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LoadedImage->FilePath)->FvFileName;\r
142 }\r
143 if (FileName != NULL) {\r
144 CopyGuid(Guid, FileName);\r
145 } else {\r
146 ZeroMem(Guid, sizeof(EFI_GUID));\r
147 }\r
148}\r
149\r
150/**\r
151 Add image structure.\r
152\r
153 @param ImageBase image base\r
154 @param ImageSize image size\r
155 @param EntryPoint image entry point\r
156 @param Guid FFS GUID of the image\r
157 @param PdbString image PDB string\r
158**/\r
159VOID\r
160AddImageStruct(\r
f2485395
SZ
161 IN PHYSICAL_ADDRESS ImageBase,\r
162 IN UINT64 ImageSize,\r
163 IN PHYSICAL_ADDRESS EntryPoint,\r
164 IN EFI_GUID *Guid,\r
165 IN CHAR8 *PdbString\r
ca41f3f4
JY
166 )\r
167{\r
168 UINTN PdbStringSize;\r
169\r
170 if (mImageStructCount >= mImageStructCountMax) {\r
171 ASSERT(FALSE);\r
172 return;\r
173 }\r
174\r
175 CopyGuid(&mImageStruct[mImageStructCount].FileGuid, Guid);\r
176 mImageStruct[mImageStructCount].ImageRef = mImageStructCount;\r
177 mImageStruct[mImageStructCount].ImageBase = ImageBase;\r
178 mImageStruct[mImageStructCount].ImageSize = ImageSize;\r
179 mImageStruct[mImageStructCount].EntryPoint = EntryPoint;\r
180 if (PdbString != NULL) {\r
181 PdbStringSize = AsciiStrSize(PdbString);\r
182 mImageStruct[mImageStructCount].PdbString = AllocateCopyPool (PdbStringSize, PdbString);\r
183 if (mImageStruct[mImageStructCount].PdbString != NULL) {\r
f2485395 184 mImageStruct[mImageStructCount].PdbStringSize = (UINT16) PdbStringSize;\r
ca41f3f4
JY
185 }\r
186 }\r
187\r
188 mImageStructCount++;\r
189}\r
190\r
191/**\r
192 return an image structure based upon image address.\r
193\r
194 @param Address image address\r
195\r
196 @return image structure\r
197**/\r
198IMAGE_STRUCT *\r
199AddressToImageStruct(\r
200 IN UINTN Address\r
201 )\r
202{\r
203 UINTN Index;\r
204\r
205 for (Index = 0; Index < mImageStructCount; Index++) {\r
206 if ((Address >= mImageStruct[Index].ImageBase) &&\r
207 (Address < mImageStruct[Index].ImageBase + mImageStruct[Index].ImageSize)) {\r
208 return &mImageStruct[Index];\r
209 }\r
210 }\r
211 return NULL;\r
212}\r
213\r
214/**\r
215 return an image reference index based upon image address.\r
216\r
217 @param Address image address\r
218\r
219 @return image reference index\r
220**/\r
f2485395 221UINT32\r
ca41f3f4
JY
222AddressToImageRef(\r
223 IN UINTN Address\r
224 )\r
225{\r
226 IMAGE_STRUCT *ImageStruct;\r
227\r
228 ImageStruct = AddressToImageStruct(Address);\r
229 if (ImageStruct != NULL) {\r
230 return ImageStruct->ImageRef;\r
231 }\r
f2485395 232 return (UINT32)-1;\r
ca41f3f4
JY
233}\r
234\r
235/**\r
236 Collect SMM image information based upon loaded image protocol.\r
237**/\r
238VOID\r
239GetSmmLoadedImage(\r
240 VOID\r
241 )\r
242{\r
243 EFI_STATUS Status;\r
244 UINTN NoHandles;\r
245 UINTN HandleBufferSize;\r
246 EFI_HANDLE *HandleBuffer;\r
247 UINTN Index;\r
248 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
249 CHAR16 *PathStr;\r
250 EFI_SMM_DRIVER_ENTRY *LoadedImagePrivate;\r
f2485395 251 PHYSICAL_ADDRESS EntryPoint;\r
ca41f3f4
JY
252 VOID *EntryPointInImage;\r
253 EFI_GUID Guid;\r
254 CHAR8 *PdbString;\r
f2485395 255 PHYSICAL_ADDRESS RealImageBase;\r
ca41f3f4
JY
256\r
257 HandleBufferSize = 0;\r
258 HandleBuffer = NULL;\r
259 Status = gSmst->SmmLocateHandle(\r
260 ByProtocol,\r
261 &gEfiLoadedImageProtocolGuid,\r
262 NULL,\r
263 &HandleBufferSize,\r
264 HandleBuffer\r
265 );\r
266 if (Status != EFI_BUFFER_TOO_SMALL) {\r
267 return;\r
268 }\r
269 HandleBuffer = AllocateZeroPool (HandleBufferSize);\r
270 if (HandleBuffer == NULL) {\r
271 return;\r
272 }\r
273 Status = gSmst->SmmLocateHandle(\r
274 ByProtocol,\r
275 &gEfiLoadedImageProtocolGuid,\r
276 NULL,\r
277 &HandleBufferSize,\r
278 HandleBuffer\r
279 );\r
280 if (EFI_ERROR(Status)) {\r
281 return;\r
282 }\r
283\r
284 NoHandles = HandleBufferSize/sizeof(EFI_HANDLE);\r
f2485395 285 mImageStructCountMax = (UINT32) NoHandles;\r
ca41f3f4
JY
286 mImageStruct = AllocateZeroPool(mImageStructCountMax * sizeof(IMAGE_STRUCT));\r
287 if (mImageStruct == NULL) {\r
288 goto Done;\r
289 }\r
290\r
291 for (Index = 0; Index < NoHandles; Index++) {\r
292 Status = gSmst->SmmHandleProtocol(\r
293 HandleBuffer[Index],\r
294 &gEfiLoadedImageProtocolGuid,\r
295 (VOID **)&LoadedImage\r
296 );\r
297 if (EFI_ERROR(Status)) {\r
298 continue;\r
299 }\r
300 PathStr = ConvertDevicePathToText(LoadedImage->FilePath, TRUE, TRUE);\r
301 GetDriverGuid(LoadedImage, &Guid);\r
302 DEBUG ((DEBUG_INFO, "Image: %g ", &Guid));\r
303\r
304 EntryPoint = 0;\r
305 LoadedImagePrivate = BASE_CR(LoadedImage, EFI_SMM_DRIVER_ENTRY, SmmLoadedImage);\r
306 RealImageBase = (UINTN)LoadedImage->ImageBase;\r
307 if (LoadedImagePrivate->Signature == EFI_SMM_DRIVER_ENTRY_SIGNATURE) {\r
f2485395
SZ
308 EntryPoint = LoadedImagePrivate->ImageEntryPoint;\r
309 if ((EntryPoint != 0) && ((EntryPoint < (UINTN)LoadedImage->ImageBase) || (EntryPoint >= ((UINTN)LoadedImage->ImageBase + LoadedImage->ImageSize)))) {\r
ca41f3f4
JY
310 //\r
311 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
312 // So patch ImageBuffer here to align the EntryPoint.\r
313 //\r
314 Status = InternalPeCoffGetEntryPoint(LoadedImage->ImageBase, &EntryPointInImage);\r
315 ASSERT_EFI_ERROR(Status);\r
316 RealImageBase = (UINTN)LoadedImage->ImageBase + EntryPoint - (UINTN)EntryPointInImage;\r
317 }\r
318 }\r
f2485395 319 DEBUG ((DEBUG_INFO, "(0x%lx - 0x%lx", RealImageBase, LoadedImage->ImageSize));\r
ca41f3f4 320 if (EntryPoint != 0) {\r
f2485395 321 DEBUG ((DEBUG_INFO, ", EntryPoint:0x%lx", EntryPoint));\r
ca41f3f4
JY
322 }\r
323 DEBUG ((DEBUG_INFO, ")\n"));\r
324\r
325 if (RealImageBase != 0) {\r
326 PdbString = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) RealImageBase);\r
327 DEBUG ((DEBUG_INFO, " pdb - %a\n", PdbString));\r
328 } else {\r
329 PdbString = NULL;\r
330 }\r
331 DEBUG ((DEBUG_INFO, " (%s)\n", PathStr));\r
332\r
f2485395 333 AddImageStruct(RealImageBase, LoadedImage->ImageSize, EntryPoint, &Guid, PdbString);\r
ca41f3f4
JY
334 }\r
335\r
336Done:\r
337 FreePool(HandleBuffer);\r
338 return;\r
339}\r
340\r
341/**\r
342 Dump SMI child context.\r
343\r
344 @param HandlerType the handler type\r
345 @param Context the handler context\r
346 @param ContextSize the handler context size\r
347**/\r
348VOID\r
349DumpSmiChildContext (\r
350 IN EFI_GUID *HandlerType,\r
351 IN VOID *Context,\r
352 IN UINTN ContextSize\r
353 )\r
354{\r
fb1c81a1
SZ
355 CHAR16 *Str;\r
356\r
ca41f3f4 357 if (CompareGuid (HandlerType, &gEfiSmmSwDispatch2ProtocolGuid)) {\r
f2485395 358 DEBUG ((DEBUG_INFO, " SwSmi - 0x%lx\n", ((SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT *)Context)->SwSmiInputValue));\r
ca41f3f4
JY
359 } else if (CompareGuid (HandlerType, &gEfiSmmSxDispatch2ProtocolGuid)) {\r
360 DEBUG ((DEBUG_INFO, " SxType - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Type));\r
361 DEBUG ((DEBUG_INFO, " SxPhase - 0x%x\n", ((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Phase));\r
362 } else if (CompareGuid (HandlerType, &gEfiSmmPowerButtonDispatch2ProtocolGuid)) {\r
363 DEBUG ((DEBUG_INFO, " PowerButtonPhase - 0x%x\n", ((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT *)Context)->Phase));\r
364 } else if (CompareGuid (HandlerType, &gEfiSmmStandbyButtonDispatch2ProtocolGuid)) {\r
365 DEBUG ((DEBUG_INFO, " StandbyButtonPhase - 0x%x\n", ((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT *)Context)->Phase));\r
366 } else if (CompareGuid (HandlerType, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid)) {\r
367 DEBUG ((DEBUG_INFO, " PeriodicTimerPeriod - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->Period));\r
368 DEBUG ((DEBUG_INFO, " PeriodicTimerSmiTickInterval - %ld\n", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->SmiTickInterval));\r
369 } else if (CompareGuid (HandlerType, &gEfiSmmGpiDispatch2ProtocolGuid)) {\r
370 DEBUG ((DEBUG_INFO, " GpiNum - 0x%lx\n", ((EFI_SMM_GPI_REGISTER_CONTEXT *)Context)->GpiNum));\r
371 } else if (CompareGuid (HandlerType, &gEfiSmmIoTrapDispatch2ProtocolGuid)) {\r
372 DEBUG ((DEBUG_INFO, " IoTrapAddress - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Address));\r
373 DEBUG ((DEBUG_INFO, " IoTrapLength - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Length));\r
374 DEBUG ((DEBUG_INFO, " IoTrapType - 0x%x\n", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Type));\r
375 } else if (CompareGuid (HandlerType, &gEfiSmmUsbDispatch2ProtocolGuid)) {\r
376 DEBUG ((DEBUG_INFO, " UsbType - 0x%x\n", ((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context)->Type));\r
fb1c81a1
SZ
377 Str = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL *)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context) + 1), TRUE, TRUE);\r
378 DEBUG ((DEBUG_INFO, " UsbDevicePath - %s\n", Str));\r
379 if (Str != NULL) {\r
380 FreePool (Str);\r
381 }\r
ca41f3f4
JY
382 } else {\r
383 DEBUG ((DEBUG_INFO, " Context - "));\r
384 InternalDumpData (Context, ContextSize);\r
385 DEBUG ((DEBUG_INFO, "\n"));\r
386 }\r
387}\r
388\r
389/**\r
390 Dump all SMI handlers associated with SmiEntry.\r
391\r
392 @param SmiEntry SMI entry.\r
393**/\r
394VOID\r
395DumpSmiHandlerOnSmiEntry(\r
396 IN SMI_ENTRY *SmiEntry\r
397 )\r
398{\r
399 LIST_ENTRY *ListEntry;\r
400 SMI_HANDLER *SmiHandler;\r
401 IMAGE_STRUCT *ImageStruct;\r
402\r
403 ListEntry = &SmiEntry->SmiHandlers;\r
404 for (ListEntry = ListEntry->ForwardLink;\r
405 ListEntry != &SmiEntry->SmiHandlers;\r
406 ListEntry = ListEntry->ForwardLink) {\r
407 SmiHandler = CR(ListEntry, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
408 ImageStruct = AddressToImageStruct((UINTN)SmiHandler->Handler);\r
409 if (ImageStruct != NULL) {\r
410 DEBUG ((DEBUG_INFO, " Module - %g", &ImageStruct->FileGuid));\r
411 }\r
412 if ((ImageStruct != NULL) && (ImageStruct->PdbString[0] != 0)) {\r
413 DEBUG ((DEBUG_INFO, " (Pdb - %a)", ImageStruct->PdbString));\r
414 }\r
415 DEBUG ((DEBUG_INFO, "\n"));\r
416 if (SmiHandler->ContextSize != 0) {\r
417 DumpSmiChildContext (&SmiEntry->HandlerType, SmiHandler->Context, SmiHandler->ContextSize);\r
418 }\r
419 DEBUG ((DEBUG_INFO, " Handler - 0x%x", SmiHandler->Handler));\r
420 if (ImageStruct != NULL) {\r
f2485395 421 DEBUG ((DEBUG_INFO, " <== RVA - 0x%x", (UINTN)SmiHandler->Handler - (UINTN) ImageStruct->ImageBase));\r
ca41f3f4
JY
422 }\r
423 DEBUG ((DEBUG_INFO, "\n"));\r
424 DEBUG ((DEBUG_INFO, " CallerAddr - 0x%x", SmiHandler->CallerAddr));\r
425 if (ImageStruct != NULL) {\r
f2485395 426 DEBUG ((DEBUG_INFO, " <== RVA - 0x%x", SmiHandler->CallerAddr - (UINTN) ImageStruct->ImageBase));\r
ca41f3f4
JY
427 }\r
428 DEBUG ((DEBUG_INFO, "\n"));\r
429 }\r
430\r
431 return;\r
432}\r
433\r
434/**\r
435 Dump all SMI entry on the list.\r
436\r
437 @param SmiEntryList a list of SMI entry.\r
438**/\r
439VOID\r
440DumpSmiEntryList(\r
441 IN LIST_ENTRY *SmiEntryList\r
442 )\r
443{\r
444 LIST_ENTRY *ListEntry;\r
445 SMI_ENTRY *SmiEntry;\r
446\r
447 ListEntry = SmiEntryList;\r
448 for (ListEntry = ListEntry->ForwardLink;\r
449 ListEntry != SmiEntryList;\r
450 ListEntry = ListEntry->ForwardLink) {\r
451 SmiEntry = CR(ListEntry, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);\r
452 DEBUG ((DEBUG_INFO, "SmiEntry - %g\n", &SmiEntry->HandlerType));\r
453 DumpSmiHandlerOnSmiEntry(SmiEntry);\r
454 }\r
455\r
456 return;\r
457}\r
458\r
459/**\r
460 SMM Ready To Lock event notification handler.\r
461\r
462 This function collects all SMM image information and build SmiHandleProfile database,\r
463 and register SmiHandlerProfile SMI handler.\r
464\r
465 @param[in] Protocol Points to the protocol's unique identifier.\r
466 @param[in] Interface Points to the interface instance.\r
467 @param[in] Handle The handle on which the interface was installed.\r
468\r
469 @retval EFI_SUCCESS Notification handler runs successfully.\r
470**/\r
471EFI_STATUS\r
472EFIAPI\r
473SmmReadyToLockInSmiHandlerProfile (\r
474 IN CONST EFI_GUID *Protocol,\r
475 IN VOID *Interface,\r
476 IN EFI_HANDLE Handle\r
477 )\r
478{\r
479 //\r
480 // Dump all image\r
481 //\r
482 DEBUG ((DEBUG_INFO, "##################\n"));\r
483 DEBUG ((DEBUG_INFO, "# IMAGE DATABASE #\n"));\r
484 DEBUG ((DEBUG_INFO, "##################\n"));\r
485 GetSmmLoadedImage ();\r
486 DEBUG ((DEBUG_INFO, "\n"));\r
487\r
488 //\r
489 // Dump SMI Handler\r
490 //\r
491 DEBUG ((DEBUG_INFO, "########################\n"));\r
492 DEBUG ((DEBUG_INFO, "# SMI Handler DATABASE #\n"));\r
493 DEBUG ((DEBUG_INFO, "########################\n"));\r
494\r
495 DEBUG ((DEBUG_INFO, "# 1. ROOT SMI Handler #\n"));\r
496 DEBUG_CODE (\r
497 DumpSmiEntryList(mSmmCoreRootSmiEntryList);\r
498 );\r
499\r
500 DEBUG ((DEBUG_INFO, "# 2. GUID SMI Handler #\n"));\r
501 DEBUG_CODE (\r
502 DumpSmiEntryList(mSmmCoreSmiEntryList);\r
503 );\r
504\r
505 DEBUG ((DEBUG_INFO, "# 3. Hardware SMI Handler #\n"));\r
506 DEBUG_CODE (\r
507 DumpSmiEntryList(mSmmCoreHardwareSmiEntryList);\r
508 );\r
509\r
510 DEBUG ((DEBUG_INFO, "\n"));\r
511\r
512 RegisterSmiHandlerProfileHandler();\r
513\r
514 if (mImageStruct != NULL) {\r
515 FreePool(mImageStruct);\r
516 }\r
517\r
518 return EFI_SUCCESS;\r
519}\r
520\r
521/**\r
522 returns SMM image data base size.\r
523\r
524 @return SMM image data base size.\r
525**/\r
526UINTN\r
527GetSmmImageDatabaseSize(\r
528 VOID\r
529 )\r
530{\r
531 UINTN Size;\r
f2485395 532 UINT32 Index;\r
ca41f3f4 533\r
f2485395 534 Size = 0;\r
ca41f3f4 535 for (Index = 0; Index < mImageStructCount; Index++) {\r
f2485395 536 Size += sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE) + GET_OCCUPIED_SIZE (mImageStruct[Index].PdbStringSize, sizeof (UINT64));\r
ca41f3f4
JY
537 }\r
538 return Size;\r
539}\r
540\r
541/**\r
542 returns all SMI handlers' size associated with SmiEntry.\r
543\r
544 @param SmiEntry SMI entry.\r
545\r
546 @return all SMI handlers' size associated with SmiEntry.\r
547**/\r
548UINTN\r
549GetSmmSmiHandlerSizeOnSmiEntry(\r
550 IN SMI_ENTRY *SmiEntry\r
551 )\r
552{\r
553 LIST_ENTRY *ListEntry;\r
554 SMI_HANDLER *SmiHandler;\r
555 UINTN Size;\r
556\r
557 Size = 0;\r
558 ListEntry = &SmiEntry->SmiHandlers;\r
559 for (ListEntry = ListEntry->ForwardLink;\r
560 ListEntry != &SmiEntry->SmiHandlers;\r
561 ListEntry = ListEntry->ForwardLink) {\r
562 SmiHandler = CR(ListEntry, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
f2485395 563 Size += sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE) + GET_OCCUPIED_SIZE (SmiHandler->ContextSize, sizeof (UINT64));\r
ca41f3f4
JY
564 }\r
565\r
566 return Size;\r
567}\r
568\r
569/**\r
570 return all SMI handler database size on the SMI entry list.\r
571\r
572 @param SmiEntryList a list of SMI entry.\r
573\r
574 @return all SMI handler database size on the SMI entry list.\r
575**/\r
576UINTN\r
577GetSmmSmiDatabaseSize(\r
578 IN LIST_ENTRY *SmiEntryList\r
579 )\r
580{\r
581 LIST_ENTRY *ListEntry;\r
582 SMI_ENTRY *SmiEntry;\r
583 UINTN Size;\r
584\r
585 Size = 0;\r
586 ListEntry = SmiEntryList;\r
587 for (ListEntry = ListEntry->ForwardLink;\r
588 ListEntry != SmiEntryList;\r
589 ListEntry = ListEntry->ForwardLink) {\r
590 SmiEntry = CR(ListEntry, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);\r
591 Size += sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE);\r
592 Size += GetSmmSmiHandlerSizeOnSmiEntry(SmiEntry);\r
593 }\r
594 return Size;\r
595}\r
596\r
597/**\r
598 return SMI handler profile database size.\r
599\r
600 @return SMI handler profile database size.\r
601**/\r
602UINTN\r
603GetSmiHandlerProfileDatabaseSize (\r
604 VOID\r
605 )\r
606{\r
607 mSmmImageDatabaseSize = GetSmmImageDatabaseSize();\r
608 mSmmRootSmiDatabaseSize = GetSmmSmiDatabaseSize(mSmmCoreRootSmiEntryList);\r
609 mSmmSmiDatabaseSize = GetSmmSmiDatabaseSize(mSmmCoreSmiEntryList);\r
610 mSmmHardwareSmiDatabaseSize = GetSmmSmiDatabaseSize(mSmmCoreHardwareSmiEntryList);\r
611\r
612 return mSmmImageDatabaseSize + mSmmSmiDatabaseSize + mSmmRootSmiDatabaseSize + mSmmHardwareSmiDatabaseSize;\r
613}\r
614\r
615/**\r
616 get SMM image database.\r
617\r
618 @param Data The buffer to hold SMM image database\r
619 @param ExpectedSize The expected size of the SMM image database\r
620\r
621 @return SMM image data base size.\r
622**/\r
623UINTN\r
624GetSmmImageDatabaseData (\r
625 IN OUT VOID *Data,\r
626 IN UINTN ExpectedSize\r
627 )\r
628{\r
629 SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct;\r
630 UINTN Size;\r
631 UINTN Index;\r
632\r
633 ImageStruct = Data;\r
634 Size = 0;\r
635 for (Index = 0; Index < mImageStructCount; Index++) {\r
636 if (Size >= ExpectedSize) {\r
637 return 0;\r
638 }\r
f2485395 639 if (sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE) + GET_OCCUPIED_SIZE (mImageStruct[Index].PdbStringSize, sizeof (UINT64)) > ExpectedSize - Size) {\r
ca41f3f4
JY
640 return 0;\r
641 }\r
642 ImageStruct->Header.Signature = SMM_CORE_IMAGE_DATABASE_SIGNATURE;\r
f2485395 643 ImageStruct->Header.Length = (UINT32)(sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE) + GET_OCCUPIED_SIZE (mImageStruct[Index].PdbStringSize, sizeof (UINT64)));\r
ca41f3f4
JY
644 ImageStruct->Header.Revision = SMM_CORE_IMAGE_DATABASE_REVISION;\r
645 CopyGuid(&ImageStruct->FileGuid, &mImageStruct[Index].FileGuid);\r
646 ImageStruct->ImageRef = mImageStruct[Index].ImageRef;\r
647 ImageStruct->EntryPoint = mImageStruct[Index].EntryPoint;\r
648 ImageStruct->ImageBase = mImageStruct[Index].ImageBase;\r
649 ImageStruct->ImageSize = mImageStruct[Index].ImageSize;\r
8ced192d
SZ
650 if (mImageStruct[Index].PdbStringSize != 0) {\r
651 ImageStruct->PdbStringOffset = sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE);\r
652 CopyMem ((VOID *)((UINTN)ImageStruct + ImageStruct->PdbStringOffset), mImageStruct[Index].PdbString, mImageStruct[Index].PdbStringSize);\r
653 } else {\r
654 ImageStruct->PdbStringOffset = 0;\r
655 }\r
ca41f3f4 656 ImageStruct = (SMM_CORE_IMAGE_DATABASE_STRUCTURE *)((UINTN)ImageStruct + ImageStruct->Header.Length);\r
f2485395 657 Size += sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE) + GET_OCCUPIED_SIZE (mImageStruct[Index].PdbStringSize, sizeof (UINT64));\r
ca41f3f4
JY
658 }\r
659\r
660 if (ExpectedSize != Size) {\r
661 return 0;\r
662 }\r
663 return Size;\r
664}\r
665\r
666/**\r
667 get all SMI handler data associated with SmiEntry.\r
668\r
669 @param SmiEntry SMI entry.\r
670 @param Data The buffer to hold all SMI handler data\r
671 @param MaxSize The max size of the SMM image database\r
672 @param Count The count of the SMI handler.\r
673\r
674 @return SMM image data base size.\r
675**/\r
676UINTN\r
677GetSmmSmiHandlerDataOnSmiEntry(\r
678 IN SMI_ENTRY *SmiEntry,\r
679 IN OUT VOID *Data,\r
680 IN UINTN MaxSize,\r
f2485395 681 OUT UINT32 *Count\r
ca41f3f4
JY
682 )\r
683{\r
684 SMM_CORE_SMI_HANDLER_STRUCTURE *SmiHandlerStruct;\r
685 LIST_ENTRY *ListEntry;\r
686 SMI_HANDLER *SmiHandler;\r
687 UINTN Size;\r
688\r
689 SmiHandlerStruct = Data;\r
690 Size = 0;\r
691 *Count = 0;\r
692 ListEntry = &SmiEntry->SmiHandlers;\r
693 for (ListEntry = ListEntry->ForwardLink;\r
694 ListEntry != &SmiEntry->SmiHandlers;\r
695 ListEntry = ListEntry->ForwardLink) {\r
696 SmiHandler = CR(ListEntry, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
697 if (Size >= MaxSize) {\r
698 *Count = 0;\r
699 return 0;\r
700 }\r
f2485395 701 if (sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE) + GET_OCCUPIED_SIZE (SmiHandler->ContextSize, sizeof (UINT64)) > MaxSize - Size) {\r
ca41f3f4
JY
702 *Count = 0;\r
703 return 0;\r
704 }\r
f2485395 705 SmiHandlerStruct->Length = (UINT32)(sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE) + GET_OCCUPIED_SIZE (SmiHandler->ContextSize, sizeof (UINT64)));\r
ca41f3f4
JY
706 SmiHandlerStruct->CallerAddr = (UINTN)SmiHandler->CallerAddr;\r
707 SmiHandlerStruct->Handler = (UINTN)SmiHandler->Handler;\r
708 SmiHandlerStruct->ImageRef = AddressToImageRef((UINTN)SmiHandler->Handler);\r
709 SmiHandlerStruct->ContextBufferSize = (UINT32)SmiHandler->ContextSize;\r
710 if (SmiHandler->ContextSize != 0) {\r
711 SmiHandlerStruct->ContextBufferOffset = sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE);\r
712 CopyMem ((UINT8 *)SmiHandlerStruct + SmiHandlerStruct->ContextBufferOffset, SmiHandler->Context, SmiHandler->ContextSize);\r
713 } else {\r
714 SmiHandlerStruct->ContextBufferOffset = 0;\r
715 }\r
f2485395 716 Size += sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE) + GET_OCCUPIED_SIZE (SmiHandler->ContextSize, sizeof (UINT64));\r
ca41f3f4
JY
717 SmiHandlerStruct = (SMM_CORE_SMI_HANDLER_STRUCTURE *)((UINTN)SmiHandlerStruct + SmiHandlerStruct->Length);\r
718 *Count = *Count + 1;\r
719 }\r
720\r
721 return Size;\r
722}\r
723\r
724/**\r
725 get all SMI handler database on the SMI entry list.\r
726\r
727 @param SmiEntryList a list of SMI entry.\r
728 @param HandlerCategory The handler category\r
729 @param Data The buffer to hold all SMI handler database\r
730 @param ExpectedSize The expected size of the SMM image database\r
731\r
732 @return all SMI database size on the SMI entry list.\r
733**/\r
734UINTN\r
735GetSmmSmiDatabaseData(\r
736 IN LIST_ENTRY *SmiEntryList,\r
737 IN UINT32 HandlerCategory,\r
738 IN OUT VOID *Data,\r
739 IN UINTN ExpectedSize\r
740 )\r
741{\r
742 SMM_CORE_SMI_DATABASE_STRUCTURE *SmiStruct;\r
743 LIST_ENTRY *ListEntry;\r
744 SMI_ENTRY *SmiEntry;\r
745 UINTN Size;\r
746 UINTN SmiHandlerSize;\r
f2485395 747 UINT32 SmiHandlerCount;\r
ca41f3f4
JY
748\r
749 SmiStruct = Data;\r
750 Size = 0;\r
751 ListEntry = SmiEntryList;\r
752 for (ListEntry = ListEntry->ForwardLink;\r
753 ListEntry != SmiEntryList;\r
754 ListEntry = ListEntry->ForwardLink) {\r
755 SmiEntry = CR(ListEntry, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);\r
756 if (Size >= ExpectedSize) {\r
757 return 0;\r
758 }\r
759 if (sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE) > ExpectedSize - Size) {\r
760 return 0;\r
761 }\r
762\r
763 SmiStruct->Header.Signature = SMM_CORE_SMI_DATABASE_SIGNATURE;\r
764 SmiStruct->Header.Length = sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE);\r
765 SmiStruct->Header.Revision = SMM_CORE_SMI_DATABASE_REVISION;\r
766 SmiStruct->HandlerCategory = HandlerCategory;\r
767 CopyGuid(&SmiStruct->HandlerType, &SmiEntry->HandlerType);\r
768 Size += sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE);\r
769 SmiHandlerSize = GetSmmSmiHandlerDataOnSmiEntry(SmiEntry, (UINT8 *)SmiStruct + SmiStruct->Header.Length, ExpectedSize - Size, &SmiHandlerCount);\r
770 SmiStruct->HandlerCount = SmiHandlerCount;\r
771 Size += SmiHandlerSize;\r
772 SmiStruct->Header.Length += (UINT32)SmiHandlerSize;\r
773 SmiStruct = (VOID *)((UINTN)SmiStruct + SmiStruct->Header.Length);\r
774 }\r
775 if (ExpectedSize != Size) {\r
776 return 0;\r
777 }\r
778 return Size;\r
779}\r
780\r
781/**\r
782 Get SMI handler profile database.\r
783\r
784 @param Data the buffer to hold SMI handler profile database\r
785\r
786 @retval EFI_SUCCESS the database is got.\r
787 @retval EFI_INVALID_PARAMETER the database size mismatch.\r
788**/\r
789EFI_STATUS\r
790GetSmiHandlerProfileDatabaseData(\r
791 IN OUT VOID *Data\r
792 )\r
793{\r
794 UINTN SmmImageDatabaseSize;\r
795 UINTN SmmSmiDatabaseSize;\r
796 UINTN SmmRootSmiDatabaseSize;\r
797 UINTN SmmHardwareSmiDatabaseSize;\r
798\r
799 DEBUG((DEBUG_VERBOSE, "GetSmiHandlerProfileDatabaseData\n"));\r
800 SmmImageDatabaseSize = GetSmmImageDatabaseData(Data, mSmmImageDatabaseSize);\r
801 if (SmmImageDatabaseSize != mSmmImageDatabaseSize) {\r
802 DEBUG((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmImageDatabaseSize mismatch!\n"));\r
803 return EFI_INVALID_PARAMETER;\r
804 }\r
805 SmmRootSmiDatabaseSize = GetSmmSmiDatabaseData(mSmmCoreRootSmiEntryList, SmmCoreSmiHandlerCategoryRootHandler, (UINT8 *)Data + SmmImageDatabaseSize, mSmmRootSmiDatabaseSize);\r
806 if (SmmRootSmiDatabaseSize != mSmmRootSmiDatabaseSize) {\r
807 DEBUG((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmRootSmiDatabaseSize mismatch!\n"));\r
808 return EFI_INVALID_PARAMETER;\r
809 }\r
810 SmmSmiDatabaseSize = GetSmmSmiDatabaseData(mSmmCoreSmiEntryList, SmmCoreSmiHandlerCategoryGuidHandler, (UINT8 *)Data + SmmImageDatabaseSize + mSmmRootSmiDatabaseSize, mSmmSmiDatabaseSize);\r
811 if (SmmSmiDatabaseSize != mSmmSmiDatabaseSize) {\r
812 DEBUG((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmSmiDatabaseSize mismatch!\n"));\r
813 return EFI_INVALID_PARAMETER;\r
814 }\r
815 SmmHardwareSmiDatabaseSize = GetSmmSmiDatabaseData(mSmmCoreHardwareSmiEntryList, SmmCoreSmiHandlerCategoryHardwareHandler, (UINT8 *)Data + SmmImageDatabaseSize + SmmRootSmiDatabaseSize + SmmSmiDatabaseSize, mSmmHardwareSmiDatabaseSize);\r
816 if (SmmHardwareSmiDatabaseSize != mSmmHardwareSmiDatabaseSize) {\r
817 DEBUG((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmHardwareSmiDatabaseSize mismatch!\n"));\r
818 return EFI_INVALID_PARAMETER;\r
819 }\r
820\r
821 return EFI_SUCCESS;\r
822}\r
823\r
824/**\r
825 build SMI handler profile database.\r
826**/\r
827VOID\r
828BuildSmiHandlerProfileDatabase(\r
829 VOID\r
830 )\r
831{\r
832 EFI_STATUS Status;\r
833 mSmiHandlerProfileDatabaseSize = GetSmiHandlerProfileDatabaseSize();\r
834 mSmiHandlerProfileDatabase = AllocatePool(mSmiHandlerProfileDatabaseSize);\r
835 if (mSmiHandlerProfileDatabase == NULL) {\r
836 return;\r
837 }\r
838 Status = GetSmiHandlerProfileDatabaseData(mSmiHandlerProfileDatabase);\r
839 if (EFI_ERROR(Status)) {\r
840 FreePool(mSmiHandlerProfileDatabase);\r
841 mSmiHandlerProfileDatabase = NULL;\r
842 }\r
843}\r
844\r
845/**\r
846 Copy SMI handler profile data.\r
847\r
848 @param DataBuffer The buffer to hold SMI handler profile data.\r
849 @param DataSize On input, data buffer size.\r
850 On output, actual data buffer size copied.\r
851 @param DataOffset On input, data buffer offset to copy.\r
852 On output, next time data buffer offset to copy.\r
853\r
854**/\r
855VOID\r
856SmiHandlerProfileCopyData(\r
857 OUT VOID *DataBuffer,\r
858 IN OUT UINT64 *DataSize,\r
859 IN OUT UINT64 *DataOffset\r
860 )\r
861{\r
862 if (*DataOffset >= mSmiHandlerProfileDatabaseSize) {\r
863 *DataOffset = mSmiHandlerProfileDatabaseSize;\r
864 return;\r
865 }\r
866 if (mSmiHandlerProfileDatabaseSize - *DataOffset < *DataSize) {\r
867 *DataSize = mSmiHandlerProfileDatabaseSize - *DataOffset;\r
868 }\r
869\r
870 CopyMem(\r
871 DataBuffer,\r
872 (UINT8 *)mSmiHandlerProfileDatabase + *DataOffset,\r
873 (UINTN)*DataSize\r
874 );\r
875 *DataOffset = *DataOffset + *DataSize;\r
876}\r
877\r
878/**\r
879 SMI handler profile handler to get info.\r
880\r
881 @param SmiHandlerProfileParameterGetInfo The parameter of SMI handler profile get info.\r
882\r
883**/\r
884VOID\r
885SmiHandlerProfileHandlerGetInfo(\r
886 IN SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *SmiHandlerProfileParameterGetInfo\r
887 )\r
888{\r
889 BOOLEAN SmiHandlerProfileRecordingStatus;\r
890\r
891 SmiHandlerProfileRecordingStatus = mSmiHandlerProfileRecordingStatus;\r
892 mSmiHandlerProfileRecordingStatus = FALSE;\r
893\r
894 SmiHandlerProfileParameterGetInfo->DataSize = mSmiHandlerProfileDatabaseSize;\r
895 SmiHandlerProfileParameterGetInfo->Header.ReturnStatus = 0;\r
896\r
897 mSmiHandlerProfileRecordingStatus = SmiHandlerProfileRecordingStatus;\r
898}\r
899\r
900/**\r
901 SMI handler profile handler to get data by offset.\r
902\r
903 @param SmiHandlerProfileParameterGetDataByOffset The parameter of SMI handler profile get data by offset.\r
904\r
905**/\r
906VOID\r
907SmiHandlerProfileHandlerGetDataByOffset(\r
908 IN SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *SmiHandlerProfileParameterGetDataByOffset\r
909 )\r
910{\r
911 SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET SmiHandlerProfileGetDataByOffset;\r
912 BOOLEAN SmiHandlerProfileRecordingStatus;\r
913\r
914 SmiHandlerProfileRecordingStatus = mSmiHandlerProfileRecordingStatus;\r
915 mSmiHandlerProfileRecordingStatus = FALSE;\r
916\r
917 CopyMem(&SmiHandlerProfileGetDataByOffset, SmiHandlerProfileParameterGetDataByOffset, sizeof(SmiHandlerProfileGetDataByOffset));\r
918\r
919 //\r
920 // Sanity check\r
921 //\r
922 if (!SmmIsBufferOutsideSmmValid((UINTN)SmiHandlerProfileGetDataByOffset.DataBuffer, (UINTN)SmiHandlerProfileGetDataByOffset.DataSize)) {\r
923 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandlerGetDataByOffset: SMI handler profile get data in SMRAM or overflow!\n"));\r
924 SmiHandlerProfileParameterGetDataByOffset->Header.ReturnStatus = (UINT64)(INT64)(INTN)EFI_ACCESS_DENIED;\r
925 goto Done;\r
926 }\r
927\r
928 SmiHandlerProfileCopyData((VOID *)(UINTN)SmiHandlerProfileGetDataByOffset.DataBuffer, &SmiHandlerProfileGetDataByOffset.DataSize, &SmiHandlerProfileGetDataByOffset.DataOffset);\r
929 CopyMem(SmiHandlerProfileParameterGetDataByOffset, &SmiHandlerProfileGetDataByOffset, sizeof(SmiHandlerProfileGetDataByOffset));\r
930 SmiHandlerProfileParameterGetDataByOffset->Header.ReturnStatus = 0;\r
931\r
932Done:\r
933 mSmiHandlerProfileRecordingStatus = SmiHandlerProfileRecordingStatus;\r
934}\r
935\r
936/**\r
937 Dispatch function for a Software SMI handler.\r
938\r
939 Caution: This function may receive untrusted input.\r
940 Communicate buffer and buffer size are external input, so this function will do basic validation.\r
941\r
942 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
943 @param Context Points to an optional handler context which was specified when the\r
944 handler was registered.\r
945 @param CommBuffer A pointer to a collection of data in memory that will\r
946 be conveyed from a non-SMM environment into an SMM environment.\r
947 @param CommBufferSize The size of the CommBuffer.\r
948\r
949 @retval EFI_SUCCESS Command is handled successfully.\r
950**/\r
951EFI_STATUS\r
952EFIAPI\r
953SmiHandlerProfileHandler(\r
954 IN EFI_HANDLE DispatchHandle,\r
955 IN CONST VOID *Context OPTIONAL,\r
956 IN OUT VOID *CommBuffer OPTIONAL,\r
957 IN OUT UINTN *CommBufferSize OPTIONAL\r
958 )\r
959{\r
960 SMI_HANDLER_PROFILE_PARAMETER_HEADER *SmiHandlerProfileParameterHeader;\r
961 UINTN TempCommBufferSize;\r
962\r
963 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler Enter\n"));\r
964\r
965 if (mSmiHandlerProfileDatabase == NULL) {\r
966 return EFI_SUCCESS;\r
967 }\r
968\r
969 //\r
970 // If input is invalid, stop processing this SMI\r
971 //\r
972 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
973 return EFI_SUCCESS;\r
974 }\r
975\r
976 TempCommBufferSize = *CommBufferSize;\r
977\r
978 if (TempCommBufferSize < sizeof(SMI_HANDLER_PROFILE_PARAMETER_HEADER)) {\r
979 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));\r
980 return EFI_SUCCESS;\r
981 }\r
982\r
983 if (!SmmIsBufferOutsideSmmValid((UINTN)CommBuffer, TempCommBufferSize)) {\r
984 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
985 return EFI_SUCCESS;\r
986 }\r
987\r
988 SmiHandlerProfileParameterHeader = (SMI_HANDLER_PROFILE_PARAMETER_HEADER *)((UINTN)CommBuffer);\r
989 SmiHandlerProfileParameterHeader->ReturnStatus = (UINT64)-1;\r
990\r
991 switch (SmiHandlerProfileParameterHeader->Command) {\r
992 case SMI_HANDLER_PROFILE_COMMAND_GET_INFO:\r
993 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandlerGetInfo\n"));\r
994 if (TempCommBufferSize != sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_INFO)) {\r
995 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));\r
996 return EFI_SUCCESS;\r
997 }\r
998 SmiHandlerProfileHandlerGetInfo((SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *)(UINTN)CommBuffer);\r
999 break;\r
1000 case SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET:\r
1001 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandlerGetDataByOffset\n"));\r
1002 if (TempCommBufferSize != sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET)) {\r
1003 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));\r
1004 return EFI_SUCCESS;\r
1005 }\r
1006 SmiHandlerProfileHandlerGetDataByOffset((SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *)(UINTN)CommBuffer);\r
1007 break;\r
1008 default:\r
1009 break;\r
1010 }\r
1011\r
1012 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler Exit\n"));\r
1013\r
1014 return EFI_SUCCESS;\r
1015}\r
1016\r
1017/**\r
1018 Register SMI handler profile handler.\r
1019**/\r
1020VOID\r
1021RegisterSmiHandlerProfileHandler (\r
1022 VOID\r
1023 )\r
1024{\r
1025 EFI_STATUS Status;\r
1026 EFI_HANDLE DispatchHandle;\r
1027\r
1028 Status = gSmst->SmiHandlerRegister (\r
1029 SmiHandlerProfileHandler,\r
1030 &gSmiHandlerProfileGuid,\r
1031 &DispatchHandle\r
1032 );\r
1033 ASSERT_EFI_ERROR (Status);\r
1034\r
1035 BuildSmiHandlerProfileDatabase();\r
1036}\r
1037\r
1038/**\r
1039 Finds the SMI entry for the requested handler type.\r
1040\r
1041 @param HandlerType The type of the interrupt\r
1042 @param Create Create a new entry if not found\r
1043\r
1044 @return SMI entry\r
1045**/\r
1046SMI_ENTRY *\r
1047SmmCoreFindHardwareSmiEntry (\r
1048 IN EFI_GUID *HandlerType,\r
1049 IN BOOLEAN Create\r
1050 )\r
1051{\r
1052 LIST_ENTRY *Link;\r
1053 SMI_ENTRY *Item;\r
1054 SMI_ENTRY *SmiEntry;\r
1055\r
1056 //\r
1057 // Search the SMI entry list for the matching GUID\r
1058 //\r
1059 SmiEntry = NULL;\r
1060 for (Link = mHardwareSmiEntryList.ForwardLink;\r
1061 Link != &mHardwareSmiEntryList;\r
1062 Link = Link->ForwardLink) {\r
1063\r
1064 Item = CR (Link, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);\r
1065 if (CompareGuid (&Item->HandlerType, HandlerType)) {\r
1066 //\r
1067 // This is the SMI entry\r
1068 //\r
1069 SmiEntry = Item;\r
1070 break;\r
1071 }\r
1072 }\r
1073\r
1074 //\r
1075 // If the protocol entry was not found and Create is TRUE, then\r
1076 // allocate a new entry\r
1077 //\r
1078 if ((SmiEntry == NULL) && Create) {\r
1079 SmiEntry = AllocatePool (sizeof(SMI_ENTRY));\r
1080 if (SmiEntry != NULL) {\r
1081 //\r
1082 // Initialize new SMI entry structure\r
1083 //\r
1084 SmiEntry->Signature = SMI_ENTRY_SIGNATURE;\r
1085 CopyGuid ((VOID *)&SmiEntry->HandlerType, HandlerType);\r
1086 InitializeListHead (&SmiEntry->SmiHandlers);\r
1087\r
1088 //\r
1089 // Add it to SMI entry list\r
1090 //\r
1091 InsertTailList (&mHardwareSmiEntryList, &SmiEntry->AllEntries);\r
1092 }\r
1093 }\r
1094 return SmiEntry;\r
1095}\r
1096\r
1c3ac4b9
JY
1097/**\r
1098 Convert EFI_SMM_USB_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT.\r
1099\r
1100 @param UsbContext A pointer to EFI_SMM_USB_REGISTER_CONTEXT\r
1101 @param UsbContextSize The size of EFI_SMM_USB_REGISTER_CONTEXT in bytes\r
1102 @param SmiHandlerUsbContextSize The size of SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT in bytes\r
1103\r
1104 @return SmiHandlerUsbContext A pointer to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT\r
1105**/\r
1106SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *\r
1107ConvertSmiHandlerUsbContext (\r
1108 IN EFI_SMM_USB_REGISTER_CONTEXT *UsbContext,\r
1109 IN UINTN UsbContextSize,\r
1110 OUT UINTN *SmiHandlerUsbContextSize\r
1111 )\r
1112{\r
1113 UINTN DevicePathSize;\r
1114 SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *SmiHandlerUsbContext;\r
1115\r
1116 ASSERT (UsbContextSize == sizeof(EFI_SMM_USB_REGISTER_CONTEXT));\r
1117\r
1118 DevicePathSize = GetDevicePathSize (UsbContext->Device);\r
1119 SmiHandlerUsbContext = AllocatePool (sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT) + DevicePathSize);\r
1120 if (SmiHandlerUsbContext == NULL) {\r
1121 *SmiHandlerUsbContextSize = 0;\r
1122 return NULL;\r
1123 }\r
1124 SmiHandlerUsbContext->Type = UsbContext->Type;\r
1125 SmiHandlerUsbContext->DevicePathSize = (UINT32)DevicePathSize;\r
1126 CopyMem (SmiHandlerUsbContext + 1, UsbContext->Device, DevicePathSize);\r
1127 *SmiHandlerUsbContextSize = sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT) + DevicePathSize;\r
1128 return SmiHandlerUsbContext;\r
1129}\r
1130\r
f2485395
SZ
1131/**\r
1132 Convert EFI_SMM_SW_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT.\r
1133\r
1134 @param SwContext A pointer to EFI_SMM_SW_REGISTER_CONTEXT\r
1135 @param SwContextSize The size of EFI_SMM_SW_REGISTER_CONTEXT in bytes\r
1136 @param SmiHandlerSwContextSize The size of SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT in bytes\r
1137\r
1138 @return SmiHandlerSwContext A pointer to SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT\r
1139**/\r
1140SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT *\r
1141ConvertSmiHandlerSwContext (\r
1142 IN EFI_SMM_SW_REGISTER_CONTEXT *SwContext,\r
1143 IN UINTN SwContextSize,\r
1144 OUT UINTN *SmiHandlerSwContextSize\r
1145 )\r
1146{\r
1147 SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT *SmiHandlerSwContext;\r
1148\r
1149 ASSERT (SwContextSize == sizeof(EFI_SMM_SW_REGISTER_CONTEXT));\r
1150\r
1151 SmiHandlerSwContext = AllocatePool (sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT));\r
1152 if (SmiHandlerSwContext == NULL) {\r
1153 *SmiHandlerSwContextSize = 0;\r
1154 return NULL;\r
1155 }\r
1156 SmiHandlerSwContext->SwSmiInputValue = SwContext->SwSmiInputValue;\r
1157 *SmiHandlerSwContextSize = sizeof (SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT);\r
1158 return SmiHandlerSwContext;\r
1159}\r
1160\r
ca41f3f4
JY
1161/**\r
1162 This function is called by SmmChildDispatcher module to report\r
1163 a new SMI handler is registered, to SmmCore.\r
1164\r
1165 @param This The protocol instance\r
1166 @param HandlerGuid The GUID to identify the type of the handler.\r
1167 For the SmmChildDispatch protocol, the HandlerGuid\r
1168 must be the GUID of SmmChildDispatch protocol.\r
1169 @param Handler The SMI handler.\r
1170 @param CallerAddress The address of the module who registers the SMI handler.\r
1171 @param Context The context of the SMI handler.\r
1172 For the SmmChildDispatch protocol, the Context\r
1173 must match the one defined for SmmChildDispatch protocol.\r
1174 @param ContextSize The size of the context in bytes.\r
1175 For the SmmChildDispatch protocol, the Context\r
1176 must match the one defined for SmmChildDispatch protocol.\r
1177\r
1178 @retval EFI_SUCCESS The information is recorded.\r
1179 @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information.\r
1180**/\r
1181EFI_STATUS\r
1182EFIAPI\r
1183SmiHandlerProfileRegisterHandler (\r
1184 IN SMI_HANDLER_PROFILE_PROTOCOL *This,\r
1185 IN EFI_GUID *HandlerGuid,\r
1186 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,\r
1187 IN PHYSICAL_ADDRESS CallerAddress,\r
e3917e22 1188 IN VOID *Context OPTIONAL,\r
ca41f3f4
JY
1189 IN UINTN ContextSize OPTIONAL\r
1190 )\r
1191{\r
1192 SMI_HANDLER *SmiHandler;\r
1193 SMI_ENTRY *SmiEntry;\r
1194 LIST_ENTRY *List;\r
1195\r
1c3ac4b9
JY
1196 if (((ContextSize == 0) && (Context != NULL)) ||\r
1197 ((ContextSize != 0) && (Context == NULL))) {\r
1198 return EFI_INVALID_PARAMETER;\r
1199 }\r
1200\r
ca41f3f4
JY
1201 SmiHandler = AllocateZeroPool (sizeof (SMI_HANDLER));\r
1202 if (SmiHandler == NULL) {\r
1203 return EFI_OUT_OF_RESOURCES;\r
1204 }\r
1205\r
1206 SmiHandler->Signature = SMI_HANDLER_SIGNATURE;\r
1207 SmiHandler->Handler = Handler;\r
1208 SmiHandler->CallerAddr = (UINTN)CallerAddress;\r
1c3ac4b9
JY
1209 SmiHandler->Context = Context;\r
1210 SmiHandler->ContextSize = ContextSize;\r
1211\r
1212 if (Context != NULL) {\r
ca41f3f4 1213 if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {\r
1c3ac4b9 1214 SmiHandler->Context = ConvertSmiHandlerUsbContext (Context, ContextSize, &SmiHandler->ContextSize);\r
f2485395
SZ
1215 } else if (CompareGuid (HandlerGuid, &gEfiSmmSwDispatch2ProtocolGuid)) {\r
1216 SmiHandler->Context = ConvertSmiHandlerSwContext (Context, ContextSize, &SmiHandler->ContextSize);\r
ca41f3f4
JY
1217 } else {\r
1218 SmiHandler->Context = AllocateCopyPool (ContextSize, Context);\r
1219 }\r
1220 }\r
1c3ac4b9
JY
1221 if (SmiHandler->Context == NULL) {\r
1222 SmiHandler->ContextSize = 0;\r
ca41f3f4
JY
1223 }\r
1224\r
1225 SmiEntry = SmmCoreFindHardwareSmiEntry (HandlerGuid, TRUE);\r
1226 if (SmiEntry == NULL) {\r
251779fc
JY
1227 if (SmiHandler->Context != NULL) {\r
1228 FreePool (SmiHandler->Context);\r
1229 }\r
1c3ac4b9 1230 FreePool (SmiHandler);\r
ca41f3f4
JY
1231 return EFI_OUT_OF_RESOURCES;\r
1232 }\r
1233\r
1234 List = &SmiEntry->SmiHandlers;\r
1235\r
1236 SmiHandler->SmiEntry = SmiEntry;\r
1237 InsertTailList (List, &SmiHandler->Link);\r
1238\r
1239 return EFI_SUCCESS;\r
1240}\r
1241\r
1242/**\r
1243 This function is called by SmmChildDispatcher module to report\r
1244 an existing SMI handler is unregistered, to SmmCore.\r
1245\r
1246 @param This The protocol instance\r
1247 @param HandlerGuid The GUID to identify the type of the handler.\r
1248 For the SmmChildDispatch protocol, the HandlerGuid\r
1249 must be the GUID of SmmChildDispatch protocol.\r
1250 @param Handler The SMI handler.\r
1c3ac4b9
JY
1251 @param Context The context of the SMI handler.\r
1252 If it is NOT NULL, it will be used to check what is registered.\r
1253 @param ContextSize The size of the context in bytes.\r
1254 If Context is NOT NULL, it will be used to check what is registered.\r
ca41f3f4
JY
1255\r
1256 @retval EFI_SUCCESS The original record is removed.\r
1257 @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler.\r
1258**/\r
1259EFI_STATUS\r
1260EFIAPI\r
1261SmiHandlerProfileUnregisterHandler (\r
1262 IN SMI_HANDLER_PROFILE_PROTOCOL *This,\r
1263 IN EFI_GUID *HandlerGuid,\r
1c3ac4b9 1264 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,\r
e3917e22 1265 IN VOID *Context OPTIONAL,\r
1c3ac4b9 1266 IN UINTN ContextSize OPTIONAL\r
ca41f3f4
JY
1267 )\r
1268{\r
1269 LIST_ENTRY *Link;\r
1270 LIST_ENTRY *Head;\r
1271 SMI_HANDLER *SmiHandler;\r
1272 SMI_ENTRY *SmiEntry;\r
1273 SMI_HANDLER *TargetSmiHandler;\r
1c3ac4b9
JY
1274 VOID *SearchContext;\r
1275 UINTN SearchContextSize;\r
1276\r
1277 if (((ContextSize == 0) && (Context != NULL)) ||\r
1278 ((ContextSize != 0) && (Context == NULL))) {\r
1279 return EFI_INVALID_PARAMETER;\r
1280 }\r
ca41f3f4
JY
1281\r
1282 SmiEntry = SmmCoreFindHardwareSmiEntry (HandlerGuid, FALSE);\r
1283 if (SmiEntry == NULL) {\r
1284 return EFI_NOT_FOUND;\r
1285 }\r
1286\r
1c3ac4b9
JY
1287 SearchContext = Context;\r
1288 SearchContextSize = ContextSize;\r
1289 if (Context != NULL) {\r
1290 if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {\r
1291 SearchContext = ConvertSmiHandlerUsbContext (Context, ContextSize, &SearchContextSize);\r
f2485395
SZ
1292 } else if (CompareGuid (HandlerGuid, &gEfiSmmSwDispatch2ProtocolGuid)) {\r
1293 SearchContext = ConvertSmiHandlerSwContext (Context, ContextSize, &SearchContextSize);\r
1c3ac4b9
JY
1294 }\r
1295 }\r
1296\r
ca41f3f4
JY
1297 TargetSmiHandler = NULL;\r
1298 Head = &SmiEntry->SmiHandlers;\r
1299 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
1300 SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
1301 if (SmiHandler->Handler == Handler) {\r
1c3ac4b9
JY
1302 if ((SearchContext == NULL) ||\r
1303 ((SearchContextSize == SmiHandler->ContextSize) && (CompareMem (SearchContext, SmiHandler->Context, SearchContextSize) == 0))) {\r
1304 TargetSmiHandler = SmiHandler;\r
1305 break;\r
1306 }\r
1307 }\r
1308 }\r
1309\r
1310 if (SearchContext != NULL) {\r
1311 if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {\r
1312 FreePool (SearchContext);\r
ca41f3f4
JY
1313 }\r
1314 }\r
1c3ac4b9 1315\r
ca41f3f4
JY
1316 if (TargetSmiHandler == NULL) {\r
1317 return EFI_NOT_FOUND;\r
1318 }\r
1319 SmiHandler = TargetSmiHandler;\r
1320\r
1321 RemoveEntryList (&SmiHandler->Link);\r
251779fc
JY
1322 if (SmiHandler->Context != NULL) {\r
1323 FreePool (SmiHandler->Context);\r
1324 }\r
ca41f3f4
JY
1325 FreePool (SmiHandler);\r
1326\r
1327 if (IsListEmpty (&SmiEntry->SmiHandlers)) {\r
1328 RemoveEntryList (&SmiEntry->AllEntries);\r
1329 FreePool (SmiEntry);\r
1330 }\r
1331\r
1332 return EFI_SUCCESS;\r
1333}\r
1334\r
1335/**\r
1336 Initialize SmiHandler profile feature.\r
1337**/\r
1338VOID\r
1339SmmCoreInitializeSmiHandlerProfile (\r
1340 VOID\r
1341 )\r
1342{\r
1343 EFI_STATUS Status;\r
1344 VOID *Registration;\r
1345 EFI_HANDLE Handle;\r
1346\r
1347 if ((PcdGet8 (PcdSmiHandlerProfilePropertyMask) & 0x1) != 0) {\r
1348 InsertTailList (&mRootSmiEntryList, &mRootSmiEntry.AllEntries);\r
1349\r
1350 Status = gSmst->SmmRegisterProtocolNotify (\r
1351 &gEfiSmmReadyToLockProtocolGuid,\r
1352 SmmReadyToLockInSmiHandlerProfile,\r
1353 &Registration\r
1354 );\r
1355 ASSERT_EFI_ERROR (Status);\r
1356\r
1357 Handle = NULL;\r
1358 Status = gSmst->SmmInstallProtocolInterface (\r
1359 &Handle,\r
1360 &gSmiHandlerProfileGuid,\r
1361 EFI_NATIVE_INTERFACE,\r
1362 &mSmiHandlerProfile\r
1363 );\r
1364 ASSERT_EFI_ERROR (Status);\r
1365 }\r
1366}\r