]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
e119fadb67e5cd3669972e226bf104dd5f29f54f
[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 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 This function check if the address is in SMRAM.
1180
1181 @param Buffer the buffer address to be checked.
1182 @param Length the buffer length to be checked.
1183
1184 @retval TRUE this address is in SMRAM.
1185 @retval FALSE this address is NOT in SMRAM.
1186
1187 **/
1188 BOOLEAN
1189 InternalIsAddressInSmram (
1190 IN PHYSICAL_ADDRESS Buffer,
1191 IN UINT64 Length
1192 )
1193 {
1194 UINTN Index;
1195
1196 for (Index = 0; Index < mFullSmramRangeCount; Index ++) {
1197 if (((Buffer >= mFullSmramRanges[Index].CpuStart) && (Buffer < mFullSmramRanges[Index].CpuStart + mFullSmramRanges[Index].PhysicalSize)) ||
1198 ((mFullSmramRanges[Index].CpuStart >= Buffer) && (mFullSmramRanges[Index].CpuStart < Buffer + Length))) {
1199 return TRUE;
1200 }
1201 }
1202
1203 return FALSE;
1204 }
1205
1206 /**
1207 This function check if the address refered by Buffer and Length is valid.
1208
1209 @param Buffer the buffer address to be checked.
1210 @param Length the buffer length to be checked.
1211
1212 @retval TRUE this address is valid.
1213 @retval FALSE this address is NOT valid.
1214 **/
1215 BOOLEAN
1216 InternalIsAddressValid (
1217 IN UINTN Buffer,
1218 IN UINTN Length
1219 )
1220 {
1221 if (Buffer > (MAX_ADDRESS - Length)) {
1222 //
1223 // Overflow happen
1224 //
1225 return FALSE;
1226 }
1227 if (InternalIsAddressInSmram ((PHYSICAL_ADDRESS) Buffer, (UINT64)Length)) {
1228 return FALSE;
1229 }
1230 return TRUE;
1231 }
1232
1233 /**
1234 Get SMRAM profile data size.
1235
1236 @return SMRAM profile data size.
1237
1238 **/
1239 UINTN
1240 SmramProfileGetDataSize (
1241 VOID
1242 )
1243 {
1244 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1245 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1246 LIST_ENTRY *DriverInfoList;
1247 LIST_ENTRY *DriverLink;
1248 UINTN TotalSize;
1249 LIST_ENTRY *Node;
1250 LIST_ENTRY *FreePageList;
1251 LIST_ENTRY *FreePoolList;
1252 FREE_POOL_HEADER *Pool;
1253 UINTN PoolListIndex;
1254 UINTN Index;
1255
1256 ContextData = GetSmramProfileContext ();
1257 if (ContextData == NULL) {
1258 return 0;
1259 }
1260
1261 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
1262 TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount;
1263
1264 DriverInfoList = ContextData->DriverInfoList;
1265 for (DriverLink = DriverInfoList->ForwardLink;
1266 DriverLink != DriverInfoList;
1267 DriverLink = DriverLink->ForwardLink) {
1268 DriverInfoData = CR (
1269 DriverLink,
1270 MEMORY_PROFILE_DRIVER_INFO_DATA,
1271 Link,
1272 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1273 );
1274 TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfoData->DriverInfo.AllocRecordCount;
1275 }
1276
1277
1278 Index = 0;
1279 FreePageList = &mSmmMemoryMap;
1280 for (Node = FreePageList->BackLink;
1281 Node != FreePageList;
1282 Node = Node->BackLink) {
1283 Index++;
1284 }
1285 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1286 FreePoolList = &mSmmPoolLists[PoolListIndex];
1287 for (Node = FreePoolList->BackLink;
1288 Node != FreePoolList;
1289 Node = Node->BackLink) {
1290 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1291 if (Pool->Header.Available) {
1292 Index++;
1293 }
1294 }
1295 }
1296
1297
1298 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1299 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1300
1301 return TotalSize;
1302 }
1303
1304 /**
1305 Copy SMRAM profile data.
1306
1307 @param ProfileBuffer The buffer to hold SMRAM profile data.
1308
1309 **/
1310 VOID
1311 SmramProfileCopyData (
1312 IN VOID *ProfileBuffer
1313 )
1314 {
1315 MEMORY_PROFILE_CONTEXT *Context;
1316 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1317 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1318 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1319 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1320 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1321 LIST_ENTRY *DriverInfoList;
1322 LIST_ENTRY *DriverLink;
1323 LIST_ENTRY *AllocInfoList;
1324 LIST_ENTRY *AllocLink;
1325 LIST_ENTRY *Node;
1326 FREE_PAGE_LIST *Pages;
1327 LIST_ENTRY *FreePageList;
1328 LIST_ENTRY *FreePoolList;
1329 FREE_POOL_HEADER *Pool;
1330 UINTN PoolListIndex;
1331 UINT32 Index;
1332 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
1333 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
1334 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor;
1335
1336 ContextData = GetSmramProfileContext ();
1337 if (ContextData == NULL) {
1338 return ;
1339 }
1340
1341 Context = ProfileBuffer;
1342 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
1343 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);
1344
1345 DriverInfoList = ContextData->DriverInfoList;
1346 for (DriverLink = DriverInfoList->ForwardLink;
1347 DriverLink != DriverInfoList;
1348 DriverLink = DriverLink->ForwardLink) {
1349 DriverInfoData = CR (
1350 DriverLink,
1351 MEMORY_PROFILE_DRIVER_INFO_DATA,
1352 Link,
1353 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1354 );
1355 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));
1356 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1);
1357
1358 AllocInfoList = DriverInfoData->AllocInfoList;
1359 for (AllocLink = AllocInfoList->ForwardLink;
1360 AllocLink != AllocInfoList;
1361 AllocLink = AllocLink->ForwardLink) {
1362 AllocInfoData = CR (
1363 AllocLink,
1364 MEMORY_PROFILE_ALLOC_INFO_DATA,
1365 Link,
1366 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1367 );
1368 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));
1369 AllocInfo += 1;
1370 }
1371
1372 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount);
1373 }
1374
1375
1376 FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) DriverInfo;
1377 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));
1378 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (FreeMemory + 1);
1379 Index = 0;
1380 FreePageList = &mSmmMemoryMap;
1381 for (Node = FreePageList->BackLink;
1382 Node != FreePageList;
1383 Node = Node->BackLink) {
1384 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1385 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1386 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1387 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1388 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages;
1389 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);
1390 MemoryProfileDescriptor++;
1391 Index++;
1392 }
1393 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1394 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];
1395 for (Node = FreePoolList->BackLink;
1396 Node != FreePoolList;
1397 Node = Node->BackLink) {
1398 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1399 if (Pool->Header.Available) {
1400 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1401 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1402 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1403 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool;
1404 MemoryProfileDescriptor->Size = Pool->Header.Size;
1405 MemoryProfileDescriptor++;
1406 Index++;
1407 }
1408 }
1409 }
1410 FreeMemory->FreeMemoryEntryCount = Index;
1411
1412 MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) MemoryProfileDescriptor;
1413 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;
1414 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1415 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;
1416 MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount;
1417 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (MemoryRange + 1);
1418 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
1419 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1420 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1421 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1422 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;
1423 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;
1424 MemoryProfileDescriptor++;
1425 }
1426 }
1427
1428 /**
1429 SMRAM profile handler to get profile info.
1430
1431 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
1432
1433 **/
1434 VOID
1435 SmramProfileHandlerGetInfo (
1436 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo
1437 )
1438 {
1439 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1440 BOOLEAN SmramProfileRecordingStatus;
1441
1442 ContextData = GetSmramProfileContext ();
1443 if (ContextData == NULL) {
1444 return ;
1445 }
1446
1447 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1448 mSmramProfileRecordingStatus = FALSE;
1449
1450 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();
1451 SmramProfileParameterGetInfo->Header.ReturnStatus = 0;
1452
1453 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1454 }
1455
1456 /**
1457 SMRAM profile handler to get profile data.
1458
1459 @param SmramProfileParameterGetData The parameter of SMM profile get data.
1460
1461 **/
1462 VOID
1463 SmramProfileHandlerGetData (
1464 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData
1465 )
1466 {
1467 UINT64 ProfileSize;
1468 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData;
1469 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1470 BOOLEAN SmramProfileRecordingStatus;
1471
1472 ContextData = GetSmramProfileContext ();
1473 if (ContextData == NULL) {
1474 return ;
1475 }
1476
1477 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1478 mSmramProfileRecordingStatus = FALSE;
1479
1480
1481 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));
1482
1483 ProfileSize = SmramProfileGetDataSize();
1484
1485 //
1486 // Sanity check
1487 //
1488 if (!InternalIsAddressValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {
1489 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
1490 SmramProfileParameterGetData->ProfileSize = ProfileSize;
1491 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;
1492 goto Done;
1493 }
1494
1495 if (SmramProfileGetData.ProfileSize < ProfileSize) {
1496 SmramProfileParameterGetData->ProfileSize = ProfileSize;
1497 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL;
1498 goto Done;
1499 }
1500
1501 SmramProfileParameterGetData->ProfileSize = ProfileSize;
1502 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer);
1503 SmramProfileParameterGetData->Header.ReturnStatus = 0;
1504
1505 Done:
1506 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1507 }
1508
1509 /**
1510 SMRAM profile handler to register SMM image.
1511
1512 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
1513
1514 **/
1515 VOID
1516 SmramProfileHandlerRegisterImage (
1517 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage
1518 )
1519 {
1520 EFI_STATUS Status;
1521 EFI_SMM_DRIVER_ENTRY DriverEntry;
1522 VOID *EntryPointInImage;
1523 BOOLEAN Ret;
1524
1525 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1526 CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));
1527 DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer;
1528 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage;
1529 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
1530 ASSERT_EFI_ERROR (Status);
1531 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1532
1533 Ret = RegisterSmramProfileImage (&DriverEntry, FALSE);
1534 if (Ret) {
1535 SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;
1536 }
1537 }
1538
1539 /**
1540 SMRAM profile handler to unregister SMM image.
1541
1542 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
1543
1544 **/
1545 VOID
1546 SmramProfileHandlerUnregisterImage (
1547 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage
1548 )
1549 {
1550 EFI_STATUS Status;
1551 EFI_SMM_DRIVER_ENTRY DriverEntry;
1552 VOID *EntryPointInImage;
1553 BOOLEAN Ret;
1554
1555 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1556 CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));
1557 DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer;
1558 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage;
1559 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
1560 ASSERT_EFI_ERROR (Status);
1561 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1562
1563 Ret = UnregisterSmramProfileImage (&DriverEntry, FALSE);
1564 if (Ret) {
1565 SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;
1566 }
1567 }
1568
1569 /**
1570 Dispatch function for a Software SMI handler.
1571
1572 Caution: This function may receive untrusted input.
1573 Communicate buffer and buffer size are external input, so this function will do basic validation.
1574
1575 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
1576 @param Context Points to an optional handler context which was specified when the
1577 handler was registered.
1578 @param CommBuffer A pointer to a collection of data in memory that will
1579 be conveyed from a non-SMM environment into an SMM environment.
1580 @param CommBufferSize The size of the CommBuffer.
1581
1582 @retval EFI_SUCCESS Command is handled successfully.
1583
1584 **/
1585 EFI_STATUS
1586 EFIAPI
1587 SmramProfileHandler (
1588 IN EFI_HANDLE DispatchHandle,
1589 IN CONST VOID *Context OPTIONAL,
1590 IN OUT VOID *CommBuffer OPTIONAL,
1591 IN OUT UINTN *CommBufferSize OPTIONAL
1592 )
1593 {
1594 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader;
1595 UINTN TempCommBufferSize;
1596
1597 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));
1598
1599 //
1600 // If input is invalid, stop processing this SMI
1601 //
1602 if (CommBuffer == NULL || CommBufferSize == NULL) {
1603 return EFI_SUCCESS;
1604 }
1605
1606 TempCommBufferSize = *CommBufferSize;
1607
1608 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {
1609 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1610 return EFI_SUCCESS;
1611 }
1612
1613 if (mSmramReadyToLock && !InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {
1614 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
1615 return EFI_SUCCESS;
1616 }
1617
1618 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer);
1619
1620 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;
1621
1622 if (GetSmramProfileContext () == NULL) {
1623 SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED;
1624 return EFI_SUCCESS;
1625 }
1626
1627 switch (SmramProfileParameterHeader->Command) {
1628 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:
1629 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n"));
1630 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {
1631 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1632 return EFI_SUCCESS;
1633 }
1634 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer);
1635 break;
1636 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:
1637 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n"));
1638 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {
1639 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1640 return EFI_SUCCESS;
1641 }
1642 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);
1643 break;
1644 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE:
1645 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n"));
1646 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) {
1647 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1648 return EFI_SUCCESS;
1649 }
1650 if (mSmramReadyToLock) {
1651 return EFI_SUCCESS;
1652 }
1653 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer);
1654 break;
1655 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE:
1656 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n"));
1657 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) {
1658 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
1659 return EFI_SUCCESS;
1660 }
1661 if (mSmramReadyToLock) {
1662 return EFI_SUCCESS;
1663 }
1664 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);
1665 break;
1666 default:
1667 break;
1668 }
1669
1670 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n"));
1671
1672 return EFI_SUCCESS;
1673 }
1674
1675 /**
1676 Register SMRAM profile handler.
1677
1678 **/
1679 VOID
1680 RegisterSmramProfileHandler (
1681 VOID
1682 )
1683 {
1684 EFI_STATUS Status;
1685 EFI_HANDLE DispatchHandle;
1686
1687 if (!IS_SMRAM_PROFILE_ENABLED) {
1688 return;
1689 }
1690
1691 Status = SmiHandlerRegister (
1692 SmramProfileHandler,
1693 &gEdkiiMemoryProfileGuid,
1694 &DispatchHandle
1695 );
1696 ASSERT_EFI_ERROR (Status);
1697 }
1698
1699 ////////////////////
1700
1701 /**
1702 Dump SMRAM range.
1703
1704 **/
1705 VOID
1706 DumpSmramRange (
1707 VOID
1708 )
1709 {
1710 UINTN Index;
1711 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1712 BOOLEAN SmramProfileRecordingStatus;
1713
1714 ContextData = GetSmramProfileContext ();
1715 if (ContextData == NULL) {
1716 return ;
1717 }
1718
1719 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1720 mSmramProfileRecordingStatus = FALSE;
1721
1722 DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));
1723
1724 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
1725
1726 DEBUG ((EFI_D_INFO, "FullSmramRange:\n"));
1727 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
1728 DEBUG ((EFI_D_INFO, " FullSmramRange (0x%x)\n", Index));
1729 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));
1730 DEBUG ((EFI_D_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));
1731 DEBUG ((EFI_D_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));
1732 DEBUG ((EFI_D_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState));
1733 }
1734
1735 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
1736
1737 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1738 }
1739
1740 /**
1741 Dump SMRAM free page list.
1742
1743 **/
1744 VOID
1745 DumpFreePagesList (
1746 VOID
1747 )
1748 {
1749 LIST_ENTRY *FreePageList;
1750 LIST_ENTRY *Node;
1751 FREE_PAGE_LIST *Pages;
1752 UINTN Index;
1753 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1754 BOOLEAN SmramProfileRecordingStatus;
1755
1756 ContextData = GetSmramProfileContext ();
1757 if (ContextData == NULL) {
1758 return ;
1759 }
1760
1761 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1762 mSmramProfileRecordingStatus = FALSE;
1763
1764 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
1765
1766 DEBUG ((EFI_D_INFO, "FreePagesList:\n"));
1767 FreePageList = &mSmmMemoryMap;
1768 for (Node = FreePageList->BackLink, Index = 0;
1769 Node != FreePageList;
1770 Node = Node->BackLink, Index++) {
1771 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1772 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));
1773 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages));
1774 DEBUG ((EFI_D_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages));
1775 }
1776
1777 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
1778
1779 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1780 }
1781
1782 /**
1783 Dump SMRAM free pool list.
1784
1785 **/
1786 VOID
1787 DumpFreePoolList (
1788 VOID
1789 )
1790 {
1791 LIST_ENTRY *FreePoolList;
1792 LIST_ENTRY *Node;
1793 FREE_POOL_HEADER *Pool;
1794 UINTN Index;
1795 UINTN PoolListIndex;
1796 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1797 BOOLEAN SmramProfileRecordingStatus;
1798
1799 ContextData = GetSmramProfileContext ();
1800 if (ContextData == NULL) {
1801 return ;
1802 }
1803
1804 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1805 mSmramProfileRecordingStatus = FALSE;
1806
1807 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
1808
1809 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1810 DEBUG ((EFI_D_INFO, "FreePoolList (%d):\n", PoolListIndex));
1811 FreePoolList = &mSmmPoolLists[PoolListIndex];
1812 for (Node = FreePoolList->BackLink, Index = 0;
1813 Node != FreePoolList;
1814 Node = Node->BackLink, Index++) {
1815 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1816 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));
1817 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool));
1818 DEBUG ((EFI_D_INFO, " Size - 0x%08x\n", Pool->Header.Size));
1819 DEBUG ((EFI_D_INFO, " Available - 0x%02x\n", Pool->Header.Available));
1820 }
1821 }
1822
1823 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
1824
1825 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1826 }
1827
1828 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = {
1829 L"Unknown",
1830 L"AllocatePages",
1831 L"FreePages",
1832 L"AllocatePool",
1833 L"FreePool",
1834 };
1835
1836 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mMemoryTypeString[] = {
1837 L"EfiReservedMemoryType",
1838 L"EfiLoaderCode",
1839 L"EfiLoaderData",
1840 L"EfiBootServicesCode",
1841 L"EfiBootServicesData",
1842 L"EfiRuntimeServicesCode",
1843 L"EfiRuntimeServicesData",
1844 L"EfiConventionalMemory",
1845 L"EfiUnusableMemory",
1846 L"EfiACPIReclaimMemory",
1847 L"EfiACPIMemoryNVS",
1848 L"EfiMemoryMappedIO",
1849 L"EfiMemoryMappedIOPortSpace",
1850 L"EfiPalCode",
1851 L"EfiOSReserved",
1852 };
1853
1854
1855 /**
1856 Dump SMRAM profile.
1857
1858 **/
1859 VOID
1860 DumpSmramProfile (
1861 VOID
1862 )
1863 {
1864 MEMORY_PROFILE_CONTEXT *Context;
1865 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1866 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1867 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1868 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1869 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1870 LIST_ENTRY *SmramDriverInfoList;
1871 UINTN DriverIndex;
1872 LIST_ENTRY *DriverLink;
1873 LIST_ENTRY *AllocInfoList;
1874 UINTN AllocIndex;
1875 LIST_ENTRY *AllocLink;
1876 BOOLEAN SmramProfileRecordingStatus;
1877 UINTN TypeIndex;
1878
1879 ContextData = GetSmramProfileContext ();
1880 if (ContextData == NULL) {
1881 return ;
1882 }
1883
1884 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
1885 mSmramProfileRecordingStatus = FALSE;
1886
1887 Context = &ContextData->Context;
1888 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
1889 DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n"));
1890
1891 DEBUG ((EFI_D_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage));
1892 DEBUG ((EFI_D_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage));
1893 for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
1894 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
1895 (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
1896 DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));
1897 DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));
1898 }
1899 }
1900 DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize));
1901 DEBUG ((EFI_D_INFO, " ImageCount - 0x%08x\n", Context->ImageCount));
1902 DEBUG ((EFI_D_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount));
1903
1904 SmramDriverInfoList = ContextData->DriverInfoList;
1905 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;
1906 DriverLink != SmramDriverInfoList;
1907 DriverLink = DriverLink->ForwardLink, DriverIndex++) {
1908 DriverInfoData = CR (
1909 DriverLink,
1910 MEMORY_PROFILE_DRIVER_INFO_DATA,
1911 Link,
1912 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1913 );
1914 DriverInfo = &DriverInfoData->DriverInfo;
1915 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));
1916 DEBUG ((EFI_D_INFO, " FileName - %g\n", &DriverInfo->FileName));
1917 DEBUG ((EFI_D_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase));
1918 DEBUG ((EFI_D_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize));
1919 DEBUG ((EFI_D_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint));
1920 DEBUG ((EFI_D_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem));
1921 DEBUG ((EFI_D_INFO, " FileType - 0x%02x\n", DriverInfo->FileType));
1922 DEBUG ((EFI_D_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage));
1923 DEBUG ((EFI_D_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage));
1924 for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
1925 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
1926 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
1927 DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));
1928 DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));
1929 }
1930 }
1931 DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount));
1932
1933 AllocInfoList = DriverInfoData->AllocInfoList;
1934 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;
1935 AllocLink != AllocInfoList;
1936 AllocLink = AllocLink->ForwardLink, AllocIndex++) {
1937 AllocInfoData = CR (
1938 AllocLink,
1939 MEMORY_PROFILE_ALLOC_INFO_DATA,
1940 Link,
1941 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1942 );
1943 AllocInfo = &AllocInfoData->AllocInfo;
1944 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));
1945 DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));
1946 DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId));
1947 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]));
1948 DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x\n", AllocInfo->MemoryType));
1949 DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer));
1950 DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size));
1951 }
1952 }
1953
1954 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
1955
1956 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
1957 }
1958
1959 /**
1960 Dump SMRAM infromation.
1961
1962 **/
1963 VOID
1964 DumpSmramInfo (
1965 VOID
1966 )
1967 {
1968 DEBUG_CODE (
1969 if (IS_SMRAM_PROFILE_ENABLED) {
1970 DumpSmramProfile ();
1971 DumpFreePagesList ();
1972 DumpFreePoolList ();
1973 DumpSmramRange ();
1974 }
1975 );
1976 }
1977