]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
MdeModulePkg DxeCore/PiSmmCore: Add UEFI memory and SMRAM profile support.
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmramProfileRecord.c
1 /** @file
2 Support routines for SMRAM profile.
3
4 Copyright (c) 2014, 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 If BIOS memory type (0 ~ EfiMaxMemoryType), it checks bit (1 << MemoryType).
714 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.
715
716 @param MemoryType Memory type.
717
718 @retval TRUE This memory type need to be recorded.
719 @retval FALSE This memory type need not to be recorded.
720
721 **/
722 BOOLEAN
723 SmmCoreNeedRecordProfile (
724 IN EFI_MEMORY_TYPE MemoryType
725 )
726 {
727 UINT64 TestBit;
728
729 if ((UINT32) MemoryType >= 0x80000000) {
730 TestBit = BIT63;
731 } else {
732 TestBit = LShiftU64 (1, MemoryType);
733 }
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), ProfileMemoryIndex = MemoryType.
745 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.
746
747 @param MemoryType Memory type.
748
749 @return EFI memory type as profile memory index.
750
751 **/
752 EFI_MEMORY_TYPE
753 GetProfileMemoryIndex (
754 IN EFI_MEMORY_TYPE MemoryType
755 )
756 {
757 if ((UINT32) MemoryType >= 0x80000000) {
758 return EfiMaxMemoryType;
759 } else {
760 return MemoryType;
761 }
762 }
763
764 /**
765 Update SMRAM profile FreeMemoryPages information
766
767 @param ContextData Memory profile context.
768
769 **/
770 VOID
771 SmramProfileUpdateFreePages (
772 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData
773 )
774 {
775 LIST_ENTRY *Node;
776 FREE_PAGE_LIST *Pages;
777 LIST_ENTRY *FreePageList;
778 UINTN NumberOfPages;
779
780 NumberOfPages = 0;
781 FreePageList = &mSmmMemoryMap;
782 for (Node = FreePageList->BackLink;
783 Node != FreePageList;
784 Node = Node->BackLink) {
785 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
786 NumberOfPages += Pages->NumberOfPages;
787 }
788
789 mSmramFreeMemory.TotalFreeMemoryPages = NumberOfPages;
790
791 if (NumberOfPages <= SMRAM_INFO_DUMP_PAGE_THRESHOLD) {
792 DumpSmramInfo ();
793 }
794 }
795
796 /**
797 Update SMRAM profile Allocate information.
798
799 @param CallerAddress Address of caller who call Allocate.
800 @param Action This Allocate action.
801 @param MemoryType Memory type.
802 @param Size Buffer size.
803 @param Buffer Buffer address.
804
805 @retval TRUE Profile udpate success.
806 @retval FALSE Profile update fail.
807
808 **/
809 BOOLEAN
810 SmmCoreUpdateProfileAllocate (
811 IN PHYSICAL_ADDRESS CallerAddress,
812 IN MEMORY_PROFILE_ACTION Action,
813 IN EFI_MEMORY_TYPE MemoryType,
814 IN UINTN Size,
815 IN VOID *Buffer
816 )
817 {
818 EFI_STATUS Status;
819 MEMORY_PROFILE_CONTEXT *Context;
820 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
821 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
822 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
823 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
824 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
825 EFI_MEMORY_TYPE ProfileMemoryIndex;
826
827 ContextData = GetSmramProfileContext ();
828 if (ContextData == NULL) {
829 return FALSE;
830 }
831
832 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
833 ASSERT (DriverInfoData != NULL);
834
835 //
836 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
837 //
838 Status = SmmInternalAllocatePool (
839 EfiRuntimeServicesData,
840 sizeof (*AllocInfoData),
841 (VOID **) &AllocInfoData
842 );
843 if (EFI_ERROR (Status)) {
844 return FALSE;
845 }
846 AllocInfo = &AllocInfoData->AllocInfo;
847 AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
848 AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
849 AllocInfo->Header.Length = sizeof (MEMORY_PROFILE_ALLOC_INFO);
850 AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION;
851 AllocInfo->CallerAddress = CallerAddress;
852 AllocInfo->SequenceId = ContextData->Context.SequenceCount;
853 AllocInfo->Action = Action;
854 AllocInfo->MemoryType = MemoryType;
855 AllocInfo->Buffer = (PHYSICAL_ADDRESS) (UINTN) Buffer;
856 AllocInfo->Size = Size;
857
858 InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);
859
860 ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);
861
862 DriverInfo = &DriverInfoData->DriverInfo;
863 DriverInfo->CurrentUsage += Size;
864 if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {
865 DriverInfo->PeakUsage = DriverInfo->CurrentUsage;
866 }
867 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;
868 if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {
869 DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];
870 }
871 DriverInfo->AllocRecordCount ++;
872
873 Context = &ContextData->Context;
874 Context->CurrentTotalUsage += Size;
875 if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {
876 Context->PeakTotalUsage = Context->CurrentTotalUsage;
877 }
878 Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;
879 if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {
880 Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];
881 }
882 Context->SequenceCount ++;
883
884 SmramProfileUpdateFreePages (ContextData);
885 return TRUE;
886 }
887
888 /**
889 Get memory profile alloc info from memory profile
890
891 @param DriverInfoData Driver info
892 @param Action This Free action
893 @param Size Buffer size
894 @param Buffer Buffer address
895
896 @return Pointer to memory profile alloc info.
897 **/
898 MEMORY_PROFILE_ALLOC_INFO_DATA *
899 GetMemoryProfileAllocInfoFromAddress (
900 IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData,
901 IN MEMORY_PROFILE_ACTION Action,
902 IN UINTN Size,
903 IN VOID *Buffer
904 )
905 {
906 LIST_ENTRY *AllocInfoList;
907 LIST_ENTRY *AllocLink;
908 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
909 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
910
911 AllocInfoList = DriverInfoData->AllocInfoList;
912
913 for (AllocLink = AllocInfoList->ForwardLink;
914 AllocLink != AllocInfoList;
915 AllocLink = AllocLink->ForwardLink) {
916 AllocInfoData = CR (
917 AllocLink,
918 MEMORY_PROFILE_ALLOC_INFO_DATA,
919 Link,
920 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
921 );
922 AllocInfo = &AllocInfoData->AllocInfo;
923 if (AllocInfo->Action != Action) {
924 continue;
925 }
926 switch (Action) {
927 case MemoryProfileActionAllocatePages:
928 if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&
929 ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) {
930 return AllocInfoData;
931 }
932 break;
933 case MemoryProfileActionAllocatePool:
934 if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {
935 return AllocInfoData;
936 }
937 break;
938 default:
939 ASSERT (FALSE);
940 break;
941 }
942 }
943
944 return NULL;
945 }
946
947 /**
948 Update SMRAM profile Free information.
949
950 @param CallerAddress Address of caller who call Free.
951 @param Action This Free action.
952 @param Size Buffer size.
953 @param Buffer Buffer address.
954
955 @retval TRUE Profile udpate success.
956 @retval FALSE Profile update fail.
957
958 **/
959 BOOLEAN
960 SmmCoreUpdateProfileFree (
961 IN PHYSICAL_ADDRESS CallerAddress,
962 IN MEMORY_PROFILE_ACTION Action,
963 IN UINTN Size,
964 IN VOID *Buffer
965 )
966 {
967 MEMORY_PROFILE_CONTEXT *Context;
968 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
969 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
970 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
971 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
972 LIST_ENTRY *DriverLink;
973 LIST_ENTRY *DriverInfoList;
974 MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData;
975 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
976 EFI_MEMORY_TYPE ProfileMemoryIndex;
977
978 ContextData = GetSmramProfileContext ();
979 if (ContextData == NULL) {
980 return FALSE;
981 }
982
983 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
984 ASSERT (DriverInfoData != NULL);
985
986 switch (Action) {
987 case MemoryProfileActionFreePages:
988 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
989 break;
990 case MemoryProfileActionFreePool:
991 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
992 break;
993 default:
994 ASSERT (FALSE);
995 AllocInfoData = NULL;
996 break;
997 }
998 if (AllocInfoData == NULL) {
999 //
1000 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1001 //
1002 DriverInfoList = ContextData->DriverInfoList;
1003
1004 for (DriverLink = DriverInfoList->ForwardLink;
1005 DriverLink != DriverInfoList;
1006 DriverLink = DriverLink->ForwardLink) {
1007 ThisDriverInfoData = CR (
1008 DriverLink,
1009 MEMORY_PROFILE_DRIVER_INFO_DATA,
1010 Link,
1011 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1012 );
1013 switch (Action) {
1014 case MemoryProfileActionFreePages:
1015 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
1016 break;
1017 case MemoryProfileActionFreePool:
1018 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
1019 break;
1020 default:
1021 ASSERT (FALSE);
1022 AllocInfoData = NULL;
1023 break;
1024 }
1025 if (AllocInfoData != NULL) {
1026 DriverInfoData = ThisDriverInfoData;
1027 break;
1028 }
1029 }
1030
1031 if (AllocInfoData == NULL) {
1032 //
1033 // No matched allocate operation is found for this free operation.
1034 // It is because the specified memory type allocate operation has been
1035 // filtered by CoreNeedRecordProfile(), but free operations have no
1036 // memory type information, they can not be filtered by CoreNeedRecordProfile().
1037 // Then, they will be filtered here.
1038 //
1039 return FALSE;
1040 }
1041 }
1042
1043 Context = &ContextData->Context;
1044 DriverInfo = &DriverInfoData->DriverInfo;
1045 AllocInfo = &AllocInfoData->AllocInfo;
1046
1047 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
1048
1049 Context->CurrentTotalUsage -= AllocInfo->Size;
1050 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1051
1052 DriverInfo->CurrentUsage -= AllocInfo->Size;
1053 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1054 DriverInfo->AllocRecordCount --;
1055
1056 RemoveEntryList (&AllocInfoData->Link);
1057
1058 if (Action == MemoryProfileActionFreePages) {
1059 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {
1060 SmmCoreUpdateProfileAllocate (
1061 AllocInfo->CallerAddress,
1062 MemoryProfileActionAllocatePages,
1063 AllocInfo->MemoryType,
1064 (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),
1065 (VOID *) (UINTN) AllocInfo->Buffer
1066 );
1067 }
1068 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {
1069 SmmCoreUpdateProfileAllocate (
1070 AllocInfo->CallerAddress,
1071 MemoryProfileActionAllocatePages,
1072 AllocInfo->MemoryType,
1073 (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),
1074 (VOID *) ((UINTN) Buffer + Size)
1075 );
1076 }
1077 }
1078
1079 //
1080 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1081 //
1082 SmmInternalFreePool (AllocInfoData);
1083
1084 return TRUE;
1085 }
1086
1087 /**
1088 Update SMRAM profile information.
1089
1090 @param CallerAddress Address of caller who call Allocate or Free.
1091 @param Action This Allocate or Free action.
1092 @param MemoryType Memory type.
1093 @param Size Buffer size.
1094 @param Buffer Buffer address.
1095
1096 @retval TRUE Profile udpate success.
1097 @retval FALSE Profile update fail.
1098
1099 **/
1100 BOOLEAN
1101 SmmCoreUpdateProfile (
1102 IN PHYSICAL_ADDRESS CallerAddress,
1103 IN MEMORY_PROFILE_ACTION Action,
1104 IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool
1105 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool
1106 IN VOID *Buffer
1107 )
1108 {
1109 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1110
1111 if (!IS_SMRAM_PROFILE_ENABLED) {
1112 return FALSE;
1113 }
1114
1115 if (!mSmramProfileRecordingStatus) {
1116 return FALSE;
1117 }
1118
1119 //
1120 // Free operations have no memory type information, so skip the check.
1121 //
1122 if ((Action == MemoryProfileActionAllocatePages) || (Action == MemoryProfileActionAllocatePool)) {
1123 //
1124 // Only record limited MemoryType.
1125 //
1126 if (!SmmCoreNeedRecordProfile (MemoryType)) {
1127 return FALSE;
1128 }
1129 }
1130
1131 ContextData = GetSmramProfileContext ();
1132 if (ContextData == NULL) {
1133 return FALSE;
1134 }
1135
1136 switch (Action) {
1137 case MemoryProfileActionAllocatePages:
1138 SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);
1139 break;
1140 case MemoryProfileActionFreePages:
1141 SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
1142 break;
1143 case MemoryProfileActionAllocatePool:
1144 SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);
1145 break;
1146 case MemoryProfileActionFreePool:
1147 SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
1148 break;
1149 default:
1150 ASSERT (FALSE);
1151 break;
1152 }
1153
1154 return TRUE;
1155 }
1156
1157 /**
1158 SMRAM profile ready to lock callback function.
1159
1160 **/
1161 VOID
1162 SmramProfileReadyToLock (
1163 VOID
1164 )
1165 {
1166 if (!IS_SMRAM_PROFILE_ENABLED) {
1167 return;
1168 }
1169
1170 DEBUG ((EFI_D_INFO, "SmramProfileReadyToLock\n"));
1171 mSmramReadyToLock = TRUE;
1172 }
1173
1174 ////////////////////
1175
1176 /**
1177 This function check if the address is in SMRAM.
1178
1179 @param Buffer the buffer address to be checked.
1180 @param Length the buffer length to be checked.
1181
1182 @retval TRUE this address is in SMRAM.
1183 @retval FALSE this address is NOT in SMRAM.
1184
1185 **/
1186 BOOLEAN
1187 InternalIsAddressInSmram (
1188 IN PHYSICAL_ADDRESS Buffer,
1189 IN UINT64 Length
1190 )
1191 {
1192 UINTN Index;
1193
1194 for (Index = 0; Index < mFullSmramRangeCount; Index ++) {
1195 if (((Buffer >= mFullSmramRanges[Index].CpuStart) && (Buffer < mFullSmramRanges[Index].CpuStart + mFullSmramRanges[Index].PhysicalSize)) ||
1196 ((mFullSmramRanges[Index].CpuStart >= Buffer) && (mFullSmramRanges[Index].CpuStart < Buffer + Length))) {
1197 return TRUE;
1198 }
1199 }
1200
1201 return FALSE;
1202 }
1203
1204 /**
1205 This function check if the address refered by Buffer and Length is valid.
1206
1207 @param Buffer the buffer address to be checked.
1208 @param Length the buffer length to be checked.
1209
1210 @retval TRUE this address is valid.
1211 @retval FALSE this address is NOT valid.
1212 **/
1213 BOOLEAN
1214 InternalIsAddressValid (
1215 IN UINTN Buffer,
1216 IN UINTN Length
1217 )
1218 {
1219 if (Buffer > (MAX_ADDRESS - Length)) {
1220 //
1221 // Overflow happen
1222 //
1223 return FALSE;
1224 }
1225 if (InternalIsAddressInSmram ((PHYSICAL_ADDRESS) Buffer, (UINT64)Length)) {
1226 return FALSE;
1227 }
1228 return TRUE;
1229 }
1230
1231 /**
1232 Get SMRAM profile data size.
1233
1234 @return SMRAM profile data size.
1235
1236 **/
1237 UINTN
1238 SmramProfileGetDataSize (
1239 VOID
1240 )
1241 {
1242 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1243 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1244 LIST_ENTRY *DriverInfoList;
1245 LIST_ENTRY *DriverLink;
1246 UINTN TotalSize;
1247 LIST_ENTRY *Node;
1248 LIST_ENTRY *FreePageList;
1249 LIST_ENTRY *FreePoolList;
1250 FREE_POOL_HEADER *Pool;
1251 UINTN PoolListIndex;
1252 UINTN Index;
1253
1254 ContextData = GetSmramProfileContext ();
1255 if (ContextData == NULL) {
1256 return 0;
1257 }
1258
1259 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
1260 TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount;
1261
1262 DriverInfoList = ContextData->DriverInfoList;
1263 for (DriverLink = DriverInfoList->ForwardLink;
1264 DriverLink != DriverInfoList;
1265 DriverLink = DriverLink->ForwardLink) {
1266 DriverInfoData = CR (
1267 DriverLink,
1268 MEMORY_PROFILE_DRIVER_INFO_DATA,
1269 Link,
1270 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1271 );
1272 TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfoData->DriverInfo.AllocRecordCount;
1273 }
1274
1275
1276 Index = 0;
1277 FreePageList = &mSmmMemoryMap;
1278 for (Node = FreePageList->BackLink;
1279 Node != FreePageList;
1280 Node = Node->BackLink) {
1281 Index++;
1282 }
1283 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1284 FreePoolList = &mSmmPoolLists[PoolListIndex];
1285 for (Node = FreePoolList->BackLink;
1286 Node != FreePoolList;
1287 Node = Node->BackLink) {
1288 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1289 if (Pool->Header.Available) {
1290 Index++;
1291 }
1292 }
1293 }
1294
1295
1296 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1297 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1298
1299 return TotalSize;
1300 }
1301
1302 /**
1303 Copy SMRAM profile data.
1304
1305 @param ProfileBuffer The buffer to hold SMRAM profile data.
1306
1307 **/
1308 VOID
1309 SmramProfileCopyData (
1310 IN VOID *ProfileBuffer
1311 )
1312 {
1313 MEMORY_PROFILE_CONTEXT *Context;
1314 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1315 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1316 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1317 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1318 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1319 LIST_ENTRY *DriverInfoList;
1320 LIST_ENTRY *DriverLink;
1321 LIST_ENTRY *AllocInfoList;
1322 LIST_ENTRY *AllocLink;
1323 LIST_ENTRY *Node;
1324 FREE_PAGE_LIST *Pages;
1325 LIST_ENTRY *FreePageList;
1326 LIST_ENTRY *FreePoolList;
1327 FREE_POOL_HEADER *Pool;
1328 UINTN PoolListIndex;
1329 UINT32 Index;
1330 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
1331 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
1332 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor;
1333
1334 ContextData = GetSmramProfileContext ();
1335 if (ContextData == NULL) {
1336 return ;
1337 }
1338
1339 Context = ProfileBuffer;
1340 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
1341 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);
1342
1343 DriverInfoList = ContextData->DriverInfoList;
1344 for (DriverLink = DriverInfoList->ForwardLink;
1345 DriverLink != DriverInfoList;
1346 DriverLink = DriverLink->ForwardLink) {
1347 DriverInfoData = CR (
1348 DriverLink,
1349 MEMORY_PROFILE_DRIVER_INFO_DATA,
1350 Link,
1351 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1352 );
1353 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));
1354 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1);
1355
1356 AllocInfoList = DriverInfoData->AllocInfoList;
1357 for (AllocLink = AllocInfoList->ForwardLink;
1358 AllocLink != AllocInfoList;
1359 AllocLink = AllocLink->ForwardLink) {
1360 AllocInfoData = CR (
1361 AllocLink,
1362 MEMORY_PROFILE_ALLOC_INFO_DATA,
1363 Link,
1364 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1365 );
1366 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));
1367 AllocInfo += 1;
1368 }
1369
1370 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount);
1371 }
1372
1373
1374 FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) DriverInfo;
1375 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));
1376 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (FreeMemory + 1);
1377 Index = 0;
1378 FreePageList = &mSmmMemoryMap;
1379 for (Node = FreePageList->BackLink;
1380 Node != FreePageList;
1381 Node = Node->BackLink) {
1382 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1383 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1384 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1385 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1386 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages;
1387 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);
1388 MemoryProfileDescriptor++;
1389 Index++;
1390 }
1391 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1392 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];
1393 for (Node = FreePoolList->BackLink;
1394 Node != FreePoolList;
1395 Node = Node->BackLink) {
1396 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1397 if (Pool->Header.Available) {
1398 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1399 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1400 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1401 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool;
1402 MemoryProfileDescriptor->Size = Pool->Header.Size;
1403 MemoryProfileDescriptor++;
1404 Index++;
1405 }
1406 }
1407 }
1408 FreeMemory->FreeMemoryEntryCount = Index;
1409
1410 MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) MemoryProfileDescriptor;
1411 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;
1412 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1413 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;
1414 MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount;
1415 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (MemoryRange + 1);
1416 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
1417 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1418 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1419 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1420 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;
1421 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;
1422 MemoryProfileDescriptor++;
1423 }
1424 }
1425
1426 /**
1427 SMRAM profile handler to get profile info.
1428
1429 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
1430
1431 **/
1432 VOID
1433 SmramProfileHandlerGetInfo (
1434 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo
1435 )
1436 {
1437 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1438 BOOLEAN SmramProfileRecordingStatus;
1439
1440 ContextData = GetSmramProfileContext ();
1441 if (ContextData == NULL) {
1442 return ;
1443 }
1444
1445 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1446 mSmramProfileRecordingStatus = FALSE;
1447
1448 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();
1449 SmramProfileParameterGetInfo->Header.ReturnStatus = 0;
1450
1451 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1452 }
1453
1454 /**
1455 SMRAM profile handler to get profile data.
1456
1457 @param SmramProfileParameterGetData The parameter of SMM profile get data.
1458
1459 **/
1460 VOID
1461 SmramProfileHandlerGetData (
1462 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData
1463 )
1464 {
1465 UINT64 ProfileSize;
1466 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData;
1467 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1468 BOOLEAN SmramProfileRecordingStatus;
1469
1470 ContextData = GetSmramProfileContext ();
1471 if (ContextData == NULL) {
1472 return ;
1473 }
1474
1475 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1476 mSmramProfileRecordingStatus = FALSE;
1477
1478
1479 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));
1480
1481 ProfileSize = SmramProfileGetDataSize();
1482
1483 //
1484 // Sanity check
1485 //
1486 if (!InternalIsAddressValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {
1487 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
1488 SmramProfileParameterGetData->ProfileSize = ProfileSize;
1489 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;
1490 goto Done;
1491 }
1492
1493 if (SmramProfileGetData.ProfileSize < ProfileSize) {
1494 SmramProfileParameterGetData->ProfileSize = ProfileSize;
1495 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL;
1496 goto Done;
1497 }
1498
1499 SmramProfileParameterGetData->ProfileSize = ProfileSize;
1500 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer);
1501 SmramProfileParameterGetData->Header.ReturnStatus = 0;
1502
1503 Done:
1504 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1505 }
1506
1507 /**
1508 SMRAM profile handler to register SMM image.
1509
1510 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
1511
1512 **/
1513 VOID
1514 SmramProfileHandlerRegisterImage (
1515 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage
1516 )
1517 {
1518 EFI_STATUS Status;
1519 EFI_SMM_DRIVER_ENTRY DriverEntry;
1520 VOID *EntryPointInImage;
1521 BOOLEAN Ret;
1522
1523 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1524 CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));
1525 DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer;
1526 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage;
1527 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
1528 ASSERT_EFI_ERROR (Status);
1529 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1530
1531 Ret = RegisterSmramProfileImage (&DriverEntry, FALSE);
1532 if (Ret) {
1533 SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;
1534 }
1535 }
1536
1537 /**
1538 SMRAM profile handler to unregister SMM image.
1539
1540 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
1541
1542 **/
1543 VOID
1544 SmramProfileHandlerUnregisterImage (
1545 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage
1546 )
1547 {
1548 EFI_STATUS Status;
1549 EFI_SMM_DRIVER_ENTRY DriverEntry;
1550 VOID *EntryPointInImage;
1551 BOOLEAN Ret;
1552
1553 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1554 CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));
1555 DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer;
1556 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage;
1557 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
1558 ASSERT_EFI_ERROR (Status);
1559 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1560
1561 Ret = UnregisterSmramProfileImage (&DriverEntry, FALSE);
1562 if (Ret) {
1563 SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;
1564 }
1565 }
1566
1567 /**
1568 Dispatch function for a Software SMI handler.
1569
1570 Caution: This function may receive untrusted input.
1571 Communicate buffer and buffer size are external input, so this function will do basic validation.
1572
1573 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
1574 @param Context Points to an optional handler context which was specified when the
1575 handler was registered.
1576 @param CommBuffer A pointer to a collection of data in memory that will
1577 be conveyed from a non-SMM environment into an SMM environment.
1578 @param CommBufferSize The size of the CommBuffer.
1579
1580 @retval EFI_SUCCESS Command is handled successfully.
1581
1582 **/
1583 EFI_STATUS
1584 EFIAPI
1585 SmramProfileHandler (
1586 IN EFI_HANDLE DispatchHandle,
1587 IN CONST VOID *Context OPTIONAL,
1588 IN OUT VOID *CommBuffer OPTIONAL,
1589 IN OUT UINTN *CommBufferSize OPTIONAL
1590 )
1591 {
1592 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader;
1593 UINTN TempCommBufferSize;
1594
1595 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));
1596
1597 //
1598 // If input is invalid, stop processing this SMI
1599 //
1600 if (CommBuffer == NULL || CommBufferSize == NULL) {
1601 return EFI_SUCCESS;
1602 }
1603
1604 TempCommBufferSize = *CommBufferSize;
1605
1606 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {
1607 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1608 return EFI_SUCCESS;
1609 }
1610
1611 if (mSmramReadyToLock && !InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {
1612 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
1613 return EFI_SUCCESS;
1614 }
1615
1616 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer);
1617
1618 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;
1619
1620 if (GetSmramProfileContext () == NULL) {
1621 SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED;
1622 return EFI_SUCCESS;
1623 }
1624
1625 switch (SmramProfileParameterHeader->Command) {
1626 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:
1627 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n"));
1628 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {
1629 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1630 return EFI_SUCCESS;
1631 }
1632 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer);
1633 break;
1634 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:
1635 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n"));
1636 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {
1637 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1638 return EFI_SUCCESS;
1639 }
1640 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);
1641 break;
1642 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE:
1643 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n"));
1644 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) {
1645 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1646 return EFI_SUCCESS;
1647 }
1648 if (mSmramReadyToLock) {
1649 return EFI_SUCCESS;
1650 }
1651 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer);
1652 break;
1653 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE:
1654 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n"));
1655 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) {
1656 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1657 return EFI_SUCCESS;
1658 }
1659 if (mSmramReadyToLock) {
1660 return EFI_SUCCESS;
1661 }
1662 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);
1663 break;
1664 default:
1665 break;
1666 }
1667
1668 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n"));
1669
1670 return EFI_SUCCESS;
1671 }
1672
1673 /**
1674 Register SMRAM profile handler.
1675
1676 **/
1677 VOID
1678 RegisterSmramProfileHandler (
1679 VOID
1680 )
1681 {
1682 EFI_STATUS Status;
1683 EFI_HANDLE DispatchHandle;
1684
1685 if (!IS_SMRAM_PROFILE_ENABLED) {
1686 return;
1687 }
1688
1689 Status = SmiHandlerRegister (
1690 SmramProfileHandler,
1691 &gEdkiiMemoryProfileGuid,
1692 &DispatchHandle
1693 );
1694 ASSERT_EFI_ERROR (Status);
1695 }
1696
1697 ////////////////////
1698
1699 /**
1700 Dump SMRAM range.
1701
1702 **/
1703 VOID
1704 DumpSmramRange (
1705 VOID
1706 )
1707 {
1708 UINTN Index;
1709 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1710 BOOLEAN SmramProfileRecordingStatus;
1711
1712 ContextData = GetSmramProfileContext ();
1713 if (ContextData == NULL) {
1714 return ;
1715 }
1716
1717 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1718 mSmramProfileRecordingStatus = FALSE;
1719
1720 DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));
1721
1722 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
1723
1724 DEBUG ((EFI_D_INFO, "FullSmramRange:\n"));
1725 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
1726 DEBUG ((EFI_D_INFO, " FullSmramRange (0x%x)\n", Index));
1727 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));
1728 DEBUG ((EFI_D_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));
1729 DEBUG ((EFI_D_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));
1730 DEBUG ((EFI_D_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState));
1731 }
1732
1733 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
1734
1735 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1736 }
1737
1738 /**
1739 Dump SMRAM free page list.
1740
1741 **/
1742 VOID
1743 DumpFreePagesList (
1744 VOID
1745 )
1746 {
1747 LIST_ENTRY *FreePageList;
1748 LIST_ENTRY *Node;
1749 FREE_PAGE_LIST *Pages;
1750 UINTN Index;
1751 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1752 BOOLEAN SmramProfileRecordingStatus;
1753
1754 ContextData = GetSmramProfileContext ();
1755 if (ContextData == NULL) {
1756 return ;
1757 }
1758
1759 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1760 mSmramProfileRecordingStatus = FALSE;
1761
1762 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
1763
1764 DEBUG ((EFI_D_INFO, "FreePagesList:\n"));
1765 FreePageList = &mSmmMemoryMap;
1766 for (Node = FreePageList->BackLink, Index = 0;
1767 Node != FreePageList;
1768 Node = Node->BackLink, Index++) {
1769 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1770 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));
1771 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages));
1772 DEBUG ((EFI_D_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages));
1773 }
1774
1775 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
1776
1777 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1778 }
1779
1780 /**
1781 Dump SMRAM free pool list.
1782
1783 **/
1784 VOID
1785 DumpFreePoolList (
1786 VOID
1787 )
1788 {
1789 LIST_ENTRY *FreePoolList;
1790 LIST_ENTRY *Node;
1791 FREE_POOL_HEADER *Pool;
1792 UINTN Index;
1793 UINTN PoolListIndex;
1794 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1795 BOOLEAN SmramProfileRecordingStatus;
1796
1797 ContextData = GetSmramProfileContext ();
1798 if (ContextData == NULL) {
1799 return ;
1800 }
1801
1802 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1803 mSmramProfileRecordingStatus = FALSE;
1804
1805 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
1806
1807 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1808 DEBUG ((EFI_D_INFO, "FreePoolList (%d):\n", PoolListIndex));
1809 FreePoolList = &mSmmPoolLists[PoolListIndex];
1810 for (Node = FreePoolList->BackLink, Index = 0;
1811 Node != FreePoolList;
1812 Node = Node->BackLink, Index++) {
1813 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1814 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));
1815 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool));
1816 DEBUG ((EFI_D_INFO, " Size - 0x%08x\n", Pool->Header.Size));
1817 DEBUG ((EFI_D_INFO, " Available - 0x%02x\n", Pool->Header.Available));
1818 }
1819 }
1820
1821 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
1822
1823 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1824 }
1825
1826 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = {
1827 L"Unknown",
1828 L"AllocatePages",
1829 L"FreePages",
1830 L"AllocatePool",
1831 L"FreePool",
1832 };
1833
1834 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mMemoryTypeString[] = {
1835 L"EfiReservedMemoryType",
1836 L"EfiLoaderCode",
1837 L"EfiLoaderData",
1838 L"EfiBootServicesCode",
1839 L"EfiBootServicesData",
1840 L"EfiRuntimeServicesCode",
1841 L"EfiRuntimeServicesData",
1842 L"EfiConventionalMemory",
1843 L"EfiUnusableMemory",
1844 L"EfiACPIReclaimMemory",
1845 L"EfiACPIMemoryNVS",
1846 L"EfiMemoryMappedIO",
1847 L"EfiMemoryMappedIOPortSpace",
1848 L"EfiPalCode",
1849 L"EfiOSReserved",
1850 };
1851
1852
1853 /**
1854 Dump SMRAM profile.
1855
1856 **/
1857 VOID
1858 DumpSmramProfile (
1859 VOID
1860 )
1861 {
1862 MEMORY_PROFILE_CONTEXT *Context;
1863 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1864 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1865 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1866 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1867 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1868 LIST_ENTRY *SmramDriverInfoList;
1869 UINTN DriverIndex;
1870 LIST_ENTRY *DriverLink;
1871 LIST_ENTRY *AllocInfoList;
1872 UINTN AllocIndex;
1873 LIST_ENTRY *AllocLink;
1874 BOOLEAN SmramProfileRecordingStatus;
1875 UINTN TypeIndex;
1876
1877 ContextData = GetSmramProfileContext ();
1878 if (ContextData == NULL) {
1879 return ;
1880 }
1881
1882 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1883 mSmramProfileRecordingStatus = FALSE;
1884
1885 Context = &ContextData->Context;
1886 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
1887 DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n"));
1888
1889 DEBUG ((EFI_D_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage));
1890 DEBUG ((EFI_D_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage));
1891 for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
1892 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
1893 (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
1894 DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));
1895 DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));
1896 }
1897 }
1898 DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize));
1899 DEBUG ((EFI_D_INFO, " ImageCount - 0x%08x\n", Context->ImageCount));
1900 DEBUG ((EFI_D_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount));
1901
1902 SmramDriverInfoList = ContextData->DriverInfoList;
1903 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;
1904 DriverLink != SmramDriverInfoList;
1905 DriverLink = DriverLink->ForwardLink, DriverIndex++) {
1906 DriverInfoData = CR (
1907 DriverLink,
1908 MEMORY_PROFILE_DRIVER_INFO_DATA,
1909 Link,
1910 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1911 );
1912 DriverInfo = &DriverInfoData->DriverInfo;
1913 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));
1914 DEBUG ((EFI_D_INFO, " FileName - %g\n", &DriverInfo->FileName));
1915 DEBUG ((EFI_D_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase));
1916 DEBUG ((EFI_D_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize));
1917 DEBUG ((EFI_D_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint));
1918 DEBUG ((EFI_D_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem));
1919 DEBUG ((EFI_D_INFO, " FileType - 0x%02x\n", DriverInfo->FileType));
1920 DEBUG ((EFI_D_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage));
1921 DEBUG ((EFI_D_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage));
1922 for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
1923 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
1924 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
1925 DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));
1926 DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));
1927 }
1928 }
1929 DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount));
1930
1931 AllocInfoList = DriverInfoData->AllocInfoList;
1932 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;
1933 AllocLink != AllocInfoList;
1934 AllocLink = AllocLink->ForwardLink, AllocIndex++) {
1935 AllocInfoData = CR (
1936 AllocLink,
1937 MEMORY_PROFILE_ALLOC_INFO_DATA,
1938 Link,
1939 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1940 );
1941 AllocInfo = &AllocInfoData->AllocInfo;
1942 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));
1943 DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));
1944 DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId));
1945 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]));
1946 DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x\n", AllocInfo->MemoryType));
1947 DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer));
1948 DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size));
1949 }
1950 }
1951
1952 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
1953
1954 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1955 }
1956
1957 /**
1958 Dump SMRAM infromation.
1959
1960 **/
1961 VOID
1962 DumpSmramInfo (
1963 VOID
1964 )
1965 {
1966 DEBUG_CODE (
1967 if (IS_SMRAM_PROFILE_ENABLED) {
1968 DumpSmramProfile ();
1969 DumpFreePagesList ();
1970 DumpFreePoolList ();
1971 DumpSmramRange ();
1972 }
1973 );
1974 }
1975