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