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