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