]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c
ShellPkg/UefiShellLib: Avoid reading undefined content before string
[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
654 ImageStruct->PdbStringOffset = sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE);\r
655 CopyMem ((VOID *)((UINTN)ImageStruct + ImageStruct->PdbStringOffset), mImageStruct[Index].PdbString, mImageStruct[Index].PdbStringSize);\r
656 ImageStruct = (SMM_CORE_IMAGE_DATABASE_STRUCTURE *)((UINTN)ImageStruct + ImageStruct->Header.Length);\r
657 Size += sizeof(SMM_CORE_IMAGE_DATABASE_STRUCTURE) + mImageStruct[Index].PdbStringSize;\r
658 }\r
659\r
660 if (ExpectedSize != Size) {\r
661 return 0;\r
662 }\r
663 return Size;\r
664}\r
665\r
666/**\r
667 get all SMI handler data associated with SmiEntry.\r
668\r
669 @param SmiEntry SMI entry.\r
670 @param Data The buffer to hold all SMI handler data\r
671 @param MaxSize The max size of the SMM image database\r
672 @param Count The count of the SMI handler.\r
673\r
674 @return SMM image data base size.\r
675**/\r
676UINTN\r
677GetSmmSmiHandlerDataOnSmiEntry(\r
678 IN SMI_ENTRY *SmiEntry,\r
679 IN OUT VOID *Data,\r
680 IN UINTN MaxSize,\r
681 OUT UINTN *Count\r
682 )\r
683{\r
684 SMM_CORE_SMI_HANDLER_STRUCTURE *SmiHandlerStruct;\r
685 LIST_ENTRY *ListEntry;\r
686 SMI_HANDLER *SmiHandler;\r
687 UINTN Size;\r
688\r
689 SmiHandlerStruct = Data;\r
690 Size = 0;\r
691 *Count = 0;\r
692 ListEntry = &SmiEntry->SmiHandlers;\r
693 for (ListEntry = ListEntry->ForwardLink;\r
694 ListEntry != &SmiEntry->SmiHandlers;\r
695 ListEntry = ListEntry->ForwardLink) {\r
696 SmiHandler = CR(ListEntry, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
697 if (Size >= MaxSize) {\r
698 *Count = 0;\r
699 return 0;\r
700 }\r
701 if (sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE) + SmiHandler->ContextSize > MaxSize - Size) {\r
702 *Count = 0;\r
703 return 0;\r
704 }\r
705 SmiHandlerStruct->Length = (UINT32)(sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE) + SmiHandler->ContextSize);\r
706 SmiHandlerStruct->CallerAddr = (UINTN)SmiHandler->CallerAddr;\r
707 SmiHandlerStruct->Handler = (UINTN)SmiHandler->Handler;\r
708 SmiHandlerStruct->ImageRef = AddressToImageRef((UINTN)SmiHandler->Handler);\r
709 SmiHandlerStruct->ContextBufferSize = (UINT32)SmiHandler->ContextSize;\r
710 if (SmiHandler->ContextSize != 0) {\r
711 SmiHandlerStruct->ContextBufferOffset = sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE);\r
712 CopyMem ((UINT8 *)SmiHandlerStruct + SmiHandlerStruct->ContextBufferOffset, SmiHandler->Context, SmiHandler->ContextSize);\r
713 } else {\r
714 SmiHandlerStruct->ContextBufferOffset = 0;\r
715 }\r
716 Size += sizeof(SMM_CORE_SMI_HANDLER_STRUCTURE) + SmiHandler->ContextSize;\r
717 SmiHandlerStruct = (SMM_CORE_SMI_HANDLER_STRUCTURE *)((UINTN)SmiHandlerStruct + SmiHandlerStruct->Length);\r
718 *Count = *Count + 1;\r
719 }\r
720\r
721 return Size;\r
722}\r
723\r
724/**\r
725 get all SMI handler database on the SMI entry list.\r
726\r
727 @param SmiEntryList a list of SMI entry.\r
728 @param HandlerCategory The handler category\r
729 @param Data The buffer to hold all SMI handler database\r
730 @param ExpectedSize The expected size of the SMM image database\r
731\r
732 @return all SMI database size on the SMI entry list.\r
733**/\r
734UINTN\r
735GetSmmSmiDatabaseData(\r
736 IN LIST_ENTRY *SmiEntryList,\r
737 IN UINT32 HandlerCategory,\r
738 IN OUT VOID *Data,\r
739 IN UINTN ExpectedSize\r
740 )\r
741{\r
742 SMM_CORE_SMI_DATABASE_STRUCTURE *SmiStruct;\r
743 LIST_ENTRY *ListEntry;\r
744 SMI_ENTRY *SmiEntry;\r
745 UINTN Size;\r
746 UINTN SmiHandlerSize;\r
747 UINTN SmiHandlerCount;\r
748\r
749 SmiStruct = Data;\r
750 Size = 0;\r
751 ListEntry = SmiEntryList;\r
752 for (ListEntry = ListEntry->ForwardLink;\r
753 ListEntry != SmiEntryList;\r
754 ListEntry = ListEntry->ForwardLink) {\r
755 SmiEntry = CR(ListEntry, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);\r
756 if (Size >= ExpectedSize) {\r
757 return 0;\r
758 }\r
759 if (sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE) > ExpectedSize - Size) {\r
760 return 0;\r
761 }\r
762\r
763 SmiStruct->Header.Signature = SMM_CORE_SMI_DATABASE_SIGNATURE;\r
764 SmiStruct->Header.Length = sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE);\r
765 SmiStruct->Header.Revision = SMM_CORE_SMI_DATABASE_REVISION;\r
766 SmiStruct->HandlerCategory = HandlerCategory;\r
767 CopyGuid(&SmiStruct->HandlerType, &SmiEntry->HandlerType);\r
768 Size += sizeof(SMM_CORE_SMI_DATABASE_STRUCTURE);\r
769 SmiHandlerSize = GetSmmSmiHandlerDataOnSmiEntry(SmiEntry, (UINT8 *)SmiStruct + SmiStruct->Header.Length, ExpectedSize - Size, &SmiHandlerCount);\r
770 SmiStruct->HandlerCount = SmiHandlerCount;\r
771 Size += SmiHandlerSize;\r
772 SmiStruct->Header.Length += (UINT32)SmiHandlerSize;\r
773 SmiStruct = (VOID *)((UINTN)SmiStruct + SmiStruct->Header.Length);\r
774 }\r
775 if (ExpectedSize != Size) {\r
776 return 0;\r
777 }\r
778 return Size;\r
779}\r
780\r
781/**\r
782 Get SMI handler profile database.\r
783\r
784 @param Data the buffer to hold SMI handler profile database\r
785\r
786 @retval EFI_SUCCESS the database is got.\r
787 @retval EFI_INVALID_PARAMETER the database size mismatch.\r
788**/\r
789EFI_STATUS\r
790GetSmiHandlerProfileDatabaseData(\r
791 IN OUT VOID *Data\r
792 )\r
793{\r
794 UINTN SmmImageDatabaseSize;\r
795 UINTN SmmSmiDatabaseSize;\r
796 UINTN SmmRootSmiDatabaseSize;\r
797 UINTN SmmHardwareSmiDatabaseSize;\r
798\r
799 DEBUG((DEBUG_VERBOSE, "GetSmiHandlerProfileDatabaseData\n"));\r
800 SmmImageDatabaseSize = GetSmmImageDatabaseData(Data, mSmmImageDatabaseSize);\r
801 if (SmmImageDatabaseSize != mSmmImageDatabaseSize) {\r
802 DEBUG((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmImageDatabaseSize mismatch!\n"));\r
803 return EFI_INVALID_PARAMETER;\r
804 }\r
805 SmmRootSmiDatabaseSize = GetSmmSmiDatabaseData(mSmmCoreRootSmiEntryList, SmmCoreSmiHandlerCategoryRootHandler, (UINT8 *)Data + SmmImageDatabaseSize, mSmmRootSmiDatabaseSize);\r
806 if (SmmRootSmiDatabaseSize != mSmmRootSmiDatabaseSize) {\r
807 DEBUG((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmRootSmiDatabaseSize mismatch!\n"));\r
808 return EFI_INVALID_PARAMETER;\r
809 }\r
810 SmmSmiDatabaseSize = GetSmmSmiDatabaseData(mSmmCoreSmiEntryList, SmmCoreSmiHandlerCategoryGuidHandler, (UINT8 *)Data + SmmImageDatabaseSize + mSmmRootSmiDatabaseSize, mSmmSmiDatabaseSize);\r
811 if (SmmSmiDatabaseSize != mSmmSmiDatabaseSize) {\r
812 DEBUG((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmSmiDatabaseSize mismatch!\n"));\r
813 return EFI_INVALID_PARAMETER;\r
814 }\r
815 SmmHardwareSmiDatabaseSize = GetSmmSmiDatabaseData(mSmmCoreHardwareSmiEntryList, SmmCoreSmiHandlerCategoryHardwareHandler, (UINT8 *)Data + SmmImageDatabaseSize + SmmRootSmiDatabaseSize + SmmSmiDatabaseSize, mSmmHardwareSmiDatabaseSize);\r
816 if (SmmHardwareSmiDatabaseSize != mSmmHardwareSmiDatabaseSize) {\r
817 DEBUG((DEBUG_ERROR, "GetSmiHandlerProfileDatabaseData - SmmHardwareSmiDatabaseSize mismatch!\n"));\r
818 return EFI_INVALID_PARAMETER;\r
819 }\r
820\r
821 return EFI_SUCCESS;\r
822}\r
823\r
824/**\r
825 build SMI handler profile database.\r
826**/\r
827VOID\r
828BuildSmiHandlerProfileDatabase(\r
829 VOID\r
830 )\r
831{\r
832 EFI_STATUS Status;\r
833 mSmiHandlerProfileDatabaseSize = GetSmiHandlerProfileDatabaseSize();\r
834 mSmiHandlerProfileDatabase = AllocatePool(mSmiHandlerProfileDatabaseSize);\r
835 if (mSmiHandlerProfileDatabase == NULL) {\r
836 return;\r
837 }\r
838 Status = GetSmiHandlerProfileDatabaseData(mSmiHandlerProfileDatabase);\r
839 if (EFI_ERROR(Status)) {\r
840 FreePool(mSmiHandlerProfileDatabase);\r
841 mSmiHandlerProfileDatabase = NULL;\r
842 }\r
843}\r
844\r
845/**\r
846 Copy SMI handler profile data.\r
847\r
848 @param DataBuffer The buffer to hold SMI handler profile data.\r
849 @param DataSize On input, data buffer size.\r
850 On output, actual data buffer size copied.\r
851 @param DataOffset On input, data buffer offset to copy.\r
852 On output, next time data buffer offset to copy.\r
853\r
854**/\r
855VOID\r
856SmiHandlerProfileCopyData(\r
857 OUT VOID *DataBuffer,\r
858 IN OUT UINT64 *DataSize,\r
859 IN OUT UINT64 *DataOffset\r
860 )\r
861{\r
862 if (*DataOffset >= mSmiHandlerProfileDatabaseSize) {\r
863 *DataOffset = mSmiHandlerProfileDatabaseSize;\r
864 return;\r
865 }\r
866 if (mSmiHandlerProfileDatabaseSize - *DataOffset < *DataSize) {\r
867 *DataSize = mSmiHandlerProfileDatabaseSize - *DataOffset;\r
868 }\r
869\r
870 CopyMem(\r
871 DataBuffer,\r
872 (UINT8 *)mSmiHandlerProfileDatabase + *DataOffset,\r
873 (UINTN)*DataSize\r
874 );\r
875 *DataOffset = *DataOffset + *DataSize;\r
876}\r
877\r
878/**\r
879 SMI handler profile handler to get info.\r
880\r
881 @param SmiHandlerProfileParameterGetInfo The parameter of SMI handler profile get info.\r
882\r
883**/\r
884VOID\r
885SmiHandlerProfileHandlerGetInfo(\r
886 IN SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *SmiHandlerProfileParameterGetInfo\r
887 )\r
888{\r
889 BOOLEAN SmiHandlerProfileRecordingStatus;\r
890\r
891 SmiHandlerProfileRecordingStatus = mSmiHandlerProfileRecordingStatus;\r
892 mSmiHandlerProfileRecordingStatus = FALSE;\r
893\r
894 SmiHandlerProfileParameterGetInfo->DataSize = mSmiHandlerProfileDatabaseSize;\r
895 SmiHandlerProfileParameterGetInfo->Header.ReturnStatus = 0;\r
896\r
897 mSmiHandlerProfileRecordingStatus = SmiHandlerProfileRecordingStatus;\r
898}\r
899\r
900/**\r
901 SMI handler profile handler to get data by offset.\r
902\r
903 @param SmiHandlerProfileParameterGetDataByOffset The parameter of SMI handler profile get data by offset.\r
904\r
905**/\r
906VOID\r
907SmiHandlerProfileHandlerGetDataByOffset(\r
908 IN SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *SmiHandlerProfileParameterGetDataByOffset\r
909 )\r
910{\r
911 SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET SmiHandlerProfileGetDataByOffset;\r
912 BOOLEAN SmiHandlerProfileRecordingStatus;\r
913\r
914 SmiHandlerProfileRecordingStatus = mSmiHandlerProfileRecordingStatus;\r
915 mSmiHandlerProfileRecordingStatus = FALSE;\r
916\r
917 CopyMem(&SmiHandlerProfileGetDataByOffset, SmiHandlerProfileParameterGetDataByOffset, sizeof(SmiHandlerProfileGetDataByOffset));\r
918\r
919 //\r
920 // Sanity check\r
921 //\r
922 if (!SmmIsBufferOutsideSmmValid((UINTN)SmiHandlerProfileGetDataByOffset.DataBuffer, (UINTN)SmiHandlerProfileGetDataByOffset.DataSize)) {\r
923 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandlerGetDataByOffset: SMI handler profile get data in SMRAM or overflow!\n"));\r
924 SmiHandlerProfileParameterGetDataByOffset->Header.ReturnStatus = (UINT64)(INT64)(INTN)EFI_ACCESS_DENIED;\r
925 goto Done;\r
926 }\r
927\r
928 SmiHandlerProfileCopyData((VOID *)(UINTN)SmiHandlerProfileGetDataByOffset.DataBuffer, &SmiHandlerProfileGetDataByOffset.DataSize, &SmiHandlerProfileGetDataByOffset.DataOffset);\r
929 CopyMem(SmiHandlerProfileParameterGetDataByOffset, &SmiHandlerProfileGetDataByOffset, sizeof(SmiHandlerProfileGetDataByOffset));\r
930 SmiHandlerProfileParameterGetDataByOffset->Header.ReturnStatus = 0;\r
931\r
932Done:\r
933 mSmiHandlerProfileRecordingStatus = SmiHandlerProfileRecordingStatus;\r
934}\r
935\r
936/**\r
937 Dispatch function for a Software SMI handler.\r
938\r
939 Caution: This function may receive untrusted input.\r
940 Communicate buffer and buffer size are external input, so this function will do basic validation.\r
941\r
942 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
943 @param Context Points to an optional handler context which was specified when the\r
944 handler was registered.\r
945 @param CommBuffer A pointer to a collection of data in memory that will\r
946 be conveyed from a non-SMM environment into an SMM environment.\r
947 @param CommBufferSize The size of the CommBuffer.\r
948\r
949 @retval EFI_SUCCESS Command is handled successfully.\r
950**/\r
951EFI_STATUS\r
952EFIAPI\r
953SmiHandlerProfileHandler(\r
954 IN EFI_HANDLE DispatchHandle,\r
955 IN CONST VOID *Context OPTIONAL,\r
956 IN OUT VOID *CommBuffer OPTIONAL,\r
957 IN OUT UINTN *CommBufferSize OPTIONAL\r
958 )\r
959{\r
960 SMI_HANDLER_PROFILE_PARAMETER_HEADER *SmiHandlerProfileParameterHeader;\r
961 UINTN TempCommBufferSize;\r
962\r
963 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler Enter\n"));\r
964\r
965 if (mSmiHandlerProfileDatabase == NULL) {\r
966 return EFI_SUCCESS;\r
967 }\r
968\r
969 //\r
970 // If input is invalid, stop processing this SMI\r
971 //\r
972 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
973 return EFI_SUCCESS;\r
974 }\r
975\r
976 TempCommBufferSize = *CommBufferSize;\r
977\r
978 if (TempCommBufferSize < sizeof(SMI_HANDLER_PROFILE_PARAMETER_HEADER)) {\r
979 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));\r
980 return EFI_SUCCESS;\r
981 }\r
982\r
983 if (!SmmIsBufferOutsideSmmValid((UINTN)CommBuffer, TempCommBufferSize)) {\r
984 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
985 return EFI_SUCCESS;\r
986 }\r
987\r
988 SmiHandlerProfileParameterHeader = (SMI_HANDLER_PROFILE_PARAMETER_HEADER *)((UINTN)CommBuffer);\r
989 SmiHandlerProfileParameterHeader->ReturnStatus = (UINT64)-1;\r
990\r
991 switch (SmiHandlerProfileParameterHeader->Command) {\r
992 case SMI_HANDLER_PROFILE_COMMAND_GET_INFO:\r
993 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandlerGetInfo\n"));\r
994 if (TempCommBufferSize != sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_INFO)) {\r
995 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));\r
996 return EFI_SUCCESS;\r
997 }\r
998 SmiHandlerProfileHandlerGetInfo((SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *)(UINTN)CommBuffer);\r
999 break;\r
1000 case SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET:\r
1001 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandlerGetDataByOffset\n"));\r
1002 if (TempCommBufferSize != sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET)) {\r
1003 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler: SMM communication buffer size invalid!\n"));\r
1004 return EFI_SUCCESS;\r
1005 }\r
1006 SmiHandlerProfileHandlerGetDataByOffset((SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *)(UINTN)CommBuffer);\r
1007 break;\r
1008 default:\r
1009 break;\r
1010 }\r
1011\r
1012 DEBUG((DEBUG_ERROR, "SmiHandlerProfileHandler Exit\n"));\r
1013\r
1014 return EFI_SUCCESS;\r
1015}\r
1016\r
1017/**\r
1018 Register SMI handler profile handler.\r
1019**/\r
1020VOID\r
1021RegisterSmiHandlerProfileHandler (\r
1022 VOID\r
1023 )\r
1024{\r
1025 EFI_STATUS Status;\r
1026 EFI_HANDLE DispatchHandle;\r
1027\r
1028 Status = gSmst->SmiHandlerRegister (\r
1029 SmiHandlerProfileHandler,\r
1030 &gSmiHandlerProfileGuid,\r
1031 &DispatchHandle\r
1032 );\r
1033 ASSERT_EFI_ERROR (Status);\r
1034\r
1035 BuildSmiHandlerProfileDatabase();\r
1036}\r
1037\r
1038/**\r
1039 Finds the SMI entry for the requested handler type.\r
1040\r
1041 @param HandlerType The type of the interrupt\r
1042 @param Create Create a new entry if not found\r
1043\r
1044 @return SMI entry\r
1045**/\r
1046SMI_ENTRY *\r
1047SmmCoreFindHardwareSmiEntry (\r
1048 IN EFI_GUID *HandlerType,\r
1049 IN BOOLEAN Create\r
1050 )\r
1051{\r
1052 LIST_ENTRY *Link;\r
1053 SMI_ENTRY *Item;\r
1054 SMI_ENTRY *SmiEntry;\r
1055\r
1056 //\r
1057 // Search the SMI entry list for the matching GUID\r
1058 //\r
1059 SmiEntry = NULL;\r
1060 for (Link = mHardwareSmiEntryList.ForwardLink;\r
1061 Link != &mHardwareSmiEntryList;\r
1062 Link = Link->ForwardLink) {\r
1063\r
1064 Item = CR (Link, SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE);\r
1065 if (CompareGuid (&Item->HandlerType, HandlerType)) {\r
1066 //\r
1067 // This is the SMI entry\r
1068 //\r
1069 SmiEntry = Item;\r
1070 break;\r
1071 }\r
1072 }\r
1073\r
1074 //\r
1075 // If the protocol entry was not found and Create is TRUE, then\r
1076 // allocate a new entry\r
1077 //\r
1078 if ((SmiEntry == NULL) && Create) {\r
1079 SmiEntry = AllocatePool (sizeof(SMI_ENTRY));\r
1080 if (SmiEntry != NULL) {\r
1081 //\r
1082 // Initialize new SMI entry structure\r
1083 //\r
1084 SmiEntry->Signature = SMI_ENTRY_SIGNATURE;\r
1085 CopyGuid ((VOID *)&SmiEntry->HandlerType, HandlerType);\r
1086 InitializeListHead (&SmiEntry->SmiHandlers);\r
1087\r
1088 //\r
1089 // Add it to SMI entry list\r
1090 //\r
1091 InsertTailList (&mHardwareSmiEntryList, &SmiEntry->AllEntries);\r
1092 }\r
1093 }\r
1094 return SmiEntry;\r
1095}\r
1096\r
1c3ac4b9
JY
1097/**\r
1098 Convert EFI_SMM_USB_REGISTER_CONTEXT to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT.\r
1099\r
1100 @param UsbContext A pointer to EFI_SMM_USB_REGISTER_CONTEXT\r
1101 @param UsbContextSize The size of EFI_SMM_USB_REGISTER_CONTEXT in bytes\r
1102 @param SmiHandlerUsbContextSize The size of SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT in bytes\r
1103\r
1104 @return SmiHandlerUsbContext A pointer to SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT\r
1105**/\r
1106SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *\r
1107ConvertSmiHandlerUsbContext (\r
1108 IN EFI_SMM_USB_REGISTER_CONTEXT *UsbContext,\r
1109 IN UINTN UsbContextSize,\r
1110 OUT UINTN *SmiHandlerUsbContextSize\r
1111 )\r
1112{\r
1113 UINTN DevicePathSize;\r
1114 SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *SmiHandlerUsbContext;\r
1115\r
1116 ASSERT (UsbContextSize == sizeof(EFI_SMM_USB_REGISTER_CONTEXT));\r
1117\r
1118 DevicePathSize = GetDevicePathSize (UsbContext->Device);\r
1119 SmiHandlerUsbContext = AllocatePool (sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT) + DevicePathSize);\r
1120 if (SmiHandlerUsbContext == NULL) {\r
1121 *SmiHandlerUsbContextSize = 0;\r
1122 return NULL;\r
1123 }\r
1124 SmiHandlerUsbContext->Type = UsbContext->Type;\r
1125 SmiHandlerUsbContext->DevicePathSize = (UINT32)DevicePathSize;\r
1126 CopyMem (SmiHandlerUsbContext + 1, UsbContext->Device, DevicePathSize);\r
1127 *SmiHandlerUsbContextSize = sizeof (SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT) + DevicePathSize;\r
1128 return SmiHandlerUsbContext;\r
1129}\r
1130\r
ca41f3f4
JY
1131/**\r
1132 This function is called by SmmChildDispatcher module to report\r
1133 a new SMI handler is registered, to SmmCore.\r
1134\r
1135 @param This The protocol instance\r
1136 @param HandlerGuid The GUID to identify the type of the handler.\r
1137 For the SmmChildDispatch protocol, the HandlerGuid\r
1138 must be the GUID of SmmChildDispatch protocol.\r
1139 @param Handler The SMI handler.\r
1140 @param CallerAddress The address of the module who registers the SMI handler.\r
1141 @param Context The context of the SMI handler.\r
1142 For the SmmChildDispatch protocol, the Context\r
1143 must match the one defined for SmmChildDispatch protocol.\r
1144 @param ContextSize The size of the context in bytes.\r
1145 For the SmmChildDispatch protocol, the Context\r
1146 must match the one defined for SmmChildDispatch protocol.\r
1147\r
1148 @retval EFI_SUCCESS The information is recorded.\r
1149 @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information.\r
1150**/\r
1151EFI_STATUS\r
1152EFIAPI\r
1153SmiHandlerProfileRegisterHandler (\r
1154 IN SMI_HANDLER_PROFILE_PROTOCOL *This,\r
1155 IN EFI_GUID *HandlerGuid,\r
1156 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,\r
1157 IN PHYSICAL_ADDRESS CallerAddress,\r
1158 IN VOID *Context, OPTIONAL\r
1159 IN UINTN ContextSize OPTIONAL\r
1160 )\r
1161{\r
1162 SMI_HANDLER *SmiHandler;\r
1163 SMI_ENTRY *SmiEntry;\r
1164 LIST_ENTRY *List;\r
1165\r
1c3ac4b9
JY
1166 if (((ContextSize == 0) && (Context != NULL)) ||\r
1167 ((ContextSize != 0) && (Context == NULL))) {\r
1168 return EFI_INVALID_PARAMETER;\r
1169 }\r
1170\r
ca41f3f4
JY
1171 SmiHandler = AllocateZeroPool (sizeof (SMI_HANDLER));\r
1172 if (SmiHandler == NULL) {\r
1173 return EFI_OUT_OF_RESOURCES;\r
1174 }\r
1175\r
1176 SmiHandler->Signature = SMI_HANDLER_SIGNATURE;\r
1177 SmiHandler->Handler = Handler;\r
1178 SmiHandler->CallerAddr = (UINTN)CallerAddress;\r
1c3ac4b9
JY
1179 SmiHandler->Context = Context;\r
1180 SmiHandler->ContextSize = ContextSize;\r
1181\r
1182 if (Context != NULL) {\r
ca41f3f4 1183 if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {\r
1c3ac4b9 1184 SmiHandler->Context = ConvertSmiHandlerUsbContext (Context, ContextSize, &SmiHandler->ContextSize);\r
ca41f3f4
JY
1185 } else {\r
1186 SmiHandler->Context = AllocateCopyPool (ContextSize, Context);\r
1187 }\r
1188 }\r
1c3ac4b9
JY
1189 if (SmiHandler->Context == NULL) {\r
1190 SmiHandler->ContextSize = 0;\r
ca41f3f4
JY
1191 }\r
1192\r
1193 SmiEntry = SmmCoreFindHardwareSmiEntry (HandlerGuid, TRUE);\r
1194 if (SmiEntry == NULL) {\r
251779fc
JY
1195 if (SmiHandler->Context != NULL) {\r
1196 FreePool (SmiHandler->Context);\r
1197 }\r
1c3ac4b9 1198 FreePool (SmiHandler);\r
ca41f3f4
JY
1199 return EFI_OUT_OF_RESOURCES;\r
1200 }\r
1201\r
1202 List = &SmiEntry->SmiHandlers;\r
1203\r
1204 SmiHandler->SmiEntry = SmiEntry;\r
1205 InsertTailList (List, &SmiHandler->Link);\r
1206\r
1207 return EFI_SUCCESS;\r
1208}\r
1209\r
1210/**\r
1211 This function is called by SmmChildDispatcher module to report\r
1212 an existing SMI handler is unregistered, to SmmCore.\r
1213\r
1214 @param This The protocol instance\r
1215 @param HandlerGuid The GUID to identify the type of the handler.\r
1216 For the SmmChildDispatch protocol, the HandlerGuid\r
1217 must be the GUID of SmmChildDispatch protocol.\r
1218 @param Handler The SMI handler.\r
1c3ac4b9
JY
1219 @param Context The context of the SMI handler.\r
1220 If it is NOT NULL, it will be used to check what is registered.\r
1221 @param ContextSize The size of the context in bytes.\r
1222 If Context is NOT NULL, it will be used to check what is registered.\r
ca41f3f4
JY
1223\r
1224 @retval EFI_SUCCESS The original record is removed.\r
1225 @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler.\r
1226**/\r
1227EFI_STATUS\r
1228EFIAPI\r
1229SmiHandlerProfileUnregisterHandler (\r
1230 IN SMI_HANDLER_PROFILE_PROTOCOL *This,\r
1231 IN EFI_GUID *HandlerGuid,\r
1c3ac4b9
JY
1232 IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,\r
1233 IN VOID *Context, OPTIONAL\r
1234 IN UINTN ContextSize OPTIONAL\r
ca41f3f4
JY
1235 )\r
1236{\r
1237 LIST_ENTRY *Link;\r
1238 LIST_ENTRY *Head;\r
1239 SMI_HANDLER *SmiHandler;\r
1240 SMI_ENTRY *SmiEntry;\r
1241 SMI_HANDLER *TargetSmiHandler;\r
1c3ac4b9
JY
1242 VOID *SearchContext;\r
1243 UINTN SearchContextSize;\r
1244\r
1245 if (((ContextSize == 0) && (Context != NULL)) ||\r
1246 ((ContextSize != 0) && (Context == NULL))) {\r
1247 return EFI_INVALID_PARAMETER;\r
1248 }\r
ca41f3f4
JY
1249\r
1250 SmiEntry = SmmCoreFindHardwareSmiEntry (HandlerGuid, FALSE);\r
1251 if (SmiEntry == NULL) {\r
1252 return EFI_NOT_FOUND;\r
1253 }\r
1254\r
1c3ac4b9
JY
1255 SearchContext = Context;\r
1256 SearchContextSize = ContextSize;\r
1257 if (Context != NULL) {\r
1258 if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {\r
1259 SearchContext = ConvertSmiHandlerUsbContext (Context, ContextSize, &SearchContextSize);\r
1260 }\r
1261 }\r
1262\r
ca41f3f4
JY
1263 TargetSmiHandler = NULL;\r
1264 Head = &SmiEntry->SmiHandlers;\r
1265 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
1266 SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);\r
1267 if (SmiHandler->Handler == Handler) {\r
1c3ac4b9
JY
1268 if ((SearchContext == NULL) ||\r
1269 ((SearchContextSize == SmiHandler->ContextSize) && (CompareMem (SearchContext, SmiHandler->Context, SearchContextSize) == 0))) {\r
1270 TargetSmiHandler = SmiHandler;\r
1271 break;\r
1272 }\r
1273 }\r
1274 }\r
1275\r
1276 if (SearchContext != NULL) {\r
1277 if (CompareGuid (HandlerGuid, &gEfiSmmUsbDispatch2ProtocolGuid)) {\r
1278 FreePool (SearchContext);\r
ca41f3f4
JY
1279 }\r
1280 }\r
1c3ac4b9 1281\r
ca41f3f4
JY
1282 if (TargetSmiHandler == NULL) {\r
1283 return EFI_NOT_FOUND;\r
1284 }\r
1285 SmiHandler = TargetSmiHandler;\r
1286\r
1287 RemoveEntryList (&SmiHandler->Link);\r
251779fc
JY
1288 if (SmiHandler->Context != NULL) {\r
1289 FreePool (SmiHandler->Context);\r
1290 }\r
ca41f3f4
JY
1291 FreePool (SmiHandler);\r
1292\r
1293 if (IsListEmpty (&SmiEntry->SmiHandlers)) {\r
1294 RemoveEntryList (&SmiEntry->AllEntries);\r
1295 FreePool (SmiEntry);\r
1296 }\r
1297\r
1298 return EFI_SUCCESS;\r
1299}\r
1300\r
1301/**\r
1302 Initialize SmiHandler profile feature.\r
1303**/\r
1304VOID\r
1305SmmCoreInitializeSmiHandlerProfile (\r
1306 VOID\r
1307 )\r
1308{\r
1309 EFI_STATUS Status;\r
1310 VOID *Registration;\r
1311 EFI_HANDLE Handle;\r
1312\r
1313 if ((PcdGet8 (PcdSmiHandlerProfilePropertyMask) & 0x1) != 0) {\r
1314 InsertTailList (&mRootSmiEntryList, &mRootSmiEntry.AllEntries);\r
1315\r
1316 Status = gSmst->SmmRegisterProtocolNotify (\r
1317 &gEfiSmmReadyToLockProtocolGuid,\r
1318 SmmReadyToLockInSmiHandlerProfile,\r
1319 &Registration\r
1320 );\r
1321 ASSERT_EFI_ERROR (Status);\r
1322\r
1323 Handle = NULL;\r
1324 Status = gSmst->SmmInstallProtocolInterface (\r
1325 &Handle,\r
1326 &gSmiHandlerProfileGuid,\r
1327 EFI_NATIVE_INTERFACE,\r
1328 &mSmiHandlerProfile\r
1329 );\r
1330 ASSERT_EFI_ERROR (Status);\r
1331 }\r
1332}\r
1333\r