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