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