]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
ac832ce38c740c096459f6914f9a35a760088d24
[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 ASSERT (DriverInfoData != NULL);
1407 ASSERT (AllocInfoData != NULL);
1408
1409 Found = TRUE;
1410
1411 Context = &ContextData->Context;
1412 DriverInfo = &DriverInfoData->DriverInfo;
1413 AllocInfo = &AllocInfoData->AllocInfo;
1414
1415 DriverInfo->AllocRecordCount --;
1416 //
1417 // Update summary if and only if it is basic action.
1418 //
1419 if (AllocInfo->Action == (AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK)) {
1420 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
1421
1422 Context->CurrentTotalUsage -= AllocInfo->Size;
1423 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1424
1425 DriverInfo->CurrentUsage -= AllocInfo->Size;
1426 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1427 }
1428
1429 RemoveEntryList (&AllocInfoData->Link);
1430
1431 if (BasicAction == MemoryProfileActionFreePages) {
1432 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {
1433 SmmCoreUpdateProfileAllocate (
1434 AllocInfo->CallerAddress,
1435 AllocInfo->Action,
1436 AllocInfo->MemoryType,
1437 (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),
1438 (VOID *) (UINTN) AllocInfo->Buffer,
1439 AllocInfoData->ActionString
1440 );
1441 }
1442 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {
1443 SmmCoreUpdateProfileAllocate (
1444 AllocInfo->CallerAddress,
1445 AllocInfo->Action,
1446 AllocInfo->MemoryType,
1447 (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),
1448 (VOID *) ((UINTN) Buffer + Size),
1449 AllocInfoData->ActionString
1450 );
1451 }
1452 }
1453
1454 //
1455 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1456 //
1457 SmmInternalFreePool (AllocInfoData);
1458 } while (TRUE);
1459 }
1460
1461 /**
1462 Update SMRAM profile information.
1463
1464 @param CallerAddress Address of caller who call Allocate or Free.
1465 @param Action This Allocate or Free action.
1466 @param MemoryType Memory type.
1467 EfiMaxMemoryType means the MemoryType is unknown.
1468 @param Size Buffer size.
1469 @param Buffer Buffer address.
1470 @param ActionString String for memory profile action.
1471 Only needed for user defined allocate action.
1472
1473 @return EFI_SUCCESS Memory profile is updated.
1474 @return EFI_UNSUPPORTED Memory profile is unsupported,
1475 or memory profile for the image is not required,
1476 or memory profile for the memory type is not required.
1477 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1478 @return EFI_ABORTED Memory profile recording is not enabled.
1479 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1480 @return EFI_NOT_FOUND No matched allocate info found for free action.
1481
1482 **/
1483 EFI_STATUS
1484 EFIAPI
1485 SmmCoreUpdateProfile (
1486 IN PHYSICAL_ADDRESS CallerAddress,
1487 IN MEMORY_PROFILE_ACTION Action,
1488 IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool
1489 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool
1490 IN VOID *Buffer,
1491 IN CHAR8 *ActionString OPTIONAL
1492 )
1493 {
1494 EFI_STATUS Status;
1495 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1496 MEMORY_PROFILE_ACTION BasicAction;
1497
1498 if (!IS_SMRAM_PROFILE_ENABLED) {
1499 return EFI_UNSUPPORTED;
1500 }
1501
1502 if (mSmramProfileGettingStatus) {
1503 return EFI_ACCESS_DENIED;
1504 }
1505
1506 if (!mSmramProfileRecordingEnable) {
1507 return EFI_ABORTED;
1508 }
1509
1510 //
1511 // Get the basic action to know how to process the record
1512 //
1513 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1514
1515 //
1516 // Free operations have no memory type information, so skip the check.
1517 //
1518 if ((BasicAction == MemoryProfileActionAllocatePages) || (BasicAction == MemoryProfileActionAllocatePool)) {
1519 //
1520 // Only record limited MemoryType.
1521 //
1522 if (!SmmCoreNeedRecordProfile (MemoryType)) {
1523 return EFI_UNSUPPORTED;
1524 }
1525 }
1526
1527 ContextData = GetSmramProfileContext ();
1528 if (ContextData == NULL) {
1529 return EFI_UNSUPPORTED;
1530 }
1531
1532 switch (BasicAction) {
1533 case MemoryProfileActionAllocatePages:
1534 Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1535 break;
1536 case MemoryProfileActionFreePages:
1537 Status = SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
1538 break;
1539 case MemoryProfileActionAllocatePool:
1540 Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1541 break;
1542 case MemoryProfileActionFreePool:
1543 Status = SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
1544 break;
1545 default:
1546 ASSERT (FALSE);
1547 Status = EFI_UNSUPPORTED;
1548 break;
1549 }
1550
1551 return Status;
1552 }
1553
1554 /**
1555 SMRAM profile ready to lock callback function.
1556
1557 **/
1558 VOID
1559 SmramProfileReadyToLock (
1560 VOID
1561 )
1562 {
1563 if (!IS_SMRAM_PROFILE_ENABLED) {
1564 return;
1565 }
1566
1567 DEBUG ((EFI_D_INFO, "SmramProfileReadyToLock\n"));
1568 mSmramReadyToLock = TRUE;
1569 }
1570
1571 ////////////////////
1572
1573 /**
1574 Get SMRAM profile data size.
1575
1576 @return SMRAM profile data size.
1577
1578 **/
1579 UINTN
1580 SmramProfileGetDataSize (
1581 VOID
1582 )
1583 {
1584 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1585 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1586 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1587 LIST_ENTRY *DriverInfoList;
1588 LIST_ENTRY *DriverLink;
1589 LIST_ENTRY *AllocInfoList;
1590 LIST_ENTRY *AllocLink;
1591 UINTN TotalSize;
1592 LIST_ENTRY *Node;
1593 LIST_ENTRY *FreePageList;
1594 LIST_ENTRY *FreePoolList;
1595 FREE_POOL_HEADER *Pool;
1596 UINTN PoolListIndex;
1597 UINTN Index;
1598
1599 ContextData = GetSmramProfileContext ();
1600 if (ContextData == NULL) {
1601 return 0;
1602 }
1603
1604 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
1605
1606 DriverInfoList = ContextData->DriverInfoList;
1607 for (DriverLink = DriverInfoList->ForwardLink;
1608 DriverLink != DriverInfoList;
1609 DriverLink = DriverLink->ForwardLink) {
1610 DriverInfoData = CR (
1611 DriverLink,
1612 MEMORY_PROFILE_DRIVER_INFO_DATA,
1613 Link,
1614 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1615 );
1616 TotalSize += DriverInfoData->DriverInfo.Header.Length;
1617
1618 AllocInfoList = DriverInfoData->AllocInfoList;
1619 for (AllocLink = AllocInfoList->ForwardLink;
1620 AllocLink != AllocInfoList;
1621 AllocLink = AllocLink->ForwardLink) {
1622 AllocInfoData = CR (
1623 AllocLink,
1624 MEMORY_PROFILE_ALLOC_INFO_DATA,
1625 Link,
1626 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1627 );
1628 TotalSize += AllocInfoData->AllocInfo.Header.Length;
1629 }
1630 }
1631
1632
1633 Index = 0;
1634 FreePageList = &mSmmMemoryMap;
1635 for (Node = FreePageList->BackLink;
1636 Node != FreePageList;
1637 Node = Node->BackLink) {
1638 Index++;
1639 }
1640 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1641 FreePoolList = &mSmmPoolLists[PoolListIndex];
1642 for (Node = FreePoolList->BackLink;
1643 Node != FreePoolList;
1644 Node = Node->BackLink) {
1645 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1646 if (Pool->Header.Available) {
1647 Index++;
1648 }
1649 }
1650 }
1651
1652
1653 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1654 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1655
1656 return TotalSize;
1657 }
1658
1659 /**
1660 Copy SMRAM profile data.
1661
1662 @param ProfileBuffer The buffer to hold SMRAM profile data.
1663 @param ProfileSize On input, profile buffer size.
1664 On output, actual profile data size copied.
1665 @param ProfileOffset On input, profile buffer offset to copy.
1666 On output, next time profile buffer offset to copy.
1667
1668 **/
1669 VOID
1670 SmramProfileCopyData (
1671 OUT VOID *ProfileBuffer,
1672 IN OUT UINT64 *ProfileSize,
1673 IN OUT UINT64 *ProfileOffset
1674 )
1675 {
1676 MEMORY_PROFILE_CONTEXT *Context;
1677 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1678 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1679 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1680 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1681 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1682 LIST_ENTRY *DriverInfoList;
1683 LIST_ENTRY *DriverLink;
1684 LIST_ENTRY *AllocInfoList;
1685 LIST_ENTRY *AllocLink;
1686 LIST_ENTRY *Node;
1687 FREE_PAGE_LIST *Pages;
1688 LIST_ENTRY *FreePageList;
1689 LIST_ENTRY *FreePoolList;
1690 FREE_POOL_HEADER *Pool;
1691 UINTN PoolListIndex;
1692 UINT32 Index;
1693 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
1694 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
1695 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor;
1696 UINT64 Offset;
1697 UINT64 RemainingSize;
1698 UINTN PdbSize;
1699 UINTN ActionStringSize;
1700
1701 ContextData = GetSmramProfileContext ();
1702 if (ContextData == NULL) {
1703 return ;
1704 }
1705
1706 RemainingSize = *ProfileSize;
1707 Offset = 0;
1708
1709 if (*ProfileOffset < sizeof (MEMORY_PROFILE_CONTEXT)) {
1710 if (RemainingSize >= sizeof (MEMORY_PROFILE_CONTEXT)) {
1711 Context = ProfileBuffer;
1712 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
1713 RemainingSize -= sizeof (MEMORY_PROFILE_CONTEXT);
1714 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_CONTEXT);
1715 } else {
1716 goto Done;
1717 }
1718 }
1719 Offset += sizeof (MEMORY_PROFILE_CONTEXT);
1720
1721 DriverInfoList = ContextData->DriverInfoList;
1722 for (DriverLink = DriverInfoList->ForwardLink;
1723 DriverLink != DriverInfoList;
1724 DriverLink = DriverLink->ForwardLink) {
1725 DriverInfoData = CR (
1726 DriverLink,
1727 MEMORY_PROFILE_DRIVER_INFO_DATA,
1728 Link,
1729 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1730 );
1731 if (*ProfileOffset < (Offset + DriverInfoData->DriverInfo.Header.Length)) {
1732 if (RemainingSize >= DriverInfoData->DriverInfo.Header.Length) {
1733 DriverInfo = ProfileBuffer;
1734 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));
1735 if (DriverInfo->PdbStringOffset != 0) {
1736 PdbSize = AsciiStrSize (DriverInfoData->PdbString);
1737 CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize);
1738 }
1739 RemainingSize -= DriverInfo->Header.Length;
1740 ProfileBuffer = (UINT8 *) ProfileBuffer + DriverInfo->Header.Length;
1741 } else {
1742 goto Done;
1743 }
1744 }
1745 Offset += DriverInfoData->DriverInfo.Header.Length;
1746
1747 AllocInfoList = DriverInfoData->AllocInfoList;
1748 for (AllocLink = AllocInfoList->ForwardLink;
1749 AllocLink != AllocInfoList;
1750 AllocLink = AllocLink->ForwardLink) {
1751 AllocInfoData = CR (
1752 AllocLink,
1753 MEMORY_PROFILE_ALLOC_INFO_DATA,
1754 Link,
1755 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1756 );
1757 if (*ProfileOffset < (Offset + AllocInfoData->AllocInfo.Header.Length)) {
1758 if (RemainingSize >= AllocInfoData->AllocInfo.Header.Length) {
1759 AllocInfo = ProfileBuffer;
1760 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));
1761 if (AllocInfo->ActionStringOffset) {
1762 ActionStringSize = AsciiStrSize (AllocInfoData->ActionString);
1763 CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize);
1764 }
1765 RemainingSize -= AllocInfo->Header.Length;
1766 ProfileBuffer = (UINT8 *) ProfileBuffer + AllocInfo->Header.Length;
1767 } else {
1768 goto Done;
1769 }
1770 }
1771 Offset += AllocInfoData->AllocInfo.Header.Length;
1772 }
1773 }
1774
1775
1776 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_FREE_MEMORY))) {
1777 if (RemainingSize >= sizeof (MEMORY_PROFILE_FREE_MEMORY)) {
1778 FreeMemory = ProfileBuffer;
1779 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));
1780 Index = 0;
1781 FreePageList = &mSmmMemoryMap;
1782 for (Node = FreePageList->BackLink;
1783 Node != FreePageList;
1784 Node = Node->BackLink) {
1785 Index++;
1786 }
1787 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1788 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];
1789 for (Node = FreePoolList->BackLink;
1790 Node != FreePoolList;
1791 Node = Node->BackLink) {
1792 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1793 if (Pool->Header.Available) {
1794 Index++;
1795 }
1796 }
1797 }
1798 FreeMemory->FreeMemoryEntryCount = Index;
1799
1800 RemainingSize -= sizeof (MEMORY_PROFILE_FREE_MEMORY);
1801 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_FREE_MEMORY);
1802 } else {
1803 goto Done;
1804 }
1805 }
1806 Offset += sizeof (MEMORY_PROFILE_FREE_MEMORY);
1807 FreePageList = &mSmmMemoryMap;
1808 for (Node = FreePageList->BackLink;
1809 Node != FreePageList;
1810 Node = Node->BackLink) {
1811 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1812 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1813 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1814 MemoryProfileDescriptor = ProfileBuffer;
1815 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1816 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1817 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1818 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages;
1819 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);
1820
1821 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1822 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1823 } else {
1824 goto Done;
1825 }
1826 }
1827 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1828 }
1829 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1830 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];
1831 for (Node = FreePoolList->BackLink;
1832 Node != FreePoolList;
1833 Node = Node->BackLink) {
1834 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1835 if (Pool->Header.Available) {
1836 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1837 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1838 MemoryProfileDescriptor = ProfileBuffer;
1839 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1840 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1841 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1842 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool;
1843 MemoryProfileDescriptor->Size = Pool->Header.Size;
1844
1845 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1846 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1847 } else {
1848 goto Done;
1849 }
1850 }
1851 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1852 }
1853 }
1854 }
1855
1856 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_MEMORY_RANGE))) {
1857 if (RemainingSize >= sizeof (MEMORY_PROFILE_MEMORY_RANGE)) {
1858 MemoryRange = ProfileBuffer;
1859 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;
1860 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1861 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;
1862 MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount;
1863
1864 RemainingSize -= sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1865 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1866 } else {
1867 goto Done;
1868 }
1869 }
1870 Offset += sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1871 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
1872 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1873 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1874 MemoryProfileDescriptor = ProfileBuffer;
1875 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1876 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1877 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1878 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;
1879 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;
1880
1881 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1882 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1883 } else {
1884 goto Done;
1885 }
1886 }
1887 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1888 }
1889
1890 Done:
1891 //
1892 // On output, actual profile data size copied.
1893 //
1894 *ProfileSize -= RemainingSize;
1895 //
1896 // On output, next time profile buffer offset to copy.
1897 //
1898 *ProfileOffset = Offset;
1899 }
1900
1901 /**
1902 Get memory profile data.
1903
1904 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1905 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1906 On return, points to the size of the data returned in ProfileBuffer.
1907 @param[out] ProfileBuffer Profile buffer.
1908
1909 @return EFI_SUCCESS Get the memory profile data successfully.
1910 @return EFI_UNSUPPORTED Memory profile is unsupported.
1911 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1912 ProfileSize is updated with the size required.
1913
1914 **/
1915 EFI_STATUS
1916 EFIAPI
1917 SmramProfileProtocolGetData (
1918 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
1919 IN OUT UINT64 *ProfileSize,
1920 OUT VOID *ProfileBuffer
1921 )
1922 {
1923 UINT64 Size;
1924 UINT64 Offset;
1925 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1926 BOOLEAN SmramProfileGettingStatus;
1927
1928 ContextData = GetSmramProfileContext ();
1929 if (ContextData == NULL) {
1930 return EFI_UNSUPPORTED;
1931 }
1932
1933 SmramProfileGettingStatus = mSmramProfileGettingStatus;
1934 mSmramProfileGettingStatus = TRUE;
1935
1936 Size = SmramProfileGetDataSize ();
1937
1938 if (*ProfileSize < Size) {
1939 *ProfileSize = Size;
1940 mSmramProfileGettingStatus = SmramProfileGettingStatus;
1941 return EFI_BUFFER_TOO_SMALL;
1942 }
1943
1944 Offset = 0;
1945 SmramProfileCopyData (ProfileBuffer, &Size, &Offset);
1946 *ProfileSize = Size;
1947
1948 mSmramProfileGettingStatus = SmramProfileGettingStatus;
1949 return EFI_SUCCESS;
1950 }
1951
1952 /**
1953 Register image to memory profile.
1954
1955 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1956 @param[in] FilePath File path of the image.
1957 @param[in] ImageBase Image base address.
1958 @param[in] ImageSize Image size.
1959 @param[in] FileType File type of the image.
1960
1961 @return EFI_SUCCESS Register successfully.
1962 @return EFI_UNSUPPORTED Memory profile is unsupported,
1963 or memory profile for the image is not required.
1964 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1965
1966 **/
1967 EFI_STATUS
1968 EFIAPI
1969 SmramProfileProtocolRegisterImage (
1970 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
1971 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1972 IN PHYSICAL_ADDRESS ImageBase,
1973 IN UINT64 ImageSize,
1974 IN EFI_FV_FILETYPE FileType
1975 )
1976 {
1977 EFI_STATUS Status;
1978 EFI_SMM_DRIVER_ENTRY DriverEntry;
1979 VOID *EntryPointInImage;
1980 EFI_GUID *Name;
1981
1982 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1983 Name = GetFileNameFromFilePath (FilePath);
1984 if (Name != NULL) {
1985 CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
1986 }
1987 DriverEntry.ImageBuffer = ImageBase;
1988 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize);
1989 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
1990 ASSERT_EFI_ERROR (Status);
1991 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1992
1993 return RegisterSmramProfileImage (&DriverEntry, FALSE);
1994 }
1995
1996 /**
1997 Unregister image from memory profile.
1998
1999 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2000 @param[in] FilePath File path of the image.
2001 @param[in] ImageBase Image base address.
2002 @param[in] ImageSize Image size.
2003
2004 @return EFI_SUCCESS Unregister successfully.
2005 @return EFI_UNSUPPORTED Memory profile is unsupported,
2006 or memory profile for the image is not required.
2007 @return EFI_NOT_FOUND The image is not found.
2008
2009 **/
2010 EFI_STATUS
2011 EFIAPI
2012 SmramProfileProtocolUnregisterImage (
2013 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2014 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
2015 IN PHYSICAL_ADDRESS ImageBase,
2016 IN UINT64 ImageSize
2017 )
2018 {
2019 EFI_STATUS Status;
2020 EFI_SMM_DRIVER_ENTRY DriverEntry;
2021 VOID *EntryPointInImage;
2022 EFI_GUID *Name;
2023
2024 ZeroMem (&DriverEntry, sizeof (DriverEntry));
2025 Name = GetFileNameFromFilePath (FilePath);
2026 if (Name != NULL) {
2027 CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
2028 }
2029 DriverEntry.ImageBuffer = ImageBase;
2030 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize);
2031 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
2032 ASSERT_EFI_ERROR (Status);
2033 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
2034
2035 return UnregisterSmramProfileImage (&DriverEntry, FALSE);
2036 }
2037
2038 /**
2039 Get memory profile recording state.
2040
2041 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2042 @param[out] RecordingState Recording state.
2043
2044 @return EFI_SUCCESS Memory profile recording state is returned.
2045 @return EFI_UNSUPPORTED Memory profile is unsupported.
2046 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2047
2048 **/
2049 EFI_STATUS
2050 EFIAPI
2051 SmramProfileProtocolGetRecordingState (
2052 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2053 OUT BOOLEAN *RecordingState
2054 )
2055 {
2056 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2057
2058 ContextData = GetSmramProfileContext ();
2059 if (ContextData == NULL) {
2060 return EFI_UNSUPPORTED;
2061 }
2062
2063 if (RecordingState == NULL) {
2064 return EFI_INVALID_PARAMETER;
2065 }
2066 *RecordingState = mSmramProfileRecordingEnable;
2067 return EFI_SUCCESS;
2068 }
2069
2070 /**
2071 Set memory profile recording state.
2072
2073 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2074 @param[in] RecordingState Recording state.
2075
2076 @return EFI_SUCCESS Set memory profile recording state successfully.
2077 @return EFI_UNSUPPORTED Memory profile is unsupported.
2078
2079 **/
2080 EFI_STATUS
2081 EFIAPI
2082 SmramProfileProtocolSetRecordingState (
2083 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2084 IN BOOLEAN RecordingState
2085 )
2086 {
2087 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2088
2089 ContextData = GetSmramProfileContext ();
2090 if (ContextData == NULL) {
2091 return EFI_UNSUPPORTED;
2092 }
2093
2094 mSmramProfileRecordingEnable = RecordingState;
2095 return EFI_SUCCESS;
2096 }
2097
2098 /**
2099 Record memory profile of multilevel caller.
2100
2101 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2102 @param[in] CallerAddress Address of caller.
2103 @param[in] Action Memory profile action.
2104 @param[in] MemoryType Memory type.
2105 EfiMaxMemoryType means the MemoryType is unknown.
2106 @param[in] Buffer Buffer address.
2107 @param[in] Size Buffer size.
2108 @param[in] ActionString String for memory profile action.
2109 Only needed for user defined allocate action.
2110
2111 @return EFI_SUCCESS Memory profile is updated.
2112 @return EFI_UNSUPPORTED Memory profile is unsupported,
2113 or memory profile for the image is not required,
2114 or memory profile for the memory type is not required.
2115 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2116 @return EFI_ABORTED Memory profile recording is not enabled.
2117 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2118 @return EFI_NOT_FOUND No matched allocate info found for free action.
2119
2120 **/
2121 EFI_STATUS
2122 EFIAPI
2123 SmramProfileProtocolRecord (
2124 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2125 IN PHYSICAL_ADDRESS CallerAddress,
2126 IN MEMORY_PROFILE_ACTION Action,
2127 IN EFI_MEMORY_TYPE MemoryType,
2128 IN VOID *Buffer,
2129 IN UINTN Size,
2130 IN CHAR8 *ActionString OPTIONAL
2131 )
2132 {
2133 return SmmCoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
2134 }
2135
2136 /**
2137 SMRAM profile handler to get profile info.
2138
2139 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2140
2141 **/
2142 VOID
2143 SmramProfileHandlerGetInfo (
2144 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo
2145 )
2146 {
2147 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2148 BOOLEAN SmramProfileGettingStatus;
2149
2150 ContextData = GetSmramProfileContext ();
2151 if (ContextData == NULL) {
2152 return ;
2153 }
2154
2155 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2156 mSmramProfileGettingStatus = TRUE;
2157
2158 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();
2159 SmramProfileParameterGetInfo->Header.ReturnStatus = 0;
2160
2161 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2162 }
2163
2164 /**
2165 SMRAM profile handler to get profile data.
2166
2167 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2168
2169 **/
2170 VOID
2171 SmramProfileHandlerGetData (
2172 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData
2173 )
2174 {
2175 UINT64 ProfileSize;
2176 UINT64 ProfileOffset;
2177 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData;
2178 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2179 BOOLEAN SmramProfileGettingStatus;
2180
2181 ContextData = GetSmramProfileContext ();
2182 if (ContextData == NULL) {
2183 return ;
2184 }
2185
2186 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2187 mSmramProfileGettingStatus = TRUE;
2188
2189
2190 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));
2191
2192 ProfileSize = SmramProfileGetDataSize();
2193
2194 //
2195 // Sanity check
2196 //
2197 if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {
2198 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2199 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2200 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;
2201 goto Done;
2202 }
2203
2204 if (SmramProfileGetData.ProfileSize < ProfileSize) {
2205 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2206 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL;
2207 goto Done;
2208 }
2209
2210 ProfileOffset = 0;
2211 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer, &ProfileSize, &ProfileOffset);
2212 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2213 SmramProfileParameterGetData->Header.ReturnStatus = 0;
2214
2215 Done:
2216 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2217 }
2218
2219 /**
2220 SMRAM profile handler to get profile data by offset.
2221
2222 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2223
2224 **/
2225 VOID
2226 SmramProfileHandlerGetDataByOffset (
2227 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *SmramProfileParameterGetDataByOffset
2228 )
2229 {
2230 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset;
2231 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2232 BOOLEAN SmramProfileGettingStatus;
2233
2234 ContextData = GetSmramProfileContext ();
2235 if (ContextData == NULL) {
2236 return ;
2237 }
2238
2239 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2240 mSmramProfileGettingStatus = TRUE;
2241
2242
2243 CopyMem (&SmramProfileGetDataByOffset, SmramProfileParameterGetDataByOffset, sizeof (SmramProfileGetDataByOffset));
2244
2245 //
2246 // Sanity check
2247 //
2248 if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetDataByOffset.ProfileBuffer, (UINTN) SmramProfileGetDataByOffset.ProfileSize)) {
2249 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2250 SmramProfileParameterGetDataByOffset->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;
2251 goto Done;
2252 }
2253
2254 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetDataByOffset.ProfileBuffer, &SmramProfileGetDataByOffset.ProfileSize, &SmramProfileGetDataByOffset.ProfileOffset);
2255 CopyMem (SmramProfileParameterGetDataByOffset, &SmramProfileGetDataByOffset, sizeof (SmramProfileGetDataByOffset));
2256 SmramProfileParameterGetDataByOffset->Header.ReturnStatus = 0;
2257
2258 Done:
2259 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2260 }
2261
2262 /**
2263 SMRAM profile handler to register SMM image.
2264
2265 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
2266
2267 **/
2268 VOID
2269 SmramProfileHandlerRegisterImage (
2270 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage
2271 )
2272 {
2273 EFI_STATUS Status;
2274 EFI_SMM_DRIVER_ENTRY DriverEntry;
2275 VOID *EntryPointInImage;
2276
2277 ZeroMem (&DriverEntry, sizeof (DriverEntry));
2278 CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));
2279 DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer;
2280 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage;
2281 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
2282 ASSERT_EFI_ERROR (Status);
2283 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
2284
2285 Status = RegisterSmramProfileImage (&DriverEntry, FALSE);
2286 if (!EFI_ERROR (Status)) {
2287 SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;
2288 }
2289 }
2290
2291 /**
2292 SMRAM profile handler to unregister SMM image.
2293
2294 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
2295
2296 **/
2297 VOID
2298 SmramProfileHandlerUnregisterImage (
2299 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage
2300 )
2301 {
2302 EFI_STATUS Status;
2303 EFI_SMM_DRIVER_ENTRY DriverEntry;
2304 VOID *EntryPointInImage;
2305
2306 ZeroMem (&DriverEntry, sizeof (DriverEntry));
2307 CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));
2308 DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer;
2309 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage;
2310 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
2311 ASSERT_EFI_ERROR (Status);
2312 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
2313
2314 Status = UnregisterSmramProfileImage (&DriverEntry, FALSE);
2315 if (!EFI_ERROR (Status)) {
2316 SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;
2317 }
2318 }
2319
2320 /**
2321 Dispatch function for a Software SMI handler.
2322
2323 Caution: This function may receive untrusted input.
2324 Communicate buffer and buffer size are external input, so this function will do basic validation.
2325
2326 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2327 @param Context Points to an optional handler context which was specified when the
2328 handler was registered.
2329 @param CommBuffer A pointer to a collection of data in memory that will
2330 be conveyed from a non-SMM environment into an SMM environment.
2331 @param CommBufferSize The size of the CommBuffer.
2332
2333 @retval EFI_SUCCESS Command is handled successfully.
2334
2335 **/
2336 EFI_STATUS
2337 EFIAPI
2338 SmramProfileHandler (
2339 IN EFI_HANDLE DispatchHandle,
2340 IN CONST VOID *Context OPTIONAL,
2341 IN OUT VOID *CommBuffer OPTIONAL,
2342 IN OUT UINTN *CommBufferSize OPTIONAL
2343 )
2344 {
2345 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader;
2346 UINTN TempCommBufferSize;
2347 SMRAM_PROFILE_PARAMETER_RECORDING_STATE *ParameterRecordingState;
2348
2349 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));
2350
2351 //
2352 // If input is invalid, stop processing this SMI
2353 //
2354 if (CommBuffer == NULL || CommBufferSize == NULL) {
2355 return EFI_SUCCESS;
2356 }
2357
2358 TempCommBufferSize = *CommBufferSize;
2359
2360 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {
2361 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2362 return EFI_SUCCESS;
2363 }
2364
2365 if (mSmramReadyToLock && !SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
2366 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2367 return EFI_SUCCESS;
2368 }
2369
2370 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer);
2371
2372 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;
2373
2374 if (GetSmramProfileContext () == NULL) {
2375 SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED;
2376 return EFI_SUCCESS;
2377 }
2378
2379 switch (SmramProfileParameterHeader->Command) {
2380 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:
2381 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n"));
2382 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {
2383 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2384 return EFI_SUCCESS;
2385 }
2386 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer);
2387 break;
2388 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:
2389 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n"));
2390 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {
2391 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2392 return EFI_SUCCESS;
2393 }
2394 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);
2395 break;
2396 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET:
2397 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetDataByOffset\n"));
2398 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET)) {
2399 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2400 return EFI_SUCCESS;
2401 }
2402 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) (UINTN) CommBuffer);
2403 break;
2404 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE:
2405 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n"));
2406 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) {
2407 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2408 return EFI_SUCCESS;
2409 }
2410 if (mSmramReadyToLock) {
2411 return EFI_SUCCESS;
2412 }
2413 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer);
2414 break;
2415 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE:
2416 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n"));
2417 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) {
2418 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2419 return EFI_SUCCESS;
2420 }
2421 if (mSmramReadyToLock) {
2422 return EFI_SUCCESS;
2423 }
2424 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);
2425 break;
2426 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE:
2427 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetRecordingState\n"));
2428 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) {
2429 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2430 return EFI_SUCCESS;
2431 }
2432 ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) (UINTN) CommBuffer;
2433 ParameterRecordingState->RecordingState = mSmramProfileRecordingEnable;
2434 ParameterRecordingState->Header.ReturnStatus = 0;
2435 break;
2436 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE:
2437 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerSetRecordingState\n"));
2438 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) {
2439 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2440 return EFI_SUCCESS;
2441 }
2442 ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) (UINTN) CommBuffer;
2443 mSmramProfileRecordingEnable = ParameterRecordingState->RecordingState;
2444 ParameterRecordingState->Header.ReturnStatus = 0;
2445 break;
2446
2447 default:
2448 break;
2449 }
2450
2451 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n"));
2452
2453 return EFI_SUCCESS;
2454 }
2455
2456 /**
2457 Register SMRAM profile handler.
2458
2459 **/
2460 VOID
2461 RegisterSmramProfileHandler (
2462 VOID
2463 )
2464 {
2465 EFI_STATUS Status;
2466 EFI_HANDLE DispatchHandle;
2467
2468 if (!IS_SMRAM_PROFILE_ENABLED) {
2469 return;
2470 }
2471
2472 Status = SmiHandlerRegister (
2473 SmramProfileHandler,
2474 &gEdkiiMemoryProfileGuid,
2475 &DispatchHandle
2476 );
2477 ASSERT_EFI_ERROR (Status);
2478 }
2479
2480 ////////////////////
2481
2482 /**
2483 Dump SMRAM range.
2484
2485 **/
2486 VOID
2487 DumpSmramRange (
2488 VOID
2489 )
2490 {
2491 UINTN Index;
2492 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2493 BOOLEAN SmramProfileGettingStatus;
2494
2495 ContextData = GetSmramProfileContext ();
2496 if (ContextData == NULL) {
2497 return ;
2498 }
2499
2500 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2501 mSmramProfileGettingStatus = TRUE;
2502
2503 DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));
2504
2505 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
2506
2507 DEBUG ((EFI_D_INFO, "FullSmramRange:\n"));
2508 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
2509 DEBUG ((EFI_D_INFO, " FullSmramRange (0x%x)\n", Index));
2510 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));
2511 DEBUG ((EFI_D_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));
2512 DEBUG ((EFI_D_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));
2513 DEBUG ((EFI_D_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState));
2514 }
2515
2516 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
2517
2518 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2519 }
2520
2521 /**
2522 Dump SMRAM free page list.
2523
2524 **/
2525 VOID
2526 DumpFreePagesList (
2527 VOID
2528 )
2529 {
2530 LIST_ENTRY *FreePageList;
2531 LIST_ENTRY *Node;
2532 FREE_PAGE_LIST *Pages;
2533 UINTN Index;
2534 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2535 BOOLEAN SmramProfileGettingStatus;
2536
2537 ContextData = GetSmramProfileContext ();
2538 if (ContextData == NULL) {
2539 return ;
2540 }
2541
2542 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2543 mSmramProfileGettingStatus = TRUE;
2544
2545 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
2546
2547 DEBUG ((EFI_D_INFO, "FreePagesList:\n"));
2548 FreePageList = &mSmmMemoryMap;
2549 for (Node = FreePageList->BackLink, Index = 0;
2550 Node != FreePageList;
2551 Node = Node->BackLink, Index++) {
2552 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
2553 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));
2554 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages));
2555 DEBUG ((EFI_D_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages));
2556 }
2557
2558 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
2559
2560 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2561 }
2562
2563 /**
2564 Dump SMRAM free pool list.
2565
2566 **/
2567 VOID
2568 DumpFreePoolList (
2569 VOID
2570 )
2571 {
2572 LIST_ENTRY *FreePoolList;
2573 LIST_ENTRY *Node;
2574 FREE_POOL_HEADER *Pool;
2575 UINTN Index;
2576 UINTN PoolListIndex;
2577 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2578 BOOLEAN SmramProfileGettingStatus;
2579
2580 ContextData = GetSmramProfileContext ();
2581 if (ContextData == NULL) {
2582 return ;
2583 }
2584
2585 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2586 mSmramProfileGettingStatus = TRUE;
2587
2588 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
2589
2590 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
2591 DEBUG ((EFI_D_INFO, "FreePoolList (%d):\n", PoolListIndex));
2592 FreePoolList = &mSmmPoolLists[PoolListIndex];
2593 for (Node = FreePoolList->BackLink, Index = 0;
2594 Node != FreePoolList;
2595 Node = Node->BackLink, Index++) {
2596 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
2597 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));
2598 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool));
2599 DEBUG ((EFI_D_INFO, " Size - 0x%08x\n", Pool->Header.Size));
2600 DEBUG ((EFI_D_INFO, " Available - 0x%02x\n", Pool->Header.Available));
2601 }
2602 }
2603
2604 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
2605
2606 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2607 }
2608
2609 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mSmmActionString[] = {
2610 "SmmUnknown",
2611 "gSmst->SmmAllocatePages",
2612 "gSmst->SmmFreePages",
2613 "gSmst->SmmAllocatePool",
2614 "gSmst->SmmFreePool",
2615 };
2616
2617 typedef struct {
2618 MEMORY_PROFILE_ACTION Action;
2619 CHAR8 *String;
2620 } ACTION_STRING;
2621
2622 ACTION_STRING mExtActionString[] = {
2623 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, "Lib:AllocatePages"},
2624 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, "Lib:AllocateRuntimePages"},
2625 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, "Lib:AllocateReservedPages"},
2626 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES, "Lib:FreePages"},
2627 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, "Lib:AllocateAlignedPages"},
2628 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, "Lib:AllocateAlignedRuntimePages"},
2629 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, "Lib:AllocateAlignedReservedPages"},
2630 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES, "Lib:FreeAlignedPages"},
2631 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, "Lib:AllocatePool"},
2632 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, "Lib:AllocateRuntimePool"},
2633 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, "Lib:AllocateReservedPool"},
2634 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL, "Lib:FreePool"},
2635 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, "Lib:AllocateZeroPool"},
2636 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, "Lib:AllocateRuntimeZeroPool"},
2637 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, "Lib:AllocateReservedZeroPool"},
2638 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, "Lib:AllocateCopyPool"},
2639 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, "Lib:AllocateRuntimeCopyPool"},
2640 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, "Lib:AllocateReservedCopyPool"},
2641 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, "Lib:ReallocatePool"},
2642 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, "Lib:ReallocateRuntimePool"},
2643 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, "Lib:ReallocateReservedPool"},
2644 };
2645
2646 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"};
2647
2648 typedef struct {
2649 EFI_MEMORY_TYPE MemoryType;
2650 CHAR8 *MemoryTypeStr;
2651 } PROFILE_MEMORY_TYPE_STRING;
2652
2653 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = {
2654 {EfiRuntimeServicesCode, "EfiRuntimeServicesCode"},
2655 {EfiRuntimeServicesData, "EfiRuntimeServicesData"}
2656 };
2657
2658 /**
2659 Memory type to string.
2660
2661 @param[in] MemoryType Memory type.
2662
2663 @return Pointer to string.
2664
2665 **/
2666 CHAR8 *
2667 ProfileMemoryTypeToStr (
2668 IN EFI_MEMORY_TYPE MemoryType
2669 )
2670 {
2671 UINTN Index;
2672 for (Index = 0; Index < sizeof (mMemoryTypeString) / sizeof (mMemoryTypeString[0]); Index++) {
2673 if (mMemoryTypeString[Index].MemoryType == MemoryType) {
2674 return mMemoryTypeString[Index].MemoryTypeStr;
2675 }
2676 }
2677
2678 return "UnexpectedMemoryType";
2679 }
2680
2681 /**
2682 Action to string.
2683
2684 @param[in] Action Profile action.
2685
2686 @return Pointer to string.
2687
2688 **/
2689 CHAR8 *
2690 ProfileActionToStr (
2691 IN MEMORY_PROFILE_ACTION Action
2692 )
2693 {
2694 UINTN Index;
2695 UINTN ActionStringCount;
2696 CHAR8 **ActionString;
2697
2698 ActionString = mSmmActionString;
2699 ActionStringCount = sizeof (mSmmActionString) / sizeof (mSmmActionString[0]);
2700
2701 if ((UINTN) (UINT32) Action < ActionStringCount) {
2702 return ActionString[Action];
2703 }
2704 for (Index = 0; Index < sizeof (mExtActionString) / sizeof (mExtActionString[0]); Index++) {
2705 if (mExtActionString[Index].Action == Action) {
2706 return mExtActionString[Index].String;
2707 }
2708 }
2709
2710 return ActionString[0];
2711 }
2712
2713 /**
2714 Dump SMRAM profile.
2715
2716 **/
2717 VOID
2718 DumpSmramProfile (
2719 VOID
2720 )
2721 {
2722 MEMORY_PROFILE_CONTEXT *Context;
2723 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
2724 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
2725 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2726 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
2727 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
2728 LIST_ENTRY *SmramDriverInfoList;
2729 UINTN DriverIndex;
2730 LIST_ENTRY *DriverLink;
2731 LIST_ENTRY *AllocInfoList;
2732 UINTN AllocIndex;
2733 LIST_ENTRY *AllocLink;
2734 BOOLEAN SmramProfileGettingStatus;
2735 UINTN TypeIndex;
2736
2737 ContextData = GetSmramProfileContext ();
2738 if (ContextData == NULL) {
2739 return ;
2740 }
2741
2742 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2743 mSmramProfileGettingStatus = TRUE;
2744
2745 Context = &ContextData->Context;
2746 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
2747 DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n"));
2748
2749 DEBUG ((EFI_D_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage));
2750 DEBUG ((EFI_D_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage));
2751 for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {
2752 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
2753 (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
2754 DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2755 DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2756 }
2757 }
2758 DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize));
2759 DEBUG ((EFI_D_INFO, " ImageCount - 0x%08x\n", Context->ImageCount));
2760 DEBUG ((EFI_D_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount));
2761
2762 SmramDriverInfoList = ContextData->DriverInfoList;
2763 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;
2764 DriverLink != SmramDriverInfoList;
2765 DriverLink = DriverLink->ForwardLink, DriverIndex++) {
2766 DriverInfoData = CR (
2767 DriverLink,
2768 MEMORY_PROFILE_DRIVER_INFO_DATA,
2769 Link,
2770 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2771 );
2772 DriverInfo = &DriverInfoData->DriverInfo;
2773 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));
2774 DEBUG ((EFI_D_INFO, " FileName - %g\n", &DriverInfo->FileName));
2775 DEBUG ((EFI_D_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase));
2776 DEBUG ((EFI_D_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize));
2777 DEBUG ((EFI_D_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint));
2778 DEBUG ((EFI_D_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem));
2779 DEBUG ((EFI_D_INFO, " FileType - 0x%02x\n", DriverInfo->FileType));
2780 DEBUG ((EFI_D_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage));
2781 DEBUG ((EFI_D_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage));
2782 for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {
2783 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
2784 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
2785 DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2786 DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2787 }
2788 }
2789 DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount));
2790
2791 AllocInfoList = DriverInfoData->AllocInfoList;
2792 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;
2793 AllocLink != AllocInfoList;
2794 AllocLink = AllocLink->ForwardLink, AllocIndex++) {
2795 AllocInfoData = CR (
2796 AllocLink,
2797 MEMORY_PROFILE_ALLOC_INFO_DATA,
2798 Link,
2799 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2800 );
2801 AllocInfo = &AllocInfoData->AllocInfo;
2802 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));
2803 DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));
2804 DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId));
2805 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) {
2806 if (AllocInfoData->ActionString != NULL) {
2807 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, AllocInfoData->ActionString));
2808 } else {
2809 DEBUG ((EFI_D_INFO, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo->Action, AllocInfo->Action));
2810 }
2811 } else {
2812 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action)));
2813 }
2814 DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType)));
2815 DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer));
2816 DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size));
2817 }
2818 }
2819
2820 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
2821
2822 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2823 }
2824
2825 /**
2826 Dump SMRAM infromation.
2827
2828 **/
2829 VOID
2830 DumpSmramInfo (
2831 VOID
2832 )
2833 {
2834 DEBUG_CODE (
2835 if (IS_SMRAM_PROFILE_ENABLED) {
2836 DumpSmramProfile ();
2837 DumpFreePagesList ();
2838 DumpFreePoolList ();
2839 DumpSmramRange ();
2840 }
2841 );
2842 }
2843