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