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