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