]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
MdeModulePkg DxeCore: Call UnregisterMemoryProfileImage correctly.
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmramProfileRecord.c
CommitLineData
84edd20b
SZ
1/** @file\r
2 Support routines for SMRAM profile.\r
3\r
842b1242 4 Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
84edd20b
SZ
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "PiSmmCore.h"\r
16\r
17#define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0)\r
18\r
19typedef struct {\r
20 UINT32 Signature;\r
21 MEMORY_PROFILE_CONTEXT Context;\r
22 LIST_ENTRY *DriverInfoList;\r
23} MEMORY_PROFILE_CONTEXT_DATA;\r
24\r
25typedef struct {\r
26 UINT32 Signature;\r
27 MEMORY_PROFILE_DRIVER_INFO DriverInfo;\r
28 LIST_ENTRY *AllocInfoList;\r
29 LIST_ENTRY Link;\r
30} MEMORY_PROFILE_DRIVER_INFO_DATA;\r
31\r
32typedef struct {\r
33 UINT32 Signature;\r
34 MEMORY_PROFILE_ALLOC_INFO AllocInfo;\r
35 LIST_ENTRY Link;\r
36} MEMORY_PROFILE_ALLOC_INFO_DATA;\r
37\r
38//\r
39// When free memory less than 4 pages, dump it.\r
40//\r
41#define SMRAM_INFO_DUMP_PAGE_THRESHOLD 4\r
42\r
43GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory = {\r
44 {\r
45 MEMORY_PROFILE_FREE_MEMORY_SIGNATURE,\r
46 sizeof (MEMORY_PROFILE_FREE_MEMORY),\r
47 MEMORY_PROFILE_FREE_MEMORY_REVISION\r
48 },\r
49 0,\r
50 0\r
51};\r
52\r
53GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);\r
54GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext = {\r
55 MEMORY_PROFILE_CONTEXT_SIGNATURE,\r
56 {\r
57 {\r
58 MEMORY_PROFILE_CONTEXT_SIGNATURE,\r
59 sizeof (MEMORY_PROFILE_CONTEXT),\r
60 MEMORY_PROFILE_CONTEXT_REVISION\r
61 },\r
62 0,\r
63 0,\r
64 {0},\r
65 {0},\r
66 0,\r
67 0,\r
68 0\r
69 },\r
70 &mImageQueue,\r
71};\r
72GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr;\r
73\r
74BOOLEAN mSmramReadyToLock;\r
75BOOLEAN mSmramProfileRecordingStatus = FALSE;\r
76\r
77/**\r
78 Return SMRAM profile context.\r
79\r
80 @return SMRAM profile context.\r
81\r
82**/\r
83MEMORY_PROFILE_CONTEXT_DATA *\r
84GetSmramProfileContext (\r
85 VOID\r
86 )\r
87{\r
88 return mSmramProfileContextPtr;\r
89}\r
90\r
91/**\r
92 Retrieves the magic value from the PE/COFF header.\r
93\r
94 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.\r
95\r
96 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32\r
97 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+\r
98\r
99**/\r
100UINT16\r
101InternalPeCoffGetPeHeaderMagicValue (\r
102 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr\r
103 )\r
104{\r
105 //\r
106 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
107 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
108 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
109 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
110 //\r
111 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
112 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
113 }\r
114 //\r
115 // Return the magic value from the PC/COFF Optional Header\r
116 //\r
117 return Hdr.Pe32->OptionalHeader.Magic;\r
118}\r
119\r
120/**\r
121 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.\r
122 If Pe32Data is NULL, then ASSERT().\r
123\r
124 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.\r
125\r
126 @return The Subsystem of the PE/COFF image.\r
127\r
128**/\r
129UINT16\r
130InternalPeCoffGetSubsystem (\r
131 IN VOID *Pe32Data\r
132 )\r
133{\r
134 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
135 EFI_IMAGE_DOS_HEADER *DosHdr;\r
136 UINT16 Magic;\r
137\r
138 ASSERT (Pe32Data != NULL);\r
139\r
140 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
141 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
142 //\r
143 // DOS image header is present, so read the PE header after the DOS image header.\r
144 //\r
145 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
146 } else {\r
147 //\r
148 // DOS image header is not present, so PE header is at the image base.\r
149 //\r
150 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;\r
151 }\r
152\r
153 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
154 return Hdr.Te->Subsystem;\r
155 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
156 Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr);\r
157 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
158 return Hdr.Pe32->OptionalHeader.Subsystem;\r
159 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
160 return Hdr.Pe32Plus->OptionalHeader.Subsystem;\r
161 }\r
162 }\r
163\r
164 return 0x0000;\r
165}\r
166\r
167/**\r
168 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded\r
169 into system memory with the PE/COFF Loader Library functions.\r
170\r
171 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry\r
172 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then\r
173 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.\r
174 If Pe32Data is NULL, then ASSERT().\r
175 If EntryPoint is NULL, then ASSERT().\r
176\r
177 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.\r
178 @param EntryPoint The pointer to entry point to the PE/COFF image to return.\r
179\r
180 @retval RETURN_SUCCESS EntryPoint was returned.\r
181 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.\r
182\r
183**/\r
184RETURN_STATUS\r
185InternalPeCoffGetEntryPoint (\r
186 IN VOID *Pe32Data,\r
187 OUT VOID **EntryPoint\r
188 )\r
189{\r
190 EFI_IMAGE_DOS_HEADER *DosHdr;\r
191 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
192\r
193 ASSERT (Pe32Data != NULL);\r
194 ASSERT (EntryPoint != NULL);\r
195\r
196 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
197 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
198 //\r
199 // DOS image header is present, so read the PE header after the DOS image header.\r
200 //\r
201 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
202 } else {\r
203 //\r
204 // DOS image header is not present, so PE header is at the image base.\r
205 //\r
206 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;\r
207 }\r
208\r
209 //\r
210 // Calculate the entry point relative to the start of the image.\r
211 // AddressOfEntryPoint is common for PE32 & PE32+\r
212 //\r
213 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
214 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);\r
215 return RETURN_SUCCESS;\r
216 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
217 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));\r
218 return RETURN_SUCCESS;\r
219 }\r
220\r
221 return RETURN_UNSUPPORTED;\r
222}\r
223\r
224/**\r
225 Build driver info.\r
226\r
227 @param ContextData Memory profile context.\r
228 @param FileName File name of the image.\r
229 @param ImageBase Image base address.\r
230 @param ImageSize Image size.\r
231 @param EntryPoint Entry point of the image.\r
232 @param ImageSubsystem Image subsystem of the image.\r
233\r
234 @param FileType File type of the image.\r
235\r
236 @return Pointer to memory profile driver info.\r
237\r
238**/\r
239MEMORY_PROFILE_DRIVER_INFO_DATA *\r
240BuildDriverInfo (\r
241 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,\r
242 IN EFI_GUID *FileName,\r
243 IN PHYSICAL_ADDRESS ImageBase,\r
244 IN UINT64 ImageSize,\r
245 IN PHYSICAL_ADDRESS EntryPoint,\r
246 IN UINT16 ImageSubsystem,\r
247 IN EFI_FV_FILETYPE FileType\r
248 )\r
249{\r
250 EFI_STATUS Status;\r
251 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
252 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
253 VOID *EntryPointInImage;\r
254\r
255 //\r
256 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.\r
257 //\r
258 Status = SmmInternalAllocatePool (\r
259 EfiRuntimeServicesData,\r
260 sizeof (*DriverInfoData) + sizeof (LIST_ENTRY),\r
261 (VOID **) &DriverInfoData\r
262 );\r
263 if (EFI_ERROR (Status)) {\r
264 return NULL;\r
265 }\r
266\r
267 ZeroMem (DriverInfoData, sizeof (*DriverInfoData));\r
268\r
269 DriverInfo = &DriverInfoData->DriverInfo;\r
270 DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;\r
271 DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;\r
272 DriverInfo->Header.Length = sizeof (MEMORY_PROFILE_DRIVER_INFO);\r
273 DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;\r
274 if (FileName != NULL) {\r
275 CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));\r
276 }\r
277 DriverInfo->ImageBase = ImageBase;\r
278 DriverInfo->ImageSize = ImageSize;\r
279 DriverInfo->EntryPoint = EntryPoint;\r
280 DriverInfo->ImageSubsystem = ImageSubsystem;\r
281 if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {\r
282 //\r
283 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
284 // So patch ImageBuffer here to align the EntryPoint.\r
285 //\r
286 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);\r
287 ASSERT_EFI_ERROR (Status);\r
288 DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
289 }\r
290 DriverInfo->FileType = FileType;\r
291 DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1);\r
292 InitializeListHead (DriverInfoData->AllocInfoList);\r
293 DriverInfo->CurrentUsage = 0;\r
294 DriverInfo->PeakUsage = 0;\r
295 DriverInfo->AllocRecordCount = 0;\r
296\r
297 InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);\r
298 ContextData->Context.ImageCount ++;\r
299 ContextData->Context.TotalImageSize += DriverInfo->ImageSize;\r
300\r
301 return DriverInfoData;\r
302}\r
303\r
304/**\r
305 Register image to DXE.\r
306\r
307 @param FileName File name of the image.\r
308 @param ImageBase Image base address.\r
309 @param ImageSize Image size.\r
310 @param FileType File type of the image.\r
311\r
312**/\r
313VOID\r
314RegisterImageToDxe (\r
315 IN EFI_GUID *FileName,\r
316 IN PHYSICAL_ADDRESS ImageBase,\r
317 IN UINT64 ImageSize,\r
318 IN EFI_FV_FILETYPE FileType\r
319 )\r
320{\r
321 EFI_STATUS Status;\r
322 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;\r
323 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;\r
324 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];\r
325\r
326 if (IS_SMRAM_PROFILE_ENABLED) {\r
327\r
328 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;\r
329 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);\r
330 if (!EFI_ERROR (Status)) {\r
331 EfiInitializeFwVolDevicepathNode (FilePath, FileName);\r
332 SetDevicePathEndNode (FilePath + 1);\r
333\r
334 Status = ProfileProtocol->RegisterImage (\r
335 ProfileProtocol,\r
336 (EFI_DEVICE_PATH_PROTOCOL *) FilePath,\r
337 ImageBase,\r
338 ImageSize,\r
339 FileType\r
340 );\r
341 }\r
342 }\r
343}\r
344\r
345/**\r
346 Unregister image from DXE.\r
347\r
348 @param FileName File name of the image.\r
349 @param ImageBase Image base address.\r
350 @param ImageSize Image size.\r
351\r
352**/\r
353VOID\r
354UnregisterImageFromDxe (\r
355 IN EFI_GUID *FileName,\r
356 IN PHYSICAL_ADDRESS ImageBase,\r
357 IN UINT64 ImageSize\r
358 )\r
359{\r
360 EFI_STATUS Status;\r
361 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;\r
362 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;\r
363 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];\r
364\r
365 if (IS_SMRAM_PROFILE_ENABLED) {\r
366\r
367 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;\r
368 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID *) &ProfileProtocol);\r
369 if (!EFI_ERROR (Status)) {\r
370 EfiInitializeFwVolDevicepathNode (FilePath, FileName);\r
371 SetDevicePathEndNode (FilePath + 1);\r
372\r
373 Status = ProfileProtocol->UnregisterImage (\r
374 ProfileProtocol,\r
375 (EFI_DEVICE_PATH_PROTOCOL *) FilePath,\r
376 ImageBase,\r
377 ImageSize\r
378 );\r
379 }\r
380 }\r
381}\r
382\r
383/**\r
384 Register SMM Core to SMRAM profile.\r
385\r
386 @param ContextData SMRAM profile context.\r
387\r
388 @retval TRUE Register success.\r
389 @retval FALSE Register fail.\r
390\r
391**/\r
392BOOLEAN\r
393RegisterSmmCore (\r
394 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData\r
395 )\r
396{\r
397 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
398 PHYSICAL_ADDRESS ImageBase;\r
399\r
400 ASSERT (ContextData != NULL);\r
401\r
402 RegisterImageToDxe (\r
403 &gEfiCallerIdGuid,\r
404 gSmmCorePrivate->PiSmmCoreImageBase,\r
405 gSmmCorePrivate->PiSmmCoreImageSize,\r
406 EFI_FV_FILETYPE_SMM_CORE\r
407 );\r
408\r
409 ImageBase = gSmmCorePrivate->PiSmmCoreImageBase;\r
410 DriverInfoData = BuildDriverInfo (\r
411 ContextData,\r
412 &gEfiCallerIdGuid,\r
413 ImageBase,\r
414 gSmmCorePrivate->PiSmmCoreImageSize,\r
415 gSmmCorePrivate->PiSmmCoreEntryPoint,\r
416 InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase),\r
417 EFI_FV_FILETYPE_SMM_CORE\r
418 );\r
419 if (DriverInfoData == NULL) {\r
420 return FALSE;\r
421 }\r
422\r
423 return TRUE;\r
424}\r
425\r
426/**\r
427 Initialize SMRAM profile.\r
428\r
429**/\r
430VOID\r
431SmramProfileInit (\r
432 VOID\r
433 )\r
434{\r
435 MEMORY_PROFILE_CONTEXT_DATA *SmramProfileContext;\r
436\r
437 if (!IS_SMRAM_PROFILE_ENABLED) {\r
438 return;\r
439 }\r
440\r
441 SmramProfileContext = GetSmramProfileContext ();\r
442 if (SmramProfileContext != NULL) {\r
443 return;\r
444 }\r
445\r
446 mSmramProfileRecordingStatus = TRUE;\r
447 mSmramProfileContextPtr = &mSmramProfileContext;\r
448\r
449 RegisterSmmCore (&mSmramProfileContext);\r
450\r
451 DEBUG ((EFI_D_INFO, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext));\r
452}\r
453\r
454/**\r
455 Register SMM image to SMRAM profile.\r
456\r
457 @param DriverEntry SMM image info.\r
458 @param RegisterToDxe Register image to DXE.\r
459\r
460 @retval TRUE Register success.\r
461 @retval FALSE Register fail.\r
462\r
463**/\r
464BOOLEAN\r
465RegisterSmramProfileImage (\r
466 IN EFI_SMM_DRIVER_ENTRY *DriverEntry,\r
467 IN BOOLEAN RegisterToDxe\r
468 )\r
469{\r
470 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
471 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
472\r
473 if (!IS_SMRAM_PROFILE_ENABLED) {\r
474 return FALSE;\r
475 }\r
476\r
477 if (RegisterToDxe) {\r
478 RegisterImageToDxe (\r
479 &DriverEntry->FileName,\r
480 DriverEntry->ImageBuffer,\r
481 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),\r
482 EFI_FV_FILETYPE_SMM\r
483 );\r
484 }\r
485\r
486 ContextData = GetSmramProfileContext ();\r
487 if (ContextData == NULL) {\r
488 return FALSE;\r
489 }\r
490\r
491 DriverInfoData = BuildDriverInfo (\r
492 ContextData,\r
493 &DriverEntry->FileName,\r
494 DriverEntry->ImageBuffer,\r
495 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),\r
496 DriverEntry->ImageEntryPoint,\r
497 InternalPeCoffGetSubsystem ((VOID *) (UINTN) DriverEntry->ImageBuffer),\r
498 EFI_FV_FILETYPE_SMM\r
499 );\r
500 if (DriverInfoData == NULL) {\r
501 return FALSE;\r
502 }\r
503\r
504 return TRUE;\r
505}\r
506\r
507/**\r
508 Search image from memory profile.\r
509\r
510 @param ContextData Memory profile context.\r
511 @param FileName Image file name.\r
512 @param Address Image Address.\r
513\r
514 @return Pointer to memory profile driver info.\r
515\r
516**/\r
517MEMORY_PROFILE_DRIVER_INFO_DATA *\r
518GetMemoryProfileDriverInfoByFileNameAndAddress (\r
519 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,\r
520 IN EFI_GUID *FileName,\r
521 IN PHYSICAL_ADDRESS Address\r
522 )\r
523{\r
524 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
525 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
526 LIST_ENTRY *DriverLink;\r
527 LIST_ENTRY *DriverInfoList;\r
528\r
529 DriverInfoList = ContextData->DriverInfoList;\r
530\r
531 for (DriverLink = DriverInfoList->ForwardLink;\r
532 DriverLink != DriverInfoList;\r
533 DriverLink = DriverLink->ForwardLink) {\r
534 DriverInfoData = CR (\r
535 DriverLink,\r
536 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
537 Link,\r
538 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
539 );\r
540 DriverInfo = &DriverInfoData->DriverInfo;\r
541 if ((CompareGuid (&DriverInfo->FileName, FileName)) &&\r
542 (Address >= DriverInfo->ImageBase) &&\r
543 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {\r
544 return DriverInfoData;\r
545 }\r
546 }\r
547\r
548 return NULL;\r
549}\r
550\r
551/**\r
552 Search dummy image from SMRAM profile.\r
553\r
554 @param ContextData Memory profile context.\r
555\r
556 @return Pointer to memory profile driver info.\r
557\r
558**/\r
559MEMORY_PROFILE_DRIVER_INFO_DATA *\r
560FindDummyImage (\r
561 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData\r
562 )\r
563{\r
564 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
565 LIST_ENTRY *DriverLink;\r
566 LIST_ENTRY *DriverInfoList;\r
567\r
568 DriverInfoList = ContextData->DriverInfoList;\r
569\r
570 for (DriverLink = DriverInfoList->ForwardLink;\r
571 DriverLink != DriverInfoList;\r
572 DriverLink = DriverLink->ForwardLink) {\r
573 DriverInfoData = CR (\r
574 DriverLink,\r
575 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
576 Link,\r
577 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
578 );\r
579 if (CompareGuid (&gZeroGuid, &DriverInfoData->DriverInfo.FileName)) {\r
580 return DriverInfoData;\r
581 }\r
582 }\r
583\r
584 return BuildDriverInfo (ContextData, &gZeroGuid, 0, 0, 0, 0, 0);\r
585}\r
586\r
587/**\r
588 Search image from memory profile.\r
589 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)\r
590\r
591 @param ContextData Memory profile context.\r
592 @param Address Image or Function address.\r
593\r
594 @return Pointer to memory profile driver info.\r
595\r
596**/\r
597MEMORY_PROFILE_DRIVER_INFO_DATA *\r
598GetMemoryProfileDriverInfoFromAddress (\r
599 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,\r
600 IN PHYSICAL_ADDRESS Address\r
601 )\r
602{\r
603 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
604 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
605 LIST_ENTRY *DriverLink;\r
606 LIST_ENTRY *DriverInfoList;\r
607\r
608 DriverInfoList = ContextData->DriverInfoList;\r
609\r
610 for (DriverLink = DriverInfoList->ForwardLink;\r
611 DriverLink != DriverInfoList;\r
612 DriverLink = DriverLink->ForwardLink) {\r
613 DriverInfoData = CR (\r
614 DriverLink,\r
615 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
616 Link,\r
617 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
618 );\r
619 DriverInfo = &DriverInfoData->DriverInfo;\r
620 if ((Address >= DriverInfo->ImageBase) &&\r
621 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {\r
622 return DriverInfoData;\r
623 }\r
624 }\r
625\r
626 //\r
627 // Should never come here.\r
628 //\r
629 return FindDummyImage (ContextData);\r
630}\r
631\r
632/**\r
633 Unregister image from SMRAM profile.\r
634\r
635 @param DriverEntry SMM image info.\r
636 @param UnregisterFromDxe Unregister image from DXE.\r
637\r
638 @retval TRUE Unregister success.\r
639 @retval FALSE Unregister fail.\r
640\r
641**/\r
642BOOLEAN\r
643UnregisterSmramProfileImage (\r
644 IN EFI_SMM_DRIVER_ENTRY *DriverEntry,\r
645 IN BOOLEAN UnregisterFromDxe\r
646 )\r
647{\r
648 EFI_STATUS Status;\r
649 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
650 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
651 EFI_GUID *FileName;\r
652 PHYSICAL_ADDRESS ImageAddress;\r
653 VOID *EntryPointInImage;\r
654\r
655 if (!IS_SMRAM_PROFILE_ENABLED) {\r
656 return FALSE;\r
657 }\r
658\r
659 if (UnregisterFromDxe) {\r
660 UnregisterImageFromDxe (\r
661 &DriverEntry->FileName,\r
662 DriverEntry->ImageBuffer,\r
663 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)\r
664 );\r
665 }\r
666\r
667 ContextData = GetSmramProfileContext ();\r
668 if (ContextData == NULL) {\r
669 return FALSE;\r
670 }\r
671\r
672 DriverInfoData = NULL;\r
673 FileName = &DriverEntry->FileName;\r
674 ImageAddress = DriverEntry->ImageBuffer;\r
675 if ((DriverEntry->ImageEntryPoint < ImageAddress) || (DriverEntry->ImageEntryPoint >= (ImageAddress + EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)))) {\r
676 //\r
677 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
678 // So patch ImageAddress here to align the EntryPoint.\r
679 //\r
680 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage);\r
681 ASSERT_EFI_ERROR (Status);\r
682 ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageEntryPoint - (UINTN) EntryPointInImage;\r
683 }\r
684 if (FileName != NULL) {\r
685 DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);\r
686 }\r
687 if (DriverInfoData == NULL) {\r
688 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);\r
689 }\r
690 if (DriverInfoData == NULL) {\r
691 return FALSE;\r
692 }\r
693\r
694 ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;\r
695\r
696 DriverInfoData->DriverInfo.ImageBase = 0;\r
697 DriverInfoData->DriverInfo.ImageSize = 0;\r
698\r
699 if (DriverInfoData->DriverInfo.PeakUsage == 0) {\r
700 ContextData->Context.ImageCount --;\r
701 RemoveEntryList (&DriverInfoData->Link);\r
702 //\r
703 // Use SmmInternalFreePool() that will not update profile for this FreePool action.\r
704 //\r
705 SmmInternalFreePool (DriverInfoData);\r
706 }\r
707\r
708 return TRUE;\r
709}\r
710\r
711/**\r
712 Return if this memory type needs to be recorded into memory profile.\r
ca949d9d 713 Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile.\r
84edd20b
SZ
714\r
715 @param MemoryType Memory type.\r
716\r
717 @retval TRUE This memory type need to be recorded.\r
718 @retval FALSE This memory type need not to be recorded.\r
719\r
720**/\r
721BOOLEAN\r
722SmmCoreNeedRecordProfile (\r
723 IN EFI_MEMORY_TYPE MemoryType\r
724 )\r
725{\r
726 UINT64 TestBit;\r
727\r
ca949d9d
SZ
728 if (MemoryType != EfiRuntimeServicesCode &&\r
729 MemoryType != EfiRuntimeServicesData) {\r
730 return FALSE;\r
84edd20b
SZ
731 }\r
732\r
ca949d9d
SZ
733 TestBit = LShiftU64 (1, MemoryType);\r
734\r
84edd20b
SZ
735 if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {\r
736 return TRUE;\r
737 } else {\r
738 return FALSE;\r
739 }\r
740}\r
741\r
742/**\r
743 Convert EFI memory type to profile memory index. The rule is:\r
ca949d9d
SZ
744 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.\r
745 As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData,\r
746 so return input memory type directly.\r
84edd20b
SZ
747\r
748 @param MemoryType Memory type.\r
749\r
750 @return EFI memory type as profile memory index.\r
751\r
752**/\r
753EFI_MEMORY_TYPE\r
754GetProfileMemoryIndex (\r
755 IN EFI_MEMORY_TYPE MemoryType\r
756 )\r
757{\r
ca949d9d 758 return MemoryType;\r
84edd20b
SZ
759}\r
760\r
761/**\r
762 Update SMRAM profile FreeMemoryPages information\r
763\r
764 @param ContextData Memory profile context.\r
765\r
766**/\r
767VOID\r
768SmramProfileUpdateFreePages (\r
769 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData\r
770 )\r
771{\r
772 LIST_ENTRY *Node;\r
773 FREE_PAGE_LIST *Pages;\r
774 LIST_ENTRY *FreePageList;\r
775 UINTN NumberOfPages;\r
776\r
777 NumberOfPages = 0;\r
778 FreePageList = &mSmmMemoryMap;\r
779 for (Node = FreePageList->BackLink;\r
780 Node != FreePageList;\r
781 Node = Node->BackLink) {\r
782 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
783 NumberOfPages += Pages->NumberOfPages;\r
784 }\r
785\r
786 mSmramFreeMemory.TotalFreeMemoryPages = NumberOfPages;\r
787\r
788 if (NumberOfPages <= SMRAM_INFO_DUMP_PAGE_THRESHOLD) {\r
789 DumpSmramInfo ();\r
790 }\r
791}\r
792\r
793/**\r
794 Update SMRAM profile Allocate information.\r
795\r
796 @param CallerAddress Address of caller who call Allocate.\r
797 @param Action This Allocate action.\r
798 @param MemoryType Memory type.\r
799 @param Size Buffer size.\r
800 @param Buffer Buffer address.\r
801\r
802 @retval TRUE Profile udpate success.\r
803 @retval FALSE Profile update fail.\r
804\r
805**/\r
806BOOLEAN\r
807SmmCoreUpdateProfileAllocate (\r
808 IN PHYSICAL_ADDRESS CallerAddress,\r
809 IN MEMORY_PROFILE_ACTION Action,\r
810 IN EFI_MEMORY_TYPE MemoryType,\r
811 IN UINTN Size,\r
812 IN VOID *Buffer\r
813 )\r
814{\r
815 EFI_STATUS Status;\r
816 MEMORY_PROFILE_CONTEXT *Context;\r
817 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
818 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
819 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
820 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
821 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
822 EFI_MEMORY_TYPE ProfileMemoryIndex;\r
823\r
f4420027
SZ
824 AllocInfoData = NULL;\r
825\r
84edd20b
SZ
826 ContextData = GetSmramProfileContext ();\r
827 if (ContextData == NULL) {\r
828 return FALSE;\r
829 }\r
830\r
831 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);\r
832 ASSERT (DriverInfoData != NULL);\r
833\r
834 //\r
835 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.\r
836 //\r
837 Status = SmmInternalAllocatePool (\r
838 EfiRuntimeServicesData,\r
839 sizeof (*AllocInfoData),\r
840 (VOID **) &AllocInfoData\r
841 );\r
842 if (EFI_ERROR (Status)) {\r
843 return FALSE;\r
844 }\r
845 AllocInfo = &AllocInfoData->AllocInfo;\r
846 AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;\r
847 AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;\r
848 AllocInfo->Header.Length = sizeof (MEMORY_PROFILE_ALLOC_INFO);\r
849 AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION;\r
850 AllocInfo->CallerAddress = CallerAddress;\r
851 AllocInfo->SequenceId = ContextData->Context.SequenceCount;\r
852 AllocInfo->Action = Action;\r
853 AllocInfo->MemoryType = MemoryType;\r
854 AllocInfo->Buffer = (PHYSICAL_ADDRESS) (UINTN) Buffer;\r
855 AllocInfo->Size = Size;\r
856\r
857 InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);\r
858\r
859 ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);\r
860\r
861 DriverInfo = &DriverInfoData->DriverInfo;\r
862 DriverInfo->CurrentUsage += Size;\r
863 if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {\r
864 DriverInfo->PeakUsage = DriverInfo->CurrentUsage;\r
865 }\r
866 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;\r
867 if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {\r
868 DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];\r
869 }\r
870 DriverInfo->AllocRecordCount ++;\r
871\r
872 Context = &ContextData->Context;\r
873 Context->CurrentTotalUsage += Size;\r
874 if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {\r
875 Context->PeakTotalUsage = Context->CurrentTotalUsage;\r
876 }\r
877 Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;\r
878 if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {\r
879 Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];\r
880 }\r
881 Context->SequenceCount ++;\r
882\r
883 SmramProfileUpdateFreePages (ContextData);\r
884 return TRUE;\r
885}\r
886\r
887/**\r
888 Get memory profile alloc info from memory profile\r
889\r
890 @param DriverInfoData Driver info\r
891 @param Action This Free action\r
892 @param Size Buffer size\r
893 @param Buffer Buffer address\r
894\r
895 @return Pointer to memory profile alloc info.\r
896**/\r
897MEMORY_PROFILE_ALLOC_INFO_DATA *\r
898GetMemoryProfileAllocInfoFromAddress (\r
899 IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData,\r
900 IN MEMORY_PROFILE_ACTION Action,\r
901 IN UINTN Size,\r
902 IN VOID *Buffer\r
903 )\r
904{\r
905 LIST_ENTRY *AllocInfoList;\r
906 LIST_ENTRY *AllocLink;\r
907 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
908 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
909\r
910 AllocInfoList = DriverInfoData->AllocInfoList;\r
911\r
912 for (AllocLink = AllocInfoList->ForwardLink;\r
913 AllocLink != AllocInfoList;\r
914 AllocLink = AllocLink->ForwardLink) {\r
915 AllocInfoData = CR (\r
916 AllocLink,\r
917 MEMORY_PROFILE_ALLOC_INFO_DATA,\r
918 Link,\r
919 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
920 );\r
921 AllocInfo = &AllocInfoData->AllocInfo;\r
922 if (AllocInfo->Action != Action) {\r
923 continue;\r
924 }\r
925 switch (Action) {\r
926 case MemoryProfileActionAllocatePages:\r
927 if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&\r
928 ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) {\r
929 return AllocInfoData;\r
930 }\r
931 break;\r
932 case MemoryProfileActionAllocatePool:\r
933 if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {\r
934 return AllocInfoData;\r
935 }\r
936 break;\r
937 default:\r
938 ASSERT (FALSE);\r
939 break;\r
940 }\r
941 }\r
942\r
943 return NULL;\r
944}\r
945\r
946/**\r
947 Update SMRAM profile Free information.\r
948\r
949 @param CallerAddress Address of caller who call Free.\r
950 @param Action This Free action.\r
951 @param Size Buffer size.\r
952 @param Buffer Buffer address.\r
953\r
954 @retval TRUE Profile udpate success.\r
955 @retval FALSE Profile update fail.\r
956\r
957**/\r
958BOOLEAN\r
959SmmCoreUpdateProfileFree (\r
960 IN PHYSICAL_ADDRESS CallerAddress,\r
961 IN MEMORY_PROFILE_ACTION Action,\r
962 IN UINTN Size,\r
963 IN VOID *Buffer\r
964 )\r
965{\r
966 MEMORY_PROFILE_CONTEXT *Context;\r
967 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
968 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
969 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
970 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
971 LIST_ENTRY *DriverLink;\r
972 LIST_ENTRY *DriverInfoList;\r
973 MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData;\r
974 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
975 EFI_MEMORY_TYPE ProfileMemoryIndex;\r
976\r
977 ContextData = GetSmramProfileContext ();\r
978 if (ContextData == NULL) {\r
979 return FALSE;\r
980 }\r
981\r
982 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);\r
983 ASSERT (DriverInfoData != NULL);\r
984\r
985 switch (Action) {\r
986 case MemoryProfileActionFreePages:\r
987 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);\r
988 break;\r
989 case MemoryProfileActionFreePool:\r
990 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);\r
991 break;\r
992 default:\r
993 ASSERT (FALSE);\r
994 AllocInfoData = NULL;\r
995 break;\r
996 }\r
997 if (AllocInfoData == NULL) {\r
998 //\r
999 // Legal case, because driver A might free memory allocated by driver B, by some protocol.\r
1000 //\r
1001 DriverInfoList = ContextData->DriverInfoList;\r
1002\r
1003 for (DriverLink = DriverInfoList->ForwardLink;\r
1004 DriverLink != DriverInfoList;\r
1005 DriverLink = DriverLink->ForwardLink) {\r
1006 ThisDriverInfoData = CR (\r
1007 DriverLink,\r
1008 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1009 Link,\r
1010 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1011 );\r
1012 switch (Action) {\r
1013 case MemoryProfileActionFreePages:\r
1014 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);\r
1015 break;\r
1016 case MemoryProfileActionFreePool:\r
1017 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);\r
1018 break;\r
1019 default:\r
1020 ASSERT (FALSE);\r
1021 AllocInfoData = NULL;\r
1022 break;\r
1023 }\r
1024 if (AllocInfoData != NULL) {\r
1025 DriverInfoData = ThisDriverInfoData;\r
1026 break;\r
1027 }\r
1028 }\r
1029\r
1030 if (AllocInfoData == NULL) {\r
1031 //\r
1032 // No matched allocate operation is found for this free operation.\r
1033 // It is because the specified memory type allocate operation has been\r
1034 // filtered by CoreNeedRecordProfile(), but free operations have no\r
1035 // memory type information, they can not be filtered by CoreNeedRecordProfile().\r
1036 // Then, they will be filtered here.\r
1037 //\r
1038 return FALSE;\r
1039 }\r
1040 }\r
1041\r
1042 Context = &ContextData->Context;\r
1043 DriverInfo = &DriverInfoData->DriverInfo;\r
1044 AllocInfo = &AllocInfoData->AllocInfo;\r
1045\r
1046 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);\r
1047\r
1048 Context->CurrentTotalUsage -= AllocInfo->Size;\r
1049 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;\r
1050\r
1051 DriverInfo->CurrentUsage -= AllocInfo->Size;\r
1052 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;\r
1053 DriverInfo->AllocRecordCount --;\r
1054\r
1055 RemoveEntryList (&AllocInfoData->Link);\r
1056\r
1057 if (Action == MemoryProfileActionFreePages) {\r
1058 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {\r
1059 SmmCoreUpdateProfileAllocate (\r
1060 AllocInfo->CallerAddress,\r
1061 MemoryProfileActionAllocatePages,\r
1062 AllocInfo->MemoryType,\r
1063 (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),\r
1064 (VOID *) (UINTN) AllocInfo->Buffer\r
1065 );\r
1066 }\r
1067 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {\r
1068 SmmCoreUpdateProfileAllocate (\r
1069 AllocInfo->CallerAddress,\r
1070 MemoryProfileActionAllocatePages,\r
1071 AllocInfo->MemoryType,\r
1072 (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),\r
1073 (VOID *) ((UINTN) Buffer + Size)\r
1074 );\r
1075 }\r
1076 }\r
1077\r
1078 //\r
1079 // Use SmmInternalFreePool() that will not update profile for this FreePool action.\r
1080 //\r
1081 SmmInternalFreePool (AllocInfoData);\r
1082\r
1083 return TRUE;\r
1084}\r
1085\r
1086/**\r
1087 Update SMRAM profile information.\r
1088\r
1089 @param CallerAddress Address of caller who call Allocate or Free.\r
1090 @param Action This Allocate or Free action.\r
1091 @param MemoryType Memory type.\r
1092 @param Size Buffer size.\r
1093 @param Buffer Buffer address.\r
1094\r
1095 @retval TRUE Profile udpate success.\r
1096 @retval FALSE Profile update fail.\r
1097\r
1098**/\r
1099BOOLEAN\r
1100SmmCoreUpdateProfile (\r
1101 IN PHYSICAL_ADDRESS CallerAddress,\r
1102 IN MEMORY_PROFILE_ACTION Action,\r
1103 IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool\r
1104 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool\r
1105 IN VOID *Buffer\r
1106 )\r
1107{\r
1108 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1109\r
1110 if (!IS_SMRAM_PROFILE_ENABLED) {\r
1111 return FALSE;\r
1112 }\r
1113\r
1114 if (!mSmramProfileRecordingStatus) {\r
1115 return FALSE;\r
1116 }\r
1117\r
1118 //\r
1119 // Free operations have no memory type information, so skip the check.\r
1120 //\r
1121 if ((Action == MemoryProfileActionAllocatePages) || (Action == MemoryProfileActionAllocatePool)) {\r
1122 //\r
1123 // Only record limited MemoryType.\r
1124 //\r
1125 if (!SmmCoreNeedRecordProfile (MemoryType)) {\r
1126 return FALSE;\r
1127 }\r
1128 }\r
1129\r
1130 ContextData = GetSmramProfileContext ();\r
1131 if (ContextData == NULL) {\r
1132 return FALSE;\r
1133 }\r
1134\r
1135 switch (Action) {\r
1136 case MemoryProfileActionAllocatePages:\r
1137 SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);\r
1138 break;\r
1139 case MemoryProfileActionFreePages:\r
1140 SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);\r
1141 break;\r
1142 case MemoryProfileActionAllocatePool:\r
1143 SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);\r
1144 break;\r
1145 case MemoryProfileActionFreePool:\r
1146 SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);\r
1147 break;\r
1148 default:\r
1149 ASSERT (FALSE);\r
1150 break;\r
1151 }\r
1152\r
1153 return TRUE;\r
1154}\r
1155\r
1156/**\r
1157 SMRAM profile ready to lock callback function.\r
1158\r
1159**/\r
1160VOID\r
1161SmramProfileReadyToLock (\r
1162 VOID\r
1163 )\r
1164{\r
1165 if (!IS_SMRAM_PROFILE_ENABLED) {\r
1166 return;\r
1167 }\r
1168\r
1169 DEBUG ((EFI_D_INFO, "SmramProfileReadyToLock\n"));\r
1170 mSmramReadyToLock = TRUE;\r
1171}\r
1172\r
1173////////////////////\r
1174\r
84edd20b
SZ
1175/**\r
1176 Get SMRAM profile data size.\r
1177\r
1178 @return SMRAM profile data size.\r
1179\r
1180**/\r
1181UINTN\r
1182SmramProfileGetDataSize (\r
1183 VOID\r
1184 )\r
1185{\r
1186 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1187 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1188 LIST_ENTRY *DriverInfoList;\r
1189 LIST_ENTRY *DriverLink;\r
1190 UINTN TotalSize;\r
1191 LIST_ENTRY *Node;\r
1192 LIST_ENTRY *FreePageList;\r
1193 LIST_ENTRY *FreePoolList;\r
1194 FREE_POOL_HEADER *Pool;\r
1195 UINTN PoolListIndex;\r
1196 UINTN Index;\r
1197\r
1198 ContextData = GetSmramProfileContext ();\r
1199 if (ContextData == NULL) {\r
1200 return 0;\r
1201 }\r
1202\r
1203 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);\r
1204 TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount;\r
1205\r
1206 DriverInfoList = ContextData->DriverInfoList;\r
1207 for (DriverLink = DriverInfoList->ForwardLink;\r
1208 DriverLink != DriverInfoList;\r
1209 DriverLink = DriverLink->ForwardLink) {\r
1210 DriverInfoData = CR (\r
1211 DriverLink,\r
1212 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1213 Link,\r
1214 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1215 );\r
1216 TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfoData->DriverInfo.AllocRecordCount;\r
1217 }\r
1218\r
1219\r
1220 Index = 0;\r
1221 FreePageList = &mSmmMemoryMap;\r
1222 for (Node = FreePageList->BackLink;\r
1223 Node != FreePageList;\r
1224 Node = Node->BackLink) {\r
1225 Index++;\r
1226 }\r
1227 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1228 FreePoolList = &mSmmPoolLists[PoolListIndex];\r
1229 for (Node = FreePoolList->BackLink;\r
1230 Node != FreePoolList;\r
1231 Node = Node->BackLink) {\r
1232 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1233 if (Pool->Header.Available) {\r
1234 Index++;\r
1235 }\r
1236 }\r
1237 }\r
1238\r
1239\r
1240 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));\r
1241 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));\r
1242\r
1243 return TotalSize;\r
1244}\r
1245\r
1246/**\r
1247 Copy SMRAM profile data.\r
1248\r
1249 @param ProfileBuffer The buffer to hold SMRAM profile data.\r
1250\r
1251**/\r
1252VOID\r
1253SmramProfileCopyData (\r
1254 IN VOID *ProfileBuffer\r
1255 )\r
1256{\r
1257 MEMORY_PROFILE_CONTEXT *Context;\r
1258 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
1259 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
1260 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1261 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1262 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
1263 LIST_ENTRY *DriverInfoList;\r
1264 LIST_ENTRY *DriverLink;\r
1265 LIST_ENTRY *AllocInfoList;\r
1266 LIST_ENTRY *AllocLink;\r
1267 LIST_ENTRY *Node;\r
1268 FREE_PAGE_LIST *Pages;\r
1269 LIST_ENTRY *FreePageList;\r
1270 LIST_ENTRY *FreePoolList;\r
1271 FREE_POOL_HEADER *Pool;\r
1272 UINTN PoolListIndex;\r
1273 UINT32 Index;\r
1274 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;\r
1275 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;\r
1276 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor;\r
1277\r
1278 ContextData = GetSmramProfileContext ();\r
1279 if (ContextData == NULL) {\r
1280 return ;\r
1281 }\r
1282\r
1283 Context = ProfileBuffer;\r
1284 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));\r
1285 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);\r
1286\r
1287 DriverInfoList = ContextData->DriverInfoList;\r
1288 for (DriverLink = DriverInfoList->ForwardLink;\r
1289 DriverLink != DriverInfoList;\r
1290 DriverLink = DriverLink->ForwardLink) {\r
1291 DriverInfoData = CR (\r
1292 DriverLink,\r
1293 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1294 Link,\r
1295 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1296 );\r
1297 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));\r
1298 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1);\r
1299\r
1300 AllocInfoList = DriverInfoData->AllocInfoList;\r
1301 for (AllocLink = AllocInfoList->ForwardLink;\r
1302 AllocLink != AllocInfoList;\r
1303 AllocLink = AllocLink->ForwardLink) {\r
1304 AllocInfoData = CR (\r
1305 AllocLink,\r
1306 MEMORY_PROFILE_ALLOC_INFO_DATA,\r
1307 Link,\r
1308 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
1309 );\r
1310 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));\r
1311 AllocInfo += 1;\r
1312 }\r
1313\r
1314 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount);\r
1315 }\r
1316\r
1317\r
1318 FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) DriverInfo;\r
1319 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));\r
1320 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (FreeMemory + 1);\r
1321 Index = 0;\r
1322 FreePageList = &mSmmMemoryMap;\r
1323 for (Node = FreePageList->BackLink;\r
1324 Node != FreePageList;\r
1325 Node = Node->BackLink) {\r
1326 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
1327 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1328 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1329 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1330 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages;\r
1331 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);\r
1332 MemoryProfileDescriptor++;\r
1333 Index++;\r
1334 }\r
1335 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1336 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];\r
1337 for (Node = FreePoolList->BackLink;\r
1338 Node != FreePoolList;\r
1339 Node = Node->BackLink) {\r
1340 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1341 if (Pool->Header.Available) {\r
1342 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1343 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1344 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1345 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool;\r
1346 MemoryProfileDescriptor->Size = Pool->Header.Size;\r
1347 MemoryProfileDescriptor++;\r
1348 Index++;\r
1349 }\r
1350 }\r
1351 }\r
1352 FreeMemory->FreeMemoryEntryCount = Index;\r
1353\r
1354 MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) MemoryProfileDescriptor;\r
1355 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;\r
1356 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);\r
1357 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;\r
1358 MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount;\r
1359 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (MemoryRange + 1);\r
1360 for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
1361 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1362 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1363 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1364 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;\r
1365 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;\r
1366 MemoryProfileDescriptor++; \r
1367 }\r
1368}\r
1369\r
1370/**\r
1371 SMRAM profile handler to get profile info.\r
1372\r
1373 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.\r
1374\r
1375**/\r
1376VOID\r
1377SmramProfileHandlerGetInfo (\r
1378 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo\r
1379 )\r
1380{\r
1381 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1382 BOOLEAN SmramProfileRecordingStatus;\r
1383\r
1384 ContextData = GetSmramProfileContext ();\r
1385 if (ContextData == NULL) {\r
1386 return ;\r
1387 }\r
1388\r
1389 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1390 mSmramProfileRecordingStatus = FALSE;\r
1391\r
1392 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();\r
1393 SmramProfileParameterGetInfo->Header.ReturnStatus = 0;\r
1394\r
1395 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1396}\r
1397\r
1398/**\r
1399 SMRAM profile handler to get profile data.\r
1400\r
1401 @param SmramProfileParameterGetData The parameter of SMM profile get data.\r
1402\r
1403**/\r
1404VOID\r
1405SmramProfileHandlerGetData (\r
1406 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData\r
1407 )\r
1408{\r
1409 UINT64 ProfileSize;\r
1410 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData;\r
1411 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1412 BOOLEAN SmramProfileRecordingStatus;\r
1413\r
1414 ContextData = GetSmramProfileContext ();\r
1415 if (ContextData == NULL) {\r
1416 return ;\r
1417 }\r
1418\r
1419 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1420 mSmramProfileRecordingStatus = FALSE;\r
1421\r
1422\r
1423 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));\r
1424\r
1425 ProfileSize = SmramProfileGetDataSize();\r
1426\r
1427 //\r
1428 // Sanity check\r
1429 //\r
842b1242 1430 if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {\r
84edd20b
SZ
1431 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));\r
1432 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1433 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;\r
1434 goto Done;\r
1435 }\r
1436\r
1437 if (SmramProfileGetData.ProfileSize < ProfileSize) {\r
1438 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1439 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL;\r
1440 goto Done;\r
1441 }\r
1442\r
1443 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1444 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer);\r
1445 SmramProfileParameterGetData->Header.ReturnStatus = 0;\r
1446\r
1447Done:\r
1448 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1449}\r
1450\r
1451/**\r
1452 SMRAM profile handler to register SMM image.\r
1453\r
1454 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.\r
1455\r
1456**/\r
1457VOID\r
1458SmramProfileHandlerRegisterImage (\r
1459 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage\r
1460 )\r
1461{\r
1462 EFI_STATUS Status;\r
1463 EFI_SMM_DRIVER_ENTRY DriverEntry;\r
1464 VOID *EntryPointInImage;\r
1465 BOOLEAN Ret;\r
1466\r
1467 ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
1468 CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));\r
1469 DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer;\r
1470 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage;\r
1471 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
1472 ASSERT_EFI_ERROR (Status);\r
1473 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
1474\r
1475 Ret = RegisterSmramProfileImage (&DriverEntry, FALSE);\r
1476 if (Ret) {\r
1477 SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;\r
1478 }\r
1479}\r
1480\r
1481/**\r
1482 SMRAM profile handler to unregister SMM image.\r
1483\r
1484 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.\r
1485\r
1486**/\r
1487VOID\r
1488SmramProfileHandlerUnregisterImage (\r
1489 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage\r
1490 )\r
1491{\r
1492 EFI_STATUS Status;\r
1493 EFI_SMM_DRIVER_ENTRY DriverEntry;\r
1494 VOID *EntryPointInImage;\r
1495 BOOLEAN Ret;\r
1496\r
1497 ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
1498 CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));\r
1499 DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer;\r
1500 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage;\r
1501 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
1502 ASSERT_EFI_ERROR (Status);\r
1503 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
1504\r
1505 Ret = UnregisterSmramProfileImage (&DriverEntry, FALSE);\r
1506 if (Ret) {\r
1507 SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;\r
1508 }\r
1509}\r
1510\r
1511/**\r
1512 Dispatch function for a Software SMI handler.\r
1513\r
1514 Caution: This function may receive untrusted input.\r
1515 Communicate buffer and buffer size are external input, so this function will do basic validation.\r
1516\r
1517 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
1518 @param Context Points to an optional handler context which was specified when the\r
1519 handler was registered.\r
1520 @param CommBuffer A pointer to a collection of data in memory that will\r
1521 be conveyed from a non-SMM environment into an SMM environment.\r
1522 @param CommBufferSize The size of the CommBuffer.\r
1523\r
1524 @retval EFI_SUCCESS Command is handled successfully.\r
1525\r
1526**/\r
1527EFI_STATUS\r
1528EFIAPI\r
1529SmramProfileHandler (\r
1530 IN EFI_HANDLE DispatchHandle,\r
1531 IN CONST VOID *Context OPTIONAL,\r
1532 IN OUT VOID *CommBuffer OPTIONAL,\r
1533 IN OUT UINTN *CommBufferSize OPTIONAL\r
1534 )\r
1535{\r
1536 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader;\r
1537 UINTN TempCommBufferSize;\r
1538\r
1539 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));\r
1540\r
1541 //\r
1542 // If input is invalid, stop processing this SMI\r
1543 //\r
1544 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
1545 return EFI_SUCCESS;\r
1546 }\r
1547\r
1548 TempCommBufferSize = *CommBufferSize;\r
1549\r
1550 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {\r
1551 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1552 return EFI_SUCCESS;\r
1553 }\r
1554\r
842b1242 1555 if (mSmramReadyToLock && !SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
84edd20b
SZ
1556 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
1557 return EFI_SUCCESS;\r
1558 }\r
1559\r
1560 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer);\r
1561\r
1562 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;\r
1563\r
1564 if (GetSmramProfileContext () == NULL) {\r
1565 SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED;\r
1566 return EFI_SUCCESS;\r
1567 }\r
1568\r
1569 switch (SmramProfileParameterHeader->Command) {\r
1570 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:\r
1571 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n"));\r
1572 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {\r
1573 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1574 return EFI_SUCCESS;\r
1575 }\r
1576 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer);\r
1577 break;\r
1578 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:\r
1579 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n"));\r
1580 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {\r
1581 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1582 return EFI_SUCCESS;\r
1583 }\r
1584 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);\r
1585 break;\r
1586 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE:\r
1587 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n"));\r
1588 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) {\r
1589 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1590 return EFI_SUCCESS;\r
1591 }\r
1592 if (mSmramReadyToLock) {\r
1593 return EFI_SUCCESS;\r
1594 }\r
1595 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer);\r
1596 break;\r
1597 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE:\r
1598 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n"));\r
1599 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) {\r
1600 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1601 return EFI_SUCCESS;\r
1602 }\r
1603 if (mSmramReadyToLock) {\r
1604 return EFI_SUCCESS;\r
1605 }\r
1606 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);\r
1607 break;\r
1608 default:\r
1609 break;\r
1610 }\r
1611\r
1612 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n"));\r
1613\r
1614 return EFI_SUCCESS;\r
1615}\r
1616\r
1617/**\r
1618 Register SMRAM profile handler.\r
1619\r
1620**/\r
1621VOID\r
1622RegisterSmramProfileHandler (\r
1623 VOID\r
1624 )\r
1625{\r
1626 EFI_STATUS Status;\r
1627 EFI_HANDLE DispatchHandle;\r
1628\r
1629 if (!IS_SMRAM_PROFILE_ENABLED) {\r
1630 return;\r
1631 }\r
1632\r
1633 Status = SmiHandlerRegister (\r
1634 SmramProfileHandler,\r
1635 &gEdkiiMemoryProfileGuid,\r
1636 &DispatchHandle\r
1637 );\r
1638 ASSERT_EFI_ERROR (Status);\r
1639}\r
1640\r
1641////////////////////\r
1642\r
1643/**\r
1644 Dump SMRAM range.\r
1645\r
1646**/\r
1647VOID\r
1648DumpSmramRange (\r
1649 VOID\r
1650 )\r
1651{\r
1652 UINTN Index;\r
1653 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1654 BOOLEAN SmramProfileRecordingStatus;\r
1655\r
1656 ContextData = GetSmramProfileContext ();\r
1657 if (ContextData == NULL) {\r
1658 return ;\r
1659 }\r
1660\r
1661 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1662 mSmramProfileRecordingStatus = FALSE;\r
1663\r
1664 DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));\r
1665\r
1666 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1667\r
1668 DEBUG ((EFI_D_INFO, "FullSmramRange:\n"));\r
1669 for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
1670 DEBUG ((EFI_D_INFO, " FullSmramRange (0x%x)\n", Index));\r
1671 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));\r
1672 DEBUG ((EFI_D_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));\r
1673 DEBUG ((EFI_D_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));\r
1674 DEBUG ((EFI_D_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState));\r
1675 }\r
1676\r
1677 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1678\r
1679 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1680}\r
1681\r
1682/**\r
1683 Dump SMRAM free page list.\r
1684\r
1685**/\r
1686VOID\r
1687DumpFreePagesList (\r
1688 VOID\r
1689 )\r
1690{\r
1691 LIST_ENTRY *FreePageList;\r
1692 LIST_ENTRY *Node;\r
1693 FREE_PAGE_LIST *Pages;\r
1694 UINTN Index;\r
1695 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1696 BOOLEAN SmramProfileRecordingStatus;\r
1697\r
1698 ContextData = GetSmramProfileContext ();\r
1699 if (ContextData == NULL) {\r
1700 return ;\r
1701 }\r
1702\r
1703 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1704 mSmramProfileRecordingStatus = FALSE;\r
1705\r
1706 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1707\r
1708 DEBUG ((EFI_D_INFO, "FreePagesList:\n"));\r
1709 FreePageList = &mSmmMemoryMap;\r
1710 for (Node = FreePageList->BackLink, Index = 0;\r
1711 Node != FreePageList;\r
1712 Node = Node->BackLink, Index++) {\r
1713 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
1714 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));\r
1715 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages));\r
1716 DEBUG ((EFI_D_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages));\r
1717 }\r
1718\r
1719 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1720\r
1721 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1722}\r
1723\r
1724/**\r
1725 Dump SMRAM free pool list.\r
1726\r
1727**/\r
1728VOID\r
1729DumpFreePoolList (\r
1730 VOID\r
1731 )\r
1732{\r
1733 LIST_ENTRY *FreePoolList;\r
1734 LIST_ENTRY *Node;\r
1735 FREE_POOL_HEADER *Pool;\r
1736 UINTN Index;\r
1737 UINTN PoolListIndex;\r
1738 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1739 BOOLEAN SmramProfileRecordingStatus;\r
1740\r
1741 ContextData = GetSmramProfileContext ();\r
1742 if (ContextData == NULL) {\r
1743 return ;\r
1744 }\r
1745\r
1746 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1747 mSmramProfileRecordingStatus = FALSE;\r
1748\r
1749 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1750\r
1751 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1752 DEBUG ((EFI_D_INFO, "FreePoolList (%d):\n", PoolListIndex));\r
1753 FreePoolList = &mSmmPoolLists[PoolListIndex];\r
1754 for (Node = FreePoolList->BackLink, Index = 0;\r
1755 Node != FreePoolList;\r
1756 Node = Node->BackLink, Index++) {\r
1757 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1758 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));\r
1759 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool));\r
1760 DEBUG ((EFI_D_INFO, " Size - 0x%08x\n", Pool->Header.Size));\r
1761 DEBUG ((EFI_D_INFO, " Available - 0x%02x\n", Pool->Header.Available));\r
1762 }\r
1763 }\r
1764\r
1765 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1766\r
1767 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1768}\r
1769\r
1770GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = {\r
1771 L"Unknown",\r
1772 L"AllocatePages",\r
1773 L"FreePages",\r
1774 L"AllocatePool",\r
1775 L"FreePool",\r
1776};\r
1777\r
ca949d9d
SZ
1778typedef struct {\r
1779 EFI_MEMORY_TYPE MemoryType;\r
1780 CHAR16 *MemoryTypeStr;\r
1781} PROFILE_MEMORY_TYPE_STRING;\r
1782\r
1783GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = {\r
1784 {EfiRuntimeServicesCode, L"EfiRuntimeServicesCode"},\r
1785 {EfiRuntimeServicesData, L"EfiRuntimeServicesData"}\r
84edd20b
SZ
1786};\r
1787\r
ca949d9d
SZ
1788/**\r
1789 Memory type to string.\r
1790\r
1791 @param[in] MemoryType Memory type.\r
1792\r
1793 @return Pointer to string.\r
1794\r
1795**/\r
1796CHAR16 *\r
1797ProfileMemoryTypeToStr (\r
1798 IN EFI_MEMORY_TYPE MemoryType\r
1799 )\r
1800{\r
1801 UINTN Index;\r
1802 for (Index = 0; Index < sizeof (mMemoryTypeString) / sizeof (mMemoryTypeString[0]); Index++) {\r
1803 if (mMemoryTypeString[Index].MemoryType == MemoryType) {\r
1804 return mMemoryTypeString[Index].MemoryTypeStr;\r
1805 }\r
1806 }\r
1807\r
1808 return L"UnexpectedMemoryType";\r
1809}\r
84edd20b
SZ
1810\r
1811/**\r
1812 Dump SMRAM profile.\r
1813\r
1814**/\r
1815VOID\r
1816DumpSmramProfile (\r
1817 VOID\r
1818 )\r
1819{\r
1820 MEMORY_PROFILE_CONTEXT *Context;\r
1821 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
1822 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
1823 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1824 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1825 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
1826 LIST_ENTRY *SmramDriverInfoList;\r
1827 UINTN DriverIndex;\r
1828 LIST_ENTRY *DriverLink;\r
1829 LIST_ENTRY *AllocInfoList;\r
1830 UINTN AllocIndex;\r
1831 LIST_ENTRY *AllocLink;\r
1832 BOOLEAN SmramProfileRecordingStatus;\r
1833 UINTN TypeIndex;\r
1834\r
1835 ContextData = GetSmramProfileContext ();\r
1836 if (ContextData == NULL) {\r
1837 return ;\r
1838 }\r
1839\r
1840 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1841 mSmramProfileRecordingStatus = FALSE;\r
1842\r
1843 Context = &ContextData->Context;\r
1844 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1845 DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n"));\r
1846\r
1847 DEBUG ((EFI_D_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage));\r
1848 DEBUG ((EFI_D_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage));\r
ca949d9d 1849 for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {\r
84edd20b
SZ
1850 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||\r
1851 (Context->PeakTotalUsageByType[TypeIndex] != 0)) {\r
ca949d9d
SZ
1852 DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));\r
1853 DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));\r
84edd20b
SZ
1854 }\r
1855 }\r
1856 DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize));\r
1857 DEBUG ((EFI_D_INFO, " ImageCount - 0x%08x\n", Context->ImageCount));\r
1858 DEBUG ((EFI_D_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount));\r
1859\r
1860 SmramDriverInfoList = ContextData->DriverInfoList;\r
1861 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;\r
1862 DriverLink != SmramDriverInfoList;\r
1863 DriverLink = DriverLink->ForwardLink, DriverIndex++) {\r
1864 DriverInfoData = CR (\r
1865 DriverLink,\r
1866 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1867 Link,\r
1868 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1869 );\r
1870 DriverInfo = &DriverInfoData->DriverInfo;\r
1871 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));\r
1872 DEBUG ((EFI_D_INFO, " FileName - %g\n", &DriverInfo->FileName));\r
1873 DEBUG ((EFI_D_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase));\r
1874 DEBUG ((EFI_D_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize));\r
1875 DEBUG ((EFI_D_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint));\r
1876 DEBUG ((EFI_D_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem));\r
1877 DEBUG ((EFI_D_INFO, " FileType - 0x%02x\n", DriverInfo->FileType));\r
1878 DEBUG ((EFI_D_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage));\r
1879 DEBUG ((EFI_D_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage));\r
ca949d9d 1880 for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {\r
84edd20b
SZ
1881 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||\r
1882 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {\r
ca949d9d
SZ
1883 DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));\r
1884 DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));\r
84edd20b
SZ
1885 }\r
1886 }\r
1887 DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount));\r
1888\r
1889 AllocInfoList = DriverInfoData->AllocInfoList;\r
1890 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;\r
1891 AllocLink != AllocInfoList;\r
1892 AllocLink = AllocLink->ForwardLink, AllocIndex++) {\r
1893 AllocInfoData = CR (\r
1894 AllocLink,\r
1895 MEMORY_PROFILE_ALLOC_INFO_DATA,\r
1896 Link,\r
1897 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
1898 );\r
1899 AllocInfo = &AllocInfoData->AllocInfo;\r
1900 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));\r
1901 DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));\r
1902 DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId));\r
1903 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]));\r
1904 DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x\n", AllocInfo->MemoryType));\r
1905 DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer));\r
1906 DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size));\r
1907 }\r
1908 }\r
1909\r
1910 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1911\r
1912 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1913}\r
1914\r
1915/**\r
1916 Dump SMRAM infromation.\r
1917\r
1918**/\r
1919VOID\r
1920DumpSmramInfo (\r
1921 VOID\r
1922 )\r
1923{\r
1924 DEBUG_CODE (\r
1925 if (IS_SMRAM_PROFILE_ENABLED) {\r
1926 DumpSmramProfile ();\r
1927 DumpFreePagesList ();\r
1928 DumpFreePoolList ();\r
1929 DumpSmramRange ();\r
1930 }\r
1931 );\r
1932}\r
1933\r