]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmramProfileRecord.c
1 /** @file
2 Support routines for SMRAM profile.
3
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "PiSmmCore.h"
10
11 #define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0)
12 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
13
14 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
15 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
16
17 typedef struct {
18 UINT32 Signature;
19 MEMORY_PROFILE_CONTEXT Context;
20 LIST_ENTRY *DriverInfoList;
21 } MEMORY_PROFILE_CONTEXT_DATA;
22
23 typedef struct {
24 UINT32 Signature;
25 MEMORY_PROFILE_DRIVER_INFO DriverInfo;
26 LIST_ENTRY *AllocInfoList;
27 CHAR8 *PdbString;
28 LIST_ENTRY Link;
29 } MEMORY_PROFILE_DRIVER_INFO_DATA;
30
31 typedef struct {
32 UINT32 Signature;
33 MEMORY_PROFILE_ALLOC_INFO AllocInfo;
34 CHAR8 *ActionString;
35 LIST_ENTRY Link;
36 } MEMORY_PROFILE_ALLOC_INFO_DATA;
37
38 //
39 // When free memory less than 4 pages, dump it.
40 //
41 #define SMRAM_INFO_DUMP_PAGE_THRESHOLD 4
42
43 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory = {
44 {
45 MEMORY_PROFILE_FREE_MEMORY_SIGNATURE,
46 sizeof (MEMORY_PROFILE_FREE_MEMORY),
47 MEMORY_PROFILE_FREE_MEMORY_REVISION
48 },
49 0,
50 0
51 };
52
53 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);
54 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext = {
55 MEMORY_PROFILE_CONTEXT_SIGNATURE,
56 {
57 {
58 MEMORY_PROFILE_CONTEXT_SIGNATURE,
59 sizeof (MEMORY_PROFILE_CONTEXT),
60 MEMORY_PROFILE_CONTEXT_REVISION
61 },
62 0,
63 0,
64 { 0 },
65 { 0 },
66 0,
67 0,
68 0
69 },
70 &mImageQueue,
71 };
72 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr = NULL;
73
74 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramReadyToLock;
75 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramProfileGettingStatus = FALSE;
76 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
77 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL *mSmramProfileDriverPath;
78 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmramProfileDriverPathSize;
79
80 /**
81 Dump SMRAM information.
82
83 **/
84 VOID
85 DumpSmramInfo (
86 VOID
87 );
88
89 /**
90 Get memory profile data.
91
92 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
93 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
94 On return, points to the size of the data returned in ProfileBuffer.
95 @param[out] ProfileBuffer Profile buffer.
96
97 @return EFI_SUCCESS Get the memory profile data successfully.
98 @return EFI_UNSUPPORTED Memory profile is unsupported.
99 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
100 ProfileSize is updated with the size required.
101
102 **/
103 EFI_STATUS
104 EFIAPI
105 SmramProfileProtocolGetData (
106 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
107 IN OUT UINT64 *ProfileSize,
108 OUT VOID *ProfileBuffer
109 );
110
111 /**
112 Register image to memory profile.
113
114 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
115 @param[in] FilePath File path of the image.
116 @param[in] ImageBase Image base address.
117 @param[in] ImageSize Image size.
118 @param[in] FileType File type of the image.
119
120 @return EFI_SUCCESS Register successfully.
121 @return EFI_UNSUPPORTED Memory profile is unsupported,
122 or memory profile for the image is not required.
123 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
124
125 **/
126 EFI_STATUS
127 EFIAPI
128 SmramProfileProtocolRegisterImage (
129 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
130 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
131 IN PHYSICAL_ADDRESS ImageBase,
132 IN UINT64 ImageSize,
133 IN EFI_FV_FILETYPE FileType
134 );
135
136 /**
137 Unregister image from memory profile.
138
139 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
140 @param[in] FilePath File path of the image.
141 @param[in] ImageBase Image base address.
142 @param[in] ImageSize Image size.
143
144 @return EFI_SUCCESS Unregister successfully.
145 @return EFI_UNSUPPORTED Memory profile is unsupported,
146 or memory profile for the image is not required.
147 @return EFI_NOT_FOUND The image is not found.
148
149 **/
150 EFI_STATUS
151 EFIAPI
152 SmramProfileProtocolUnregisterImage (
153 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
154 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
155 IN PHYSICAL_ADDRESS ImageBase,
156 IN UINT64 ImageSize
157 );
158
159 /**
160 Get memory profile recording state.
161
162 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
163 @param[out] RecordingState Recording state.
164
165 @return EFI_SUCCESS Memory profile recording state is returned.
166 @return EFI_UNSUPPORTED Memory profile is unsupported.
167 @return EFI_INVALID_PARAMETER RecordingState is NULL.
168
169 **/
170 EFI_STATUS
171 EFIAPI
172 SmramProfileProtocolGetRecordingState (
173 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
174 OUT BOOLEAN *RecordingState
175 );
176
177 /**
178 Set memory profile recording state.
179
180 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
181 @param[in] RecordingState Recording state.
182
183 @return EFI_SUCCESS Set memory profile recording state successfully.
184 @return EFI_UNSUPPORTED Memory profile is unsupported.
185
186 **/
187 EFI_STATUS
188 EFIAPI
189 SmramProfileProtocolSetRecordingState (
190 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
191 IN BOOLEAN RecordingState
192 );
193
194 /**
195 Record memory profile of multilevel caller.
196
197 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
198 @param[in] CallerAddress Address of caller.
199 @param[in] Action Memory profile action.
200 @param[in] MemoryType Memory type.
201 EfiMaxMemoryType means the MemoryType is unknown.
202 @param[in] Buffer Buffer address.
203 @param[in] Size Buffer size.
204 @param[in] ActionString String for memory profile action.
205 Only needed for user defined allocate action.
206
207 @return EFI_SUCCESS Memory profile is updated.
208 @return EFI_UNSUPPORTED Memory profile is unsupported,
209 or memory profile for the image is not required,
210 or memory profile for the memory type is not required.
211 @return EFI_ACCESS_DENIED It is during memory profile data getting.
212 @return EFI_ABORTED Memory profile recording is not enabled.
213 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
214 @return EFI_NOT_FOUND No matched allocate info found for free action.
215
216 **/
217 EFI_STATUS
218 EFIAPI
219 SmramProfileProtocolRecord (
220 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
221 IN PHYSICAL_ADDRESS CallerAddress,
222 IN MEMORY_PROFILE_ACTION Action,
223 IN EFI_MEMORY_TYPE MemoryType,
224 IN VOID *Buffer,
225 IN UINTN Size,
226 IN CHAR8 *ActionString OPTIONAL
227 );
228
229 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_SMM_MEMORY_PROFILE_PROTOCOL mSmmProfileProtocol = {
230 SmramProfileProtocolGetData,
231 SmramProfileProtocolRegisterImage,
232 SmramProfileProtocolUnregisterImage,
233 SmramProfileProtocolGetRecordingState,
234 SmramProfileProtocolSetRecordingState,
235 SmramProfileProtocolRecord,
236 };
237
238 /**
239 Return SMRAM profile context.
240
241 @return SMRAM profile context.
242
243 **/
244 MEMORY_PROFILE_CONTEXT_DATA *
245 GetSmramProfileContext (
246 VOID
247 )
248 {
249 return mSmramProfileContextPtr;
250 }
251
252 /**
253 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
254 If Pe32Data is NULL, then ASSERT().
255
256 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
257
258 @return The Subsystem of the PE/COFF image.
259
260 **/
261 UINT16
262 InternalPeCoffGetSubsystem (
263 IN VOID *Pe32Data
264 )
265 {
266 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
267 EFI_IMAGE_DOS_HEADER *DosHdr;
268 UINT16 Magic;
269
270 ASSERT (Pe32Data != NULL);
271
272 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
273 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
274 //
275 // DOS image header is present, so read the PE header after the DOS image header.
276 //
277 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
278 } else {
279 //
280 // DOS image header is not present, so PE header is at the image base.
281 //
282 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
283 }
284
285 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
286 return Hdr.Te->Subsystem;
287 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
288 Magic = Hdr.Pe32->OptionalHeader.Magic;
289 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
290 return Hdr.Pe32->OptionalHeader.Subsystem;
291 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
292 return Hdr.Pe32Plus->OptionalHeader.Subsystem;
293 }
294 }
295
296 return 0x0000;
297 }
298
299 /**
300 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
301 into system memory with the PE/COFF Loader Library functions.
302
303 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
304 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
305 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
306 If Pe32Data is NULL, then ASSERT().
307 If EntryPoint is NULL, then ASSERT().
308
309 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
310 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
311
312 @retval RETURN_SUCCESS EntryPoint was returned.
313 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
314
315 **/
316 RETURN_STATUS
317 InternalPeCoffGetEntryPoint (
318 IN VOID *Pe32Data,
319 OUT VOID **EntryPoint
320 )
321 {
322 EFI_IMAGE_DOS_HEADER *DosHdr;
323 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
324
325 ASSERT (Pe32Data != NULL);
326 ASSERT (EntryPoint != NULL);
327
328 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
329 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
330 //
331 // DOS image header is present, so read the PE header after the DOS image header.
332 //
333 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
334 } else {
335 //
336 // DOS image header is not present, so PE header is at the image base.
337 //
338 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
339 }
340
341 //
342 // Calculate the entry point relative to the start of the image.
343 // AddressOfEntryPoint is common for PE32 & PE32+
344 //
345 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
346 *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
347 return RETURN_SUCCESS;
348 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
349 *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
350 return RETURN_SUCCESS;
351 }
352
353 return RETURN_UNSUPPORTED;
354 }
355
356 /**
357 Build driver info.
358
359 @param ContextData Memory profile context.
360 @param FileName File name of the image.
361 @param ImageBase Image base address.
362 @param ImageSize Image size.
363 @param EntryPoint Entry point of the image.
364 @param ImageSubsystem Image subsystem of the image.
365 @param FileType File type of the image.
366
367 @return Pointer to memory profile driver info.
368
369 **/
370 MEMORY_PROFILE_DRIVER_INFO_DATA *
371 BuildDriverInfo (
372 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
373 IN EFI_GUID *FileName,
374 IN PHYSICAL_ADDRESS ImageBase,
375 IN UINT64 ImageSize,
376 IN PHYSICAL_ADDRESS EntryPoint,
377 IN UINT16 ImageSubsystem,
378 IN EFI_FV_FILETYPE FileType
379 )
380 {
381 EFI_STATUS Status;
382 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
383 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
384 VOID *EntryPointInImage;
385 CHAR8 *PdbString;
386 UINTN PdbSize;
387 UINTN PdbOccupiedSize;
388
389 PdbSize = 0;
390 PdbOccupiedSize = 0;
391 PdbString = NULL;
392 if (ImageBase != 0) {
393 PdbString = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageBase);
394 if (PdbString != NULL) {
395 PdbSize = AsciiStrSize (PdbString);
396 PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
397 }
398 }
399
400 //
401 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
402 //
403 Status = SmmInternalAllocatePool (
404 EfiRuntimeServicesData,
405 sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize,
406 (VOID **)&DriverInfoData
407 );
408 if (EFI_ERROR (Status)) {
409 return NULL;
410 }
411
412 ASSERT (DriverInfoData != NULL);
413
414 ZeroMem (DriverInfoData, sizeof (*DriverInfoData));
415
416 DriverInfo = &DriverInfoData->DriverInfo;
417 DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
418 DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
419 DriverInfo->Header.Length = (UINT16)(sizeof (MEMORY_PROFILE_DRIVER_INFO) + PdbOccupiedSize);
420 DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;
421 if (FileName != NULL) {
422 CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));
423 }
424
425 DriverInfo->ImageBase = ImageBase;
426 DriverInfo->ImageSize = ImageSize;
427 DriverInfo->EntryPoint = EntryPoint;
428 DriverInfo->ImageSubsystem = ImageSubsystem;
429 if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {
430 //
431 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
432 // So patch ImageBuffer here to align the EntryPoint.
433 //
434 Status = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)ImageBase, &EntryPointInImage);
435 ASSERT_EFI_ERROR (Status);
436 DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
437 }
438
439 DriverInfo->FileType = FileType;
440 DriverInfoData->AllocInfoList = (LIST_ENTRY *)(DriverInfoData + 1);
441 InitializeListHead (DriverInfoData->AllocInfoList);
442 DriverInfo->CurrentUsage = 0;
443 DriverInfo->PeakUsage = 0;
444 DriverInfo->AllocRecordCount = 0;
445 if (PdbSize != 0) {
446 DriverInfo->PdbStringOffset = (UINT16)sizeof (MEMORY_PROFILE_DRIVER_INFO);
447 DriverInfoData->PdbString = (CHAR8 *)(DriverInfoData->AllocInfoList + 1);
448 CopyMem (DriverInfoData->PdbString, PdbString, PdbSize);
449 } else {
450 DriverInfo->PdbStringOffset = 0;
451 DriverInfoData->PdbString = NULL;
452 }
453
454 InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);
455 ContextData->Context.ImageCount++;
456 ContextData->Context.TotalImageSize += DriverInfo->ImageSize;
457
458 return DriverInfoData;
459 }
460
461 /**
462 Register image to DXE.
463
464 @param FileName File name of the image.
465 @param ImageBase Image base address.
466 @param ImageSize Image size.
467 @param FileType File type of the image.
468
469 **/
470 VOID
471 RegisterImageToDxe (
472 IN EFI_GUID *FileName,
473 IN PHYSICAL_ADDRESS ImageBase,
474 IN UINT64 ImageSize,
475 IN EFI_FV_FILETYPE FileType
476 )
477 {
478 EFI_STATUS Status;
479 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
480 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
481 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
482
483 if (IS_UEFI_MEMORY_PROFILE_ENABLED) {
484 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
485 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **)&ProfileProtocol);
486 if (!EFI_ERROR (Status)) {
487 EfiInitializeFwVolDevicepathNode (FilePath, FileName);
488 SetDevicePathEndNode (FilePath + 1);
489
490 Status = ProfileProtocol->RegisterImage (
491 ProfileProtocol,
492 (EFI_DEVICE_PATH_PROTOCOL *)FilePath,
493 ImageBase,
494 ImageSize,
495 FileType
496 );
497 }
498 }
499 }
500
501 /**
502 Unregister image from DXE.
503
504 @param FileName File name of the image.
505 @param ImageBase Image base address.
506 @param ImageSize Image size.
507
508 **/
509 VOID
510 UnregisterImageFromDxe (
511 IN EFI_GUID *FileName,
512 IN PHYSICAL_ADDRESS ImageBase,
513 IN UINT64 ImageSize
514 )
515 {
516 EFI_STATUS Status;
517 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
518 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
519 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
520
521 if (IS_UEFI_MEMORY_PROFILE_ENABLED) {
522 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
523 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID *)&ProfileProtocol);
524 if (!EFI_ERROR (Status)) {
525 EfiInitializeFwVolDevicepathNode (FilePath, FileName);
526 SetDevicePathEndNode (FilePath + 1);
527
528 Status = ProfileProtocol->UnregisterImage (
529 ProfileProtocol,
530 (EFI_DEVICE_PATH_PROTOCOL *)FilePath,
531 ImageBase,
532 ImageSize
533 );
534 }
535 }
536 }
537
538 /**
539 Return if record for this driver is needed..
540
541 @param DriverFilePath Driver file path.
542
543 @retval TRUE Record for this driver is needed.
544 @retval FALSE Record for this driver is not needed.
545
546 **/
547 BOOLEAN
548 NeedRecordThisDriver (
549 IN EFI_DEVICE_PATH_PROTOCOL *DriverFilePath
550 )
551 {
552 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
553 EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance;
554 UINTN DevicePathSize;
555 UINTN FilePathSize;
556
557 if (!IsDevicePathValid (mSmramProfileDriverPath, mSmramProfileDriverPathSize)) {
558 //
559 // Invalid Device Path means record all.
560 //
561 return TRUE;
562 }
563
564 //
565 // Record FilePath without end node.
566 //
567 FilePathSize = GetDevicePathSize (DriverFilePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
568
569 DevicePathInstance = mSmramProfileDriverPath;
570 do {
571 //
572 // Find End node (it might be END_ENTIRE or END_INSTANCE)
573 //
574 TmpDevicePath = DevicePathInstance;
575 while (!IsDevicePathEndType (TmpDevicePath)) {
576 TmpDevicePath = NextDevicePathNode (TmpDevicePath);
577 }
578
579 //
580 // Do not compare END node
581 //
582 DevicePathSize = (UINTN)TmpDevicePath - (UINTN)DevicePathInstance;
583 if ((FilePathSize == DevicePathSize) &&
584 (CompareMem (DriverFilePath, DevicePathInstance, DevicePathSize) == 0))
585 {
586 return TRUE;
587 }
588
589 //
590 // Get next instance
591 //
592 DevicePathInstance = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)DevicePathInstance + DevicePathSize + DevicePathNodeLength (TmpDevicePath));
593 } while (DevicePathSubType (TmpDevicePath) != END_ENTIRE_DEVICE_PATH_SUBTYPE);
594
595 return FALSE;
596 }
597
598 /**
599 Register SMM Core to SMRAM profile.
600
601 @param ContextData SMRAM profile context.
602
603 @retval TRUE Register success.
604 @retval FALSE Register fail.
605
606 **/
607 BOOLEAN
608 RegisterSmmCore (
609 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData
610 )
611 {
612 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
613 PHYSICAL_ADDRESS ImageBase;
614 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
615 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
616
617 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
618 EfiInitializeFwVolDevicepathNode (FilePath, &gEfiCallerIdGuid);
619 SetDevicePathEndNode (FilePath + 1);
620
621 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *)FilePath)) {
622 return FALSE;
623 }
624
625 ImageBase = gSmmCorePrivate->PiSmmCoreImageBase;
626 DriverInfoData = BuildDriverInfo (
627 ContextData,
628 &gEfiCallerIdGuid,
629 ImageBase,
630 gSmmCorePrivate->PiSmmCoreImageSize,
631 gSmmCorePrivate->PiSmmCoreEntryPoint,
632 InternalPeCoffGetSubsystem ((VOID *)(UINTN)ImageBase),
633 EFI_FV_FILETYPE_SMM_CORE
634 );
635 if (DriverInfoData == NULL) {
636 return FALSE;
637 }
638
639 return TRUE;
640 }
641
642 /**
643 Initialize SMRAM profile.
644
645 **/
646 VOID
647 SmramProfileInit (
648 VOID
649 )
650 {
651 MEMORY_PROFILE_CONTEXT_DATA *SmramProfileContext;
652
653 RegisterImageToDxe (
654 &gEfiCallerIdGuid,
655 gSmmCorePrivate->PiSmmCoreImageBase,
656 gSmmCorePrivate->PiSmmCoreImageSize,
657 EFI_FV_FILETYPE_SMM_CORE
658 );
659
660 if (!IS_SMRAM_PROFILE_ENABLED) {
661 return;
662 }
663
664 SmramProfileContext = GetSmramProfileContext ();
665 if (SmramProfileContext != NULL) {
666 return;
667 }
668
669 mSmramProfileGettingStatus = FALSE;
670 if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) {
671 mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
672 } else {
673 mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE;
674 }
675
676 mSmramProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath);
677 mSmramProfileDriverPath = AllocateCopyPool (mSmramProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath));
678 mSmramProfileContextPtr = &mSmramProfileContext;
679
680 RegisterSmmCore (&mSmramProfileContext);
681
682 DEBUG ((DEBUG_INFO, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext));
683 }
684
685 /**
686 Install SMRAM profile protocol.
687
688 **/
689 VOID
690 SmramProfileInstallProtocol (
691 VOID
692 )
693 {
694 EFI_HANDLE Handle;
695 EFI_STATUS Status;
696
697 if (!IS_SMRAM_PROFILE_ENABLED) {
698 return;
699 }
700
701 Handle = NULL;
702 Status = SmmInstallProtocolInterface (
703 &Handle,
704 &gEdkiiSmmMemoryProfileGuid,
705 EFI_NATIVE_INTERFACE,
706 &mSmmProfileProtocol
707 );
708 ASSERT_EFI_ERROR (Status);
709 }
710
711 /**
712 Get the GUID file name from the file path.
713
714 @param FilePath File path.
715
716 @return The GUID file name from the file path.
717
718 **/
719 EFI_GUID *
720 GetFileNameFromFilePath (
721 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
722 )
723 {
724 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *ThisFilePath;
725 EFI_GUID *FileName;
726
727 FileName = NULL;
728 if (FilePath != NULL) {
729 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePath;
730 while (!IsDevicePathEnd (ThisFilePath)) {
731 FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath);
732 if (FileName != NULL) {
733 break;
734 }
735
736 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)NextDevicePathNode (ThisFilePath);
737 }
738 }
739
740 return FileName;
741 }
742
743 /**
744 Register SMM image to SMRAM profile.
745
746 @param DriverEntry SMM image info.
747 @param RegisterToDxe Register image to DXE.
748
749 @return EFI_SUCCESS Register successfully.
750 @return EFI_UNSUPPORTED Memory profile is unsupported,
751 or memory profile for the image is not required.
752 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
753
754 **/
755 EFI_STATUS
756 RegisterSmramProfileImage (
757 IN EFI_SMM_DRIVER_ENTRY *DriverEntry,
758 IN BOOLEAN RegisterToDxe
759 )
760 {
761 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
762 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
763 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
764 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
765
766 if (RegisterToDxe) {
767 RegisterImageToDxe (
768 &DriverEntry->FileName,
769 DriverEntry->ImageBuffer,
770 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),
771 EFI_FV_FILETYPE_SMM
772 );
773 }
774
775 if (!IS_SMRAM_PROFILE_ENABLED) {
776 return EFI_UNSUPPORTED;
777 }
778
779 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
780 EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName);
781 SetDevicePathEndNode (FilePath + 1);
782
783 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *)FilePath)) {
784 return EFI_UNSUPPORTED;
785 }
786
787 ContextData = GetSmramProfileContext ();
788 if (ContextData == NULL) {
789 return EFI_UNSUPPORTED;
790 }
791
792 DriverInfoData = BuildDriverInfo (
793 ContextData,
794 &DriverEntry->FileName,
795 DriverEntry->ImageBuffer,
796 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),
797 DriverEntry->ImageEntryPoint,
798 InternalPeCoffGetSubsystem ((VOID *)(UINTN)DriverEntry->ImageBuffer),
799 EFI_FV_FILETYPE_SMM
800 );
801 if (DriverInfoData == NULL) {
802 return EFI_OUT_OF_RESOURCES;
803 }
804
805 return EFI_SUCCESS;
806 }
807
808 /**
809 Search image from memory profile.
810
811 @param ContextData Memory profile context.
812 @param FileName Image file name.
813 @param Address Image Address.
814
815 @return Pointer to memory profile driver info.
816
817 **/
818 MEMORY_PROFILE_DRIVER_INFO_DATA *
819 GetMemoryProfileDriverInfoByFileNameAndAddress (
820 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
821 IN EFI_GUID *FileName,
822 IN PHYSICAL_ADDRESS Address
823 )
824 {
825 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
826 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
827 LIST_ENTRY *DriverLink;
828 LIST_ENTRY *DriverInfoList;
829
830 DriverInfoList = ContextData->DriverInfoList;
831
832 for (DriverLink = DriverInfoList->ForwardLink;
833 DriverLink != DriverInfoList;
834 DriverLink = DriverLink->ForwardLink)
835 {
836 DriverInfoData = CR (
837 DriverLink,
838 MEMORY_PROFILE_DRIVER_INFO_DATA,
839 Link,
840 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
841 );
842 DriverInfo = &DriverInfoData->DriverInfo;
843 if ((CompareGuid (&DriverInfo->FileName, FileName)) &&
844 (Address >= DriverInfo->ImageBase) &&
845 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize)))
846 {
847 return DriverInfoData;
848 }
849 }
850
851 return NULL;
852 }
853
854 /**
855 Search image from memory profile.
856 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)
857
858 @param ContextData Memory profile context.
859 @param Address Image or Function address.
860
861 @return Pointer to memory profile driver info.
862
863 **/
864 MEMORY_PROFILE_DRIVER_INFO_DATA *
865 GetMemoryProfileDriverInfoFromAddress (
866 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
867 IN PHYSICAL_ADDRESS Address
868 )
869 {
870 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
871 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
872 LIST_ENTRY *DriverLink;
873 LIST_ENTRY *DriverInfoList;
874
875 DriverInfoList = ContextData->DriverInfoList;
876
877 for (DriverLink = DriverInfoList->ForwardLink;
878 DriverLink != DriverInfoList;
879 DriverLink = DriverLink->ForwardLink)
880 {
881 DriverInfoData = CR (
882 DriverLink,
883 MEMORY_PROFILE_DRIVER_INFO_DATA,
884 Link,
885 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
886 );
887 DriverInfo = &DriverInfoData->DriverInfo;
888 if ((Address >= DriverInfo->ImageBase) &&
889 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize)))
890 {
891 return DriverInfoData;
892 }
893 }
894
895 return NULL;
896 }
897
898 /**
899 Unregister image from SMRAM profile.
900
901 @param DriverEntry SMM image info.
902 @param UnregisterFromDxe Unregister image from DXE.
903
904 @return EFI_SUCCESS Unregister successfully.
905 @return EFI_UNSUPPORTED Memory profile is unsupported,
906 or memory profile for the image is not required.
907 @return EFI_NOT_FOUND The image is not found.
908
909 **/
910 EFI_STATUS
911 UnregisterSmramProfileImage (
912 IN EFI_SMM_DRIVER_ENTRY *DriverEntry,
913 IN BOOLEAN UnregisterFromDxe
914 )
915 {
916 EFI_STATUS Status;
917 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
918 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
919 EFI_GUID *FileName;
920 PHYSICAL_ADDRESS ImageAddress;
921 VOID *EntryPointInImage;
922 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
923 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
924
925 if (UnregisterFromDxe) {
926 UnregisterImageFromDxe (
927 &DriverEntry->FileName,
928 DriverEntry->ImageBuffer,
929 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)
930 );
931 }
932
933 if (!IS_SMRAM_PROFILE_ENABLED) {
934 return EFI_UNSUPPORTED;
935 }
936
937 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
938 EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName);
939 SetDevicePathEndNode (FilePath + 1);
940
941 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *)FilePath)) {
942 return EFI_UNSUPPORTED;
943 }
944
945 ContextData = GetSmramProfileContext ();
946 if (ContextData == NULL) {
947 return EFI_UNSUPPORTED;
948 }
949
950 DriverInfoData = NULL;
951 FileName = &DriverEntry->FileName;
952 ImageAddress = DriverEntry->ImageBuffer;
953 if ((DriverEntry->ImageEntryPoint < ImageAddress) || (DriverEntry->ImageEntryPoint >= (ImageAddress + EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)))) {
954 //
955 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
956 // So patch ImageAddress here to align the EntryPoint.
957 //
958 Status = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)ImageAddress, &EntryPointInImage);
959 ASSERT_EFI_ERROR (Status);
960 ImageAddress = ImageAddress + (UINTN)DriverEntry->ImageEntryPoint - (UINTN)EntryPointInImage;
961 }
962
963 if (FileName != NULL) {
964 DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);
965 }
966
967 if (DriverInfoData == NULL) {
968 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);
969 }
970
971 if (DriverInfoData == NULL) {
972 return EFI_NOT_FOUND;
973 }
974
975 ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;
976
977 // Keep the ImageBase for RVA calculation in Application.
978 // DriverInfoData->DriverInfo.ImageBase = 0;
979 DriverInfoData->DriverInfo.ImageSize = 0;
980
981 if (DriverInfoData->DriverInfo.PeakUsage == 0) {
982 ContextData->Context.ImageCount--;
983 RemoveEntryList (&DriverInfoData->Link);
984 //
985 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
986 //
987 SmmInternalFreePool (DriverInfoData);
988 }
989
990 return EFI_SUCCESS;
991 }
992
993 /**
994 Return if this memory type needs to be recorded into memory profile.
995 Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile.
996
997 @param MemoryType Memory type.
998
999 @retval TRUE This memory type need to be recorded.
1000 @retval FALSE This memory type need not to be recorded.
1001
1002 **/
1003 BOOLEAN
1004 SmmCoreNeedRecordProfile (
1005 IN EFI_MEMORY_TYPE MemoryType
1006 )
1007 {
1008 UINT64 TestBit;
1009
1010 if ((MemoryType != EfiRuntimeServicesCode) &&
1011 (MemoryType != EfiRuntimeServicesData))
1012 {
1013 return FALSE;
1014 }
1015
1016 TestBit = LShiftU64 (1, MemoryType);
1017
1018 if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {
1019 return TRUE;
1020 } else {
1021 return FALSE;
1022 }
1023 }
1024
1025 /**
1026 Convert EFI memory type to profile memory index. The rule is:
1027 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
1028 As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData,
1029 so return input memory type directly.
1030
1031 @param MemoryType Memory type.
1032
1033 @return EFI memory type as profile memory index.
1034
1035 **/
1036 EFI_MEMORY_TYPE
1037 GetProfileMemoryIndex (
1038 IN EFI_MEMORY_TYPE MemoryType
1039 )
1040 {
1041 return MemoryType;
1042 }
1043
1044 /**
1045 Update SMRAM profile FreeMemoryPages information
1046
1047 @param ContextData Memory profile context.
1048
1049 **/
1050 VOID
1051 SmramProfileUpdateFreePages (
1052 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData
1053 )
1054 {
1055 LIST_ENTRY *Node;
1056 FREE_PAGE_LIST *Pages;
1057 LIST_ENTRY *FreePageList;
1058 UINTN NumberOfPages;
1059
1060 NumberOfPages = 0;
1061 FreePageList = &mSmmMemoryMap;
1062 for (Node = FreePageList->BackLink;
1063 Node != FreePageList;
1064 Node = Node->BackLink)
1065 {
1066 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1067 NumberOfPages += Pages->NumberOfPages;
1068 }
1069
1070 mSmramFreeMemory.TotalFreeMemoryPages = NumberOfPages;
1071
1072 if (NumberOfPages <= SMRAM_INFO_DUMP_PAGE_THRESHOLD) {
1073 DumpSmramInfo ();
1074 }
1075 }
1076
1077 /**
1078 Update SMRAM profile Allocate information.
1079
1080 @param CallerAddress Address of caller who call Allocate.
1081 @param Action This Allocate action.
1082 @param MemoryType Memory type.
1083 @param Size Buffer size.
1084 @param Buffer Buffer address.
1085 @param ActionString String for memory profile action.
1086
1087 @return EFI_SUCCESS Memory profile is updated.
1088 @return EFI_UNSUPPORTED Memory profile is unsupported,
1089 or memory profile for the image is not required.
1090 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1091
1092 **/
1093 EFI_STATUS
1094 SmmCoreUpdateProfileAllocate (
1095 IN PHYSICAL_ADDRESS CallerAddress,
1096 IN MEMORY_PROFILE_ACTION Action,
1097 IN EFI_MEMORY_TYPE MemoryType,
1098 IN UINTN Size,
1099 IN VOID *Buffer,
1100 IN CHAR8 *ActionString OPTIONAL
1101 )
1102 {
1103 EFI_STATUS Status;
1104 MEMORY_PROFILE_CONTEXT *Context;
1105 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1106 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1107 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1108 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1109 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1110 EFI_MEMORY_TYPE ProfileMemoryIndex;
1111 MEMORY_PROFILE_ACTION BasicAction;
1112 UINTN ActionStringSize;
1113 UINTN ActionStringOccupiedSize;
1114
1115 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1116
1117 ContextData = GetSmramProfileContext ();
1118 if (ContextData == NULL) {
1119 return EFI_UNSUPPORTED;
1120 }
1121
1122 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
1123 if (DriverInfoData == NULL) {
1124 return EFI_UNSUPPORTED;
1125 }
1126
1127 ActionStringSize = 0;
1128 ActionStringOccupiedSize = 0;
1129 if (ActionString != NULL) {
1130 ActionStringSize = AsciiStrSize (ActionString);
1131 ActionStringOccupiedSize = GET_OCCUPIED_SIZE (ActionStringSize, sizeof (UINT64));
1132 }
1133
1134 //
1135 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
1136 //
1137 AllocInfoData = NULL;
1138 Status = SmmInternalAllocatePool (
1139 EfiRuntimeServicesData,
1140 sizeof (*AllocInfoData) + ActionStringSize,
1141 (VOID **)&AllocInfoData
1142 );
1143 if (EFI_ERROR (Status)) {
1144 return EFI_OUT_OF_RESOURCES;
1145 }
1146
1147 ASSERT (AllocInfoData != NULL);
1148
1149 //
1150 // Only update SequenceCount if and only if it is basic action.
1151 //
1152 if (Action == BasicAction) {
1153 ContextData->Context.SequenceCount++;
1154 }
1155
1156 AllocInfo = &AllocInfoData->AllocInfo;
1157 AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
1158 AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
1159 AllocInfo->Header.Length = (UINT16)(sizeof (MEMORY_PROFILE_ALLOC_INFO) + ActionStringOccupiedSize);
1160 AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION;
1161 AllocInfo->CallerAddress = CallerAddress;
1162 AllocInfo->SequenceId = ContextData->Context.SequenceCount;
1163 AllocInfo->Action = Action;
1164 AllocInfo->MemoryType = MemoryType;
1165 AllocInfo->Buffer = (PHYSICAL_ADDRESS)(UINTN)Buffer;
1166 AllocInfo->Size = Size;
1167 if (ActionString != NULL) {
1168 AllocInfo->ActionStringOffset = (UINT16)sizeof (MEMORY_PROFILE_ALLOC_INFO);
1169 AllocInfoData->ActionString = (CHAR8 *)(AllocInfoData + 1);
1170 CopyMem (AllocInfoData->ActionString, ActionString, ActionStringSize);
1171 } else {
1172 AllocInfo->ActionStringOffset = 0;
1173 AllocInfoData->ActionString = NULL;
1174 }
1175
1176 InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);
1177
1178 Context = &ContextData->Context;
1179 DriverInfo = &DriverInfoData->DriverInfo;
1180 DriverInfo->AllocRecordCount++;
1181
1182 //
1183 // Update summary if and only if it is basic action.
1184 //
1185 if (Action == BasicAction) {
1186 ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);
1187
1188 DriverInfo->CurrentUsage += Size;
1189 if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {
1190 DriverInfo->PeakUsage = DriverInfo->CurrentUsage;
1191 }
1192
1193 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;
1194 if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {
1195 DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];
1196 }
1197
1198 Context->CurrentTotalUsage += Size;
1199 if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {
1200 Context->PeakTotalUsage = Context->CurrentTotalUsage;
1201 }
1202
1203 Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;
1204 if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {
1205 Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];
1206 }
1207
1208 SmramProfileUpdateFreePages (ContextData);
1209 }
1210
1211 return EFI_SUCCESS;
1212 }
1213
1214 /**
1215 Get memory profile alloc info from memory profile
1216
1217 @param DriverInfoData Driver info
1218 @param BasicAction This Free basic action
1219 @param Size Buffer size
1220 @param Buffer Buffer address
1221
1222 @return Pointer to memory profile alloc info.
1223 **/
1224 MEMORY_PROFILE_ALLOC_INFO_DATA *
1225 GetMemoryProfileAllocInfoFromAddress (
1226 IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData,
1227 IN MEMORY_PROFILE_ACTION BasicAction,
1228 IN UINTN Size,
1229 IN VOID *Buffer
1230 )
1231 {
1232 LIST_ENTRY *AllocInfoList;
1233 LIST_ENTRY *AllocLink;
1234 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1235 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1236
1237 AllocInfoList = DriverInfoData->AllocInfoList;
1238
1239 for (AllocLink = AllocInfoList->ForwardLink;
1240 AllocLink != AllocInfoList;
1241 AllocLink = AllocLink->ForwardLink)
1242 {
1243 AllocInfoData = CR (
1244 AllocLink,
1245 MEMORY_PROFILE_ALLOC_INFO_DATA,
1246 Link,
1247 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1248 );
1249 AllocInfo = &AllocInfoData->AllocInfo;
1250 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK) != BasicAction) {
1251 continue;
1252 }
1253
1254 switch (BasicAction) {
1255 case MemoryProfileActionAllocatePages:
1256 if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS)(UINTN)Buffer) &&
1257 ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS)(UINTN)Buffer + Size)))
1258 {
1259 return AllocInfoData;
1260 }
1261
1262 break;
1263 case MemoryProfileActionAllocatePool:
1264 if (AllocInfo->Buffer == (PHYSICAL_ADDRESS)(UINTN)Buffer) {
1265 return AllocInfoData;
1266 }
1267
1268 break;
1269 default:
1270 ASSERT (FALSE);
1271 break;
1272 }
1273 }
1274
1275 return NULL;
1276 }
1277
1278 /**
1279 Update SMRAM profile Free information.
1280
1281 @param CallerAddress Address of caller who call Free.
1282 @param Action This Free action.
1283 @param Size Buffer size.
1284 @param Buffer Buffer address.
1285
1286 @return EFI_SUCCESS Memory profile is updated.
1287 @return EFI_UNSUPPORTED Memory profile is unsupported.
1288 @return EFI_NOT_FOUND No matched allocate info found for free action.
1289
1290 **/
1291 EFI_STATUS
1292 SmmCoreUpdateProfileFree (
1293 IN PHYSICAL_ADDRESS CallerAddress,
1294 IN MEMORY_PROFILE_ACTION Action,
1295 IN UINTN Size,
1296 IN VOID *Buffer
1297 )
1298 {
1299 MEMORY_PROFILE_CONTEXT *Context;
1300 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1301 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1302 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1303 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1304 LIST_ENTRY *DriverLink;
1305 LIST_ENTRY *DriverInfoList;
1306 MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData;
1307 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1308 EFI_MEMORY_TYPE ProfileMemoryIndex;
1309 MEMORY_PROFILE_ACTION BasicAction;
1310 BOOLEAN Found;
1311
1312 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1313
1314 ContextData = GetSmramProfileContext ();
1315 if (ContextData == NULL) {
1316 return EFI_UNSUPPORTED;
1317 }
1318
1319 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
1320
1321 //
1322 // Do not return if DriverInfoData == NULL here,
1323 // because driver A might free memory allocated by driver B.
1324 //
1325
1326 //
1327 // Need use do-while loop to find all possible record,
1328 // because one address might be recorded multiple times.
1329 //
1330 Found = FALSE;
1331 AllocInfoData = NULL;
1332 do {
1333 if (DriverInfoData != NULL) {
1334 switch (BasicAction) {
1335 case MemoryProfileActionFreePages:
1336 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
1337 break;
1338 case MemoryProfileActionFreePool:
1339 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
1340 break;
1341 default:
1342 ASSERT (FALSE);
1343 AllocInfoData = NULL;
1344 break;
1345 }
1346 }
1347
1348 if (AllocInfoData == NULL) {
1349 //
1350 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1351 //
1352 DriverInfoList = ContextData->DriverInfoList;
1353
1354 for (DriverLink = DriverInfoList->ForwardLink;
1355 DriverLink != DriverInfoList;
1356 DriverLink = DriverLink->ForwardLink)
1357 {
1358 ThisDriverInfoData = CR (
1359 DriverLink,
1360 MEMORY_PROFILE_DRIVER_INFO_DATA,
1361 Link,
1362 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1363 );
1364 switch (BasicAction) {
1365 case MemoryProfileActionFreePages:
1366 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
1367 break;
1368 case MemoryProfileActionFreePool:
1369 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
1370 break;
1371 default:
1372 ASSERT (FALSE);
1373 AllocInfoData = NULL;
1374 break;
1375 }
1376
1377 if (AllocInfoData != NULL) {
1378 DriverInfoData = ThisDriverInfoData;
1379 break;
1380 }
1381 }
1382
1383 if (AllocInfoData == NULL) {
1384 //
1385 // If (!Found), no matched allocate info is found for this free action.
1386 // It is because the specified memory type allocate actions have been filtered by
1387 // CoreNeedRecordProfile(), but free actions have no memory type information,
1388 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1389 // filtered here.
1390 //
1391 // If (Found), it is normal exit path.
1392 return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
1393 }
1394 }
1395
1396 ASSERT (DriverInfoData != NULL);
1397 ASSERT (AllocInfoData != NULL);
1398
1399 Found = TRUE;
1400
1401 Context = &ContextData->Context;
1402 DriverInfo = &DriverInfoData->DriverInfo;
1403 AllocInfo = &AllocInfoData->AllocInfo;
1404
1405 DriverInfo->AllocRecordCount--;
1406 //
1407 // Update summary if and only if it is basic action.
1408 //
1409 if (AllocInfo->Action == (AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK)) {
1410 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
1411
1412 Context->CurrentTotalUsage -= AllocInfo->Size;
1413 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1414
1415 DriverInfo->CurrentUsage -= AllocInfo->Size;
1416 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1417 }
1418
1419 RemoveEntryList (&AllocInfoData->Link);
1420
1421 if (BasicAction == MemoryProfileActionFreePages) {
1422 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS)(UINTN)Buffer) {
1423 SmmCoreUpdateProfileAllocate (
1424 AllocInfo->CallerAddress,
1425 AllocInfo->Action,
1426 AllocInfo->MemoryType,
1427 (UINTN)((PHYSICAL_ADDRESS)(UINTN)Buffer - AllocInfo->Buffer),
1428 (VOID *)(UINTN)AllocInfo->Buffer,
1429 AllocInfoData->ActionString
1430 );
1431 }
1432
1433 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS)(UINTN)Buffer + Size)) {
1434 SmmCoreUpdateProfileAllocate (
1435 AllocInfo->CallerAddress,
1436 AllocInfo->Action,
1437 AllocInfo->MemoryType,
1438 (UINTN)((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS)(UINTN)Buffer + Size)),
1439 (VOID *)((UINTN)Buffer + Size),
1440 AllocInfoData->ActionString
1441 );
1442 }
1443 }
1444
1445 //
1446 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1447 //
1448 SmmInternalFreePool (AllocInfoData);
1449 } while (TRUE);
1450 }
1451
1452 /**
1453 Update SMRAM profile information.
1454
1455 @param CallerAddress Address of caller who call Allocate or Free.
1456 @param Action This Allocate or Free action.
1457 @param MemoryType Memory type.
1458 EfiMaxMemoryType means the MemoryType is unknown.
1459 @param Size Buffer size.
1460 @param Buffer Buffer address.
1461 @param ActionString String for memory profile action.
1462 Only needed for user defined allocate action.
1463
1464 @return EFI_SUCCESS Memory profile is updated.
1465 @return EFI_UNSUPPORTED Memory profile is unsupported,
1466 or memory profile for the image is not required,
1467 or memory profile for the memory type is not required.
1468 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1469 @return EFI_ABORTED Memory profile recording is not enabled.
1470 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1471 @return EFI_NOT_FOUND No matched allocate info found for free action.
1472
1473 **/
1474 EFI_STATUS
1475 EFIAPI
1476 SmmCoreUpdateProfile (
1477 IN PHYSICAL_ADDRESS CallerAddress,
1478 IN MEMORY_PROFILE_ACTION Action,
1479 IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool
1480 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool
1481 IN VOID *Buffer,
1482 IN CHAR8 *ActionString OPTIONAL
1483 )
1484 {
1485 EFI_STATUS Status;
1486 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1487 MEMORY_PROFILE_ACTION BasicAction;
1488
1489 if (!IS_SMRAM_PROFILE_ENABLED) {
1490 return EFI_UNSUPPORTED;
1491 }
1492
1493 if (mSmramProfileGettingStatus) {
1494 return EFI_ACCESS_DENIED;
1495 }
1496
1497 if (!mSmramProfileRecordingEnable) {
1498 return EFI_ABORTED;
1499 }
1500
1501 //
1502 // Get the basic action to know how to process the record
1503 //
1504 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1505
1506 //
1507 // Free operations have no memory type information, so skip the check.
1508 //
1509 if ((BasicAction == MemoryProfileActionAllocatePages) || (BasicAction == MemoryProfileActionAllocatePool)) {
1510 //
1511 // Only record limited MemoryType.
1512 //
1513 if (!SmmCoreNeedRecordProfile (MemoryType)) {
1514 return EFI_UNSUPPORTED;
1515 }
1516 }
1517
1518 ContextData = GetSmramProfileContext ();
1519 if (ContextData == NULL) {
1520 return EFI_UNSUPPORTED;
1521 }
1522
1523 switch (BasicAction) {
1524 case MemoryProfileActionAllocatePages:
1525 Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1526 break;
1527 case MemoryProfileActionFreePages:
1528 Status = SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
1529 break;
1530 case MemoryProfileActionAllocatePool:
1531 Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1532 break;
1533 case MemoryProfileActionFreePool:
1534 Status = SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
1535 break;
1536 default:
1537 ASSERT (FALSE);
1538 Status = EFI_UNSUPPORTED;
1539 break;
1540 }
1541
1542 return Status;
1543 }
1544
1545 /**
1546 SMRAM profile ready to lock callback function.
1547
1548 **/
1549 VOID
1550 SmramProfileReadyToLock (
1551 VOID
1552 )
1553 {
1554 if (!IS_SMRAM_PROFILE_ENABLED) {
1555 return;
1556 }
1557
1558 DEBUG ((DEBUG_INFO, "SmramProfileReadyToLock\n"));
1559 mSmramReadyToLock = TRUE;
1560 }
1561
1562 ////////////////////
1563
1564 /**
1565 Get SMRAM profile data size.
1566
1567 @return SMRAM profile data size.
1568
1569 **/
1570 UINTN
1571 SmramProfileGetDataSize (
1572 VOID
1573 )
1574 {
1575 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1576 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1577 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1578 LIST_ENTRY *DriverInfoList;
1579 LIST_ENTRY *DriverLink;
1580 LIST_ENTRY *AllocInfoList;
1581 LIST_ENTRY *AllocLink;
1582 UINTN TotalSize;
1583 LIST_ENTRY *Node;
1584 LIST_ENTRY *FreePageList;
1585 LIST_ENTRY *FreePoolList;
1586 FREE_POOL_HEADER *Pool;
1587 UINTN PoolListIndex;
1588 UINTN Index;
1589 UINTN SmmPoolTypeIndex;
1590
1591 ContextData = GetSmramProfileContext ();
1592 if (ContextData == NULL) {
1593 return 0;
1594 }
1595
1596 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
1597
1598 DriverInfoList = ContextData->DriverInfoList;
1599 for (DriverLink = DriverInfoList->ForwardLink;
1600 DriverLink != DriverInfoList;
1601 DriverLink = DriverLink->ForwardLink)
1602 {
1603 DriverInfoData = CR (
1604 DriverLink,
1605 MEMORY_PROFILE_DRIVER_INFO_DATA,
1606 Link,
1607 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1608 );
1609 TotalSize += DriverInfoData->DriverInfo.Header.Length;
1610
1611 AllocInfoList = DriverInfoData->AllocInfoList;
1612 for (AllocLink = AllocInfoList->ForwardLink;
1613 AllocLink != AllocInfoList;
1614 AllocLink = AllocLink->ForwardLink)
1615 {
1616 AllocInfoData = CR (
1617 AllocLink,
1618 MEMORY_PROFILE_ALLOC_INFO_DATA,
1619 Link,
1620 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1621 );
1622 TotalSize += AllocInfoData->AllocInfo.Header.Length;
1623 }
1624 }
1625
1626 Index = 0;
1627 FreePageList = &mSmmMemoryMap;
1628 for (Node = FreePageList->BackLink;
1629 Node != FreePageList;
1630 Node = Node->BackLink)
1631 {
1632 Index++;
1633 }
1634
1635 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) {
1636 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1637 FreePoolList = &mSmmPoolLists[SmmPoolTypeIndex][PoolListIndex];
1638 for (Node = FreePoolList->BackLink;
1639 Node != FreePoolList;
1640 Node = Node->BackLink)
1641 {
1642 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1643 if (Pool->Header.Available) {
1644 Index++;
1645 }
1646 }
1647 }
1648 }
1649
1650 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1651 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1652
1653 return TotalSize;
1654 }
1655
1656 /**
1657 Copy SMRAM profile data.
1658
1659 @param ProfileBuffer The buffer to hold SMRAM profile data.
1660 @param ProfileSize On input, profile buffer size.
1661 On output, actual profile data size copied.
1662 @param ProfileOffset On input, profile buffer offset to copy.
1663 On output, next time profile buffer offset to copy.
1664
1665 **/
1666 VOID
1667 SmramProfileCopyData (
1668 OUT VOID *ProfileBuffer,
1669 IN OUT UINT64 *ProfileSize,
1670 IN OUT UINT64 *ProfileOffset
1671 )
1672 {
1673 MEMORY_PROFILE_CONTEXT *Context;
1674 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1675 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1676 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1677 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1678 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1679 LIST_ENTRY *DriverInfoList;
1680 LIST_ENTRY *DriverLink;
1681 LIST_ENTRY *AllocInfoList;
1682 LIST_ENTRY *AllocLink;
1683 LIST_ENTRY *Node;
1684 FREE_PAGE_LIST *Pages;
1685 LIST_ENTRY *FreePageList;
1686 LIST_ENTRY *FreePoolList;
1687 FREE_POOL_HEADER *Pool;
1688 UINTN PoolListIndex;
1689 UINT32 Index;
1690 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
1691 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
1692 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor;
1693 UINT64 Offset;
1694 UINT64 RemainingSize;
1695 UINTN PdbSize;
1696 UINTN ActionStringSize;
1697 UINTN SmmPoolTypeIndex;
1698
1699 ContextData = GetSmramProfileContext ();
1700 if (ContextData == NULL) {
1701 return;
1702 }
1703
1704 RemainingSize = *ProfileSize;
1705 Offset = 0;
1706
1707 if (*ProfileOffset < sizeof (MEMORY_PROFILE_CONTEXT)) {
1708 if (RemainingSize >= sizeof (MEMORY_PROFILE_CONTEXT)) {
1709 Context = ProfileBuffer;
1710 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
1711 RemainingSize -= sizeof (MEMORY_PROFILE_CONTEXT);
1712 ProfileBuffer = (UINT8 *)ProfileBuffer + sizeof (MEMORY_PROFILE_CONTEXT);
1713 } else {
1714 goto Done;
1715 }
1716 }
1717
1718 Offset += sizeof (MEMORY_PROFILE_CONTEXT);
1719
1720 DriverInfoList = ContextData->DriverInfoList;
1721 for (DriverLink = DriverInfoList->ForwardLink;
1722 DriverLink != DriverInfoList;
1723 DriverLink = DriverLink->ForwardLink)
1724 {
1725 DriverInfoData = CR (
1726 DriverLink,
1727 MEMORY_PROFILE_DRIVER_INFO_DATA,
1728 Link,
1729 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1730 );
1731 if (*ProfileOffset < (Offset + DriverInfoData->DriverInfo.Header.Length)) {
1732 if (RemainingSize >= DriverInfoData->DriverInfo.Header.Length) {
1733 DriverInfo = ProfileBuffer;
1734 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));
1735 if (DriverInfo->PdbStringOffset != 0) {
1736 PdbSize = AsciiStrSize (DriverInfoData->PdbString);
1737 CopyMem ((VOID *)((UINTN)DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize);
1738 }
1739
1740 RemainingSize -= DriverInfo->Header.Length;
1741 ProfileBuffer = (UINT8 *)ProfileBuffer + DriverInfo->Header.Length;
1742 } else {
1743 goto Done;
1744 }
1745 }
1746
1747 Offset += DriverInfoData->DriverInfo.Header.Length;
1748
1749 AllocInfoList = DriverInfoData->AllocInfoList;
1750 for (AllocLink = AllocInfoList->ForwardLink;
1751 AllocLink != AllocInfoList;
1752 AllocLink = AllocLink->ForwardLink)
1753 {
1754 AllocInfoData = CR (
1755 AllocLink,
1756 MEMORY_PROFILE_ALLOC_INFO_DATA,
1757 Link,
1758 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1759 );
1760 if (*ProfileOffset < (Offset + AllocInfoData->AllocInfo.Header.Length)) {
1761 if (RemainingSize >= AllocInfoData->AllocInfo.Header.Length) {
1762 AllocInfo = ProfileBuffer;
1763 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));
1764 if (AllocInfo->ActionStringOffset) {
1765 ActionStringSize = AsciiStrSize (AllocInfoData->ActionString);
1766 CopyMem ((VOID *)((UINTN)AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize);
1767 }
1768
1769 RemainingSize -= AllocInfo->Header.Length;
1770 ProfileBuffer = (UINT8 *)ProfileBuffer + AllocInfo->Header.Length;
1771 } else {
1772 goto Done;
1773 }
1774 }
1775
1776 Offset += AllocInfoData->AllocInfo.Header.Length;
1777 }
1778 }
1779
1780 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_FREE_MEMORY))) {
1781 if (RemainingSize >= sizeof (MEMORY_PROFILE_FREE_MEMORY)) {
1782 FreeMemory = ProfileBuffer;
1783 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));
1784 Index = 0;
1785 FreePageList = &mSmmMemoryMap;
1786 for (Node = FreePageList->BackLink;
1787 Node != FreePageList;
1788 Node = Node->BackLink)
1789 {
1790 Index++;
1791 }
1792
1793 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) {
1794 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1795 FreePoolList = &mSmmPoolLists[SmmPoolTypeIndex][MAX_POOL_INDEX - PoolListIndex - 1];
1796 for (Node = FreePoolList->BackLink;
1797 Node != FreePoolList;
1798 Node = Node->BackLink)
1799 {
1800 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1801 if (Pool->Header.Available) {
1802 Index++;
1803 }
1804 }
1805 }
1806 }
1807
1808 FreeMemory->FreeMemoryEntryCount = Index;
1809
1810 RemainingSize -= sizeof (MEMORY_PROFILE_FREE_MEMORY);
1811 ProfileBuffer = (UINT8 *)ProfileBuffer + sizeof (MEMORY_PROFILE_FREE_MEMORY);
1812 } else {
1813 goto Done;
1814 }
1815 }
1816
1817 Offset += sizeof (MEMORY_PROFILE_FREE_MEMORY);
1818 FreePageList = &mSmmMemoryMap;
1819 for (Node = FreePageList->BackLink;
1820 Node != FreePageList;
1821 Node = Node->BackLink)
1822 {
1823 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1824 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1825 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1826 MemoryProfileDescriptor = ProfileBuffer;
1827 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1828 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1829 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1830 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS)(UINTN)Pages;
1831 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);
1832
1833 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1834 ProfileBuffer = (UINT8 *)ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1835 } else {
1836 goto Done;
1837 }
1838 }
1839
1840 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1841 }
1842
1843 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) {
1844 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1845 FreePoolList = &mSmmPoolLists[SmmPoolTypeIndex][MAX_POOL_INDEX - PoolListIndex - 1];
1846 for (Node = FreePoolList->BackLink;
1847 Node != FreePoolList;
1848 Node = Node->BackLink)
1849 {
1850 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1851 if (Pool->Header.Available) {
1852 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1853 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1854 MemoryProfileDescriptor = ProfileBuffer;
1855 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1856 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1857 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1858 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS)(UINTN)Pool;
1859 MemoryProfileDescriptor->Size = Pool->Header.Size;
1860
1861 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1862 ProfileBuffer = (UINT8 *)ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1863 } else {
1864 goto Done;
1865 }
1866 }
1867
1868 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1869 }
1870 }
1871 }
1872 }
1873
1874 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_MEMORY_RANGE))) {
1875 if (RemainingSize >= sizeof (MEMORY_PROFILE_MEMORY_RANGE)) {
1876 MemoryRange = ProfileBuffer;
1877 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;
1878 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1879 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;
1880 MemoryRange->MemoryRangeCount = (UINT32)mFullSmramRangeCount;
1881
1882 RemainingSize -= sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1883 ProfileBuffer = (UINT8 *)ProfileBuffer + sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1884 } else {
1885 goto Done;
1886 }
1887 }
1888
1889 Offset += sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1890 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
1891 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1892 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1893 MemoryProfileDescriptor = ProfileBuffer;
1894 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1895 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1896 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1897 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;
1898 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;
1899
1900 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1901 ProfileBuffer = (UINT8 *)ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1902 } else {
1903 goto Done;
1904 }
1905 }
1906
1907 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1908 }
1909
1910 Done:
1911 //
1912 // On output, actual profile data size copied.
1913 //
1914 *ProfileSize -= RemainingSize;
1915 //
1916 // On output, next time profile buffer offset to copy.
1917 //
1918 *ProfileOffset = Offset;
1919 }
1920
1921 /**
1922 Get memory profile data.
1923
1924 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1925 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1926 On return, points to the size of the data returned in ProfileBuffer.
1927 @param[out] ProfileBuffer Profile buffer.
1928
1929 @return EFI_SUCCESS Get the memory profile data successfully.
1930 @return EFI_UNSUPPORTED Memory profile is unsupported.
1931 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1932 ProfileSize is updated with the size required.
1933
1934 **/
1935 EFI_STATUS
1936 EFIAPI
1937 SmramProfileProtocolGetData (
1938 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
1939 IN OUT UINT64 *ProfileSize,
1940 OUT VOID *ProfileBuffer
1941 )
1942 {
1943 UINT64 Size;
1944 UINT64 Offset;
1945 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1946 BOOLEAN SmramProfileGettingStatus;
1947
1948 ContextData = GetSmramProfileContext ();
1949 if (ContextData == NULL) {
1950 return EFI_UNSUPPORTED;
1951 }
1952
1953 SmramProfileGettingStatus = mSmramProfileGettingStatus;
1954 mSmramProfileGettingStatus = TRUE;
1955
1956 Size = SmramProfileGetDataSize ();
1957
1958 if (*ProfileSize < Size) {
1959 *ProfileSize = Size;
1960 mSmramProfileGettingStatus = SmramProfileGettingStatus;
1961 return EFI_BUFFER_TOO_SMALL;
1962 }
1963
1964 Offset = 0;
1965 SmramProfileCopyData (ProfileBuffer, &Size, &Offset);
1966 *ProfileSize = Size;
1967
1968 mSmramProfileGettingStatus = SmramProfileGettingStatus;
1969 return EFI_SUCCESS;
1970 }
1971
1972 /**
1973 Register image to memory profile.
1974
1975 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1976 @param[in] FilePath File path of the image.
1977 @param[in] ImageBase Image base address.
1978 @param[in] ImageSize Image size.
1979 @param[in] FileType File type of the image.
1980
1981 @return EFI_SUCCESS Register successfully.
1982 @return EFI_UNSUPPORTED Memory profile is unsupported,
1983 or memory profile for the image is not required.
1984 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1985
1986 **/
1987 EFI_STATUS
1988 EFIAPI
1989 SmramProfileProtocolRegisterImage (
1990 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
1991 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1992 IN PHYSICAL_ADDRESS ImageBase,
1993 IN UINT64 ImageSize,
1994 IN EFI_FV_FILETYPE FileType
1995 )
1996 {
1997 EFI_STATUS Status;
1998 EFI_SMM_DRIVER_ENTRY DriverEntry;
1999 VOID *EntryPointInImage;
2000 EFI_GUID *Name;
2001
2002 ZeroMem (&DriverEntry, sizeof (DriverEntry));
2003 Name = GetFileNameFromFilePath (FilePath);
2004 if (Name != NULL) {
2005 CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
2006 }
2007
2008 DriverEntry.ImageBuffer = ImageBase;
2009 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN)ImageSize);
2010 Status = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)DriverEntry.ImageBuffer, &EntryPointInImage);
2011 ASSERT_EFI_ERROR (Status);
2012 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
2013
2014 return RegisterSmramProfileImage (&DriverEntry, FALSE);
2015 }
2016
2017 /**
2018 Unregister image from memory profile.
2019
2020 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2021 @param[in] FilePath File path of the image.
2022 @param[in] ImageBase Image base address.
2023 @param[in] ImageSize Image size.
2024
2025 @return EFI_SUCCESS Unregister successfully.
2026 @return EFI_UNSUPPORTED Memory profile is unsupported,
2027 or memory profile for the image is not required.
2028 @return EFI_NOT_FOUND The image is not found.
2029
2030 **/
2031 EFI_STATUS
2032 EFIAPI
2033 SmramProfileProtocolUnregisterImage (
2034 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2035 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
2036 IN PHYSICAL_ADDRESS ImageBase,
2037 IN UINT64 ImageSize
2038 )
2039 {
2040 EFI_STATUS Status;
2041 EFI_SMM_DRIVER_ENTRY DriverEntry;
2042 VOID *EntryPointInImage;
2043 EFI_GUID *Name;
2044
2045 ZeroMem (&DriverEntry, sizeof (DriverEntry));
2046 Name = GetFileNameFromFilePath (FilePath);
2047 if (Name != NULL) {
2048 CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
2049 }
2050
2051 DriverEntry.ImageBuffer = ImageBase;
2052 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN)ImageSize);
2053 Status = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)DriverEntry.ImageBuffer, &EntryPointInImage);
2054 ASSERT_EFI_ERROR (Status);
2055 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
2056
2057 return UnregisterSmramProfileImage (&DriverEntry, FALSE);
2058 }
2059
2060 /**
2061 Get memory profile recording state.
2062
2063 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2064 @param[out] RecordingState Recording state.
2065
2066 @return EFI_SUCCESS Memory profile recording state is returned.
2067 @return EFI_UNSUPPORTED Memory profile is unsupported.
2068 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2069
2070 **/
2071 EFI_STATUS
2072 EFIAPI
2073 SmramProfileProtocolGetRecordingState (
2074 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2075 OUT BOOLEAN *RecordingState
2076 )
2077 {
2078 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2079
2080 ContextData = GetSmramProfileContext ();
2081 if (ContextData == NULL) {
2082 return EFI_UNSUPPORTED;
2083 }
2084
2085 if (RecordingState == NULL) {
2086 return EFI_INVALID_PARAMETER;
2087 }
2088
2089 *RecordingState = mSmramProfileRecordingEnable;
2090 return EFI_SUCCESS;
2091 }
2092
2093 /**
2094 Set memory profile recording state.
2095
2096 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2097 @param[in] RecordingState Recording state.
2098
2099 @return EFI_SUCCESS Set memory profile recording state successfully.
2100 @return EFI_UNSUPPORTED Memory profile is unsupported.
2101
2102 **/
2103 EFI_STATUS
2104 EFIAPI
2105 SmramProfileProtocolSetRecordingState (
2106 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2107 IN BOOLEAN RecordingState
2108 )
2109 {
2110 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2111
2112 ContextData = GetSmramProfileContext ();
2113 if (ContextData == NULL) {
2114 return EFI_UNSUPPORTED;
2115 }
2116
2117 mSmramProfileRecordingEnable = RecordingState;
2118 return EFI_SUCCESS;
2119 }
2120
2121 /**
2122 Record memory profile of multilevel caller.
2123
2124 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2125 @param[in] CallerAddress Address of caller.
2126 @param[in] Action Memory profile action.
2127 @param[in] MemoryType Memory type.
2128 EfiMaxMemoryType means the MemoryType is unknown.
2129 @param[in] Buffer Buffer address.
2130 @param[in] Size Buffer size.
2131 @param[in] ActionString String for memory profile action.
2132 Only needed for user defined allocate action.
2133
2134 @return EFI_SUCCESS Memory profile is updated.
2135 @return EFI_UNSUPPORTED Memory profile is unsupported,
2136 or memory profile for the image is not required,
2137 or memory profile for the memory type is not required.
2138 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2139 @return EFI_ABORTED Memory profile recording is not enabled.
2140 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2141 @return EFI_NOT_FOUND No matched allocate info found for free action.
2142
2143 **/
2144 EFI_STATUS
2145 EFIAPI
2146 SmramProfileProtocolRecord (
2147 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2148 IN PHYSICAL_ADDRESS CallerAddress,
2149 IN MEMORY_PROFILE_ACTION Action,
2150 IN EFI_MEMORY_TYPE MemoryType,
2151 IN VOID *Buffer,
2152 IN UINTN Size,
2153 IN CHAR8 *ActionString OPTIONAL
2154 )
2155 {
2156 return SmmCoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
2157 }
2158
2159 /**
2160 SMRAM profile handler to get profile info.
2161
2162 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2163
2164 **/
2165 VOID
2166 SmramProfileHandlerGetInfo (
2167 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo
2168 )
2169 {
2170 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2171 BOOLEAN SmramProfileGettingStatus;
2172
2173 ContextData = GetSmramProfileContext ();
2174 if (ContextData == NULL) {
2175 return;
2176 }
2177
2178 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2179 mSmramProfileGettingStatus = TRUE;
2180
2181 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize ();
2182 SmramProfileParameterGetInfo->Header.ReturnStatus = 0;
2183
2184 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2185 }
2186
2187 /**
2188 SMRAM profile handler to get profile data.
2189
2190 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2191
2192 **/
2193 VOID
2194 SmramProfileHandlerGetData (
2195 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData
2196 )
2197 {
2198 UINT64 ProfileSize;
2199 UINT64 ProfileOffset;
2200 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData;
2201 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2202 BOOLEAN SmramProfileGettingStatus;
2203
2204 ContextData = GetSmramProfileContext ();
2205 if (ContextData == NULL) {
2206 return;
2207 }
2208
2209 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2210 mSmramProfileGettingStatus = TRUE;
2211
2212 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));
2213
2214 ProfileSize = SmramProfileGetDataSize ();
2215
2216 //
2217 // Sanity check
2218 //
2219 if (!SmmIsBufferOutsideSmmValid ((UINTN)SmramProfileGetData.ProfileBuffer, (UINTN)ProfileSize)) {
2220 DEBUG ((DEBUG_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2221 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2222 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64)(INT64)(INTN)EFI_ACCESS_DENIED;
2223 goto Done;
2224 }
2225
2226 if (SmramProfileGetData.ProfileSize < ProfileSize) {
2227 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2228 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64)(INT64)(INTN)EFI_BUFFER_TOO_SMALL;
2229 goto Done;
2230 }
2231
2232 ProfileOffset = 0;
2233 SmramProfileCopyData ((VOID *)(UINTN)SmramProfileGetData.ProfileBuffer, &ProfileSize, &ProfileOffset);
2234 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2235 SmramProfileParameterGetData->Header.ReturnStatus = 0;
2236
2237 Done:
2238 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2239 }
2240
2241 /**
2242 SMRAM profile handler to get profile data by offset.
2243
2244 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2245
2246 **/
2247 VOID
2248 SmramProfileHandlerGetDataByOffset (
2249 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *SmramProfileParameterGetDataByOffset
2250 )
2251 {
2252 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset;
2253 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2254 BOOLEAN SmramProfileGettingStatus;
2255
2256 ContextData = GetSmramProfileContext ();
2257 if (ContextData == NULL) {
2258 return;
2259 }
2260
2261 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2262 mSmramProfileGettingStatus = TRUE;
2263
2264 CopyMem (&SmramProfileGetDataByOffset, SmramProfileParameterGetDataByOffset, sizeof (SmramProfileGetDataByOffset));
2265
2266 //
2267 // Sanity check
2268 //
2269 if (!SmmIsBufferOutsideSmmValid ((UINTN)SmramProfileGetDataByOffset.ProfileBuffer, (UINTN)SmramProfileGetDataByOffset.ProfileSize)) {
2270 DEBUG ((DEBUG_ERROR, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2271 SmramProfileParameterGetDataByOffset->Header.ReturnStatus = (UINT64)(INT64)(INTN)EFI_ACCESS_DENIED;
2272 goto Done;
2273 }
2274
2275 SmramProfileCopyData ((VOID *)(UINTN)SmramProfileGetDataByOffset.ProfileBuffer, &SmramProfileGetDataByOffset.ProfileSize, &SmramProfileGetDataByOffset.ProfileOffset);
2276 CopyMem (SmramProfileParameterGetDataByOffset, &SmramProfileGetDataByOffset, sizeof (SmramProfileGetDataByOffset));
2277 SmramProfileParameterGetDataByOffset->Header.ReturnStatus = 0;
2278
2279 Done:
2280 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2281 }
2282
2283 /**
2284 Dispatch function for a Software SMI handler.
2285
2286 Caution: This function may receive untrusted input.
2287 Communicate buffer and buffer size are external input, so this function will do basic validation.
2288
2289 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2290 @param Context Points to an optional handler context which was specified when the
2291 handler was registered.
2292 @param CommBuffer A pointer to a collection of data in memory that will
2293 be conveyed from a non-SMM environment into an SMM environment.
2294 @param CommBufferSize The size of the CommBuffer.
2295
2296 @retval EFI_SUCCESS Command is handled successfully.
2297
2298 **/
2299 EFI_STATUS
2300 EFIAPI
2301 SmramProfileHandler (
2302 IN EFI_HANDLE DispatchHandle,
2303 IN CONST VOID *Context OPTIONAL,
2304 IN OUT VOID *CommBuffer OPTIONAL,
2305 IN OUT UINTN *CommBufferSize OPTIONAL
2306 )
2307 {
2308 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader;
2309 UINTN TempCommBufferSize;
2310 SMRAM_PROFILE_PARAMETER_RECORDING_STATE *ParameterRecordingState;
2311
2312 DEBUG ((DEBUG_ERROR, "SmramProfileHandler Enter\n"));
2313
2314 //
2315 // If input is invalid, stop processing this SMI
2316 //
2317 if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {
2318 return EFI_SUCCESS;
2319 }
2320
2321 TempCommBufferSize = *CommBufferSize;
2322
2323 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {
2324 DEBUG ((DEBUG_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2325 return EFI_SUCCESS;
2326 }
2327
2328 if (mSmramReadyToLock && !SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
2329 DEBUG ((DEBUG_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2330 return EFI_SUCCESS;
2331 }
2332
2333 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *)((UINTN)CommBuffer);
2334
2335 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;
2336
2337 if (GetSmramProfileContext () == NULL) {
2338 SmramProfileParameterHeader->ReturnStatus = (UINT64)(INT64)(INTN)EFI_UNSUPPORTED;
2339 return EFI_SUCCESS;
2340 }
2341
2342 switch (SmramProfileParameterHeader->Command) {
2343 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:
2344 DEBUG ((DEBUG_ERROR, "SmramProfileHandlerGetInfo\n"));
2345 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {
2346 DEBUG ((DEBUG_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2347 return EFI_SUCCESS;
2348 }
2349
2350 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *)(UINTN)CommBuffer);
2351 break;
2352 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:
2353 DEBUG ((DEBUG_ERROR, "SmramProfileHandlerGetData\n"));
2354 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {
2355 DEBUG ((DEBUG_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2356 return EFI_SUCCESS;
2357 }
2358
2359 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *)(UINTN)CommBuffer);
2360 break;
2361 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET:
2362 DEBUG ((DEBUG_ERROR, "SmramProfileHandlerGetDataByOffset\n"));
2363 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET)) {
2364 DEBUG ((DEBUG_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2365 return EFI_SUCCESS;
2366 }
2367
2368 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *)(UINTN)CommBuffer);
2369 break;
2370 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE:
2371 DEBUG ((DEBUG_ERROR, "SmramProfileHandlerGetRecordingState\n"));
2372 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) {
2373 DEBUG ((DEBUG_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2374 return EFI_SUCCESS;
2375 }
2376
2377 ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *)(UINTN)CommBuffer;
2378 ParameterRecordingState->RecordingState = mSmramProfileRecordingEnable;
2379 ParameterRecordingState->Header.ReturnStatus = 0;
2380 break;
2381 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE:
2382 DEBUG ((DEBUG_ERROR, "SmramProfileHandlerSetRecordingState\n"));
2383 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) {
2384 DEBUG ((DEBUG_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2385 return EFI_SUCCESS;
2386 }
2387
2388 ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *)(UINTN)CommBuffer;
2389 mSmramProfileRecordingEnable = ParameterRecordingState->RecordingState;
2390 ParameterRecordingState->Header.ReturnStatus = 0;
2391 break;
2392
2393 //
2394 // Below 2 commands have been deprecated. They may not be (re-)used.
2395 //
2396 case SMRAM_PROFILE_COMMAND_DEPRECATED1:
2397 case SMRAM_PROFILE_COMMAND_DEPRECATED2:
2398 ASSERT (FALSE);
2399 //
2400 // Fall-through to the default (unrecognized command) case.
2401 //
2402 default:
2403 break;
2404 }
2405
2406 DEBUG ((DEBUG_ERROR, "SmramProfileHandler Exit\n"));
2407
2408 return EFI_SUCCESS;
2409 }
2410
2411 /**
2412 Register SMRAM profile handler.
2413
2414 **/
2415 VOID
2416 RegisterSmramProfileHandler (
2417 VOID
2418 )
2419 {
2420 EFI_STATUS Status;
2421 EFI_HANDLE DispatchHandle;
2422
2423 if (!IS_SMRAM_PROFILE_ENABLED) {
2424 return;
2425 }
2426
2427 Status = SmiHandlerRegister (
2428 SmramProfileHandler,
2429 &gEdkiiMemoryProfileGuid,
2430 &DispatchHandle
2431 );
2432 ASSERT_EFI_ERROR (Status);
2433 }
2434
2435 ////////////////////
2436
2437 /**
2438 Dump SMRAM range.
2439
2440 **/
2441 VOID
2442 DumpSmramRange (
2443 VOID
2444 )
2445 {
2446 UINTN Index;
2447 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2448 BOOLEAN SmramProfileGettingStatus;
2449
2450 ContextData = GetSmramProfileContext ();
2451 if (ContextData == NULL) {
2452 return;
2453 }
2454
2455 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2456 mSmramProfileGettingStatus = TRUE;
2457
2458 DEBUG ((DEBUG_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));
2459
2460 DEBUG ((DEBUG_INFO, "======= SmramProfile begin =======\n"));
2461
2462 DEBUG ((DEBUG_INFO, "FullSmramRange:\n"));
2463 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
2464 DEBUG ((DEBUG_INFO, " FullSmramRange (0x%x)\n", Index));
2465 DEBUG ((DEBUG_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));
2466 DEBUG ((DEBUG_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));
2467 DEBUG ((DEBUG_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));
2468 DEBUG ((DEBUG_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState));
2469 }
2470
2471 DEBUG ((DEBUG_INFO, "======= SmramProfile end =======\n"));
2472
2473 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2474 }
2475
2476 /**
2477 Dump SMRAM free page list.
2478
2479 **/
2480 VOID
2481 DumpFreePagesList (
2482 VOID
2483 )
2484 {
2485 LIST_ENTRY *FreePageList;
2486 LIST_ENTRY *Node;
2487 FREE_PAGE_LIST *Pages;
2488 UINTN Index;
2489 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2490 BOOLEAN SmramProfileGettingStatus;
2491
2492 ContextData = GetSmramProfileContext ();
2493 if (ContextData == NULL) {
2494 return;
2495 }
2496
2497 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2498 mSmramProfileGettingStatus = TRUE;
2499
2500 DEBUG ((DEBUG_INFO, "======= SmramProfile begin =======\n"));
2501
2502 DEBUG ((DEBUG_INFO, "FreePagesList:\n"));
2503 FreePageList = &mSmmMemoryMap;
2504 for (Node = FreePageList->BackLink, Index = 0;
2505 Node != FreePageList;
2506 Node = Node->BackLink, Index++)
2507 {
2508 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
2509 DEBUG ((DEBUG_INFO, " Index - 0x%x\n", Index));
2510 DEBUG ((DEBUG_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS)(UINTN)Pages));
2511 DEBUG ((DEBUG_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages));
2512 }
2513
2514 DEBUG ((DEBUG_INFO, "======= SmramProfile end =======\n"));
2515
2516 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2517 }
2518
2519 /**
2520 Dump SMRAM free pool list.
2521
2522 **/
2523 VOID
2524 DumpFreePoolList (
2525 VOID
2526 )
2527 {
2528 LIST_ENTRY *FreePoolList;
2529 LIST_ENTRY *Node;
2530 FREE_POOL_HEADER *Pool;
2531 UINTN Index;
2532 UINTN PoolListIndex;
2533 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2534 BOOLEAN SmramProfileGettingStatus;
2535 UINTN SmmPoolTypeIndex;
2536
2537 ContextData = GetSmramProfileContext ();
2538 if (ContextData == NULL) {
2539 return;
2540 }
2541
2542 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2543 mSmramProfileGettingStatus = TRUE;
2544
2545 DEBUG ((DEBUG_INFO, "======= SmramProfile begin =======\n"));
2546
2547 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) {
2548 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
2549 DEBUG ((DEBUG_INFO, "FreePoolList(%d)(%d):\n", SmmPoolTypeIndex, PoolListIndex));
2550 FreePoolList = &mSmmPoolLists[SmmPoolTypeIndex][PoolListIndex];
2551 for (Node = FreePoolList->BackLink, Index = 0;
2552 Node != FreePoolList;
2553 Node = Node->BackLink, Index++)
2554 {
2555 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
2556 DEBUG ((DEBUG_INFO, " Index - 0x%x\n", Index));
2557 DEBUG ((DEBUG_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS)(UINTN)Pool));
2558 DEBUG ((DEBUG_INFO, " Size - 0x%08x\n", Pool->Header.Size));
2559 DEBUG ((DEBUG_INFO, " Available - 0x%02x\n", Pool->Header.Available));
2560 }
2561 }
2562 }
2563
2564 DEBUG ((DEBUG_INFO, "======= SmramProfile end =======\n"));
2565
2566 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2567 }
2568
2569 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mSmmActionString[] = {
2570 "SmmUnknown",
2571 "gSmst->SmmAllocatePages",
2572 "gSmst->SmmFreePages",
2573 "gSmst->SmmAllocatePool",
2574 "gSmst->SmmFreePool",
2575 };
2576
2577 typedef struct {
2578 MEMORY_PROFILE_ACTION Action;
2579 CHAR8 *String;
2580 } ACTION_STRING;
2581
2582 GLOBAL_REMOVE_IF_UNREFERENCED ACTION_STRING mExtActionString[] = {
2583 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, "Lib:AllocatePages" },
2584 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, "Lib:AllocateRuntimePages" },
2585 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, "Lib:AllocateReservedPages" },
2586 { MEMORY_PROFILE_ACTION_LIB_FREE_PAGES, "Lib:FreePages" },
2587 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, "Lib:AllocateAlignedPages" },
2588 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, "Lib:AllocateAlignedRuntimePages" },
2589 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, "Lib:AllocateAlignedReservedPages" },
2590 { MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES, "Lib:FreeAlignedPages" },
2591 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, "Lib:AllocatePool" },
2592 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, "Lib:AllocateRuntimePool" },
2593 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, "Lib:AllocateReservedPool" },
2594 { MEMORY_PROFILE_ACTION_LIB_FREE_POOL, "Lib:FreePool" },
2595 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, "Lib:AllocateZeroPool" },
2596 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, "Lib:AllocateRuntimeZeroPool" },
2597 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, "Lib:AllocateReservedZeroPool" },
2598 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, "Lib:AllocateCopyPool" },
2599 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, "Lib:AllocateRuntimeCopyPool" },
2600 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, "Lib:AllocateReservedCopyPool" },
2601 { MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, "Lib:ReallocatePool" },
2602 { MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, "Lib:ReallocateRuntimePool" },
2603 { MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, "Lib:ReallocateReservedPool" },
2604 };
2605
2606 typedef struct {
2607 EFI_MEMORY_TYPE MemoryType;
2608 CHAR8 *MemoryTypeStr;
2609 } PROFILE_MEMORY_TYPE_STRING;
2610
2611 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = {
2612 { EfiRuntimeServicesCode, "EfiRuntimeServicesCode" },
2613 { EfiRuntimeServicesData, "EfiRuntimeServicesData" }
2614 };
2615
2616 /**
2617 Memory type to string.
2618
2619 @param[in] MemoryType Memory type.
2620
2621 @return Pointer to string.
2622
2623 **/
2624 CHAR8 *
2625 ProfileMemoryTypeToStr (
2626 IN EFI_MEMORY_TYPE MemoryType
2627 )
2628 {
2629 UINTN Index;
2630
2631 for (Index = 0; Index < ARRAY_SIZE (mMemoryTypeString); Index++) {
2632 if (mMemoryTypeString[Index].MemoryType == MemoryType) {
2633 return mMemoryTypeString[Index].MemoryTypeStr;
2634 }
2635 }
2636
2637 return "UnexpectedMemoryType";
2638 }
2639
2640 /**
2641 Action to string.
2642
2643 @param[in] Action Profile action.
2644
2645 @return Pointer to string.
2646
2647 **/
2648 CHAR8 *
2649 ProfileActionToStr (
2650 IN MEMORY_PROFILE_ACTION Action
2651 )
2652 {
2653 UINTN Index;
2654 UINTN ActionStringCount;
2655 CHAR8 **ActionString;
2656
2657 ActionString = mSmmActionString;
2658 ActionStringCount = ARRAY_SIZE (mSmmActionString);
2659
2660 if ((UINTN)(UINT32)Action < ActionStringCount) {
2661 return ActionString[Action];
2662 }
2663
2664 for (Index = 0; Index < ARRAY_SIZE (mExtActionString); Index++) {
2665 if (mExtActionString[Index].Action == Action) {
2666 return mExtActionString[Index].String;
2667 }
2668 }
2669
2670 return ActionString[0];
2671 }
2672
2673 /**
2674 Dump SMRAM profile.
2675
2676 **/
2677 VOID
2678 DumpSmramProfile (
2679 VOID
2680 )
2681 {
2682 MEMORY_PROFILE_CONTEXT *Context;
2683 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
2684 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
2685 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2686 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
2687 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
2688 LIST_ENTRY *SmramDriverInfoList;
2689 UINTN DriverIndex;
2690 LIST_ENTRY *DriverLink;
2691 LIST_ENTRY *AllocInfoList;
2692 UINTN AllocIndex;
2693 LIST_ENTRY *AllocLink;
2694 BOOLEAN SmramProfileGettingStatus;
2695 UINTN TypeIndex;
2696
2697 ContextData = GetSmramProfileContext ();
2698 if (ContextData == NULL) {
2699 return;
2700 }
2701
2702 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2703 mSmramProfileGettingStatus = TRUE;
2704
2705 Context = &ContextData->Context;
2706 DEBUG ((DEBUG_INFO, "======= SmramProfile begin =======\n"));
2707 DEBUG ((DEBUG_INFO, "MEMORY_PROFILE_CONTEXT\n"));
2708
2709 DEBUG ((DEBUG_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage));
2710 DEBUG ((DEBUG_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage));
2711 for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {
2712 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
2713 (Context->PeakTotalUsageByType[TypeIndex] != 0))
2714 {
2715 DEBUG ((DEBUG_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2716 DEBUG ((DEBUG_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2717 }
2718 }
2719
2720 DEBUG ((DEBUG_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize));
2721 DEBUG ((DEBUG_INFO, " ImageCount - 0x%08x\n", Context->ImageCount));
2722 DEBUG ((DEBUG_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount));
2723
2724 SmramDriverInfoList = ContextData->DriverInfoList;
2725 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;
2726 DriverLink != SmramDriverInfoList;
2727 DriverLink = DriverLink->ForwardLink, DriverIndex++)
2728 {
2729 DriverInfoData = CR (
2730 DriverLink,
2731 MEMORY_PROFILE_DRIVER_INFO_DATA,
2732 Link,
2733 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2734 );
2735 DriverInfo = &DriverInfoData->DriverInfo;
2736 DEBUG ((DEBUG_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));
2737 DEBUG ((DEBUG_INFO, " FileName - %g\n", &DriverInfo->FileName));
2738 DEBUG ((DEBUG_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase));
2739 DEBUG ((DEBUG_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize));
2740 DEBUG ((DEBUG_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint));
2741 DEBUG ((DEBUG_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem));
2742 DEBUG ((DEBUG_INFO, " FileType - 0x%02x\n", DriverInfo->FileType));
2743 DEBUG ((DEBUG_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage));
2744 DEBUG ((DEBUG_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage));
2745 for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {
2746 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
2747 (DriverInfo->PeakUsageByType[TypeIndex] != 0))
2748 {
2749 DEBUG ((DEBUG_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2750 DEBUG ((DEBUG_INFO, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2751 }
2752 }
2753
2754 DEBUG ((DEBUG_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount));
2755
2756 AllocInfoList = DriverInfoData->AllocInfoList;
2757 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;
2758 AllocLink != AllocInfoList;
2759 AllocLink = AllocLink->ForwardLink, AllocIndex++)
2760 {
2761 AllocInfoData = CR (
2762 AllocLink,
2763 MEMORY_PROFILE_ALLOC_INFO_DATA,
2764 Link,
2765 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2766 );
2767 AllocInfo = &AllocInfoData->AllocInfo;
2768 DEBUG ((DEBUG_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));
2769 DEBUG ((DEBUG_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));
2770 DEBUG ((DEBUG_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId));
2771 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) {
2772 if (AllocInfoData->ActionString != NULL) {
2773 DEBUG ((DEBUG_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, AllocInfoData->ActionString));
2774 } else {
2775 DEBUG ((DEBUG_INFO, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo->Action, AllocInfo->Action));
2776 }
2777 } else {
2778 DEBUG ((DEBUG_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action)));
2779 }
2780
2781 DEBUG ((DEBUG_INFO, " MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType)));
2782 DEBUG ((DEBUG_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer));
2783 DEBUG ((DEBUG_INFO, " Size - 0x%016lx\n", AllocInfo->Size));
2784 }
2785 }
2786
2787 DEBUG ((DEBUG_INFO, "======= SmramProfile end =======\n"));
2788
2789 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2790 }
2791
2792 /**
2793 Dump SMRAM information.
2794
2795 **/
2796 VOID
2797 DumpSmramInfo (
2798 VOID
2799 )
2800 {
2801 DEBUG_CODE_BEGIN ();
2802 if (IS_SMRAM_PROFILE_ENABLED) {
2803 DumpSmramProfile ();
2804 DumpFreePagesList ();
2805 DumpFreePoolList ();
2806 DumpSmramRange ();
2807 }
2808
2809 DEBUG_CODE_END ();
2810 }