83ed43a16e957f7c1317950ee818aa3ba11bd430
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / MemoryProfileRecord.c
1 /** @file
2 Support routines for UEFI memory profile.
3
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "DxeMain.h"
16 #include "Imem.h"
17
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 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);
46 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext = {
47 MEMORY_PROFILE_CONTEXT_SIGNATURE,
48 {
49 {
50 MEMORY_PROFILE_CONTEXT_SIGNATURE,
51 sizeof (MEMORY_PROFILE_CONTEXT),
52 MEMORY_PROFILE_CONTEXT_REVISION
53 },
54 0,
55 0,
56 {0},
57 {0},
58 0,
59 0,
60 0
61 },
62 &mImageQueue,
63 };
64 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mMemoryProfileContextPtr = NULL;
65
66 GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOCK mMemoryProfileLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
67 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileGettingStatus = FALSE;
68 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
69 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL *mMemoryProfileDriverPath;
70 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMemoryProfileDriverPathSize;
71
72 /**
73 Get memory profile data.
74
75 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
76 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
77 On return, points to the size of the data returned in ProfileBuffer.
78 @param[out] ProfileBuffer Profile buffer.
79
80 @return EFI_SUCCESS Get the memory profile data successfully.
81 @return EFI_UNSUPPORTED Memory profile is unsupported.
82 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
83 ProfileSize is updated with the size required.
84
85 **/
86 EFI_STATUS
87 EFIAPI
88 ProfileProtocolGetData (
89 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
90 IN OUT UINT64 *ProfileSize,
91 OUT VOID *ProfileBuffer
92 );
93
94 /**
95 Register image to memory profile.
96
97 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
98 @param[in] FilePath File path of the image.
99 @param[in] ImageBase Image base address.
100 @param[in] ImageSize Image size.
101 @param[in] FileType File type of the image.
102
103 @return EFI_SUCCESS Register successfully.
104 @return EFI_UNSUPPORTED Memory profile is unsupported,
105 or memory profile for the image is not required.
106 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
107
108 **/
109 EFI_STATUS
110 EFIAPI
111 ProfileProtocolRegisterImage (
112 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
113 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
114 IN PHYSICAL_ADDRESS ImageBase,
115 IN UINT64 ImageSize,
116 IN EFI_FV_FILETYPE FileType
117 );
118
119 /**
120 Unregister image from memory profile.
121
122 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
123 @param[in] FilePath File path of the image.
124 @param[in] ImageBase Image base address.
125 @param[in] ImageSize Image size.
126
127 @return EFI_SUCCESS Unregister successfully.
128 @return EFI_UNSUPPORTED Memory profile is unsupported,
129 or memory profile for the image is not required.
130 @return EFI_NOT_FOUND The image is not found.
131
132 **/
133 EFI_STATUS
134 EFIAPI
135 ProfileProtocolUnregisterImage (
136 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
137 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
138 IN PHYSICAL_ADDRESS ImageBase,
139 IN UINT64 ImageSize
140 );
141
142 /**
143 Get memory profile recording state.
144
145 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
146 @param[out] RecordingState Recording state.
147
148 @return EFI_SUCCESS Memory profile recording state is returned.
149 @return EFI_UNSUPPORTED Memory profile is unsupported.
150 @return EFI_INVALID_PARAMETER RecordingState is NULL.
151
152 **/
153 EFI_STATUS
154 EFIAPI
155 ProfileProtocolGetRecordingState (
156 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
157 OUT BOOLEAN *RecordingState
158 );
159
160 /**
161 Set memory profile recording state.
162
163 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
164 @param[in] RecordingState Recording state.
165
166 @return EFI_SUCCESS Set memory profile recording state successfully.
167 @return EFI_UNSUPPORTED Memory profile is unsupported.
168
169 **/
170 EFI_STATUS
171 EFIAPI
172 ProfileProtocolSetRecordingState (
173 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
174 IN BOOLEAN RecordingState
175 );
176
177 /**
178 Record memory profile of multilevel caller.
179
180 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
181 @param[in] CallerAddress Address of caller.
182 @param[in] Action Memory profile action.
183 @param[in] MemoryType Memory type.
184 EfiMaxMemoryType means the MemoryType is unknown.
185 @param[in] Buffer Buffer address.
186 @param[in] Size Buffer size.
187 @param[in] ActionString String for memory profile action.
188 Only needed for user defined allocate action.
189
190 @return EFI_SUCCESS Memory profile is updated.
191 @return EFI_UNSUPPORTED Memory profile is unsupported,
192 or memory profile for the image is not required,
193 or memory profile for the memory type is not required.
194 @return EFI_ACCESS_DENIED It is during memory profile data getting.
195 @return EFI_ABORTED Memory profile recording is not enabled.
196 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
197 @return EFI_NOT_FOUND No matched allocate info found for free action.
198
199 **/
200 EFI_STATUS
201 EFIAPI
202 ProfileProtocolRecord (
203 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
204 IN PHYSICAL_ADDRESS CallerAddress,
205 IN MEMORY_PROFILE_ACTION Action,
206 IN EFI_MEMORY_TYPE MemoryType,
207 IN VOID *Buffer,
208 IN UINTN Size,
209 IN CHAR8 *ActionString OPTIONAL
210 );
211
212 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol = {
213 ProfileProtocolGetData,
214 ProfileProtocolRegisterImage,
215 ProfileProtocolUnregisterImage,
216 ProfileProtocolGetRecordingState,
217 ProfileProtocolSetRecordingState,
218 ProfileProtocolRecord,
219 };
220
221 /**
222 Acquire lock on mMemoryProfileLock.
223 **/
224 VOID
225 CoreAcquireMemoryProfileLock (
226 VOID
227 )
228 {
229 CoreAcquireLock (&mMemoryProfileLock);
230 }
231
232 /**
233 Release lock on mMemoryProfileLock.
234 **/
235 VOID
236 CoreReleaseMemoryProfileLock (
237 VOID
238 )
239 {
240 CoreReleaseLock (&mMemoryProfileLock);
241 }
242
243 /**
244 Return memory profile context.
245
246 @return Memory profile context.
247
248 **/
249 MEMORY_PROFILE_CONTEXT_DATA *
250 GetMemoryProfileContext (
251 VOID
252 )
253 {
254 return mMemoryProfileContextPtr;
255 }
256
257 /**
258 Retrieves the magic value from the PE/COFF header.
259
260 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
261
262 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
263 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
264
265 **/
266 UINT16
267 InternalPeCoffGetPeHeaderMagicValue (
268 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
269 )
270 {
271 //
272 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
273 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
274 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
275 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
276 //
277 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
278 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
279 }
280 //
281 // Return the magic value from the PC/COFF Optional Header
282 //
283 return Hdr.Pe32->OptionalHeader.Magic;
284 }
285
286 /**
287 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
288 If Pe32Data is NULL, then ASSERT().
289
290 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
291
292 @return The Subsystem of the PE/COFF image.
293
294 **/
295 UINT16
296 InternalPeCoffGetSubsystem (
297 IN VOID *Pe32Data
298 )
299 {
300 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
301 EFI_IMAGE_DOS_HEADER *DosHdr;
302 UINT16 Magic;
303
304 ASSERT (Pe32Data != NULL);
305
306 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
307 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
308 //
309 // DOS image header is present, so read the PE header after the DOS image header.
310 //
311 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
312 } else {
313 //
314 // DOS image header is not present, so PE header is at the image base.
315 //
316 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;
317 }
318
319 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
320 return Hdr.Te->Subsystem;
321 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
322 Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr);
323 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
324 return Hdr.Pe32->OptionalHeader.Subsystem;
325 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
326 return Hdr.Pe32Plus->OptionalHeader.Subsystem;
327 }
328 }
329
330 return 0x0000;
331 }
332
333 /**
334 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
335 into system memory with the PE/COFF Loader Library functions.
336
337 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
338 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
339 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
340 If Pe32Data is NULL, then ASSERT().
341 If EntryPoint is NULL, then ASSERT().
342
343 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
344 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
345
346 @retval RETURN_SUCCESS EntryPoint was returned.
347 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
348
349 **/
350 RETURN_STATUS
351 InternalPeCoffGetEntryPoint (
352 IN VOID *Pe32Data,
353 OUT VOID **EntryPoint
354 )
355 {
356 EFI_IMAGE_DOS_HEADER *DosHdr;
357 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
358
359 ASSERT (Pe32Data != NULL);
360 ASSERT (EntryPoint != NULL);
361
362 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
363 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
364 //
365 // DOS image header is present, so read the PE header after the DOS image header.
366 //
367 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
368 } else {
369 //
370 // DOS image header is not present, so PE header is at the image base.
371 //
372 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;
373 }
374
375 //
376 // Calculate the entry point relative to the start of the image.
377 // AddressOfEntryPoint is common for PE32 & PE32+
378 //
379 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
380 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
381 return RETURN_SUCCESS;
382 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
383 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
384 return RETURN_SUCCESS;
385 }
386
387 return RETURN_UNSUPPORTED;
388 }
389
390 /**
391 Build driver info.
392
393 @param ContextData Memory profile context.
394 @param FileName File name of the image.
395 @param ImageBase Image base address.
396 @param ImageSize Image size.
397 @param EntryPoint Entry point of the image.
398 @param ImageSubsystem Image subsystem of the image.
399 @param FileType File type of the image.
400
401 @return Pointer to memory profile driver info.
402
403 **/
404 MEMORY_PROFILE_DRIVER_INFO_DATA *
405 BuildDriverInfo (
406 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
407 IN EFI_GUID *FileName,
408 IN PHYSICAL_ADDRESS ImageBase,
409 IN UINT64 ImageSize,
410 IN PHYSICAL_ADDRESS EntryPoint,
411 IN UINT16 ImageSubsystem,
412 IN EFI_FV_FILETYPE FileType
413 )
414 {
415 EFI_STATUS Status;
416 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
417 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
418 VOID *EntryPointInImage;
419 CHAR8 *PdbString;
420 UINTN PdbSize;
421 UINTN PdbOccupiedSize;
422
423 PdbSize = 0;
424 PdbOccupiedSize = 0;
425 PdbString = NULL;
426 if (ImageBase != 0) {
427 PdbString = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageBase);
428 if (PdbString != NULL) {
429 PdbSize = AsciiStrSize (PdbString);
430 PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
431 }
432 }
433
434 //
435 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
436 //
437 Status = CoreInternalAllocatePool (
438 EfiBootServicesData,
439 sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize,
440 (VOID **) &DriverInfoData
441 );
442 if (EFI_ERROR (Status)) {
443 return NULL;
444 }
445 ASSERT (DriverInfoData != NULL);
446
447 ZeroMem (DriverInfoData, sizeof (*DriverInfoData));
448
449 DriverInfo = &DriverInfoData->DriverInfo;
450 DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
451 DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
452 DriverInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_DRIVER_INFO) + PdbOccupiedSize);
453 DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;
454 if (FileName != NULL) {
455 CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));
456 }
457 DriverInfo->ImageBase = ImageBase;
458 DriverInfo->ImageSize = ImageSize;
459 DriverInfo->EntryPoint = EntryPoint;
460 DriverInfo->ImageSubsystem = ImageSubsystem;
461 if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {
462 //
463 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
464 // So patch ImageBuffer here to align the EntryPoint.
465 //
466 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
467 ASSERT_EFI_ERROR (Status);
468 DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
469 }
470 DriverInfo->FileType = FileType;
471 DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1);
472 InitializeListHead (DriverInfoData->AllocInfoList);
473 DriverInfo->CurrentUsage = 0;
474 DriverInfo->PeakUsage = 0;
475 DriverInfo->AllocRecordCount = 0;
476 if (PdbSize != 0) {
477 DriverInfo->PdbStringOffset = (UINT16) sizeof (MEMORY_PROFILE_DRIVER_INFO);
478 DriverInfoData->PdbString = (CHAR8 *) (DriverInfoData->AllocInfoList + 1);
479 CopyMem (DriverInfoData->PdbString, PdbString, PdbSize);
480 } else {
481 DriverInfo->PdbStringOffset = 0;
482 DriverInfoData->PdbString = NULL;
483 }
484
485 InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);
486 ContextData->Context.ImageCount ++;
487 ContextData->Context.TotalImageSize += DriverInfo->ImageSize;
488
489 return DriverInfoData;
490 }
491
492 /**
493 Return if record for this driver is needed..
494
495 @param DriverFilePath Driver file path.
496
497 @retval TRUE Record for this driver is needed.
498 @retval FALSE Record for this driver is not needed.
499
500 **/
501 BOOLEAN
502 NeedRecordThisDriver (
503 IN EFI_DEVICE_PATH_PROTOCOL *DriverFilePath
504 )
505 {
506 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
507 EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance;
508 UINTN DevicePathSize;
509 UINTN FilePathSize;
510
511 if (!IsDevicePathValid (mMemoryProfileDriverPath, mMemoryProfileDriverPathSize)) {
512 //
513 // Invalid Device Path means record all.
514 //
515 return TRUE;
516 }
517
518 //
519 // Record FilePath without END node.
520 //
521 FilePathSize = GetDevicePathSize (DriverFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
522
523 DevicePathInstance = mMemoryProfileDriverPath;
524 do {
525 //
526 // Find END node (it might be END_ENTIRE or END_INSTANCE).
527 //
528 TmpDevicePath = DevicePathInstance;
529 while (!IsDevicePathEndType (TmpDevicePath)) {
530 TmpDevicePath = NextDevicePathNode (TmpDevicePath);
531 }
532
533 //
534 // Do not compare END node.
535 //
536 DevicePathSize = (UINTN)TmpDevicePath - (UINTN)DevicePathInstance;
537 if ((FilePathSize == DevicePathSize) &&
538 (CompareMem (DriverFilePath, DevicePathInstance, DevicePathSize) == 0)) {
539 return TRUE;
540 }
541
542 //
543 // Get next instance.
544 //
545 DevicePathInstance = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)DevicePathInstance + DevicePathSize + DevicePathNodeLength(TmpDevicePath));
546 } while (DevicePathSubType (TmpDevicePath) != END_ENTIRE_DEVICE_PATH_SUBTYPE);
547
548 return FALSE;
549 }
550
551 /**
552 Register DXE Core to memory profile.
553
554 @param HobStart The start address of the HOB.
555 @param ContextData Memory profile context.
556
557 @retval TRUE Register success.
558 @retval FALSE Register fail.
559
560 **/
561 BOOLEAN
562 RegisterDxeCore (
563 IN VOID *HobStart,
564 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData
565 )
566 {
567 EFI_PEI_HOB_POINTERS DxeCoreHob;
568 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
569 PHYSICAL_ADDRESS ImageBase;
570 UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)];
571 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
572
573 ASSERT (ContextData != NULL);
574
575 //
576 // Searching for image hob
577 //
578 DxeCoreHob.Raw = HobStart;
579 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {
580 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
581 //
582 // Find Dxe Core HOB
583 //
584 break;
585 }
586 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
587 }
588 ASSERT (DxeCoreHob.Raw != NULL);
589
590 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer;
591 EfiInitializeFwVolDevicepathNode (FilePath, &DxeCoreHob.MemoryAllocationModule->ModuleName);
592 SetDevicePathEndNode (FilePath + 1);
593
594 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) {
595 return FALSE;
596 }
597
598 ImageBase = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
599 DriverInfoData = BuildDriverInfo (
600 ContextData,
601 &DxeCoreHob.MemoryAllocationModule->ModuleName,
602 ImageBase,
603 DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength,
604 DxeCoreHob.MemoryAllocationModule->EntryPoint,
605 InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase),
606 EFI_FV_FILETYPE_DXE_CORE
607 );
608 if (DriverInfoData == NULL) {
609 return FALSE;
610 }
611
612 return TRUE;
613 }
614
615 /**
616 Initialize memory profile.
617
618 @param HobStart The start address of the HOB.
619
620 **/
621 VOID
622 MemoryProfileInit (
623 IN VOID *HobStart
624 )
625 {
626 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
627
628 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
629 return;
630 }
631
632 ContextData = GetMemoryProfileContext ();
633 if (ContextData != NULL) {
634 return;
635 }
636
637 mMemoryProfileGettingStatus = FALSE;
638 if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) {
639 mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
640 } else {
641 mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE;
642 }
643 mMemoryProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath);
644 mMemoryProfileDriverPath = AllocateCopyPool (mMemoryProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath));
645 mMemoryProfileContextPtr = &mMemoryProfileContext;
646
647 RegisterDxeCore (HobStart, &mMemoryProfileContext);
648
649 DEBUG ((EFI_D_INFO, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext));
650 }
651
652 /**
653 Install memory profile protocol.
654
655 **/
656 VOID
657 MemoryProfileInstallProtocol (
658 VOID
659 )
660 {
661 EFI_HANDLE Handle;
662 EFI_STATUS Status;
663
664 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
665 return;
666 }
667
668 Handle = NULL;
669 Status = CoreInstallMultipleProtocolInterfaces (
670 &Handle,
671 &gEdkiiMemoryProfileGuid,
672 &mProfileProtocol,
673 NULL
674 );
675 ASSERT_EFI_ERROR (Status);
676 }
677
678 /**
679 Get the GUID file name from the file path.
680
681 @param FilePath File path.
682
683 @return The GUID file name from the file path.
684
685 **/
686 EFI_GUID *
687 GetFileNameFromFilePath (
688 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
689 )
690 {
691 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *ThisFilePath;
692 EFI_GUID *FileName;
693
694 FileName = NULL;
695 if (FilePath != NULL) {
696 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePath;
697 while (!IsDevicePathEnd (ThisFilePath)) {
698 FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath);
699 if (FileName != NULL) {
700 break;
701 }
702 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) NextDevicePathNode (ThisFilePath);
703 }
704 }
705
706 return FileName;
707 }
708
709 /**
710 Register image to memory profile.
711
712 @param DriverEntry Image info.
713 @param FileType Image file type.
714
715 @return EFI_SUCCESS Register successfully.
716 @return EFI_UNSUPPORTED Memory profile is unsupported,
717 or memory profile for the image is not required.
718 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
719
720 **/
721 EFI_STATUS
722 RegisterMemoryProfileImage (
723 IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry,
724 IN EFI_FV_FILETYPE FileType
725 )
726 {
727 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
728 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
729
730 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
731 return EFI_UNSUPPORTED;
732 }
733
734 if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) {
735 return EFI_UNSUPPORTED;
736 }
737
738 ContextData = GetMemoryProfileContext ();
739 if (ContextData == NULL) {
740 return EFI_UNSUPPORTED;
741 }
742
743 DriverInfoData = BuildDriverInfo (
744 ContextData,
745 GetFileNameFromFilePath (DriverEntry->Info.FilePath),
746 DriverEntry->ImageContext.ImageAddress,
747 DriverEntry->ImageContext.ImageSize,
748 DriverEntry->ImageContext.EntryPoint,
749 DriverEntry->ImageContext.ImageType,
750 FileType
751 );
752 if (DriverInfoData == NULL) {
753 return EFI_OUT_OF_RESOURCES;
754 }
755
756 return EFI_SUCCESS;
757 }
758
759 /**
760 Search image from memory profile.
761
762 @param ContextData Memory profile context.
763 @param FileName Image file name.
764 @param Address Image Address.
765
766 @return Pointer to memory profile driver info.
767
768 **/
769 MEMORY_PROFILE_DRIVER_INFO_DATA *
770 GetMemoryProfileDriverInfoByFileNameAndAddress (
771 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
772 IN EFI_GUID *FileName,
773 IN PHYSICAL_ADDRESS Address
774 )
775 {
776 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
777 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
778 LIST_ENTRY *DriverLink;
779 LIST_ENTRY *DriverInfoList;
780
781 DriverInfoList = ContextData->DriverInfoList;
782
783 for (DriverLink = DriverInfoList->ForwardLink;
784 DriverLink != DriverInfoList;
785 DriverLink = DriverLink->ForwardLink) {
786 DriverInfoData = CR (
787 DriverLink,
788 MEMORY_PROFILE_DRIVER_INFO_DATA,
789 Link,
790 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
791 );
792 DriverInfo = &DriverInfoData->DriverInfo;
793 if ((CompareGuid (&DriverInfo->FileName, FileName)) &&
794 (Address >= DriverInfo->ImageBase) &&
795 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {
796 return DriverInfoData;
797 }
798 }
799
800 return NULL;
801 }
802
803 /**
804 Search image from memory profile.
805 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize).
806
807 @param ContextData Memory profile context.
808 @param Address Image or Function address.
809
810 @return Pointer to memory profile driver info.
811
812 **/
813 MEMORY_PROFILE_DRIVER_INFO_DATA *
814 GetMemoryProfileDriverInfoFromAddress (
815 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
816 IN PHYSICAL_ADDRESS Address
817 )
818 {
819 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
820 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
821 LIST_ENTRY *DriverLink;
822 LIST_ENTRY *DriverInfoList;
823
824 DriverInfoList = ContextData->DriverInfoList;
825
826 for (DriverLink = DriverInfoList->ForwardLink;
827 DriverLink != DriverInfoList;
828 DriverLink = DriverLink->ForwardLink) {
829 DriverInfoData = CR (
830 DriverLink,
831 MEMORY_PROFILE_DRIVER_INFO_DATA,
832 Link,
833 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
834 );
835 DriverInfo = &DriverInfoData->DriverInfo;
836 if ((Address >= DriverInfo->ImageBase) &&
837 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {
838 return DriverInfoData;
839 }
840 }
841
842 return NULL;
843 }
844
845 /**
846 Unregister image from memory profile.
847
848 @param DriverEntry Image info.
849
850 @return EFI_SUCCESS Unregister successfully.
851 @return EFI_UNSUPPORTED Memory profile is unsupported,
852 or memory profile for the image is not required.
853 @return EFI_NOT_FOUND The image is not found.
854
855 **/
856 EFI_STATUS
857 UnregisterMemoryProfileImage (
858 IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry
859 )
860 {
861 EFI_STATUS Status;
862 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
863 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
864 EFI_GUID *FileName;
865 PHYSICAL_ADDRESS ImageAddress;
866 VOID *EntryPointInImage;
867
868 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
869 return EFI_UNSUPPORTED;
870 }
871
872 if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) {
873 return EFI_UNSUPPORTED;
874 }
875
876 ContextData = GetMemoryProfileContext ();
877 if (ContextData == NULL) {
878 return EFI_UNSUPPORTED;
879 }
880
881 DriverInfoData = NULL;
882 FileName = GetFileNameFromFilePath (DriverEntry->Info.FilePath);
883 ImageAddress = DriverEntry->ImageContext.ImageAddress;
884 if ((DriverEntry->ImageContext.EntryPoint < ImageAddress) || (DriverEntry->ImageContext.EntryPoint >= (ImageAddress + DriverEntry->ImageContext.ImageSize))) {
885 //
886 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
887 // So patch ImageAddress here to align the EntryPoint.
888 //
889 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage);
890 ASSERT_EFI_ERROR (Status);
891 ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageContext.EntryPoint - (UINTN) EntryPointInImage;
892 }
893 if (FileName != NULL) {
894 DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);
895 }
896 if (DriverInfoData == NULL) {
897 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);
898 }
899 if (DriverInfoData == NULL) {
900 return EFI_NOT_FOUND;
901 }
902
903 ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;
904
905 // Keep the ImageBase for RVA calculation in Application.
906 //DriverInfoData->DriverInfo.ImageBase = 0;
907 DriverInfoData->DriverInfo.ImageSize = 0;
908
909 if (DriverInfoData->DriverInfo.PeakUsage == 0) {
910 ContextData->Context.ImageCount --;
911 RemoveEntryList (&DriverInfoData->Link);
912 //
913 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
914 //
915 CoreInternalFreePool (DriverInfoData, NULL);
916 }
917
918 return EFI_SUCCESS;
919 }
920
921 /**
922 Return if this memory type needs to be recorded into memory profile.
923 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), it checks bit (1 << MemoryType).
924 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.
925 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), it checks bit62 - 0x4000000000000000.
926
927 @param MemoryType Memory type.
928
929 @retval TRUE This memory type need to be recorded.
930 @retval FALSE This memory type need not to be recorded.
931
932 **/
933 BOOLEAN
934 CoreNeedRecordProfile (
935 IN EFI_MEMORY_TYPE MemoryType
936 )
937 {
938 UINT64 TestBit;
939
940 if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
941 TestBit = BIT63;
942 } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
943 TestBit = BIT62;
944 } else {
945 TestBit = LShiftU64 (1, MemoryType);
946 }
947
948 if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {
949 return TRUE;
950 } else {
951 return FALSE;
952 }
953 }
954
955 /**
956 Convert EFI memory type to profile memory index. The rule is:
957 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
958 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.
959 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType + 1.
960
961 @param MemoryType Memory type.
962
963 @return Profile memory index.
964
965 **/
966 UINTN
967 GetProfileMemoryIndex (
968 IN EFI_MEMORY_TYPE MemoryType
969 )
970 {
971 if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
972 return EfiMaxMemoryType;
973 } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
974 return EfiMaxMemoryType + 1;
975 } else {
976 return MemoryType;
977 }
978 }
979
980 /**
981 Update memory profile Allocate information.
982
983 @param CallerAddress Address of caller who call Allocate.
984 @param Action This Allocate action.
985 @param MemoryType Memory type.
986 @param Size Buffer size.
987 @param Buffer Buffer address.
988 @param ActionString String for memory profile action.
989
990 @return EFI_SUCCESS Memory profile is updated.
991 @return EFI_UNSUPPORTED Memory profile is unsupported,
992 or memory profile for the image is not required.
993 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
994
995 **/
996 EFI_STATUS
997 CoreUpdateProfileAllocate (
998 IN PHYSICAL_ADDRESS CallerAddress,
999 IN MEMORY_PROFILE_ACTION Action,
1000 IN EFI_MEMORY_TYPE MemoryType,
1001 IN UINTN Size,
1002 IN VOID *Buffer,
1003 IN CHAR8 *ActionString OPTIONAL
1004 )
1005 {
1006 EFI_STATUS Status;
1007 MEMORY_PROFILE_CONTEXT *Context;
1008 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1009 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1010 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1011 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1012 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1013 UINTN ProfileMemoryIndex;
1014 MEMORY_PROFILE_ACTION BasicAction;
1015 UINTN ActionStringSize;
1016 UINTN ActionStringOccupiedSize;
1017
1018 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1019
1020 ContextData = GetMemoryProfileContext ();
1021 if (ContextData == NULL) {
1022 return EFI_UNSUPPORTED;
1023 }
1024
1025 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
1026 if (DriverInfoData == NULL) {
1027 return EFI_UNSUPPORTED;
1028 }
1029
1030 ActionStringSize = 0;
1031 ActionStringOccupiedSize = 0;
1032 if (ActionString != NULL) {
1033 ActionStringSize = AsciiStrSize (ActionString);
1034 ActionStringOccupiedSize = GET_OCCUPIED_SIZE (ActionStringSize, sizeof (UINT64));
1035 }
1036
1037 //
1038 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
1039 //
1040 AllocInfoData = NULL;
1041 Status = CoreInternalAllocatePool (
1042 EfiBootServicesData,
1043 sizeof (*AllocInfoData) + ActionStringSize,
1044 (VOID **) &AllocInfoData
1045 );
1046 if (EFI_ERROR (Status)) {
1047 return EFI_OUT_OF_RESOURCES;
1048 }
1049 ASSERT (AllocInfoData != NULL);
1050
1051 //
1052 // Only update SequenceCount if and only if it is basic action.
1053 //
1054 if (Action == BasicAction) {
1055 ContextData->Context.SequenceCount ++;
1056 }
1057
1058 AllocInfo = &AllocInfoData->AllocInfo;
1059 AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
1060 AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
1061 AllocInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_ALLOC_INFO) + ActionStringOccupiedSize);
1062 AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION;
1063 AllocInfo->CallerAddress = CallerAddress;
1064 AllocInfo->SequenceId = ContextData->Context.SequenceCount;
1065 AllocInfo->Action = Action;
1066 AllocInfo->MemoryType = MemoryType;
1067 AllocInfo->Buffer = (PHYSICAL_ADDRESS) (UINTN) Buffer;
1068 AllocInfo->Size = Size;
1069 if (ActionString != NULL) {
1070 AllocInfo->ActionStringOffset = (UINT16) sizeof (MEMORY_PROFILE_ALLOC_INFO);
1071 AllocInfoData->ActionString = (CHAR8 *) (AllocInfoData + 1);
1072 CopyMem (AllocInfoData->ActionString, ActionString, ActionStringSize);
1073 } else {
1074 AllocInfo->ActionStringOffset = 0;
1075 AllocInfoData->ActionString = NULL;
1076 }
1077
1078 InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);
1079
1080 Context = &ContextData->Context;
1081 DriverInfo = &DriverInfoData->DriverInfo;
1082 DriverInfo->AllocRecordCount ++;
1083
1084 //
1085 // Update summary if and only if it is basic action.
1086 //
1087 if (Action == BasicAction) {
1088 ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);
1089
1090 DriverInfo->CurrentUsage += Size;
1091 if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {
1092 DriverInfo->PeakUsage = DriverInfo->CurrentUsage;
1093 }
1094 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;
1095 if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {
1096 DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];
1097 }
1098
1099 Context->CurrentTotalUsage += Size;
1100 if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {
1101 Context->PeakTotalUsage = Context->CurrentTotalUsage;
1102 }
1103 Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;
1104 if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {
1105 Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];
1106 }
1107 }
1108
1109 return EFI_SUCCESS;
1110 }
1111
1112 /**
1113 Get memory profile alloc info from memory profile.
1114
1115 @param DriverInfoData Driver info.
1116 @param BasicAction This Free basic action.
1117 @param Size Buffer size.
1118 @param Buffer Buffer address.
1119
1120 @return Pointer to memory profile alloc info.
1121
1122 **/
1123 MEMORY_PROFILE_ALLOC_INFO_DATA *
1124 GetMemoryProfileAllocInfoFromAddress (
1125 IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData,
1126 IN MEMORY_PROFILE_ACTION BasicAction,
1127 IN UINTN Size,
1128 IN VOID *Buffer
1129 )
1130 {
1131 LIST_ENTRY *AllocInfoList;
1132 LIST_ENTRY *AllocLink;
1133 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1134 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1135
1136 AllocInfoList = DriverInfoData->AllocInfoList;
1137
1138 for (AllocLink = AllocInfoList->ForwardLink;
1139 AllocLink != AllocInfoList;
1140 AllocLink = AllocLink->ForwardLink) {
1141 AllocInfoData = CR (
1142 AllocLink,
1143 MEMORY_PROFILE_ALLOC_INFO_DATA,
1144 Link,
1145 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1146 );
1147 AllocInfo = &AllocInfoData->AllocInfo;
1148 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK) != BasicAction) {
1149 continue;
1150 }
1151 switch (BasicAction) {
1152 case MemoryProfileActionAllocatePages:
1153 if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&
1154 ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) {
1155 return AllocInfoData;
1156 }
1157 break;
1158 case MemoryProfileActionAllocatePool:
1159 if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {
1160 return AllocInfoData;
1161 }
1162 break;
1163 default:
1164 ASSERT (FALSE);
1165 break;
1166 }
1167 }
1168
1169 return NULL;
1170 }
1171
1172 /**
1173 Update memory profile Free information.
1174
1175 @param CallerAddress Address of caller who call Free.
1176 @param Action This Free action.
1177 @param Size Buffer size.
1178 @param Buffer Buffer address.
1179
1180 @return EFI_SUCCESS Memory profile is updated.
1181 @return EFI_UNSUPPORTED Memory profile is unsupported.
1182 @return EFI_NOT_FOUND No matched allocate info found for free action.
1183
1184 **/
1185 EFI_STATUS
1186 CoreUpdateProfileFree (
1187 IN PHYSICAL_ADDRESS CallerAddress,
1188 IN MEMORY_PROFILE_ACTION Action,
1189 IN UINTN Size,
1190 IN VOID *Buffer
1191 )
1192 {
1193 MEMORY_PROFILE_CONTEXT *Context;
1194 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1195 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1196 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1197 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1198 LIST_ENTRY *DriverLink;
1199 LIST_ENTRY *DriverInfoList;
1200 MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData;
1201 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1202 UINTN ProfileMemoryIndex;
1203 MEMORY_PROFILE_ACTION BasicAction;
1204 BOOLEAN Found;
1205
1206 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1207
1208 ContextData = GetMemoryProfileContext ();
1209 if (ContextData == NULL) {
1210 return EFI_UNSUPPORTED;
1211 }
1212
1213 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
1214
1215 //
1216 // Do not return if DriverInfoData == NULL here,
1217 // because driver A might free memory allocated by driver B.
1218 //
1219
1220 //
1221 // Need use do-while loop to find all possible records,
1222 // because one address might be recorded multiple times.
1223 //
1224 Found = FALSE;
1225 AllocInfoData = NULL;
1226 do {
1227 if (DriverInfoData != NULL) {
1228 switch (BasicAction) {
1229 case MemoryProfileActionFreePages:
1230 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
1231 break;
1232 case MemoryProfileActionFreePool:
1233 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
1234 break;
1235 default:
1236 ASSERT (FALSE);
1237 AllocInfoData = NULL;
1238 break;
1239 }
1240 }
1241 if (AllocInfoData == NULL) {
1242 //
1243 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1244 //
1245 DriverInfoList = ContextData->DriverInfoList;
1246
1247 for (DriverLink = DriverInfoList->ForwardLink;
1248 DriverLink != DriverInfoList;
1249 DriverLink = DriverLink->ForwardLink) {
1250 ThisDriverInfoData = CR (
1251 DriverLink,
1252 MEMORY_PROFILE_DRIVER_INFO_DATA,
1253 Link,
1254 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1255 );
1256 switch (BasicAction) {
1257 case MemoryProfileActionFreePages:
1258 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
1259 break;
1260 case MemoryProfileActionFreePool:
1261 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
1262 break;
1263 default:
1264 ASSERT (FALSE);
1265 AllocInfoData = NULL;
1266 break;
1267 }
1268 if (AllocInfoData != NULL) {
1269 DriverInfoData = ThisDriverInfoData;
1270 break;
1271 }
1272 }
1273
1274 if (AllocInfoData == NULL) {
1275 //
1276 // If (!Found), no matched allocate info is found for this free action.
1277 // It is because the specified memory type allocate actions have been filtered by
1278 // CoreNeedRecordProfile(), but free actions may have no memory type information,
1279 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1280 // filtered here.
1281 //
1282 // If (Found), it is normal exit path.
1283 return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
1284 }
1285 }
1286
1287 ASSERT (DriverInfoData != NULL);
1288 ASSERT (AllocInfoData != NULL);
1289
1290 Found = TRUE;
1291
1292 Context = &ContextData->Context;
1293 DriverInfo = &DriverInfoData->DriverInfo;
1294 AllocInfo = &AllocInfoData->AllocInfo;
1295
1296 DriverInfo->AllocRecordCount --;
1297 //
1298 // Update summary if and only if it is basic action.
1299 //
1300 if (AllocInfo->Action == (AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK)) {
1301 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
1302
1303 Context->CurrentTotalUsage -= AllocInfo->Size;
1304 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1305
1306 DriverInfo->CurrentUsage -= AllocInfo->Size;
1307 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1308 }
1309
1310 RemoveEntryList (&AllocInfoData->Link);
1311
1312 if (BasicAction == MemoryProfileActionFreePages) {
1313 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {
1314 CoreUpdateProfileAllocate (
1315 AllocInfo->CallerAddress,
1316 AllocInfo->Action,
1317 AllocInfo->MemoryType,
1318 (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),
1319 (VOID *) (UINTN) AllocInfo->Buffer,
1320 AllocInfoData->ActionString
1321 );
1322 }
1323 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {
1324 CoreUpdateProfileAllocate (
1325 AllocInfo->CallerAddress,
1326 AllocInfo->Action,
1327 AllocInfo->MemoryType,
1328 (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),
1329 (VOID *) ((UINTN) Buffer + Size),
1330 AllocInfoData->ActionString
1331 );
1332 }
1333 }
1334
1335 //
1336 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
1337 //
1338 CoreInternalFreePool (AllocInfoData, NULL);
1339 } while (TRUE);
1340 }
1341
1342 /**
1343 Update memory profile information.
1344
1345 @param CallerAddress Address of caller who call Allocate or Free.
1346 @param Action This Allocate or Free action.
1347 @param MemoryType Memory type.
1348 EfiMaxMemoryType means the MemoryType is unknown.
1349 @param Size Buffer size.
1350 @param Buffer Buffer address.
1351 @param ActionString String for memory profile action.
1352 Only needed for user defined allocate action.
1353
1354 @return EFI_SUCCESS Memory profile is updated.
1355 @return EFI_UNSUPPORTED Memory profile is unsupported,
1356 or memory profile for the image is not required,
1357 or memory profile for the memory type is not required.
1358 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1359 @return EFI_ABORTED Memory profile recording is not enabled.
1360 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1361 @return EFI_NOT_FOUND No matched allocate info found for free action.
1362
1363 **/
1364 EFI_STATUS
1365 EFIAPI
1366 CoreUpdateProfile (
1367 IN PHYSICAL_ADDRESS CallerAddress,
1368 IN MEMORY_PROFILE_ACTION Action,
1369 IN EFI_MEMORY_TYPE MemoryType,
1370 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool
1371 IN VOID *Buffer,
1372 IN CHAR8 *ActionString OPTIONAL
1373 )
1374 {
1375 EFI_STATUS Status;
1376 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1377 MEMORY_PROFILE_ACTION BasicAction;
1378
1379 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
1380 return EFI_UNSUPPORTED;
1381 }
1382
1383 if (mMemoryProfileGettingStatus) {
1384 return EFI_ACCESS_DENIED;
1385 }
1386
1387 if (!mMemoryProfileRecordingEnable) {
1388 return EFI_ABORTED;
1389 }
1390
1391 //
1392 // Get the basic action to know how to process the record
1393 //
1394 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1395
1396 //
1397 // EfiMaxMemoryType means the MemoryType is unknown.
1398 //
1399 if (MemoryType != EfiMaxMemoryType) {
1400 //
1401 // Only record limited MemoryType.
1402 //
1403 if (!CoreNeedRecordProfile (MemoryType)) {
1404 return EFI_UNSUPPORTED;
1405 }
1406 }
1407
1408 ContextData = GetMemoryProfileContext ();
1409 if (ContextData == NULL) {
1410 return EFI_UNSUPPORTED;
1411 }
1412
1413 CoreAcquireMemoryProfileLock ();
1414 switch (BasicAction) {
1415 case MemoryProfileActionAllocatePages:
1416 Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1417 break;
1418 case MemoryProfileActionFreePages:
1419 Status = CoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
1420 break;
1421 case MemoryProfileActionAllocatePool:
1422 Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1423 break;
1424 case MemoryProfileActionFreePool:
1425 Status = CoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
1426 break;
1427 default:
1428 ASSERT (FALSE);
1429 Status = EFI_UNSUPPORTED;
1430 break;
1431 }
1432 CoreReleaseMemoryProfileLock ();
1433
1434 return Status;
1435 }
1436
1437 ////////////////////
1438
1439 /**
1440 Get memory profile data size.
1441
1442 @return Memory profile data size.
1443
1444 **/
1445 UINTN
1446 MemoryProfileGetDataSize (
1447 VOID
1448 )
1449 {
1450 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1451 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1452 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1453 LIST_ENTRY *DriverInfoList;
1454 LIST_ENTRY *DriverLink;
1455 LIST_ENTRY *AllocInfoList;
1456 LIST_ENTRY *AllocLink;
1457 UINTN TotalSize;
1458
1459
1460 ContextData = GetMemoryProfileContext ();
1461 if (ContextData == NULL) {
1462 return 0;
1463 }
1464
1465 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
1466
1467 DriverInfoList = ContextData->DriverInfoList;
1468 for (DriverLink = DriverInfoList->ForwardLink;
1469 DriverLink != DriverInfoList;
1470 DriverLink = DriverLink->ForwardLink) {
1471 DriverInfoData = CR (
1472 DriverLink,
1473 MEMORY_PROFILE_DRIVER_INFO_DATA,
1474 Link,
1475 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1476 );
1477 TotalSize += DriverInfoData->DriverInfo.Header.Length;
1478
1479 AllocInfoList = DriverInfoData->AllocInfoList;
1480 for (AllocLink = AllocInfoList->ForwardLink;
1481 AllocLink != AllocInfoList;
1482 AllocLink = AllocLink->ForwardLink) {
1483 AllocInfoData = CR (
1484 AllocLink,
1485 MEMORY_PROFILE_ALLOC_INFO_DATA,
1486 Link,
1487 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1488 );
1489 TotalSize += AllocInfoData->AllocInfo.Header.Length;
1490 }
1491 }
1492
1493 return TotalSize;
1494 }
1495
1496 /**
1497 Copy memory profile data.
1498
1499 @param ProfileBuffer The buffer to hold memory profile data.
1500
1501 **/
1502 VOID
1503 MemoryProfileCopyData (
1504 IN VOID *ProfileBuffer
1505 )
1506 {
1507 MEMORY_PROFILE_CONTEXT *Context;
1508 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1509 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1510 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1511 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1512 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1513 LIST_ENTRY *DriverInfoList;
1514 LIST_ENTRY *DriverLink;
1515 LIST_ENTRY *AllocInfoList;
1516 LIST_ENTRY *AllocLink;
1517 UINTN PdbSize;
1518 UINTN ActionStringSize;
1519
1520 ContextData = GetMemoryProfileContext ();
1521 if (ContextData == NULL) {
1522 return ;
1523 }
1524
1525 Context = ProfileBuffer;
1526 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
1527 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);
1528
1529 DriverInfoList = ContextData->DriverInfoList;
1530 for (DriverLink = DriverInfoList->ForwardLink;
1531 DriverLink != DriverInfoList;
1532 DriverLink = DriverLink->ForwardLink) {
1533 DriverInfoData = CR (
1534 DriverLink,
1535 MEMORY_PROFILE_DRIVER_INFO_DATA,
1536 Link,
1537 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1538 );
1539 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));
1540 if (DriverInfo->PdbStringOffset != 0) {
1541 PdbSize = AsciiStrSize (DriverInfoData->PdbString);
1542 CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize);
1543 }
1544 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
1545
1546 AllocInfoList = DriverInfoData->AllocInfoList;
1547 for (AllocLink = AllocInfoList->ForwardLink;
1548 AllocLink != AllocInfoList;
1549 AllocLink = AllocLink->ForwardLink) {
1550 AllocInfoData = CR (
1551 AllocLink,
1552 MEMORY_PROFILE_ALLOC_INFO_DATA,
1553 Link,
1554 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1555 );
1556 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));
1557 if (AllocInfo->ActionStringOffset != 0) {
1558 ActionStringSize = AsciiStrSize (AllocInfoData->ActionString);
1559 CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize);
1560 }
1561 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
1562 }
1563
1564 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
1565 }
1566 }
1567
1568 /**
1569 Get memory profile data.
1570
1571 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1572 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1573 On return, points to the size of the data returned in ProfileBuffer.
1574 @param[out] ProfileBuffer Profile buffer.
1575
1576 @return EFI_SUCCESS Get the memory profile data successfully.
1577 @return EFI_UNSUPPORTED Memory profile is unsupported.
1578 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1579 ProfileSize is updated with the size required.
1580
1581 **/
1582 EFI_STATUS
1583 EFIAPI
1584 ProfileProtocolGetData (
1585 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1586 IN OUT UINT64 *ProfileSize,
1587 OUT VOID *ProfileBuffer
1588 )
1589 {
1590 UINTN Size;
1591 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1592 BOOLEAN MemoryProfileGettingStatus;
1593
1594 ContextData = GetMemoryProfileContext ();
1595 if (ContextData == NULL) {
1596 return EFI_UNSUPPORTED;
1597 }
1598
1599 MemoryProfileGettingStatus = mMemoryProfileGettingStatus;
1600 mMemoryProfileGettingStatus = TRUE;
1601
1602 Size = MemoryProfileGetDataSize ();
1603
1604 if (*ProfileSize < Size) {
1605 *ProfileSize = Size;
1606 mMemoryProfileGettingStatus = MemoryProfileGettingStatus;
1607 return EFI_BUFFER_TOO_SMALL;
1608 }
1609
1610 *ProfileSize = Size;
1611 MemoryProfileCopyData (ProfileBuffer);
1612
1613 mMemoryProfileGettingStatus = MemoryProfileGettingStatus;
1614 return EFI_SUCCESS;
1615 }
1616
1617 /**
1618 Register image to memory profile.
1619
1620 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1621 @param[in] FilePath File path of the image.
1622 @param[in] ImageBase Image base address.
1623 @param[in] ImageSize Image size.
1624 @param[in] FileType File type of the image.
1625
1626 @return EFI_SUCCESS Register successfully.
1627 @return EFI_UNSUPPORTED Memory profile is unsupported,
1628 or memory profile for the image is not required.
1629 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1630
1631 **/
1632 EFI_STATUS
1633 EFIAPI
1634 ProfileProtocolRegisterImage (
1635 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1636 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1637 IN PHYSICAL_ADDRESS ImageBase,
1638 IN UINT64 ImageSize,
1639 IN EFI_FV_FILETYPE FileType
1640 )
1641 {
1642 EFI_STATUS Status;
1643 LOADED_IMAGE_PRIVATE_DATA DriverEntry;
1644 VOID *EntryPointInImage;
1645
1646 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1647 DriverEntry.Info.FilePath = FilePath;
1648 DriverEntry.ImageContext.ImageAddress = ImageBase;
1649 DriverEntry.ImageContext.ImageSize = ImageSize;
1650 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
1651 ASSERT_EFI_ERROR (Status);
1652 DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1653 DriverEntry.ImageContext.ImageType = InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase);
1654
1655 return RegisterMemoryProfileImage (&DriverEntry, FileType);
1656 }
1657
1658 /**
1659 Unregister image from memory profile.
1660
1661 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1662 @param[in] FilePath File path of the image.
1663 @param[in] ImageBase Image base address.
1664 @param[in] ImageSize Image size.
1665
1666 @return EFI_SUCCESS Unregister successfully.
1667 @return EFI_UNSUPPORTED Memory profile is unsupported,
1668 or memory profile for the image is not required.
1669 @return EFI_NOT_FOUND The image is not found.
1670
1671 **/
1672 EFI_STATUS
1673 EFIAPI
1674 ProfileProtocolUnregisterImage (
1675 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1676 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1677 IN PHYSICAL_ADDRESS ImageBase,
1678 IN UINT64 ImageSize
1679 )
1680 {
1681 EFI_STATUS Status;
1682 LOADED_IMAGE_PRIVATE_DATA DriverEntry;
1683 VOID *EntryPointInImage;
1684
1685 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1686 DriverEntry.Info.FilePath = FilePath;
1687 DriverEntry.ImageContext.ImageAddress = ImageBase;
1688 DriverEntry.ImageContext.ImageSize = ImageSize;
1689 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
1690 ASSERT_EFI_ERROR (Status);
1691 DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1692
1693 return UnregisterMemoryProfileImage (&DriverEntry);
1694 }
1695
1696 /**
1697 Get memory profile recording state.
1698
1699 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1700 @param[out] RecordingState Recording state.
1701
1702 @return EFI_SUCCESS Memory profile recording state is returned.
1703 @return EFI_UNSUPPORTED Memory profile is unsupported.
1704 @return EFI_INVALID_PARAMETER RecordingState is NULL.
1705
1706 **/
1707 EFI_STATUS
1708 EFIAPI
1709 ProfileProtocolGetRecordingState (
1710 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1711 OUT BOOLEAN *RecordingState
1712 )
1713 {
1714 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1715
1716 ContextData = GetMemoryProfileContext ();
1717 if (ContextData == NULL) {
1718 return EFI_UNSUPPORTED;
1719 }
1720
1721 if (RecordingState == NULL) {
1722 return EFI_INVALID_PARAMETER;
1723 }
1724 *RecordingState = mMemoryProfileRecordingEnable;
1725 return EFI_SUCCESS;
1726 }
1727
1728 /**
1729 Set memory profile recording state.
1730
1731 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1732 @param[in] RecordingState Recording state.
1733
1734 @return EFI_SUCCESS Set memory profile recording state successfully.
1735 @return EFI_UNSUPPORTED Memory profile is unsupported.
1736
1737 **/
1738 EFI_STATUS
1739 EFIAPI
1740 ProfileProtocolSetRecordingState (
1741 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1742 IN BOOLEAN RecordingState
1743 )
1744 {
1745 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1746
1747 ContextData = GetMemoryProfileContext ();
1748 if (ContextData == NULL) {
1749 return EFI_UNSUPPORTED;
1750 }
1751
1752 mMemoryProfileRecordingEnable = RecordingState;
1753 return EFI_SUCCESS;
1754 }
1755
1756 /**
1757 Record memory profile of multilevel caller.
1758
1759 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1760 @param[in] CallerAddress Address of caller.
1761 @param[in] Action Memory profile action.
1762 @param[in] MemoryType Memory type.
1763 EfiMaxMemoryType means the MemoryType is unknown.
1764 @param[in] Buffer Buffer address.
1765 @param[in] Size Buffer size.
1766 @param[in] ActionString String for memory profile action.
1767 Only needed for user defined allocate action.
1768
1769 @return EFI_SUCCESS Memory profile is updated.
1770 @return EFI_UNSUPPORTED Memory profile is unsupported,
1771 or memory profile for the image is not required,
1772 or memory profile for the memory type is not required.
1773 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1774 @return EFI_ABORTED Memory profile recording is not enabled.
1775 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1776 @return EFI_NOT_FOUND No matched allocate info found for free action.
1777
1778 **/
1779 EFI_STATUS
1780 EFIAPI
1781 ProfileProtocolRecord (
1782 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1783 IN PHYSICAL_ADDRESS CallerAddress,
1784 IN MEMORY_PROFILE_ACTION Action,
1785 IN EFI_MEMORY_TYPE MemoryType,
1786 IN VOID *Buffer,
1787 IN UINTN Size,
1788 IN CHAR8 *ActionString OPTIONAL
1789 )
1790 {
1791 return CoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1792 }
1793
1794 ////////////////////