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