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