]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c
MdeModulePkg MemoryProfile: Add ASSERTs to make sure pointers are not NULL
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / MemoryProfileRecord.c
1 /** @file
2 Support routines for UEFI memory 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 "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 EFI_LOCK mMemoryProfileLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
67 BOOLEAN mMemoryProfileGettingStatus = FALSE;
68 BOOLEAN mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
69 EFI_DEVICE_PATH_PROTOCOL *mMemoryProfileDriverPath;
70 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 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
446 ZeroMem (DriverInfoData, sizeof (*DriverInfoData));
447
448 DriverInfo = &DriverInfoData->DriverInfo;
449 DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
450 DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
451 DriverInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_DRIVER_INFO) + PdbOccupiedSize);
452 DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;
453 if (FileName != NULL) {
454 CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));
455 }
456 DriverInfo->ImageBase = ImageBase;
457 DriverInfo->ImageSize = ImageSize;
458 DriverInfo->EntryPoint = EntryPoint;
459 DriverInfo->ImageSubsystem = ImageSubsystem;
460 if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {
461 //
462 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
463 // So patch ImageBuffer here to align the EntryPoint.
464 //
465 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
466 ASSERT_EFI_ERROR (Status);
467 DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
468 }
469 DriverInfo->FileType = FileType;
470 DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1);
471 InitializeListHead (DriverInfoData->AllocInfoList);
472 DriverInfo->CurrentUsage = 0;
473 DriverInfo->PeakUsage = 0;
474 DriverInfo->AllocRecordCount = 0;
475 if (PdbSize != 0) {
476 DriverInfo->PdbStringOffset = (UINT16) sizeof (MEMORY_PROFILE_DRIVER_INFO);
477 DriverInfoData->PdbString = (CHAR8 *) (DriverInfoData->AllocInfoList + 1);
478 CopyMem (DriverInfoData->PdbString, PdbString, PdbSize);
479 } else {
480 DriverInfo->PdbStringOffset = 0;
481 DriverInfoData->PdbString = NULL;
482 }
483
484 InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);
485 ContextData->Context.ImageCount ++;
486 ContextData->Context.TotalImageSize += DriverInfo->ImageSize;
487
488 return DriverInfoData;
489 }
490
491 /**
492 Return if record for this driver is needed..
493
494 @param DriverFilePath Driver file path.
495
496 @retval TRUE Record for this driver is needed.
497 @retval FALSE Record for this driver is not needed.
498
499 **/
500 BOOLEAN
501 NeedRecordThisDriver (
502 IN EFI_DEVICE_PATH_PROTOCOL *DriverFilePath
503 )
504 {
505 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
506 EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance;
507 UINTN DevicePathSize;
508 UINTN FilePathSize;
509
510 if (!IsDevicePathValid (mMemoryProfileDriverPath, mMemoryProfileDriverPathSize)) {
511 //
512 // Invalid Device Path means record all.
513 //
514 return TRUE;
515 }
516
517 //
518 // Record FilePath without END node.
519 //
520 FilePathSize = GetDevicePathSize (DriverFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
521
522 DevicePathInstance = mMemoryProfileDriverPath;
523 do {
524 //
525 // Find END node (it might be END_ENTIRE or END_INSTANCE).
526 //
527 TmpDevicePath = DevicePathInstance;
528 while (!IsDevicePathEndType (TmpDevicePath)) {
529 TmpDevicePath = NextDevicePathNode (TmpDevicePath);
530 }
531
532 //
533 // Do not compare END node.
534 //
535 DevicePathSize = (UINTN)TmpDevicePath - (UINTN)DevicePathInstance;
536 if ((FilePathSize == DevicePathSize) &&
537 (CompareMem (DriverFilePath, DevicePathInstance, DevicePathSize) == 0)) {
538 return TRUE;
539 }
540
541 //
542 // Get next instance.
543 //
544 DevicePathInstance = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)DevicePathInstance + DevicePathSize + DevicePathNodeLength(TmpDevicePath));
545 } while (DevicePathSubType (TmpDevicePath) != END_ENTIRE_DEVICE_PATH_SUBTYPE);
546
547 return FALSE;
548 }
549
550 /**
551 Register DXE Core to memory profile.
552
553 @param HobStart The start address of the HOB.
554 @param ContextData Memory profile context.
555
556 @retval TRUE Register success.
557 @retval FALSE Register fail.
558
559 **/
560 BOOLEAN
561 RegisterDxeCore (
562 IN VOID *HobStart,
563 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData
564 )
565 {
566 EFI_PEI_HOB_POINTERS DxeCoreHob;
567 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
568 PHYSICAL_ADDRESS ImageBase;
569 UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)];
570 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
571
572 ASSERT (ContextData != NULL);
573
574 //
575 // Searching for image hob
576 //
577 DxeCoreHob.Raw = HobStart;
578 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {
579 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
580 //
581 // Find Dxe Core HOB
582 //
583 break;
584 }
585 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
586 }
587 ASSERT (DxeCoreHob.Raw != NULL);
588
589 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer;
590 EfiInitializeFwVolDevicepathNode (FilePath, &DxeCoreHob.MemoryAllocationModule->ModuleName);
591 SetDevicePathEndNode (FilePath + 1);
592
593 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) {
594 return FALSE;
595 }
596
597 ImageBase = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
598 DriverInfoData = BuildDriverInfo (
599 ContextData,
600 &DxeCoreHob.MemoryAllocationModule->ModuleName,
601 ImageBase,
602 DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength,
603 DxeCoreHob.MemoryAllocationModule->EntryPoint,
604 InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase),
605 EFI_FV_FILETYPE_DXE_CORE
606 );
607 if (DriverInfoData == NULL) {
608 return FALSE;
609 }
610
611 return TRUE;
612 }
613
614 /**
615 Initialize memory profile.
616
617 @param HobStart The start address of the HOB.
618
619 **/
620 VOID
621 MemoryProfileInit (
622 IN VOID *HobStart
623 )
624 {
625 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
626
627 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
628 return;
629 }
630
631 ContextData = GetMemoryProfileContext ();
632 if (ContextData != NULL) {
633 return;
634 }
635
636 mMemoryProfileGettingStatus = FALSE;
637 if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) {
638 mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
639 } else {
640 mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE;
641 }
642 mMemoryProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath);
643 mMemoryProfileDriverPath = AllocateCopyPool (mMemoryProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath));
644 mMemoryProfileContextPtr = &mMemoryProfileContext;
645
646 RegisterDxeCore (HobStart, &mMemoryProfileContext);
647
648 DEBUG ((EFI_D_INFO, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext));
649 }
650
651 /**
652 Install memory profile protocol.
653
654 **/
655 VOID
656 MemoryProfileInstallProtocol (
657 VOID
658 )
659 {
660 EFI_HANDLE Handle;
661 EFI_STATUS Status;
662
663 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
664 return;
665 }
666
667 Handle = NULL;
668 Status = CoreInstallMultipleProtocolInterfaces (
669 &Handle,
670 &gEdkiiMemoryProfileGuid,
671 &mProfileProtocol,
672 NULL
673 );
674 ASSERT_EFI_ERROR (Status);
675 }
676
677 /**
678 Get the GUID file name from the file path.
679
680 @param FilePath File path.
681
682 @return The GUID file name from the file path.
683
684 **/
685 EFI_GUID *
686 GetFileNameFromFilePath (
687 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
688 )
689 {
690 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *ThisFilePath;
691 EFI_GUID *FileName;
692
693 FileName = NULL;
694 if (FilePath != NULL) {
695 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePath;
696 while (!IsDevicePathEnd (ThisFilePath)) {
697 FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath);
698 if (FileName != NULL) {
699 break;
700 }
701 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) NextDevicePathNode (ThisFilePath);
702 }
703 }
704
705 return FileName;
706 }
707
708 /**
709 Register image to memory profile.
710
711 @param DriverEntry Image info.
712 @param FileType Image file type.
713
714 @return EFI_SUCCESS Register successfully.
715 @return EFI_UNSUPPORTED Memory profile is unsupported,
716 or memory profile for the image is not required.
717 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
718
719 **/
720 EFI_STATUS
721 RegisterMemoryProfileImage (
722 IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry,
723 IN EFI_FV_FILETYPE FileType
724 )
725 {
726 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
727 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
728
729 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
730 return EFI_UNSUPPORTED;
731 }
732
733 if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) {
734 return EFI_UNSUPPORTED;
735 }
736
737 ContextData = GetMemoryProfileContext ();
738 if (ContextData == NULL) {
739 return EFI_UNSUPPORTED;
740 }
741
742 DriverInfoData = BuildDriverInfo (
743 ContextData,
744 GetFileNameFromFilePath (DriverEntry->Info.FilePath),
745 DriverEntry->ImageContext.ImageAddress,
746 DriverEntry->ImageContext.ImageSize,
747 DriverEntry->ImageContext.EntryPoint,
748 DriverEntry->ImageContext.ImageType,
749 FileType
750 );
751 if (DriverInfoData == NULL) {
752 return EFI_OUT_OF_RESOURCES;
753 }
754
755 return EFI_SUCCESS;
756 }
757
758 /**
759 Search image from memory profile.
760
761 @param ContextData Memory profile context.
762 @param FileName Image file name.
763 @param Address Image Address.
764
765 @return Pointer to memory profile driver info.
766
767 **/
768 MEMORY_PROFILE_DRIVER_INFO_DATA *
769 GetMemoryProfileDriverInfoByFileNameAndAddress (
770 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
771 IN EFI_GUID *FileName,
772 IN PHYSICAL_ADDRESS Address
773 )
774 {
775 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
776 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
777 LIST_ENTRY *DriverLink;
778 LIST_ENTRY *DriverInfoList;
779
780 DriverInfoList = ContextData->DriverInfoList;
781
782 for (DriverLink = DriverInfoList->ForwardLink;
783 DriverLink != DriverInfoList;
784 DriverLink = DriverLink->ForwardLink) {
785 DriverInfoData = CR (
786 DriverLink,
787 MEMORY_PROFILE_DRIVER_INFO_DATA,
788 Link,
789 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
790 );
791 DriverInfo = &DriverInfoData->DriverInfo;
792 if ((CompareGuid (&DriverInfo->FileName, FileName)) &&
793 (Address >= DriverInfo->ImageBase) &&
794 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {
795 return DriverInfoData;
796 }
797 }
798
799 return NULL;
800 }
801
802 /**
803 Search image from memory profile.
804 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize).
805
806 @param ContextData Memory profile context.
807 @param Address Image or Function address.
808
809 @return Pointer to memory profile driver info.
810
811 **/
812 MEMORY_PROFILE_DRIVER_INFO_DATA *
813 GetMemoryProfileDriverInfoFromAddress (
814 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,
815 IN PHYSICAL_ADDRESS Address
816 )
817 {
818 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
819 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
820 LIST_ENTRY *DriverLink;
821 LIST_ENTRY *DriverInfoList;
822
823 DriverInfoList = ContextData->DriverInfoList;
824
825 for (DriverLink = DriverInfoList->ForwardLink;
826 DriverLink != DriverInfoList;
827 DriverLink = DriverLink->ForwardLink) {
828 DriverInfoData = CR (
829 DriverLink,
830 MEMORY_PROFILE_DRIVER_INFO_DATA,
831 Link,
832 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
833 );
834 DriverInfo = &DriverInfoData->DriverInfo;
835 if ((Address >= DriverInfo->ImageBase) &&
836 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {
837 return DriverInfoData;
838 }
839 }
840
841 return NULL;
842 }
843
844 /**
845 Unregister image from memory profile.
846
847 @param DriverEntry Image info.
848
849 @return EFI_SUCCESS Unregister successfully.
850 @return EFI_UNSUPPORTED Memory profile is unsupported,
851 or memory profile for the image is not required.
852 @return EFI_NOT_FOUND The image is not found.
853
854 **/
855 EFI_STATUS
856 UnregisterMemoryProfileImage (
857 IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry
858 )
859 {
860 EFI_STATUS Status;
861 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
862 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
863 EFI_GUID *FileName;
864 PHYSICAL_ADDRESS ImageAddress;
865 VOID *EntryPointInImage;
866
867 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
868 return EFI_UNSUPPORTED;
869 }
870
871 if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) {
872 return EFI_UNSUPPORTED;
873 }
874
875 ContextData = GetMemoryProfileContext ();
876 if (ContextData == NULL) {
877 return EFI_UNSUPPORTED;
878 }
879
880 DriverInfoData = NULL;
881 FileName = GetFileNameFromFilePath (DriverEntry->Info.FilePath);
882 ImageAddress = DriverEntry->ImageContext.ImageAddress;
883 if ((DriverEntry->ImageContext.EntryPoint < ImageAddress) || (DriverEntry->ImageContext.EntryPoint >= (ImageAddress + DriverEntry->ImageContext.ImageSize))) {
884 //
885 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
886 // So patch ImageAddress here to align the EntryPoint.
887 //
888 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage);
889 ASSERT_EFI_ERROR (Status);
890 ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageContext.EntryPoint - (UINTN) EntryPointInImage;
891 }
892 if (FileName != NULL) {
893 DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);
894 }
895 if (DriverInfoData == NULL) {
896 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);
897 }
898 if (DriverInfoData == NULL) {
899 return EFI_NOT_FOUND;
900 }
901
902 ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;
903
904 // Keep the ImageBase for RVA calculation in Application.
905 //DriverInfoData->DriverInfo.ImageBase = 0;
906 DriverInfoData->DriverInfo.ImageSize = 0;
907
908 if (DriverInfoData->DriverInfo.PeakUsage == 0) {
909 ContextData->Context.ImageCount --;
910 RemoveEntryList (&DriverInfoData->Link);
911 //
912 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
913 //
914 CoreInternalFreePool (DriverInfoData, NULL);
915 }
916
917 return EFI_SUCCESS;
918 }
919
920 /**
921 Return if this memory type needs to be recorded into memory profile.
922 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), it checks bit (1 << MemoryType).
923 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.
924 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), it checks bit62 - 0x4000000000000000.
925
926 @param MemoryType Memory type.
927
928 @retval TRUE This memory type need to be recorded.
929 @retval FALSE This memory type need not to be recorded.
930
931 **/
932 BOOLEAN
933 CoreNeedRecordProfile (
934 IN EFI_MEMORY_TYPE MemoryType
935 )
936 {
937 UINT64 TestBit;
938
939 if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
940 TestBit = BIT63;
941 } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
942 TestBit = BIT62;
943 } else {
944 TestBit = LShiftU64 (1, MemoryType);
945 }
946
947 if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {
948 return TRUE;
949 } else {
950 return FALSE;
951 }
952 }
953
954 /**
955 Convert EFI memory type to profile memory index. The rule is:
956 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
957 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.
958 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType + 1.
959
960 @param MemoryType Memory type.
961
962 @return Profile memory index.
963
964 **/
965 UINTN
966 GetProfileMemoryIndex (
967 IN EFI_MEMORY_TYPE MemoryType
968 )
969 {
970 if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
971 return EfiMaxMemoryType;
972 } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
973 return EfiMaxMemoryType + 1;
974 } else {
975 return MemoryType;
976 }
977 }
978
979 /**
980 Update memory profile Allocate information.
981
982 @param CallerAddress Address of caller who call Allocate.
983 @param Action This Allocate action.
984 @param MemoryType Memory type.
985 @param Size Buffer size.
986 @param Buffer Buffer address.
987 @param ActionString String for memory profile action.
988
989 @return EFI_SUCCESS Memory profile is updated.
990 @return EFI_UNSUPPORTED Memory profile is unsupported,
991 or memory profile for the image is not required.
992 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
993
994 **/
995 EFI_STATUS
996 CoreUpdateProfileAllocate (
997 IN PHYSICAL_ADDRESS CallerAddress,
998 IN MEMORY_PROFILE_ACTION Action,
999 IN EFI_MEMORY_TYPE MemoryType,
1000 IN UINTN Size,
1001 IN VOID *Buffer,
1002 IN CHAR8 *ActionString OPTIONAL
1003 )
1004 {
1005 EFI_STATUS Status;
1006 MEMORY_PROFILE_CONTEXT *Context;
1007 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1008 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1009 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1010 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1011 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1012 UINTN ProfileMemoryIndex;
1013 MEMORY_PROFILE_ACTION BasicAction;
1014 UINTN ActionStringSize;
1015 UINTN ActionStringOccupiedSize;
1016
1017 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1018
1019 ContextData = GetMemoryProfileContext ();
1020 if (ContextData == NULL) {
1021 return EFI_UNSUPPORTED;
1022 }
1023
1024 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
1025 if (DriverInfoData == NULL) {
1026 return EFI_UNSUPPORTED;
1027 }
1028
1029 ActionStringSize = 0;
1030 ActionStringOccupiedSize = 0;
1031 if (ActionString != NULL) {
1032 ActionStringSize = AsciiStrSize (ActionString);
1033 ActionStringOccupiedSize = GET_OCCUPIED_SIZE (ActionStringSize, sizeof (UINT64));
1034 }
1035
1036 //
1037 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
1038 //
1039 AllocInfoData = NULL;
1040 Status = CoreInternalAllocatePool (
1041 EfiBootServicesData,
1042 sizeof (*AllocInfoData) + ActionStringSize,
1043 (VOID **) &AllocInfoData
1044 );
1045 if (EFI_ERROR (Status)) {
1046 return EFI_OUT_OF_RESOURCES;
1047 }
1048 ASSERT (AllocInfoData != NULL);
1049
1050 //
1051 // Only update SequenceCount if and only if it is basic action.
1052 //
1053 if (Action == BasicAction) {
1054 ContextData->Context.SequenceCount ++;
1055 }
1056
1057 AllocInfo = &AllocInfoData->AllocInfo;
1058 AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
1059 AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
1060 AllocInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_ALLOC_INFO) + ActionStringOccupiedSize);
1061 AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION;
1062 AllocInfo->CallerAddress = CallerAddress;
1063 AllocInfo->SequenceId = ContextData->Context.SequenceCount;
1064 AllocInfo->Action = Action;
1065 AllocInfo->MemoryType = MemoryType;
1066 AllocInfo->Buffer = (PHYSICAL_ADDRESS) (UINTN) Buffer;
1067 AllocInfo->Size = Size;
1068 if (ActionString != NULL) {
1069 AllocInfo->ActionStringOffset = (UINT16) sizeof (MEMORY_PROFILE_ALLOC_INFO);
1070 AllocInfoData->ActionString = (CHAR8 *) (AllocInfoData + 1);
1071 CopyMem (AllocInfoData->ActionString, ActionString, ActionStringSize);
1072 } else {
1073 AllocInfo->ActionStringOffset = 0;
1074 AllocInfoData->ActionString = NULL;
1075 }
1076
1077 InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);
1078
1079 Context = &ContextData->Context;
1080 DriverInfo = &DriverInfoData->DriverInfo;
1081 DriverInfo->AllocRecordCount ++;
1082
1083 //
1084 // Update summary if and only if it is basic action.
1085 //
1086 if (Action == BasicAction) {
1087 ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);
1088
1089 DriverInfo->CurrentUsage += Size;
1090 if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {
1091 DriverInfo->PeakUsage = DriverInfo->CurrentUsage;
1092 }
1093 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;
1094 if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {
1095 DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];
1096 }
1097
1098 Context->CurrentTotalUsage += Size;
1099 if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {
1100 Context->PeakTotalUsage = Context->CurrentTotalUsage;
1101 }
1102 Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;
1103 if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {
1104 Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];
1105 }
1106 }
1107
1108 return EFI_SUCCESS;
1109 }
1110
1111 /**
1112 Get memory profile alloc info from memory profile.
1113
1114 @param DriverInfoData Driver info.
1115 @param BasicAction This Free basic action.
1116 @param Size Buffer size.
1117 @param Buffer Buffer address.
1118
1119 @return Pointer to memory profile alloc info.
1120
1121 **/
1122 MEMORY_PROFILE_ALLOC_INFO_DATA *
1123 GetMemoryProfileAllocInfoFromAddress (
1124 IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData,
1125 IN MEMORY_PROFILE_ACTION BasicAction,
1126 IN UINTN Size,
1127 IN VOID *Buffer
1128 )
1129 {
1130 LIST_ENTRY *AllocInfoList;
1131 LIST_ENTRY *AllocLink;
1132 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1133 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1134
1135 AllocInfoList = DriverInfoData->AllocInfoList;
1136
1137 for (AllocLink = AllocInfoList->ForwardLink;
1138 AllocLink != AllocInfoList;
1139 AllocLink = AllocLink->ForwardLink) {
1140 AllocInfoData = CR (
1141 AllocLink,
1142 MEMORY_PROFILE_ALLOC_INFO_DATA,
1143 Link,
1144 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1145 );
1146 AllocInfo = &AllocInfoData->AllocInfo;
1147 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK) != BasicAction) {
1148 continue;
1149 }
1150 switch (BasicAction) {
1151 case MemoryProfileActionAllocatePages:
1152 if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&
1153 ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) {
1154 return AllocInfoData;
1155 }
1156 break;
1157 case MemoryProfileActionAllocatePool:
1158 if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {
1159 return AllocInfoData;
1160 }
1161 break;
1162 default:
1163 ASSERT (FALSE);
1164 break;
1165 }
1166 }
1167
1168 return NULL;
1169 }
1170
1171 /**
1172 Update memory profile Free information.
1173
1174 @param CallerAddress Address of caller who call Free.
1175 @param Action This Free action.
1176 @param Size Buffer size.
1177 @param Buffer Buffer address.
1178
1179 @return EFI_SUCCESS Memory profile is updated.
1180 @return EFI_UNSUPPORTED Memory profile is unsupported.
1181 @return EFI_NOT_FOUND No matched allocate info found for free action.
1182
1183 **/
1184 EFI_STATUS
1185 CoreUpdateProfileFree (
1186 IN PHYSICAL_ADDRESS CallerAddress,
1187 IN MEMORY_PROFILE_ACTION Action,
1188 IN UINTN Size,
1189 IN VOID *Buffer
1190 )
1191 {
1192 MEMORY_PROFILE_CONTEXT *Context;
1193 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1194 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1195 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1196 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1197 LIST_ENTRY *DriverLink;
1198 LIST_ENTRY *DriverInfoList;
1199 MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData;
1200 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1201 UINTN ProfileMemoryIndex;
1202 MEMORY_PROFILE_ACTION BasicAction;
1203 BOOLEAN Found;
1204
1205 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1206
1207 ContextData = GetMemoryProfileContext ();
1208 if (ContextData == NULL) {
1209 return EFI_UNSUPPORTED;
1210 }
1211
1212 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
1213
1214 //
1215 // Do not return if DriverInfoData == NULL here,
1216 // because driver A might free memory allocated by driver B.
1217 //
1218
1219 //
1220 // Need use do-while loop to find all possible records,
1221 // because one address might be recorded multiple times.
1222 //
1223 Found = FALSE;
1224 AllocInfoData = NULL;
1225 do {
1226 if (DriverInfoData != NULL) {
1227 switch (BasicAction) {
1228 case MemoryProfileActionFreePages:
1229 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
1230 break;
1231 case MemoryProfileActionFreePool:
1232 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
1233 break;
1234 default:
1235 ASSERT (FALSE);
1236 AllocInfoData = NULL;
1237 break;
1238 }
1239 }
1240 if (AllocInfoData == NULL) {
1241 //
1242 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1243 //
1244 DriverInfoList = ContextData->DriverInfoList;
1245
1246 for (DriverLink = DriverInfoList->ForwardLink;
1247 DriverLink != DriverInfoList;
1248 DriverLink = DriverLink->ForwardLink) {
1249 ThisDriverInfoData = CR (
1250 DriverLink,
1251 MEMORY_PROFILE_DRIVER_INFO_DATA,
1252 Link,
1253 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1254 );
1255 switch (BasicAction) {
1256 case MemoryProfileActionFreePages:
1257 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
1258 break;
1259 case MemoryProfileActionFreePool:
1260 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
1261 break;
1262 default:
1263 ASSERT (FALSE);
1264 AllocInfoData = NULL;
1265 break;
1266 }
1267 if (AllocInfoData != NULL) {
1268 DriverInfoData = ThisDriverInfoData;
1269 break;
1270 }
1271 }
1272
1273 if (AllocInfoData == NULL) {
1274 //
1275 // If (!Found), no matched allocate info is found for this free action.
1276 // It is because the specified memory type allocate actions have been filtered by
1277 // CoreNeedRecordProfile(), but free actions may have no memory type information,
1278 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1279 // filtered here.
1280 //
1281 // If (Found), it is normal exit path.
1282 return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
1283 }
1284 }
1285
1286 ASSERT (DriverInfoData != NULL);
1287 ASSERT (AllocInfoData != NULL);
1288
1289 Found = TRUE;
1290
1291 Context = &ContextData->Context;
1292 DriverInfo = &DriverInfoData->DriverInfo;
1293 AllocInfo = &AllocInfoData->AllocInfo;
1294
1295 DriverInfo->AllocRecordCount --;
1296 //
1297 // Update summary if and only if it is basic action.
1298 //
1299 if (AllocInfo->Action == (AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK)) {
1300 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
1301
1302 Context->CurrentTotalUsage -= AllocInfo->Size;
1303 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1304
1305 DriverInfo->CurrentUsage -= AllocInfo->Size;
1306 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
1307 }
1308
1309 RemoveEntryList (&AllocInfoData->Link);
1310
1311 if (BasicAction == MemoryProfileActionFreePages) {
1312 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {
1313 CoreUpdateProfileAllocate (
1314 AllocInfo->CallerAddress,
1315 AllocInfo->Action,
1316 AllocInfo->MemoryType,
1317 (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),
1318 (VOID *) (UINTN) AllocInfo->Buffer,
1319 AllocInfoData->ActionString
1320 );
1321 }
1322 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {
1323 CoreUpdateProfileAllocate (
1324 AllocInfo->CallerAddress,
1325 AllocInfo->Action,
1326 AllocInfo->MemoryType,
1327 (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),
1328 (VOID *) ((UINTN) Buffer + Size),
1329 AllocInfoData->ActionString
1330 );
1331 }
1332 }
1333
1334 //
1335 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
1336 //
1337 CoreInternalFreePool (AllocInfoData, NULL);
1338 } while (TRUE);
1339 }
1340
1341 /**
1342 Update memory profile information.
1343
1344 @param CallerAddress Address of caller who call Allocate or Free.
1345 @param Action This Allocate or Free action.
1346 @param MemoryType Memory type.
1347 EfiMaxMemoryType means the MemoryType is unknown.
1348 @param Size Buffer size.
1349 @param Buffer Buffer address.
1350 @param ActionString String for memory profile action.
1351 Only needed for user defined allocate action.
1352
1353 @return EFI_SUCCESS Memory profile is updated.
1354 @return EFI_UNSUPPORTED Memory profile is unsupported,
1355 or memory profile for the image is not required,
1356 or memory profile for the memory type is not required.
1357 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1358 @return EFI_ABORTED Memory profile recording is not enabled.
1359 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1360 @return EFI_NOT_FOUND No matched allocate info found for free action.
1361
1362 **/
1363 EFI_STATUS
1364 EFIAPI
1365 CoreUpdateProfile (
1366 IN PHYSICAL_ADDRESS CallerAddress,
1367 IN MEMORY_PROFILE_ACTION Action,
1368 IN EFI_MEMORY_TYPE MemoryType,
1369 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool
1370 IN VOID *Buffer,
1371 IN CHAR8 *ActionString OPTIONAL
1372 )
1373 {
1374 EFI_STATUS Status;
1375 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1376 MEMORY_PROFILE_ACTION BasicAction;
1377
1378 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
1379 return EFI_UNSUPPORTED;
1380 }
1381
1382 if (mMemoryProfileGettingStatus) {
1383 return EFI_ACCESS_DENIED;
1384 }
1385
1386 if (!mMemoryProfileRecordingEnable) {
1387 return EFI_ABORTED;
1388 }
1389
1390 //
1391 // Get the basic action to know how to process the record
1392 //
1393 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
1394
1395 //
1396 // EfiMaxMemoryType means the MemoryType is unknown.
1397 //
1398 if (MemoryType != EfiMaxMemoryType) {
1399 //
1400 // Only record limited MemoryType.
1401 //
1402 if (!CoreNeedRecordProfile (MemoryType)) {
1403 return EFI_UNSUPPORTED;
1404 }
1405 }
1406
1407 ContextData = GetMemoryProfileContext ();
1408 if (ContextData == NULL) {
1409 return EFI_UNSUPPORTED;
1410 }
1411
1412 CoreAcquireMemoryProfileLock ();
1413 switch (BasicAction) {
1414 case MemoryProfileActionAllocatePages:
1415 Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1416 break;
1417 case MemoryProfileActionFreePages:
1418 Status = CoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
1419 break;
1420 case MemoryProfileActionAllocatePool:
1421 Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1422 break;
1423 case MemoryProfileActionFreePool:
1424 Status = CoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
1425 break;
1426 default:
1427 ASSERT (FALSE);
1428 Status = EFI_UNSUPPORTED;
1429 break;
1430 }
1431 CoreReleaseMemoryProfileLock ();
1432
1433 return Status;
1434 }
1435
1436 ////////////////////
1437
1438 /**
1439 Get memory profile data size.
1440
1441 @return Memory profile data size.
1442
1443 **/
1444 UINTN
1445 MemoryProfileGetDataSize (
1446 VOID
1447 )
1448 {
1449 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1450 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1451 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1452 LIST_ENTRY *DriverInfoList;
1453 LIST_ENTRY *DriverLink;
1454 LIST_ENTRY *AllocInfoList;
1455 LIST_ENTRY *AllocLink;
1456 UINTN TotalSize;
1457
1458
1459 ContextData = GetMemoryProfileContext ();
1460 if (ContextData == NULL) {
1461 return 0;
1462 }
1463
1464 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
1465
1466 DriverInfoList = ContextData->DriverInfoList;
1467 for (DriverLink = DriverInfoList->ForwardLink;
1468 DriverLink != DriverInfoList;
1469 DriverLink = DriverLink->ForwardLink) {
1470 DriverInfoData = CR (
1471 DriverLink,
1472 MEMORY_PROFILE_DRIVER_INFO_DATA,
1473 Link,
1474 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1475 );
1476 TotalSize += DriverInfoData->DriverInfo.Header.Length;
1477
1478 AllocInfoList = DriverInfoData->AllocInfoList;
1479 for (AllocLink = AllocInfoList->ForwardLink;
1480 AllocLink != AllocInfoList;
1481 AllocLink = AllocLink->ForwardLink) {
1482 AllocInfoData = CR (
1483 AllocLink,
1484 MEMORY_PROFILE_ALLOC_INFO_DATA,
1485 Link,
1486 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1487 );
1488 TotalSize += AllocInfoData->AllocInfo.Header.Length;
1489 }
1490 }
1491
1492 return TotalSize;
1493 }
1494
1495 /**
1496 Copy memory profile data.
1497
1498 @param ProfileBuffer The buffer to hold memory profile data.
1499
1500 **/
1501 VOID
1502 MemoryProfileCopyData (
1503 IN VOID *ProfileBuffer
1504 )
1505 {
1506 MEMORY_PROFILE_CONTEXT *Context;
1507 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
1508 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
1509 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1510 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;
1511 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;
1512 LIST_ENTRY *DriverInfoList;
1513 LIST_ENTRY *DriverLink;
1514 LIST_ENTRY *AllocInfoList;
1515 LIST_ENTRY *AllocLink;
1516 UINTN PdbSize;
1517 UINTN ActionStringSize;
1518
1519 ContextData = GetMemoryProfileContext ();
1520 if (ContextData == NULL) {
1521 return ;
1522 }
1523
1524 Context = ProfileBuffer;
1525 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
1526 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);
1527
1528 DriverInfoList = ContextData->DriverInfoList;
1529 for (DriverLink = DriverInfoList->ForwardLink;
1530 DriverLink != DriverInfoList;
1531 DriverLink = DriverLink->ForwardLink) {
1532 DriverInfoData = CR (
1533 DriverLink,
1534 MEMORY_PROFILE_DRIVER_INFO_DATA,
1535 Link,
1536 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1537 );
1538 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));
1539 if (DriverInfo->PdbStringOffset != 0) {
1540 PdbSize = AsciiStrSize (DriverInfoData->PdbString);
1541 CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize);
1542 }
1543 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
1544
1545 AllocInfoList = DriverInfoData->AllocInfoList;
1546 for (AllocLink = AllocInfoList->ForwardLink;
1547 AllocLink != AllocInfoList;
1548 AllocLink = AllocLink->ForwardLink) {
1549 AllocInfoData = CR (
1550 AllocLink,
1551 MEMORY_PROFILE_ALLOC_INFO_DATA,
1552 Link,
1553 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1554 );
1555 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));
1556 if (AllocInfo->ActionStringOffset != 0) {
1557 ActionStringSize = AsciiStrSize (AllocInfoData->ActionString);
1558 CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize);
1559 }
1560 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
1561 }
1562
1563 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
1564 }
1565 }
1566
1567 /**
1568 Get memory profile data.
1569
1570 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1571 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1572 On return, points to the size of the data returned in ProfileBuffer.
1573 @param[out] ProfileBuffer Profile buffer.
1574
1575 @return EFI_SUCCESS Get the memory profile data successfully.
1576 @return EFI_UNSUPPORTED Memory profile is unsupported.
1577 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1578 ProfileSize is updated with the size required.
1579
1580 **/
1581 EFI_STATUS
1582 EFIAPI
1583 ProfileProtocolGetData (
1584 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1585 IN OUT UINT64 *ProfileSize,
1586 OUT VOID *ProfileBuffer
1587 )
1588 {
1589 UINTN Size;
1590 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1591 BOOLEAN MemoryProfileGettingStatus;
1592
1593 ContextData = GetMemoryProfileContext ();
1594 if (ContextData == NULL) {
1595 return EFI_UNSUPPORTED;
1596 }
1597
1598 MemoryProfileGettingStatus = mMemoryProfileGettingStatus;
1599 mMemoryProfileGettingStatus = TRUE;
1600
1601 Size = MemoryProfileGetDataSize ();
1602
1603 if (*ProfileSize < Size) {
1604 *ProfileSize = Size;
1605 mMemoryProfileGettingStatus = MemoryProfileGettingStatus;
1606 return EFI_BUFFER_TOO_SMALL;
1607 }
1608
1609 *ProfileSize = Size;
1610 MemoryProfileCopyData (ProfileBuffer);
1611
1612 mMemoryProfileGettingStatus = MemoryProfileGettingStatus;
1613 return EFI_SUCCESS;
1614 }
1615
1616 /**
1617 Register image to memory profile.
1618
1619 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1620 @param[in] FilePath File path of the image.
1621 @param[in] ImageBase Image base address.
1622 @param[in] ImageSize Image size.
1623 @param[in] FileType File type of the image.
1624
1625 @return EFI_SUCCESS Register successfully.
1626 @return EFI_UNSUPPORTED Memory profile is unsupported,
1627 or memory profile for the image is not required.
1628 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1629
1630 **/
1631 EFI_STATUS
1632 EFIAPI
1633 ProfileProtocolRegisterImage (
1634 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1635 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1636 IN PHYSICAL_ADDRESS ImageBase,
1637 IN UINT64 ImageSize,
1638 IN EFI_FV_FILETYPE FileType
1639 )
1640 {
1641 EFI_STATUS Status;
1642 LOADED_IMAGE_PRIVATE_DATA DriverEntry;
1643 VOID *EntryPointInImage;
1644
1645 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1646 DriverEntry.Info.FilePath = FilePath;
1647 DriverEntry.ImageContext.ImageAddress = ImageBase;
1648 DriverEntry.ImageContext.ImageSize = ImageSize;
1649 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
1650 ASSERT_EFI_ERROR (Status);
1651 DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1652 DriverEntry.ImageContext.ImageType = InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase);
1653
1654 return RegisterMemoryProfileImage (&DriverEntry, FileType);
1655 }
1656
1657 /**
1658 Unregister image from memory profile.
1659
1660 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1661 @param[in] FilePath File path of the image.
1662 @param[in] ImageBase Image base address.
1663 @param[in] ImageSize Image size.
1664
1665 @return EFI_SUCCESS Unregister successfully.
1666 @return EFI_UNSUPPORTED Memory profile is unsupported,
1667 or memory profile for the image is not required.
1668 @return EFI_NOT_FOUND The image is not found.
1669
1670 **/
1671 EFI_STATUS
1672 EFIAPI
1673 ProfileProtocolUnregisterImage (
1674 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1675 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
1676 IN PHYSICAL_ADDRESS ImageBase,
1677 IN UINT64 ImageSize
1678 )
1679 {
1680 EFI_STATUS Status;
1681 LOADED_IMAGE_PRIVATE_DATA DriverEntry;
1682 VOID *EntryPointInImage;
1683
1684 ZeroMem (&DriverEntry, sizeof (DriverEntry));
1685 DriverEntry.Info.FilePath = FilePath;
1686 DriverEntry.ImageContext.ImageAddress = ImageBase;
1687 DriverEntry.ImageContext.ImageSize = ImageSize;
1688 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
1689 ASSERT_EFI_ERROR (Status);
1690 DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
1691
1692 return UnregisterMemoryProfileImage (&DriverEntry);
1693 }
1694
1695 /**
1696 Get memory profile recording state.
1697
1698 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1699 @param[out] RecordingState Recording state.
1700
1701 @return EFI_SUCCESS Memory profile recording state is returned.
1702 @return EFI_UNSUPPORTED Memory profile is unsupported.
1703 @return EFI_INVALID_PARAMETER RecordingState is NULL.
1704
1705 **/
1706 EFI_STATUS
1707 EFIAPI
1708 ProfileProtocolGetRecordingState (
1709 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1710 OUT BOOLEAN *RecordingState
1711 )
1712 {
1713 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1714
1715 ContextData = GetMemoryProfileContext ();
1716 if (ContextData == NULL) {
1717 return EFI_UNSUPPORTED;
1718 }
1719
1720 if (RecordingState == NULL) {
1721 return EFI_INVALID_PARAMETER;
1722 }
1723 *RecordingState = mMemoryProfileRecordingEnable;
1724 return EFI_SUCCESS;
1725 }
1726
1727 /**
1728 Set memory profile recording state.
1729
1730 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1731 @param[in] RecordingState Recording state.
1732
1733 @return EFI_SUCCESS Set memory profile recording state successfully.
1734 @return EFI_UNSUPPORTED Memory profile is unsupported.
1735
1736 **/
1737 EFI_STATUS
1738 EFIAPI
1739 ProfileProtocolSetRecordingState (
1740 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1741 IN BOOLEAN RecordingState
1742 )
1743 {
1744 MEMORY_PROFILE_CONTEXT_DATA *ContextData;
1745
1746 ContextData = GetMemoryProfileContext ();
1747 if (ContextData == NULL) {
1748 return EFI_UNSUPPORTED;
1749 }
1750
1751 mMemoryProfileRecordingEnable = RecordingState;
1752 return EFI_SUCCESS;
1753 }
1754
1755 /**
1756 Record memory profile of multilevel caller.
1757
1758 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1759 @param[in] CallerAddress Address of caller.
1760 @param[in] Action Memory profile action.
1761 @param[in] MemoryType Memory type.
1762 EfiMaxMemoryType means the MemoryType is unknown.
1763 @param[in] Buffer Buffer address.
1764 @param[in] Size Buffer size.
1765 @param[in] ActionString String for memory profile action.
1766 Only needed for user defined allocate action.
1767
1768 @return EFI_SUCCESS Memory profile is updated.
1769 @return EFI_UNSUPPORTED Memory profile is unsupported,
1770 or memory profile for the image is not required,
1771 or memory profile for the memory type is not required.
1772 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1773 @return EFI_ABORTED Memory profile recording is not enabled.
1774 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1775 @return EFI_NOT_FOUND No matched allocate info found for free action.
1776
1777 **/
1778 EFI_STATUS
1779 EFIAPI
1780 ProfileProtocolRecord (
1781 IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
1782 IN PHYSICAL_ADDRESS CallerAddress,
1783 IN MEMORY_PROFILE_ACTION Action,
1784 IN EFI_MEMORY_TYPE MemoryType,
1785 IN VOID *Buffer,
1786 IN UINTN Size,
1787 IN CHAR8 *ActionString OPTIONAL
1788 )
1789 {
1790 return CoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
1791 }
1792
1793 ////////////////////