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