]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
MdeModulePkg MemoryProfile: ASSERT to ensure 'DriverInfoData' is not NULL
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmramProfileRecord.c
1 /** @file
2 Support routines for SMRAM profile.
3
4 Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "PiSmmCore.h"
16
17 #define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0)
18 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
19
20 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
21 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
22
23 typedef struct {
24 UINT32 Signature;
25 MEMORY_PROFILE_CONTEXT Context;
26 LIST_ENTRY *DriverInfoList;
27 } MEMORY_PROFILE_CONTEXT_DATA;
28
29 typedef struct {
30 UINT32 Signature;
31 MEMORY_PROFILE_DRIVER_INFO DriverInfo;
32 LIST_ENTRY *AllocInfoList;
33 CHAR8 *PdbString;
34 LIST_ENTRY Link;
35 } MEMORY_PROFILE_DRIVER_INFO_DATA;
36
37 typedef struct {
38 UINT32 Signature;
39 MEMORY_PROFILE_ALLOC_INFO AllocInfo;
40 CHAR8 *ActionString;
41 LIST_ENTRY Link;
42 } MEMORY_PROFILE_ALLOC_INFO_DATA;
43
44 //
45 // When free memory less than 4 pages, dump it.
46 //
47 #define SMRAM_INFO_DUMP_PAGE_THRESHOLD 4
48
49 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory = {
50 {
51 MEMORY_PROFILE_FREE_MEMORY_SIGNATURE,
52 sizeof (MEMORY_PROFILE_FREE_MEMORY),
53 MEMORY_PROFILE_FREE_MEMORY_REVISION
54 },
55 0,
56 0
57 };
58
59 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);
60 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext = {
61 MEMORY_PROFILE_CONTEXT_SIGNATURE,
62 {
63 {
64 MEMORY_PROFILE_CONTEXT_SIGNATURE,
65 sizeof (MEMORY_PROFILE_CONTEXT),
66 MEMORY_PROFILE_CONTEXT_REVISION
67 },
68 0,
69 0,
70 {0},
71 {0},
72 0,
73 0,
74 0
75 },
76 &mImageQueue,
77 };
78 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr = NULL;
79
80 BOOLEAN mSmramReadyToLock;
81 BOOLEAN mSmramProfileGettingStatus = FALSE;
82 BOOLEAN mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
83 EFI_DEVICE_PATH_PROTOCOL *mSmramProfileDriverPath;
84 UINTN mSmramProfileDriverPathSize;
85
86 /**
87 Dump SMRAM infromation.
88
89 **/
90 VOID
91 DumpSmramInfo (
92 VOID
93 );
94
95 /**
96 Get memory profile data.
97
98 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
99 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
100 On return, points to the size of the data returned in ProfileBuffer.
101 @param[out] ProfileBuffer Profile buffer.
102
103 @return EFI_SUCCESS Get the memory profile data successfully.
104 @return EFI_UNSUPPORTED Memory profile is unsupported.
105 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
106 ProfileSize is updated with the size required.
107
108 **/
109 EFI_STATUS
110 EFIAPI
111 SmramProfileProtocolGetData (
112 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
113 IN OUT UINT64 *ProfileSize,
114 OUT VOID *ProfileBuffer
115 );
116
117 /**
118 Register image to memory profile.
119
120 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
121 @param[in] FilePath File path of the image.
122 @param[in] ImageBase Image base address.
123 @param[in] ImageSize Image size.
124 @param[in] FileType File type of the image.
125
126 @return EFI_SUCCESS Register successfully.
127 @return EFI_UNSUPPORTED Memory profile is unsupported,
128 or memory profile for the image is not required.
129 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
130
131 **/
132 EFI_STATUS
133 EFIAPI
134 SmramProfileProtocolRegisterImage (
135 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
136 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
137 IN PHYSICAL_ADDRESS ImageBase,
138 IN UINT64 ImageSize,
139 IN EFI_FV_FILETYPE FileType
140 );
141
142 /**
143 Unregister image from memory profile.
144
145 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
146 @param[in] FilePath File path of the image.
147 @param[in] ImageBase Image base address.
148 @param[in] ImageSize Image size.
149
150 @return EFI_SUCCESS Unregister successfully.
151 @return EFI_UNSUPPORTED Memory profile is unsupported,
152 or memory profile for the image is not required.
153 @return EFI_NOT_FOUND The image is not found.
154
155 **/
156 EFI_STATUS
157 EFIAPI
158 SmramProfileProtocolUnregisterImage (
159 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
160 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
161 IN PHYSICAL_ADDRESS ImageBase,
162 IN UINT64 ImageSize
163 );
164
165 /**
166 Get memory profile recording state.
167
168 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
169 @param[out] RecordingState Recording state.
170
171 @return EFI_SUCCESS Memory profile recording state is returned.
172 @return EFI_UNSUPPORTED Memory profile is unsupported.
173 @return EFI_INVALID_PARAMETER RecordingState is NULL.
174
175 **/
176 EFI_STATUS
177 EFIAPI
178 SmramProfileProtocolGetRecordingState (
179 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
180 OUT BOOLEAN *RecordingState
181 );
182
183 /**
184 Set memory profile recording state.
185
186 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
187 @param[in] RecordingState Recording state.
188
189 @return EFI_SUCCESS Set memory profile recording state successfully.
190 @return EFI_UNSUPPORTED Memory profile is unsupported.
191
192 **/
193 EFI_STATUS
194 EFIAPI
195 SmramProfileProtocolSetRecordingState (
196 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
197 IN BOOLEAN RecordingState
198 );
199
200 /**
201 Record memory profile of multilevel caller.
202
203 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
204 @param[in] CallerAddress Address of caller.
205 @param[in] Action Memory profile action.
206 @param[in] MemoryType Memory type.
207 EfiMaxMemoryType means the MemoryType is unknown.
208 @param[in] Buffer Buffer address.
209 @param[in] Size Buffer size.
210 @param[in] ActionString String for memory profile action.
211 Only needed for user defined allocate action.
212
213 @return EFI_SUCCESS Memory profile is updated.
214 @return EFI_UNSUPPORTED Memory profile is unsupported,
215 or memory profile for the image is not required,
216 or memory profile for the memory type is not required.
217 @return EFI_ACCESS_DENIED It is during memory profile data getting.
218 @return EFI_ABORTED Memory profile recording is not enabled.
219 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
220 @return EFI_NOT_FOUND No matched allocate info found for free action.
221
222 **/
223 EFI_STATUS
224 EFIAPI
225 SmramProfileProtocolRecord (
226 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
227 IN PHYSICAL_ADDRESS CallerAddress,
228 IN MEMORY_PROFILE_ACTION Action,
229 IN EFI_MEMORY_TYPE MemoryType,
230 IN VOID *Buffer,
231 IN UINTN Size,
232 IN CHAR8 *ActionString OPTIONAL
233 );
234
235 EDKII_SMM_MEMORY_PROFILE_PROTOCOL mSmmProfileProtocol = {
236 SmramProfileProtocolGetData,
237 SmramProfileProtocolRegisterImage,
238 SmramProfileProtocolUnregisterImage,
239 SmramProfileProtocolGetRecordingState,
240 SmramProfileProtocolSetRecordingState,
241 SmramProfileProtocolRecord,
242 };
243
244 /**
245 Return SMRAM profile context.
246
247 @return SMRAM profile context.
248
249 **/
250 MEMORY_PROFILE_CONTEXT_DATA *
251 GetSmramProfileContext (
252 VOID
253 )
254 {
255 return mSmramProfileContextPtr;
256 }
257
258 /**
259 Retrieves the magic value from the PE/COFF header.
260
261 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
262
263 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
264 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
265
266 **/
267 UINT16
268 InternalPeCoffGetPeHeaderMagicValue (
269 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
270 )
271 {
272 //
273 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
274 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
275 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
276 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
277 //
278 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
279 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
280 }
281 //
282 // Return the magic value from the PC/COFF Optional Header
283 //
284 return Hdr.Pe32->OptionalHeader.Magic;
285 }
286
287 /**
288 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
289 If Pe32Data is NULL, then ASSERT().
290
291 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
292
293 @return The Subsystem of the PE/COFF image.
294
295 **/
296 UINT16
297 InternalPeCoffGetSubsystem (
298 IN VOID *Pe32Data
299 )
300 {
301 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
302 EFI_IMAGE_DOS_HEADER *DosHdr;
303 UINT16 Magic;
304
305 ASSERT (Pe32Data != NULL);
306
307 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
308 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
309 //
310 // DOS image header is present, so read the PE header after the DOS image header.
311 //
312 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
313 } else {
314 //
315 // DOS image header is not present, so PE header is at the image base.
316 //
317 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;
318 }
319
320 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
321 return Hdr.Te->Subsystem;
322 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
323 Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr);
324 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
325 return Hdr.Pe32->OptionalHeader.Subsystem;
326 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
327 return Hdr.Pe32Plus->OptionalHeader.Subsystem;
328 }
329 }
330
331 return 0x0000;
332 }
333
334 /**
335 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
336 into system memory with the PE/COFF Loader Library functions.
337
338 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
339 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
340 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
341 If Pe32Data is NULL, then ASSERT().
342 If EntryPoint is NULL, then ASSERT().
343
344 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
345 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
346
347 @retval RETURN_SUCCESS EntryPoint was returned.
348 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
349
350 **/
351 RETURN_STATUS
352 InternalPeCoffGetEntryPoint (
353 IN VOID *Pe32Data,
354 OUT VOID **EntryPoint
355 )
356 {
357 EFI_IMAGE_DOS_HEADER *DosHdr;
358 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
359
360 ASSERT (Pe32Data != NULL);
361 ASSERT (EntryPoint != NULL);
362
363 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
364 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
365 //
366 // DOS image header is present, so read the PE header after the DOS image header.
367 //
368 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
369 } else {
370 //
371 // DOS image header is not present, so PE header is at the image base.
372 //
373 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;
374 }
375
376 //
377 // Calculate the entry point relative to the start of the image.
378 // AddressOfEntryPoint is common for PE32 & PE32+
379 //
380 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
381 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
382 return RETURN_SUCCESS;
383 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
384 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
385 return RETURN_SUCCESS;
386 }
387
388 return RETURN_UNSUPPORTED;
389 }
390
391 /**
392 Build driver info.
393
394 @param ContextData Memory profile context.
395 @param FileName File name of the image.
396 @param ImageBase Image base address.
397 @param ImageSize Image size.
398 @param EntryPoint Entry point of the image.
399 @param ImageSubsystem Image subsystem of the image.
400 @param FileType File type of the image.
401
402 @return Pointer to memory profile driver info.
403
404 **/
405 MEMORY_PROFILE_DRIVER_INFO_DATA *
406 BuildDriverInfo (
407 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
408 IN EFI_GUID *FileName,
409 IN PHYSICAL_ADDRESS ImageBase,
410 IN UINT64 ImageSize,
411 IN PHYSICAL_ADDRESS EntryPoint,
412 IN UINT16 ImageSubsystem,
413 IN EFI_FV_FILETYPE FileType
414 )
415 {
416 EFI_STATUS Status;
417 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
418 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
419 VOID *EntryPointInImage;
420 CHAR8 *PdbString;
421 UINTN PdbSize;
422 UINTN PdbOccupiedSize;
423
424 PdbSize = 0;
425 PdbOccupiedSize = 0;
426 PdbString = NULL;
427 if (ImageBase != 0) {
428 PdbString = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageBase);
429 if (PdbString != NULL) {
430 PdbSize = AsciiStrSize (PdbString);
431 PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
432 }
433 }
434
435 //
436 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
437 //
438 Status = SmmInternalAllocatePool (
439 EfiRuntimeServicesData,
440 sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize,
441 (VOID **) &DriverInfoData
442 );
443 if (EFI_ERROR (Status)) {
444 return NULL;
445 }
446 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
1600 ContextData = GetSmramProfileContext ();
1601 if (ContextData == NULL) {
1602 return 0;
1603 }
1604
1605 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
1606
1607 DriverInfoList = ContextData->DriverInfoList;
1608 for (DriverLink = DriverInfoList->ForwardLink;
1609 DriverLink != DriverInfoList;
1610 DriverLink = DriverLink->ForwardLink) {
1611 DriverInfoData = CR (
1612 DriverLink,
1613 MEMORY_PROFILE_DRIVER_INFO_DATA,
1614 Link,
1615 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1616 );
1617 TotalSize += DriverInfoData->DriverInfo.Header.Length;
1618
1619 AllocInfoList = DriverInfoData->AllocInfoList;
1620 for (AllocLink = AllocInfoList->ForwardLink;
1621 AllocLink != AllocInfoList;
1622 AllocLink = AllocLink->ForwardLink) {
1623 AllocInfoData = CR (
1624 AllocLink,
1625 MEMORY_PROFILE_ALLOC_INFO_DATA,
1626 Link,
1627 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1628 );
1629 TotalSize += AllocInfoData->AllocInfo.Header.Length;
1630 }
1631 }
1632
1633
1634 Index = 0;
1635 FreePageList = &mSmmMemoryMap;
1636 for (Node = FreePageList->BackLink;
1637 Node != FreePageList;
1638 Node = Node->BackLink) {
1639 Index++;
1640 }
1641 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1642 FreePoolList = &mSmmPoolLists[PoolListIndex];
1643 for (Node = FreePoolList->BackLink;
1644 Node != FreePoolList;
1645 Node = Node->BackLink) {
1646 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1647 if (Pool->Header.Available) {
1648 Index++;
1649 }
1650 }
1651 }
1652
1653
1654 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1655 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));
1656
1657 return TotalSize;
1658 }
1659
1660 /**
1661 Copy SMRAM profile data.
1662
1663 @param ProfileBuffer The buffer to hold SMRAM profile data.
1664 @param ProfileSize On input, profile buffer size.
1665 On output, actual profile data size copied.
1666 @param ProfileOffset On input, profile buffer offset to copy.
1667 On output, next time profile buffer offset to copy.
1668
1669 **/
1670 VOID
1671 SmramProfileCopyData (
1672 OUT VOID *ProfileBuffer,
1673 IN OUT UINT64 *ProfileSize,
1674 IN OUT UINT64 *ProfileOffset
1675 )
1676 {
1677 MEMORY_PROFILE_CONTEXT *Context;
1678 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1679 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1680 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1681 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1682 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1683 LIST_ENTRY *DriverInfoList;
1684 LIST_ENTRY *DriverLink;
1685 LIST_ENTRY *AllocInfoList;
1686 LIST_ENTRY *AllocLink;
1687 LIST_ENTRY *Node;
1688 FREE_PAGE_LIST *Pages;
1689 LIST_ENTRY *FreePageList;
1690 LIST_ENTRY *FreePoolList;
1691 FREE_POOL_HEADER *Pool;
1692 UINTN PoolListIndex;
1693 UINT32 Index;
1694 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
1695 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
1696 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor;
1697 UINT64 Offset;
1698 UINT64 RemainingSize;
1699 UINTN PdbSize;
1700 UINTN ActionStringSize;
1701
1702 ContextData = GetSmramProfileContext ();
1703 if (ContextData == NULL) {
1704 return ;
1705 }
1706
1707 RemainingSize = *ProfileSize;
1708 Offset = 0;
1709
1710 if (*ProfileOffset < sizeof (MEMORY_PROFILE_CONTEXT)) {
1711 if (RemainingSize >= sizeof (MEMORY_PROFILE_CONTEXT)) {
1712 Context = ProfileBuffer;
1713 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
1714 RemainingSize -= sizeof (MEMORY_PROFILE_CONTEXT);
1715 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_CONTEXT);
1716 } else {
1717 goto Done;
1718 }
1719 }
1720 Offset += sizeof (MEMORY_PROFILE_CONTEXT);
1721
1722 DriverInfoList = ContextData->DriverInfoList;
1723 for (DriverLink = DriverInfoList->ForwardLink;
1724 DriverLink != DriverInfoList;
1725 DriverLink = DriverLink->ForwardLink) {
1726 DriverInfoData = CR (
1727 DriverLink,
1728 MEMORY_PROFILE_DRIVER_INFO_DATA,
1729 Link,
1730 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1731 );
1732 if (*ProfileOffset < (Offset + DriverInfoData->DriverInfo.Header.Length)) {
1733 if (RemainingSize >= DriverInfoData->DriverInfo.Header.Length) {
1734 DriverInfo = ProfileBuffer;
1735 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));
1736 if (DriverInfo->PdbStringOffset != 0) {
1737 PdbSize = AsciiStrSize (DriverInfoData->PdbString);
1738 CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize);
1739 }
1740 RemainingSize -= DriverInfo->Header.Length;
1741 ProfileBuffer = (UINT8 *) ProfileBuffer + DriverInfo->Header.Length;
1742 } else {
1743 goto Done;
1744 }
1745 }
1746 Offset += DriverInfoData->DriverInfo.Header.Length;
1747
1748 AllocInfoList = DriverInfoData->AllocInfoList;
1749 for (AllocLink = AllocInfoList->ForwardLink;
1750 AllocLink != AllocInfoList;
1751 AllocLink = AllocLink->ForwardLink) {
1752 AllocInfoData = CR (
1753 AllocLink,
1754 MEMORY_PROFILE_ALLOC_INFO_DATA,
1755 Link,
1756 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1757 );
1758 if (*ProfileOffset < (Offset + AllocInfoData->AllocInfo.Header.Length)) {
1759 if (RemainingSize >= AllocInfoData->AllocInfo.Header.Length) {
1760 AllocInfo = ProfileBuffer;
1761 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));
1762 if (AllocInfo->ActionStringOffset) {
1763 ActionStringSize = AsciiStrSize (AllocInfoData->ActionString);
1764 CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize);
1765 }
1766 RemainingSize -= AllocInfo->Header.Length;
1767 ProfileBuffer = (UINT8 *) ProfileBuffer + AllocInfo->Header.Length;
1768 } else {
1769 goto Done;
1770 }
1771 }
1772 Offset += AllocInfoData->AllocInfo.Header.Length;
1773 }
1774 }
1775
1776
1777 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_FREE_MEMORY))) {
1778 if (RemainingSize >= sizeof (MEMORY_PROFILE_FREE_MEMORY)) {
1779 FreeMemory = ProfileBuffer;
1780 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));
1781 Index = 0;
1782 FreePageList = &mSmmMemoryMap;
1783 for (Node = FreePageList->BackLink;
1784 Node != FreePageList;
1785 Node = Node->BackLink) {
1786 Index++;
1787 }
1788 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1789 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];
1790 for (Node = FreePoolList->BackLink;
1791 Node != FreePoolList;
1792 Node = Node->BackLink) {
1793 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1794 if (Pool->Header.Available) {
1795 Index++;
1796 }
1797 }
1798 }
1799 FreeMemory->FreeMemoryEntryCount = Index;
1800
1801 RemainingSize -= sizeof (MEMORY_PROFILE_FREE_MEMORY);
1802 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_FREE_MEMORY);
1803 } else {
1804 goto Done;
1805 }
1806 }
1807 Offset += sizeof (MEMORY_PROFILE_FREE_MEMORY);
1808 FreePageList = &mSmmMemoryMap;
1809 for (Node = FreePageList->BackLink;
1810 Node != FreePageList;
1811 Node = Node->BackLink) {
1812 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1813 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1814 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1815 MemoryProfileDescriptor = ProfileBuffer;
1816 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1817 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1818 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1819 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages;
1820 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);
1821
1822 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1823 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1824 } else {
1825 goto Done;
1826 }
1827 }
1828 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1829 }
1830 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
1831 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];
1832 for (Node = FreePoolList->BackLink;
1833 Node != FreePoolList;
1834 Node = Node->BackLink) {
1835 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
1836 if (Pool->Header.Available) {
1837 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1838 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1839 MemoryProfileDescriptor = ProfileBuffer;
1840 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1841 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1842 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1843 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool;
1844 MemoryProfileDescriptor->Size = Pool->Header.Size;
1845
1846 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1847 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1848 } else {
1849 goto Done;
1850 }
1851 }
1852 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1853 }
1854 }
1855 }
1856
1857 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_MEMORY_RANGE))) {
1858 if (RemainingSize >= sizeof (MEMORY_PROFILE_MEMORY_RANGE)) {
1859 MemoryRange = ProfileBuffer;
1860 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;
1861 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1862 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;
1863 MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount;
1864
1865 RemainingSize -= sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1866 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1867 } else {
1868 goto Done;
1869 }
1870 }
1871 Offset += sizeof (MEMORY_PROFILE_MEMORY_RANGE);
1872 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
1873 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {
1874 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {
1875 MemoryProfileDescriptor = ProfileBuffer;
1876 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;
1877 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);
1878 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;
1879 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;
1880 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;
1881
1882 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);
1883 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);
1884 } else {
1885 goto Done;
1886 }
1887 }
1888 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);
1889 }
1890
1891 Done:
1892 //
1893 // On output, actual profile data size copied.
1894 //
1895 *ProfileSize -= RemainingSize;
1896 //
1897 // On output, next time profile buffer offset to copy.
1898 //
1899 *ProfileOffset = Offset;
1900 }
1901
1902 /**
1903 Get memory profile data.
1904
1905 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1906 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1907 On return, points to the size of the data returned in ProfileBuffer.
1908 @param[out] ProfileBuffer Profile buffer.
1909
1910 @return EFI_SUCCESS Get the memory profile data successfully.
1911 @return EFI_UNSUPPORTED Memory profile is unsupported.
1912 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1913 ProfileSize is updated with the size required.
1914
1915 **/
1916 EFI_STATUS
1917 EFIAPI
1918 SmramProfileProtocolGetData (
1919 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
1920 IN OUT UINT64 *ProfileSize,
1921 OUT VOID *ProfileBuffer
1922 )
1923 {
1924 UINT64 Size;
1925 UINT64 Offset;
1926 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1927 BOOLEAN SmramProfileGettingStatus;
1928
1929 ContextData = GetSmramProfileContext ();
1930 if (ContextData == NULL) {
1931 return EFI_UNSUPPORTED;
1932 }
1933
1934 SmramProfileGettingStatus = mSmramProfileGettingStatus;
1935 mSmramProfileGettingStatus = TRUE;
1936
1937 Size = SmramProfileGetDataSize ();
1938
1939 if (*ProfileSize < Size) {
1940 *ProfileSize = Size;
1941 mSmramProfileGettingStatus = SmramProfileGettingStatus;
1942 return EFI_BUFFER_TOO_SMALL;
1943 }
1944
1945 Offset = 0;
1946 SmramProfileCopyData (ProfileBuffer, &Size, &Offset);
1947 *ProfileSize = Size;
1948
1949 mSmramProfileGettingStatus = SmramProfileGettingStatus;
1950 return EFI_SUCCESS;
1951 }
1952
1953 /**
1954 Register image to memory profile.
1955
1956 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1957 @param[in] FilePath File path of the image.
1958 @param[in] ImageBase Image base address.
1959 @param[in] ImageSize Image size.
1960 @param[in] FileType File type of the image.
1961
1962 @return EFI_SUCCESS Register successfully.
1963 @return EFI_UNSUPPORTED Memory profile is unsupported,
1964 or memory profile for the image is not required.
1965 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1966
1967 **/
1968 EFI_STATUS
1969 EFIAPI
1970 SmramProfileProtocolRegisterImage (
1971 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
1972 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1973 IN PHYSICAL_ADDRESS ImageBase,
1974 IN UINT64 ImageSize,
1975 IN EFI_FV_FILETYPE FileType
1976 )
1977 {
1978 EFI_STATUS Status;
1979 EFI_SMM_DRIVER_ENTRY DriverEntry;
1980 VOID *EntryPointInImage;
1981 EFI_GUID *Name;
1982
1983 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1984 Name = GetFileNameFromFilePath (FilePath);
1985 if (Name != NULL) {
1986 CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
1987 }
1988 DriverEntry.ImageBuffer = ImageBase;
1989 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize);
1990 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
1991 ASSERT_EFI_ERROR (Status);
1992 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1993
1994 return RegisterSmramProfileImage (&DriverEntry, FALSE);
1995 }
1996
1997 /**
1998 Unregister image from memory profile.
1999
2000 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2001 @param[in] FilePath File path of the image.
2002 @param[in] ImageBase Image base address.
2003 @param[in] ImageSize Image size.
2004
2005 @return EFI_SUCCESS Unregister successfully.
2006 @return EFI_UNSUPPORTED Memory profile is unsupported,
2007 or memory profile for the image is not required.
2008 @return EFI_NOT_FOUND The image is not found.
2009
2010 **/
2011 EFI_STATUS
2012 EFIAPI
2013 SmramProfileProtocolUnregisterImage (
2014 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2015 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
2016 IN PHYSICAL_ADDRESS ImageBase,
2017 IN UINT64 ImageSize
2018 )
2019 {
2020 EFI_STATUS Status;
2021 EFI_SMM_DRIVER_ENTRY DriverEntry;
2022 VOID *EntryPointInImage;
2023 EFI_GUID *Name;
2024
2025 ZeroMem (&DriverEntry, sizeof (DriverEntry));
2026 Name = GetFileNameFromFilePath (FilePath);
2027 if (Name != NULL) {
2028 CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
2029 }
2030 DriverEntry.ImageBuffer = ImageBase;
2031 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize);
2032 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
2033 ASSERT_EFI_ERROR (Status);
2034 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
2035
2036 return UnregisterSmramProfileImage (&DriverEntry, FALSE);
2037 }
2038
2039 /**
2040 Get memory profile recording state.
2041
2042 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2043 @param[out] RecordingState Recording state.
2044
2045 @return EFI_SUCCESS Memory profile recording state is returned.
2046 @return EFI_UNSUPPORTED Memory profile is unsupported.
2047 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2048
2049 **/
2050 EFI_STATUS
2051 EFIAPI
2052 SmramProfileProtocolGetRecordingState (
2053 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2054 OUT BOOLEAN *RecordingState
2055 )
2056 {
2057 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2058
2059 ContextData = GetSmramProfileContext ();
2060 if (ContextData == NULL) {
2061 return EFI_UNSUPPORTED;
2062 }
2063
2064 if (RecordingState == NULL) {
2065 return EFI_INVALID_PARAMETER;
2066 }
2067 *RecordingState = mSmramProfileRecordingEnable;
2068 return EFI_SUCCESS;
2069 }
2070
2071 /**
2072 Set memory profile recording state.
2073
2074 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2075 @param[in] RecordingState Recording state.
2076
2077 @return EFI_SUCCESS Set memory profile recording state successfully.
2078 @return EFI_UNSUPPORTED Memory profile is unsupported.
2079
2080 **/
2081 EFI_STATUS
2082 EFIAPI
2083 SmramProfileProtocolSetRecordingState (
2084 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2085 IN BOOLEAN RecordingState
2086 )
2087 {
2088 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2089
2090 ContextData = GetSmramProfileContext ();
2091 if (ContextData == NULL) {
2092 return EFI_UNSUPPORTED;
2093 }
2094
2095 mSmramProfileRecordingEnable = RecordingState;
2096 return EFI_SUCCESS;
2097 }
2098
2099 /**
2100 Record memory profile of multilevel caller.
2101
2102 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2103 @param[in] CallerAddress Address of caller.
2104 @param[in] Action Memory profile action.
2105 @param[in] MemoryType Memory type.
2106 EfiMaxMemoryType means the MemoryType is unknown.
2107 @param[in] Buffer Buffer address.
2108 @param[in] Size Buffer size.
2109 @param[in] ActionString String for memory profile action.
2110 Only needed for user defined allocate action.
2111
2112 @return EFI_SUCCESS Memory profile is updated.
2113 @return EFI_UNSUPPORTED Memory profile is unsupported,
2114 or memory profile for the image is not required,
2115 or memory profile for the memory type is not required.
2116 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2117 @return EFI_ABORTED Memory profile recording is not enabled.
2118 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2119 @return EFI_NOT_FOUND No matched allocate info found for free action.
2120
2121 **/
2122 EFI_STATUS
2123 EFIAPI
2124 SmramProfileProtocolRecord (
2125 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,
2126 IN PHYSICAL_ADDRESS CallerAddress,
2127 IN MEMORY_PROFILE_ACTION Action,
2128 IN EFI_MEMORY_TYPE MemoryType,
2129 IN VOID *Buffer,
2130 IN UINTN Size,
2131 IN CHAR8 *ActionString OPTIONAL
2132 )
2133 {
2134 return SmmCoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
2135 }
2136
2137 /**
2138 SMRAM profile handler to get profile info.
2139
2140 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2141
2142 **/
2143 VOID
2144 SmramProfileHandlerGetInfo (
2145 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo
2146 )
2147 {
2148 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2149 BOOLEAN SmramProfileGettingStatus;
2150
2151 ContextData = GetSmramProfileContext ();
2152 if (ContextData == NULL) {
2153 return ;
2154 }
2155
2156 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2157 mSmramProfileGettingStatus = TRUE;
2158
2159 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();
2160 SmramProfileParameterGetInfo->Header.ReturnStatus = 0;
2161
2162 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2163 }
2164
2165 /**
2166 SMRAM profile handler to get profile data.
2167
2168 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2169
2170 **/
2171 VOID
2172 SmramProfileHandlerGetData (
2173 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData
2174 )
2175 {
2176 UINT64 ProfileSize;
2177 UINT64 ProfileOffset;
2178 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData;
2179 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2180 BOOLEAN SmramProfileGettingStatus;
2181
2182 ContextData = GetSmramProfileContext ();
2183 if (ContextData == NULL) {
2184 return ;
2185 }
2186
2187 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2188 mSmramProfileGettingStatus = TRUE;
2189
2190
2191 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));
2192
2193 ProfileSize = SmramProfileGetDataSize();
2194
2195 //
2196 // Sanity check
2197 //
2198 if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {
2199 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2200 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2201 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;
2202 goto Done;
2203 }
2204
2205 if (SmramProfileGetData.ProfileSize < ProfileSize) {
2206 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2207 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL;
2208 goto Done;
2209 }
2210
2211 ProfileOffset = 0;
2212 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer, &ProfileSize, &ProfileOffset);
2213 SmramProfileParameterGetData->ProfileSize = ProfileSize;
2214 SmramProfileParameterGetData->Header.ReturnStatus = 0;
2215
2216 Done:
2217 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2218 }
2219
2220 /**
2221 SMRAM profile handler to get profile data by offset.
2222
2223 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2224
2225 **/
2226 VOID
2227 SmramProfileHandlerGetDataByOffset (
2228 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *SmramProfileParameterGetDataByOffset
2229 )
2230 {
2231 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset;
2232 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2233 BOOLEAN SmramProfileGettingStatus;
2234
2235 ContextData = GetSmramProfileContext ();
2236 if (ContextData == NULL) {
2237 return ;
2238 }
2239
2240 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2241 mSmramProfileGettingStatus = TRUE;
2242
2243
2244 CopyMem (&SmramProfileGetDataByOffset, SmramProfileParameterGetDataByOffset, sizeof (SmramProfileGetDataByOffset));
2245
2246 //
2247 // Sanity check
2248 //
2249 if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetDataByOffset.ProfileBuffer, (UINTN) SmramProfileGetDataByOffset.ProfileSize)) {
2250 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2251 SmramProfileParameterGetDataByOffset->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;
2252 goto Done;
2253 }
2254
2255 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetDataByOffset.ProfileBuffer, &SmramProfileGetDataByOffset.ProfileSize, &SmramProfileGetDataByOffset.ProfileOffset);
2256 CopyMem (SmramProfileParameterGetDataByOffset, &SmramProfileGetDataByOffset, sizeof (SmramProfileGetDataByOffset));
2257 SmramProfileParameterGetDataByOffset->Header.ReturnStatus = 0;
2258
2259 Done:
2260 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2261 }
2262
2263 /**
2264 SMRAM profile handler to register SMM image.
2265
2266 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
2267
2268 **/
2269 VOID
2270 SmramProfileHandlerRegisterImage (
2271 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage
2272 )
2273 {
2274 EFI_STATUS Status;
2275 EFI_SMM_DRIVER_ENTRY DriverEntry;
2276 VOID *EntryPointInImage;
2277
2278 ZeroMem (&DriverEntry, sizeof (DriverEntry));
2279 CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));
2280 DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer;
2281 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage;
2282 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
2283 ASSERT_EFI_ERROR (Status);
2284 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
2285
2286 Status = RegisterSmramProfileImage (&DriverEntry, FALSE);
2287 if (!EFI_ERROR (Status)) {
2288 SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;
2289 }
2290 }
2291
2292 /**
2293 SMRAM profile handler to unregister SMM image.
2294
2295 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
2296
2297 **/
2298 VOID
2299 SmramProfileHandlerUnregisterImage (
2300 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage
2301 )
2302 {
2303 EFI_STATUS Status;
2304 EFI_SMM_DRIVER_ENTRY DriverEntry;
2305 VOID *EntryPointInImage;
2306
2307 ZeroMem (&DriverEntry, sizeof (DriverEntry));
2308 CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));
2309 DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer;
2310 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage;
2311 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);
2312 ASSERT_EFI_ERROR (Status);
2313 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
2314
2315 Status = UnregisterSmramProfileImage (&DriverEntry, FALSE);
2316 if (!EFI_ERROR (Status)) {
2317 SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;
2318 }
2319 }
2320
2321 /**
2322 Dispatch function for a Software SMI handler.
2323
2324 Caution: This function may receive untrusted input.
2325 Communicate buffer and buffer size are external input, so this function will do basic validation.
2326
2327 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2328 @param Context Points to an optional handler context which was specified when the
2329 handler was registered.
2330 @param CommBuffer A pointer to a collection of data in memory that will
2331 be conveyed from a non-SMM environment into an SMM environment.
2332 @param CommBufferSize The size of the CommBuffer.
2333
2334 @retval EFI_SUCCESS Command is handled successfully.
2335
2336 **/
2337 EFI_STATUS
2338 EFIAPI
2339 SmramProfileHandler (
2340 IN EFI_HANDLE DispatchHandle,
2341 IN CONST VOID *Context OPTIONAL,
2342 IN OUT VOID *CommBuffer OPTIONAL,
2343 IN OUT UINTN *CommBufferSize OPTIONAL
2344 )
2345 {
2346 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader;
2347 UINTN TempCommBufferSize;
2348 SMRAM_PROFILE_PARAMETER_RECORDING_STATE *ParameterRecordingState;
2349
2350 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));
2351
2352 //
2353 // If input is invalid, stop processing this SMI
2354 //
2355 if (CommBuffer == NULL || CommBufferSize == NULL) {
2356 return EFI_SUCCESS;
2357 }
2358
2359 TempCommBufferSize = *CommBufferSize;
2360
2361 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {
2362 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2363 return EFI_SUCCESS;
2364 }
2365
2366 if (mSmramReadyToLock && !SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
2367 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2368 return EFI_SUCCESS;
2369 }
2370
2371 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer);
2372
2373 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;
2374
2375 if (GetSmramProfileContext () == NULL) {
2376 SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED;
2377 return EFI_SUCCESS;
2378 }
2379
2380 switch (SmramProfileParameterHeader->Command) {
2381 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:
2382 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n"));
2383 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {
2384 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2385 return EFI_SUCCESS;
2386 }
2387 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer);
2388 break;
2389 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:
2390 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n"));
2391 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {
2392 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2393 return EFI_SUCCESS;
2394 }
2395 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);
2396 break;
2397 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET:
2398 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetDataByOffset\n"));
2399 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET)) {
2400 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2401 return EFI_SUCCESS;
2402 }
2403 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) (UINTN) CommBuffer);
2404 break;
2405 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE:
2406 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n"));
2407 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) {
2408 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2409 return EFI_SUCCESS;
2410 }
2411 if (mSmramReadyToLock) {
2412 return EFI_SUCCESS;
2413 }
2414 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer);
2415 break;
2416 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE:
2417 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n"));
2418 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) {
2419 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2420 return EFI_SUCCESS;
2421 }
2422 if (mSmramReadyToLock) {
2423 return EFI_SUCCESS;
2424 }
2425 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);
2426 break;
2427 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE:
2428 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetRecordingState\n"));
2429 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) {
2430 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2431 return EFI_SUCCESS;
2432 }
2433 ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) (UINTN) CommBuffer;
2434 ParameterRecordingState->RecordingState = mSmramProfileRecordingEnable;
2435 ParameterRecordingState->Header.ReturnStatus = 0;
2436 break;
2437 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE:
2438 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerSetRecordingState\n"));
2439 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) {
2440 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2441 return EFI_SUCCESS;
2442 }
2443 ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) (UINTN) CommBuffer;
2444 mSmramProfileRecordingEnable = ParameterRecordingState->RecordingState;
2445 ParameterRecordingState->Header.ReturnStatus = 0;
2446 break;
2447
2448 default:
2449 break;
2450 }
2451
2452 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n"));
2453
2454 return EFI_SUCCESS;
2455 }
2456
2457 /**
2458 Register SMRAM profile handler.
2459
2460 **/
2461 VOID
2462 RegisterSmramProfileHandler (
2463 VOID
2464 )
2465 {
2466 EFI_STATUS Status;
2467 EFI_HANDLE DispatchHandle;
2468
2469 if (!IS_SMRAM_PROFILE_ENABLED) {
2470 return;
2471 }
2472
2473 Status = SmiHandlerRegister (
2474 SmramProfileHandler,
2475 &gEdkiiMemoryProfileGuid,
2476 &DispatchHandle
2477 );
2478 ASSERT_EFI_ERROR (Status);
2479 }
2480
2481 ////////////////////
2482
2483 /**
2484 Dump SMRAM range.
2485
2486 **/
2487 VOID
2488 DumpSmramRange (
2489 VOID
2490 )
2491 {
2492 UINTN Index;
2493 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2494 BOOLEAN SmramProfileGettingStatus;
2495
2496 ContextData = GetSmramProfileContext ();
2497 if (ContextData == NULL) {
2498 return ;
2499 }
2500
2501 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2502 mSmramProfileGettingStatus = TRUE;
2503
2504 DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));
2505
2506 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
2507
2508 DEBUG ((EFI_D_INFO, "FullSmramRange:\n"));
2509 for (Index = 0; Index < mFullSmramRangeCount; Index++) {
2510 DEBUG ((EFI_D_INFO, " FullSmramRange (0x%x)\n", Index));
2511 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));
2512 DEBUG ((EFI_D_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));
2513 DEBUG ((EFI_D_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));
2514 DEBUG ((EFI_D_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState));
2515 }
2516
2517 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
2518
2519 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2520 }
2521
2522 /**
2523 Dump SMRAM free page list.
2524
2525 **/
2526 VOID
2527 DumpFreePagesList (
2528 VOID
2529 )
2530 {
2531 LIST_ENTRY *FreePageList;
2532 LIST_ENTRY *Node;
2533 FREE_PAGE_LIST *Pages;
2534 UINTN Index;
2535 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2536 BOOLEAN SmramProfileGettingStatus;
2537
2538 ContextData = GetSmramProfileContext ();
2539 if (ContextData == NULL) {
2540 return ;
2541 }
2542
2543 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2544 mSmramProfileGettingStatus = TRUE;
2545
2546 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
2547
2548 DEBUG ((EFI_D_INFO, "FreePagesList:\n"));
2549 FreePageList = &mSmmMemoryMap;
2550 for (Node = FreePageList->BackLink, Index = 0;
2551 Node != FreePageList;
2552 Node = Node->BackLink, Index++) {
2553 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
2554 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));
2555 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages));
2556 DEBUG ((EFI_D_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages));
2557 }
2558
2559 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
2560
2561 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2562 }
2563
2564 /**
2565 Dump SMRAM free pool list.
2566
2567 **/
2568 VOID
2569 DumpFreePoolList (
2570 VOID
2571 )
2572 {
2573 LIST_ENTRY *FreePoolList;
2574 LIST_ENTRY *Node;
2575 FREE_POOL_HEADER *Pool;
2576 UINTN Index;
2577 UINTN PoolListIndex;
2578 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2579 BOOLEAN SmramProfileGettingStatus;
2580
2581 ContextData = GetSmramProfileContext ();
2582 if (ContextData == NULL) {
2583 return ;
2584 }
2585
2586 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2587 mSmramProfileGettingStatus = TRUE;
2588
2589 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
2590
2591 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {
2592 DEBUG ((EFI_D_INFO, "FreePoolList (%d):\n", PoolListIndex));
2593 FreePoolList = &mSmmPoolLists[PoolListIndex];
2594 for (Node = FreePoolList->BackLink, Index = 0;
2595 Node != FreePoolList;
2596 Node = Node->BackLink, Index++) {
2597 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);
2598 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));
2599 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool));
2600 DEBUG ((EFI_D_INFO, " Size - 0x%08x\n", Pool->Header.Size));
2601 DEBUG ((EFI_D_INFO, " Available - 0x%02x\n", Pool->Header.Available));
2602 }
2603 }
2604
2605 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
2606
2607 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2608 }
2609
2610 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mSmmActionString[] = {
2611 "SmmUnknown",
2612 "gSmst->SmmAllocatePages",
2613 "gSmst->SmmFreePages",
2614 "gSmst->SmmAllocatePool",
2615 "gSmst->SmmFreePool",
2616 };
2617
2618 typedef struct {
2619 MEMORY_PROFILE_ACTION Action;
2620 CHAR8 *String;
2621 } ACTION_STRING;
2622
2623 ACTION_STRING mExtActionString[] = {
2624 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, "Lib:AllocatePages"},
2625 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, "Lib:AllocateRuntimePages"},
2626 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, "Lib:AllocateReservedPages"},
2627 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES, "Lib:FreePages"},
2628 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, "Lib:AllocateAlignedPages"},
2629 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, "Lib:AllocateAlignedRuntimePages"},
2630 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, "Lib:AllocateAlignedReservedPages"},
2631 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES, "Lib:FreeAlignedPages"},
2632 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, "Lib:AllocatePool"},
2633 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, "Lib:AllocateRuntimePool"},
2634 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, "Lib:AllocateReservedPool"},
2635 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL, "Lib:FreePool"},
2636 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, "Lib:AllocateZeroPool"},
2637 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, "Lib:AllocateRuntimeZeroPool"},
2638 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, "Lib:AllocateReservedZeroPool"},
2639 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, "Lib:AllocateCopyPool"},
2640 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, "Lib:AllocateRuntimeCopyPool"},
2641 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, "Lib:AllocateReservedCopyPool"},
2642 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, "Lib:ReallocatePool"},
2643 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, "Lib:ReallocateRuntimePool"},
2644 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, "Lib:ReallocateReservedPool"},
2645 };
2646
2647 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"};
2648
2649 typedef struct {
2650 EFI_MEMORY_TYPE MemoryType;
2651 CHAR8 *MemoryTypeStr;
2652 } PROFILE_MEMORY_TYPE_STRING;
2653
2654 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = {
2655 {EfiRuntimeServicesCode, "EfiRuntimeServicesCode"},
2656 {EfiRuntimeServicesData, "EfiRuntimeServicesData"}
2657 };
2658
2659 /**
2660 Memory type to string.
2661
2662 @param[in] MemoryType Memory type.
2663
2664 @return Pointer to string.
2665
2666 **/
2667 CHAR8 *
2668 ProfileMemoryTypeToStr (
2669 IN EFI_MEMORY_TYPE MemoryType
2670 )
2671 {
2672 UINTN Index;
2673 for (Index = 0; Index < sizeof (mMemoryTypeString) / sizeof (mMemoryTypeString[0]); Index++) {
2674 if (mMemoryTypeString[Index].MemoryType == MemoryType) {
2675 return mMemoryTypeString[Index].MemoryTypeStr;
2676 }
2677 }
2678
2679 return "UnexpectedMemoryType";
2680 }
2681
2682 /**
2683 Action to string.
2684
2685 @param[in] Action Profile action.
2686
2687 @return Pointer to string.
2688
2689 **/
2690 CHAR8 *
2691 ProfileActionToStr (
2692 IN MEMORY_PROFILE_ACTION Action
2693 )
2694 {
2695 UINTN Index;
2696 UINTN ActionStringCount;
2697 CHAR8 **ActionString;
2698
2699 ActionString = mSmmActionString;
2700 ActionStringCount = sizeof (mSmmActionString) / sizeof (mSmmActionString[0]);
2701
2702 if ((UINTN) (UINT32) Action < ActionStringCount) {
2703 return ActionString[Action];
2704 }
2705 for (Index = 0; Index < sizeof (mExtActionString) / sizeof (mExtActionString[0]); Index++) {
2706 if (mExtActionString[Index].Action == Action) {
2707 return mExtActionString[Index].String;
2708 }
2709 }
2710
2711 return ActionString[0];
2712 }
2713
2714 /**
2715 Dump SMRAM profile.
2716
2717 **/
2718 VOID
2719 DumpSmramProfile (
2720 VOID
2721 )
2722 {
2723 MEMORY_PROFILE_CONTEXT *Context;
2724 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
2725 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
2726 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
2727 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
2728 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
2729 LIST_ENTRY *SmramDriverInfoList;
2730 UINTN DriverIndex;
2731 LIST_ENTRY *DriverLink;
2732 LIST_ENTRY *AllocInfoList;
2733 UINTN AllocIndex;
2734 LIST_ENTRY *AllocLink;
2735 BOOLEAN SmramProfileGettingStatus;
2736 UINTN TypeIndex;
2737
2738 ContextData = GetSmramProfileContext ();
2739 if (ContextData == NULL) {
2740 return ;
2741 }
2742
2743 SmramProfileGettingStatus = mSmramProfileGettingStatus;
2744 mSmramProfileGettingStatus = TRUE;
2745
2746 Context = &ContextData->Context;
2747 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
2748 DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n"));
2749
2750 DEBUG ((EFI_D_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage));
2751 DEBUG ((EFI_D_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage));
2752 for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {
2753 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
2754 (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
2755 DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2756 DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2757 }
2758 }
2759 DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize));
2760 DEBUG ((EFI_D_INFO, " ImageCount - 0x%08x\n", Context->ImageCount));
2761 DEBUG ((EFI_D_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount));
2762
2763 SmramDriverInfoList = ContextData->DriverInfoList;
2764 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;
2765 DriverLink != SmramDriverInfoList;
2766 DriverLink = DriverLink->ForwardLink, DriverIndex++) {
2767 DriverInfoData = CR (
2768 DriverLink,
2769 MEMORY_PROFILE_DRIVER_INFO_DATA,
2770 Link,
2771 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2772 );
2773 DriverInfo = &DriverInfoData->DriverInfo;
2774 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));
2775 DEBUG ((EFI_D_INFO, " FileName - %g\n", &DriverInfo->FileName));
2776 DEBUG ((EFI_D_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase));
2777 DEBUG ((EFI_D_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize));
2778 DEBUG ((EFI_D_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint));
2779 DEBUG ((EFI_D_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem));
2780 DEBUG ((EFI_D_INFO, " FileType - 0x%02x\n", DriverInfo->FileType));
2781 DEBUG ((EFI_D_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage));
2782 DEBUG ((EFI_D_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage));
2783 for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {
2784 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
2785 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
2786 DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2787 DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));
2788 }
2789 }
2790 DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount));
2791
2792 AllocInfoList = DriverInfoData->AllocInfoList;
2793 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;
2794 AllocLink != AllocInfoList;
2795 AllocLink = AllocLink->ForwardLink, AllocIndex++) {
2796 AllocInfoData = CR (
2797 AllocLink,
2798 MEMORY_PROFILE_ALLOC_INFO_DATA,
2799 Link,
2800 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2801 );
2802 AllocInfo = &AllocInfoData->AllocInfo;
2803 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));
2804 DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));
2805 DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId));
2806 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) {
2807 if (AllocInfoData->ActionString != NULL) {
2808 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, AllocInfoData->ActionString));
2809 } else {
2810 DEBUG ((EFI_D_INFO, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo->Action, AllocInfo->Action));
2811 }
2812 } else {
2813 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action)));
2814 }
2815 DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType)));
2816 DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer));
2817 DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size));
2818 }
2819 }
2820
2821 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
2822
2823 mSmramProfileGettingStatus = SmramProfileGettingStatus;
2824 }
2825
2826 /**
2827 Dump SMRAM infromation.
2828
2829 **/
2830 VOID
2831 DumpSmramInfo (
2832 VOID
2833 )
2834 {
2835 DEBUG_CODE (
2836 if (IS_SMRAM_PROFILE_ENABLED) {
2837 DumpSmramProfile ();
2838 DumpFreePagesList ();
2839 DumpFreePoolList ();
2840 DumpSmramRange ();
2841 }
2842 );
2843 }
2844