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