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