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