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