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