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