]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
MdeModulePkg DxeCore: Check pointer AllocInfoData before dereferencing.
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmramProfileRecord.c
CommitLineData
84edd20b
SZ
1/** @file\r
2 Support routines for SMRAM profile.\r
3\r
4 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
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 "PiSmmCore.h"\r
16\r
17#define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0)\r
18\r
19typedef struct {\r
20 UINT32 Signature;\r
21 MEMORY_PROFILE_CONTEXT Context;\r
22 LIST_ENTRY *DriverInfoList;\r
23} MEMORY_PROFILE_CONTEXT_DATA;\r
24\r
25typedef struct {\r
26 UINT32 Signature;\r
27 MEMORY_PROFILE_DRIVER_INFO DriverInfo;\r
28 LIST_ENTRY *AllocInfoList;\r
29 LIST_ENTRY Link;\r
30} MEMORY_PROFILE_DRIVER_INFO_DATA;\r
31\r
32typedef struct {\r
33 UINT32 Signature;\r
34 MEMORY_PROFILE_ALLOC_INFO AllocInfo;\r
35 LIST_ENTRY Link;\r
36} MEMORY_PROFILE_ALLOC_INFO_DATA;\r
37\r
38//\r
39// When free memory less than 4 pages, dump it.\r
40//\r
41#define SMRAM_INFO_DUMP_PAGE_THRESHOLD 4\r
42\r
43GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory = {\r
44 {\r
45 MEMORY_PROFILE_FREE_MEMORY_SIGNATURE,\r
46 sizeof (MEMORY_PROFILE_FREE_MEMORY),\r
47 MEMORY_PROFILE_FREE_MEMORY_REVISION\r
48 },\r
49 0,\r
50 0\r
51};\r
52\r
53GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);\r
54GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext = {\r
55 MEMORY_PROFILE_CONTEXT_SIGNATURE,\r
56 {\r
57 {\r
58 MEMORY_PROFILE_CONTEXT_SIGNATURE,\r
59 sizeof (MEMORY_PROFILE_CONTEXT),\r
60 MEMORY_PROFILE_CONTEXT_REVISION\r
61 },\r
62 0,\r
63 0,\r
64 {0},\r
65 {0},\r
66 0,\r
67 0,\r
68 0\r
69 },\r
70 &mImageQueue,\r
71};\r
72GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr;\r
73\r
74BOOLEAN mSmramReadyToLock;\r
75BOOLEAN mSmramProfileRecordingStatus = FALSE;\r
76\r
77/**\r
78 Return SMRAM profile context.\r
79\r
80 @return SMRAM profile context.\r
81\r
82**/\r
83MEMORY_PROFILE_CONTEXT_DATA *\r
84GetSmramProfileContext (\r
85 VOID\r
86 )\r
87{\r
88 return mSmramProfileContextPtr;\r
89}\r
90\r
91/**\r
92 Retrieves the magic value from the PE/COFF header.\r
93\r
94 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.\r
95\r
96 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32\r
97 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+\r
98\r
99**/\r
100UINT16\r
101InternalPeCoffGetPeHeaderMagicValue (\r
102 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr\r
103 )\r
104{\r
105 //\r
106 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
107 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
108 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
109 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
110 //\r
111 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
112 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
113 }\r
114 //\r
115 // Return the magic value from the PC/COFF Optional Header\r
116 //\r
117 return Hdr.Pe32->OptionalHeader.Magic;\r
118}\r
119\r
120/**\r
121 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.\r
122 If Pe32Data is NULL, then ASSERT().\r
123\r
124 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.\r
125\r
126 @return The Subsystem of the PE/COFF image.\r
127\r
128**/\r
129UINT16\r
130InternalPeCoffGetSubsystem (\r
131 IN VOID *Pe32Data\r
132 )\r
133{\r
134 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
135 EFI_IMAGE_DOS_HEADER *DosHdr;\r
136 UINT16 Magic;\r
137\r
138 ASSERT (Pe32Data != NULL);\r
139\r
140 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
141 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
142 //\r
143 // DOS image header is present, so read the PE header after the DOS image header.\r
144 //\r
145 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
146 } else {\r
147 //\r
148 // DOS image header is not present, so PE header is at the image base.\r
149 //\r
150 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;\r
151 }\r
152\r
153 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
154 return Hdr.Te->Subsystem;\r
155 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
156 Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr);\r
157 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
158 return Hdr.Pe32->OptionalHeader.Subsystem;\r
159 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
160 return Hdr.Pe32Plus->OptionalHeader.Subsystem;\r
161 }\r
162 }\r
163\r
164 return 0x0000;\r
165}\r
166\r
167/**\r
168 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded\r
169 into system memory with the PE/COFF Loader Library functions.\r
170\r
171 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry\r
172 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then\r
173 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.\r
174 If Pe32Data is NULL, then ASSERT().\r
175 If EntryPoint is NULL, then ASSERT().\r
176\r
177 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.\r
178 @param EntryPoint The pointer to entry point to the PE/COFF image to return.\r
179\r
180 @retval RETURN_SUCCESS EntryPoint was returned.\r
181 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.\r
182\r
183**/\r
184RETURN_STATUS\r
185InternalPeCoffGetEntryPoint (\r
186 IN VOID *Pe32Data,\r
187 OUT VOID **EntryPoint\r
188 )\r
189{\r
190 EFI_IMAGE_DOS_HEADER *DosHdr;\r
191 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
192\r
193 ASSERT (Pe32Data != NULL);\r
194 ASSERT (EntryPoint != NULL);\r
195\r
196 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
197 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
198 //\r
199 // DOS image header is present, so read the PE header after the DOS image header.\r
200 //\r
201 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
202 } else {\r
203 //\r
204 // DOS image header is not present, so PE header is at the image base.\r
205 //\r
206 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;\r
207 }\r
208\r
209 //\r
210 // Calculate the entry point relative to the start of the image.\r
211 // AddressOfEntryPoint is common for PE32 & PE32+\r
212 //\r
213 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
214 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);\r
215 return RETURN_SUCCESS;\r
216 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
217 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));\r
218 return RETURN_SUCCESS;\r
219 }\r
220\r
221 return RETURN_UNSUPPORTED;\r
222}\r
223\r
224/**\r
225 Build driver info.\r
226\r
227 @param ContextData Memory profile context.\r
228 @param FileName File name of the image.\r
229 @param ImageBase Image base address.\r
230 @param ImageSize Image size.\r
231 @param EntryPoint Entry point of the image.\r
232 @param ImageSubsystem Image subsystem of the image.\r
233\r
234 @param FileType File type of the image.\r
235\r
236 @return Pointer to memory profile driver info.\r
237\r
238**/\r
239MEMORY_PROFILE_DRIVER_INFO_DATA *\r
240BuildDriverInfo (\r
241 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,\r
242 IN EFI_GUID *FileName,\r
243 IN PHYSICAL_ADDRESS ImageBase,\r
244 IN UINT64 ImageSize,\r
245 IN PHYSICAL_ADDRESS EntryPoint,\r
246 IN UINT16 ImageSubsystem,\r
247 IN EFI_FV_FILETYPE FileType\r
248 )\r
249{\r
250 EFI_STATUS Status;\r
251 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
252 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
253 VOID *EntryPointInImage;\r
254\r
255 //\r
256 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.\r
257 //\r
258 Status = SmmInternalAllocatePool (\r
259 EfiRuntimeServicesData,\r
260 sizeof (*DriverInfoData) + sizeof (LIST_ENTRY),\r
261 (VOID **) &DriverInfoData\r
262 );\r
263 if (EFI_ERROR (Status)) {\r
264 return NULL;\r
265 }\r
266\r
267 ZeroMem (DriverInfoData, sizeof (*DriverInfoData));\r
268\r
269 DriverInfo = &DriverInfoData->DriverInfo;\r
270 DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;\r
271 DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;\r
272 DriverInfo->Header.Length = sizeof (MEMORY_PROFILE_DRIVER_INFO);\r
273 DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;\r
274 if (FileName != NULL) {\r
275 CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));\r
276 }\r
277 DriverInfo->ImageBase = ImageBase;\r
278 DriverInfo->ImageSize = ImageSize;\r
279 DriverInfo->EntryPoint = EntryPoint;\r
280 DriverInfo->ImageSubsystem = ImageSubsystem;\r
281 if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {\r
282 //\r
283 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
284 // So patch ImageBuffer here to align the EntryPoint.\r
285 //\r
286 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);\r
287 ASSERT_EFI_ERROR (Status);\r
288 DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
289 }\r
290 DriverInfo->FileType = FileType;\r
291 DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1);\r
292 InitializeListHead (DriverInfoData->AllocInfoList);\r
293 DriverInfo->CurrentUsage = 0;\r
294 DriverInfo->PeakUsage = 0;\r
295 DriverInfo->AllocRecordCount = 0;\r
296\r
297 InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);\r
298 ContextData->Context.ImageCount ++;\r
299 ContextData->Context.TotalImageSize += DriverInfo->ImageSize;\r
300\r
301 return DriverInfoData;\r
302}\r
303\r
304/**\r
305 Register image to DXE.\r
306\r
307 @param FileName File name of the image.\r
308 @param ImageBase Image base address.\r
309 @param ImageSize Image size.\r
310 @param FileType File type of the image.\r
311\r
312**/\r
313VOID\r
314RegisterImageToDxe (\r
315 IN EFI_GUID *FileName,\r
316 IN PHYSICAL_ADDRESS ImageBase,\r
317 IN UINT64 ImageSize,\r
318 IN EFI_FV_FILETYPE FileType\r
319 )\r
320{\r
321 EFI_STATUS Status;\r
322 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;\r
323 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;\r
324 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];\r
325\r
326 if (IS_SMRAM_PROFILE_ENABLED) {\r
327\r
328 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;\r
329 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);\r
330 if (!EFI_ERROR (Status)) {\r
331 EfiInitializeFwVolDevicepathNode (FilePath, FileName);\r
332 SetDevicePathEndNode (FilePath + 1);\r
333\r
334 Status = ProfileProtocol->RegisterImage (\r
335 ProfileProtocol,\r
336 (EFI_DEVICE_PATH_PROTOCOL *) FilePath,\r
337 ImageBase,\r
338 ImageSize,\r
339 FileType\r
340 );\r
341 }\r
342 }\r
343}\r
344\r
345/**\r
346 Unregister image from DXE.\r
347\r
348 @param FileName File name of the image.\r
349 @param ImageBase Image base address.\r
350 @param ImageSize Image size.\r
351\r
352**/\r
353VOID\r
354UnregisterImageFromDxe (\r
355 IN EFI_GUID *FileName,\r
356 IN PHYSICAL_ADDRESS ImageBase,\r
357 IN UINT64 ImageSize\r
358 )\r
359{\r
360 EFI_STATUS Status;\r
361 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;\r
362 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;\r
363 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];\r
364\r
365 if (IS_SMRAM_PROFILE_ENABLED) {\r
366\r
367 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;\r
368 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID *) &ProfileProtocol);\r
369 if (!EFI_ERROR (Status)) {\r
370 EfiInitializeFwVolDevicepathNode (FilePath, FileName);\r
371 SetDevicePathEndNode (FilePath + 1);\r
372\r
373 Status = ProfileProtocol->UnregisterImage (\r
374 ProfileProtocol,\r
375 (EFI_DEVICE_PATH_PROTOCOL *) FilePath,\r
376 ImageBase,\r
377 ImageSize\r
378 );\r
379 }\r
380 }\r
381}\r
382\r
383/**\r
384 Register SMM Core to SMRAM profile.\r
385\r
386 @param ContextData SMRAM profile context.\r
387\r
388 @retval TRUE Register success.\r
389 @retval FALSE Register fail.\r
390\r
391**/\r
392BOOLEAN\r
393RegisterSmmCore (\r
394 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData\r
395 )\r
396{\r
397 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
398 PHYSICAL_ADDRESS ImageBase;\r
399\r
400 ASSERT (ContextData != NULL);\r
401\r
402 RegisterImageToDxe (\r
403 &gEfiCallerIdGuid,\r
404 gSmmCorePrivate->PiSmmCoreImageBase,\r
405 gSmmCorePrivate->PiSmmCoreImageSize,\r
406 EFI_FV_FILETYPE_SMM_CORE\r
407 );\r
408\r
409 ImageBase = gSmmCorePrivate->PiSmmCoreImageBase;\r
410 DriverInfoData = BuildDriverInfo (\r
411 ContextData,\r
412 &gEfiCallerIdGuid,\r
413 ImageBase,\r
414 gSmmCorePrivate->PiSmmCoreImageSize,\r
415 gSmmCorePrivate->PiSmmCoreEntryPoint,\r
416 InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase),\r
417 EFI_FV_FILETYPE_SMM_CORE\r
418 );\r
419 if (DriverInfoData == NULL) {\r
420 return FALSE;\r
421 }\r
422\r
423 return TRUE;\r
424}\r
425\r
426/**\r
427 Initialize SMRAM profile.\r
428\r
429**/\r
430VOID\r
431SmramProfileInit (\r
432 VOID\r
433 )\r
434{\r
435 MEMORY_PROFILE_CONTEXT_DATA *SmramProfileContext;\r
436\r
437 if (!IS_SMRAM_PROFILE_ENABLED) {\r
438 return;\r
439 }\r
440\r
441 SmramProfileContext = GetSmramProfileContext ();\r
442 if (SmramProfileContext != NULL) {\r
443 return;\r
444 }\r
445\r
446 mSmramProfileRecordingStatus = TRUE;\r
447 mSmramProfileContextPtr = &mSmramProfileContext;\r
448\r
449 RegisterSmmCore (&mSmramProfileContext);\r
450\r
451 DEBUG ((EFI_D_INFO, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext));\r
452}\r
453\r
454/**\r
455 Register SMM image to SMRAM profile.\r
456\r
457 @param DriverEntry SMM image info.\r
458 @param RegisterToDxe Register image to DXE.\r
459\r
460 @retval TRUE Register success.\r
461 @retval FALSE Register fail.\r
462\r
463**/\r
464BOOLEAN\r
465RegisterSmramProfileImage (\r
466 IN EFI_SMM_DRIVER_ENTRY *DriverEntry,\r
467 IN BOOLEAN RegisterToDxe\r
468 )\r
469{\r
470 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
471 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
472\r
473 if (!IS_SMRAM_PROFILE_ENABLED) {\r
474 return FALSE;\r
475 }\r
476\r
477 if (RegisterToDxe) {\r
478 RegisterImageToDxe (\r
479 &DriverEntry->FileName,\r
480 DriverEntry->ImageBuffer,\r
481 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),\r
482 EFI_FV_FILETYPE_SMM\r
483 );\r
484 }\r
485\r
486 ContextData = GetSmramProfileContext ();\r
487 if (ContextData == NULL) {\r
488 return FALSE;\r
489 }\r
490\r
491 DriverInfoData = BuildDriverInfo (\r
492 ContextData,\r
493 &DriverEntry->FileName,\r
494 DriverEntry->ImageBuffer,\r
495 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),\r
496 DriverEntry->ImageEntryPoint,\r
497 InternalPeCoffGetSubsystem ((VOID *) (UINTN) DriverEntry->ImageBuffer),\r
498 EFI_FV_FILETYPE_SMM\r
499 );\r
500 if (DriverInfoData == NULL) {\r
501 return FALSE;\r
502 }\r
503\r
504 return TRUE;\r
505}\r
506\r
507/**\r
508 Search image from memory profile.\r
509\r
510 @param ContextData Memory profile context.\r
511 @param FileName Image file name.\r
512 @param Address Image Address.\r
513\r
514 @return Pointer to memory profile driver info.\r
515\r
516**/\r
517MEMORY_PROFILE_DRIVER_INFO_DATA *\r
518GetMemoryProfileDriverInfoByFileNameAndAddress (\r
519 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,\r
520 IN EFI_GUID *FileName,\r
521 IN PHYSICAL_ADDRESS Address\r
522 )\r
523{\r
524 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
525 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
526 LIST_ENTRY *DriverLink;\r
527 LIST_ENTRY *DriverInfoList;\r
528\r
529 DriverInfoList = ContextData->DriverInfoList;\r
530\r
531 for (DriverLink = DriverInfoList->ForwardLink;\r
532 DriverLink != DriverInfoList;\r
533 DriverLink = DriverLink->ForwardLink) {\r
534 DriverInfoData = CR (\r
535 DriverLink,\r
536 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
537 Link,\r
538 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
539 );\r
540 DriverInfo = &DriverInfoData->DriverInfo;\r
541 if ((CompareGuid (&DriverInfo->FileName, FileName)) &&\r
542 (Address >= DriverInfo->ImageBase) &&\r
543 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {\r
544 return DriverInfoData;\r
545 }\r
546 }\r
547\r
548 return NULL;\r
549}\r
550\r
551/**\r
552 Search dummy image from SMRAM profile.\r
553\r
554 @param ContextData Memory profile context.\r
555\r
556 @return Pointer to memory profile driver info.\r
557\r
558**/\r
559MEMORY_PROFILE_DRIVER_INFO_DATA *\r
560FindDummyImage (\r
561 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData\r
562 )\r
563{\r
564 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
565 LIST_ENTRY *DriverLink;\r
566 LIST_ENTRY *DriverInfoList;\r
567\r
568 DriverInfoList = ContextData->DriverInfoList;\r
569\r
570 for (DriverLink = DriverInfoList->ForwardLink;\r
571 DriverLink != DriverInfoList;\r
572 DriverLink = DriverLink->ForwardLink) {\r
573 DriverInfoData = CR (\r
574 DriverLink,\r
575 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
576 Link,\r
577 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
578 );\r
579 if (CompareGuid (&gZeroGuid, &DriverInfoData->DriverInfo.FileName)) {\r
580 return DriverInfoData;\r
581 }\r
582 }\r
583\r
584 return BuildDriverInfo (ContextData, &gZeroGuid, 0, 0, 0, 0, 0);\r
585}\r
586\r
587/**\r
588 Search image from memory profile.\r
589 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)\r
590\r
591 @param ContextData Memory profile context.\r
592 @param Address Image or Function address.\r
593\r
594 @return Pointer to memory profile driver info.\r
595\r
596**/\r
597MEMORY_PROFILE_DRIVER_INFO_DATA *\r
598GetMemoryProfileDriverInfoFromAddress (\r
599 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData,\r
600 IN PHYSICAL_ADDRESS Address\r
601 )\r
602{\r
603 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
604 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
605 LIST_ENTRY *DriverLink;\r
606 LIST_ENTRY *DriverInfoList;\r
607\r
608 DriverInfoList = ContextData->DriverInfoList;\r
609\r
610 for (DriverLink = DriverInfoList->ForwardLink;\r
611 DriverLink != DriverInfoList;\r
612 DriverLink = DriverLink->ForwardLink) {\r
613 DriverInfoData = CR (\r
614 DriverLink,\r
615 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
616 Link,\r
617 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
618 );\r
619 DriverInfo = &DriverInfoData->DriverInfo;\r
620 if ((Address >= DriverInfo->ImageBase) &&\r
621 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {\r
622 return DriverInfoData;\r
623 }\r
624 }\r
625\r
626 //\r
627 // Should never come here.\r
628 //\r
629 return FindDummyImage (ContextData);\r
630}\r
631\r
632/**\r
633 Unregister image from SMRAM profile.\r
634\r
635 @param DriverEntry SMM image info.\r
636 @param UnregisterFromDxe Unregister image from DXE.\r
637\r
638 @retval TRUE Unregister success.\r
639 @retval FALSE Unregister fail.\r
640\r
641**/\r
642BOOLEAN\r
643UnregisterSmramProfileImage (\r
644 IN EFI_SMM_DRIVER_ENTRY *DriverEntry,\r
645 IN BOOLEAN UnregisterFromDxe\r
646 )\r
647{\r
648 EFI_STATUS Status;\r
649 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
650 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
651 EFI_GUID *FileName;\r
652 PHYSICAL_ADDRESS ImageAddress;\r
653 VOID *EntryPointInImage;\r
654\r
655 if (!IS_SMRAM_PROFILE_ENABLED) {\r
656 return FALSE;\r
657 }\r
658\r
659 if (UnregisterFromDxe) {\r
660 UnregisterImageFromDxe (\r
661 &DriverEntry->FileName,\r
662 DriverEntry->ImageBuffer,\r
663 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)\r
664 );\r
665 }\r
666\r
667 ContextData = GetSmramProfileContext ();\r
668 if (ContextData == NULL) {\r
669 return FALSE;\r
670 }\r
671\r
672 DriverInfoData = NULL;\r
673 FileName = &DriverEntry->FileName;\r
674 ImageAddress = DriverEntry->ImageBuffer;\r
675 if ((DriverEntry->ImageEntryPoint < ImageAddress) || (DriverEntry->ImageEntryPoint >= (ImageAddress + EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)))) {\r
676 //\r
677 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
678 // So patch ImageAddress here to align the EntryPoint.\r
679 //\r
680 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage);\r
681 ASSERT_EFI_ERROR (Status);\r
682 ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageEntryPoint - (UINTN) EntryPointInImage;\r
683 }\r
684 if (FileName != NULL) {\r
685 DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);\r
686 }\r
687 if (DriverInfoData == NULL) {\r
688 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);\r
689 }\r
690 if (DriverInfoData == NULL) {\r
691 return FALSE;\r
692 }\r
693\r
694 ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;\r
695\r
696 DriverInfoData->DriverInfo.ImageBase = 0;\r
697 DriverInfoData->DriverInfo.ImageSize = 0;\r
698\r
699 if (DriverInfoData->DriverInfo.PeakUsage == 0) {\r
700 ContextData->Context.ImageCount --;\r
701 RemoveEntryList (&DriverInfoData->Link);\r
702 //\r
703 // Use SmmInternalFreePool() that will not update profile for this FreePool action.\r
704 //\r
705 SmmInternalFreePool (DriverInfoData);\r
706 }\r
707\r
708 return TRUE;\r
709}\r
710\r
711/**\r
712 Return if this memory type needs to be recorded into memory profile.\r
713 If BIOS memory type (0 ~ EfiMaxMemoryType), it checks bit (1 << MemoryType).\r
714 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.\r
715\r
716 @param MemoryType Memory type.\r
717\r
718 @retval TRUE This memory type need to be recorded.\r
719 @retval FALSE This memory type need not to be recorded.\r
720\r
721**/\r
722BOOLEAN\r
723SmmCoreNeedRecordProfile (\r
724 IN EFI_MEMORY_TYPE MemoryType\r
725 )\r
726{\r
727 UINT64 TestBit;\r
728\r
729 if ((UINT32) MemoryType >= 0x80000000) {\r
730 TestBit = BIT63;\r
731 } else {\r
732 TestBit = LShiftU64 (1, MemoryType);\r
733 }\r
734\r
735 if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {\r
736 return TRUE;\r
737 } else {\r
738 return FALSE;\r
739 }\r
740}\r
741\r
742/**\r
743 Convert EFI memory type to profile memory index. The rule is:\r
744 If BIOS memory type (0 ~ EfiMaxMemoryType), ProfileMemoryIndex = MemoryType.\r
745 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.\r
746\r
747 @param MemoryType Memory type.\r
748\r
749 @return EFI memory type as profile memory index.\r
750\r
751**/\r
752EFI_MEMORY_TYPE\r
753GetProfileMemoryIndex (\r
754 IN EFI_MEMORY_TYPE MemoryType\r
755 )\r
756{\r
757 if ((UINT32) MemoryType >= 0x80000000) {\r
758 return EfiMaxMemoryType;\r
759 } else {\r
760 return MemoryType;\r
761 }\r
762}\r
763\r
764/**\r
765 Update SMRAM profile FreeMemoryPages information\r
766\r
767 @param ContextData Memory profile context.\r
768\r
769**/\r
770VOID\r
771SmramProfileUpdateFreePages (\r
772 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData\r
773 )\r
774{\r
775 LIST_ENTRY *Node;\r
776 FREE_PAGE_LIST *Pages;\r
777 LIST_ENTRY *FreePageList;\r
778 UINTN NumberOfPages;\r
779\r
780 NumberOfPages = 0;\r
781 FreePageList = &mSmmMemoryMap;\r
782 for (Node = FreePageList->BackLink;\r
783 Node != FreePageList;\r
784 Node = Node->BackLink) {\r
785 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
786 NumberOfPages += Pages->NumberOfPages;\r
787 }\r
788\r
789 mSmramFreeMemory.TotalFreeMemoryPages = NumberOfPages;\r
790\r
791 if (NumberOfPages <= SMRAM_INFO_DUMP_PAGE_THRESHOLD) {\r
792 DumpSmramInfo ();\r
793 }\r
794}\r
795\r
796/**\r
797 Update SMRAM profile Allocate information.\r
798\r
799 @param CallerAddress Address of caller who call Allocate.\r
800 @param Action This Allocate action.\r
801 @param MemoryType Memory type.\r
802 @param Size Buffer size.\r
803 @param Buffer Buffer address.\r
804\r
805 @retval TRUE Profile udpate success.\r
806 @retval FALSE Profile update fail.\r
807\r
808**/\r
809BOOLEAN\r
810SmmCoreUpdateProfileAllocate (\r
811 IN PHYSICAL_ADDRESS CallerAddress,\r
812 IN MEMORY_PROFILE_ACTION Action,\r
813 IN EFI_MEMORY_TYPE MemoryType,\r
814 IN UINTN Size,\r
815 IN VOID *Buffer\r
816 )\r
817{\r
818 EFI_STATUS Status;\r
819 MEMORY_PROFILE_CONTEXT *Context;\r
820 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
821 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
822 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
823 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
824 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
825 EFI_MEMORY_TYPE ProfileMemoryIndex;\r
826\r
f4420027
SZ
827 AllocInfoData = NULL;\r
828\r
84edd20b
SZ
829 ContextData = GetSmramProfileContext ();\r
830 if (ContextData == NULL) {\r
831 return FALSE;\r
832 }\r
833\r
834 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);\r
835 ASSERT (DriverInfoData != NULL);\r
836\r
837 //\r
838 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.\r
839 //\r
840 Status = SmmInternalAllocatePool (\r
841 EfiRuntimeServicesData,\r
842 sizeof (*AllocInfoData),\r
843 (VOID **) &AllocInfoData\r
844 );\r
845 if (EFI_ERROR (Status)) {\r
846 return FALSE;\r
847 }\r
848 AllocInfo = &AllocInfoData->AllocInfo;\r
849 AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;\r
850 AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;\r
851 AllocInfo->Header.Length = sizeof (MEMORY_PROFILE_ALLOC_INFO);\r
852 AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION;\r
853 AllocInfo->CallerAddress = CallerAddress;\r
854 AllocInfo->SequenceId = ContextData->Context.SequenceCount;\r
855 AllocInfo->Action = Action;\r
856 AllocInfo->MemoryType = MemoryType;\r
857 AllocInfo->Buffer = (PHYSICAL_ADDRESS) (UINTN) Buffer;\r
858 AllocInfo->Size = Size;\r
859\r
860 InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);\r
861\r
862 ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);\r
863\r
864 DriverInfo = &DriverInfoData->DriverInfo;\r
865 DriverInfo->CurrentUsage += Size;\r
866 if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {\r
867 DriverInfo->PeakUsage = DriverInfo->CurrentUsage;\r
868 }\r
869 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;\r
870 if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {\r
871 DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];\r
872 }\r
873 DriverInfo->AllocRecordCount ++;\r
874\r
875 Context = &ContextData->Context;\r
876 Context->CurrentTotalUsage += Size;\r
877 if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {\r
878 Context->PeakTotalUsage = Context->CurrentTotalUsage;\r
879 }\r
880 Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;\r
881 if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {\r
882 Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];\r
883 }\r
884 Context->SequenceCount ++;\r
885\r
886 SmramProfileUpdateFreePages (ContextData);\r
887 return TRUE;\r
888}\r
889\r
890/**\r
891 Get memory profile alloc info from memory profile\r
892\r
893 @param DriverInfoData Driver info\r
894 @param Action This Free action\r
895 @param Size Buffer size\r
896 @param Buffer Buffer address\r
897\r
898 @return Pointer to memory profile alloc info.\r
899**/\r
900MEMORY_PROFILE_ALLOC_INFO_DATA *\r
901GetMemoryProfileAllocInfoFromAddress (\r
902 IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData,\r
903 IN MEMORY_PROFILE_ACTION Action,\r
904 IN UINTN Size,\r
905 IN VOID *Buffer\r
906 )\r
907{\r
908 LIST_ENTRY *AllocInfoList;\r
909 LIST_ENTRY *AllocLink;\r
910 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
911 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
912\r
913 AllocInfoList = DriverInfoData->AllocInfoList;\r
914\r
915 for (AllocLink = AllocInfoList->ForwardLink;\r
916 AllocLink != AllocInfoList;\r
917 AllocLink = AllocLink->ForwardLink) {\r
918 AllocInfoData = CR (\r
919 AllocLink,\r
920 MEMORY_PROFILE_ALLOC_INFO_DATA,\r
921 Link,\r
922 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
923 );\r
924 AllocInfo = &AllocInfoData->AllocInfo;\r
925 if (AllocInfo->Action != Action) {\r
926 continue;\r
927 }\r
928 switch (Action) {\r
929 case MemoryProfileActionAllocatePages:\r
930 if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&\r
931 ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) {\r
932 return AllocInfoData;\r
933 }\r
934 break;\r
935 case MemoryProfileActionAllocatePool:\r
936 if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {\r
937 return AllocInfoData;\r
938 }\r
939 break;\r
940 default:\r
941 ASSERT (FALSE);\r
942 break;\r
943 }\r
944 }\r
945\r
946 return NULL;\r
947}\r
948\r
949/**\r
950 Update SMRAM profile Free information.\r
951\r
952 @param CallerAddress Address of caller who call Free.\r
953 @param Action This Free action.\r
954 @param Size Buffer size.\r
955 @param Buffer Buffer address.\r
956\r
957 @retval TRUE Profile udpate success.\r
958 @retval FALSE Profile update fail.\r
959\r
960**/\r
961BOOLEAN\r
962SmmCoreUpdateProfileFree (\r
963 IN PHYSICAL_ADDRESS CallerAddress,\r
964 IN MEMORY_PROFILE_ACTION Action,\r
965 IN UINTN Size,\r
966 IN VOID *Buffer\r
967 )\r
968{\r
969 MEMORY_PROFILE_CONTEXT *Context;\r
970 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
971 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
972 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
973 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
974 LIST_ENTRY *DriverLink;\r
975 LIST_ENTRY *DriverInfoList;\r
976 MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData;\r
977 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
978 EFI_MEMORY_TYPE ProfileMemoryIndex;\r
979\r
980 ContextData = GetSmramProfileContext ();\r
981 if (ContextData == NULL) {\r
982 return FALSE;\r
983 }\r
984\r
985 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);\r
986 ASSERT (DriverInfoData != NULL);\r
987\r
988 switch (Action) {\r
989 case MemoryProfileActionFreePages:\r
990 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);\r
991 break;\r
992 case MemoryProfileActionFreePool:\r
993 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);\r
994 break;\r
995 default:\r
996 ASSERT (FALSE);\r
997 AllocInfoData = NULL;\r
998 break;\r
999 }\r
1000 if (AllocInfoData == NULL) {\r
1001 //\r
1002 // Legal case, because driver A might free memory allocated by driver B, by some protocol.\r
1003 //\r
1004 DriverInfoList = ContextData->DriverInfoList;\r
1005\r
1006 for (DriverLink = DriverInfoList->ForwardLink;\r
1007 DriverLink != DriverInfoList;\r
1008 DriverLink = DriverLink->ForwardLink) {\r
1009 ThisDriverInfoData = CR (\r
1010 DriverLink,\r
1011 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1012 Link,\r
1013 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1014 );\r
1015 switch (Action) {\r
1016 case MemoryProfileActionFreePages:\r
1017 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);\r
1018 break;\r
1019 case MemoryProfileActionFreePool:\r
1020 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);\r
1021 break;\r
1022 default:\r
1023 ASSERT (FALSE);\r
1024 AllocInfoData = NULL;\r
1025 break;\r
1026 }\r
1027 if (AllocInfoData != NULL) {\r
1028 DriverInfoData = ThisDriverInfoData;\r
1029 break;\r
1030 }\r
1031 }\r
1032\r
1033 if (AllocInfoData == NULL) {\r
1034 //\r
1035 // No matched allocate operation is found for this free operation.\r
1036 // It is because the specified memory type allocate operation has been\r
1037 // filtered by CoreNeedRecordProfile(), but free operations have no\r
1038 // memory type information, they can not be filtered by CoreNeedRecordProfile().\r
1039 // Then, they will be filtered here.\r
1040 //\r
1041 return FALSE;\r
1042 }\r
1043 }\r
1044\r
1045 Context = &ContextData->Context;\r
1046 DriverInfo = &DriverInfoData->DriverInfo;\r
1047 AllocInfo = &AllocInfoData->AllocInfo;\r
1048\r
1049 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);\r
1050\r
1051 Context->CurrentTotalUsage -= AllocInfo->Size;\r
1052 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;\r
1053\r
1054 DriverInfo->CurrentUsage -= AllocInfo->Size;\r
1055 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;\r
1056 DriverInfo->AllocRecordCount --;\r
1057\r
1058 RemoveEntryList (&AllocInfoData->Link);\r
1059\r
1060 if (Action == MemoryProfileActionFreePages) {\r
1061 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {\r
1062 SmmCoreUpdateProfileAllocate (\r
1063 AllocInfo->CallerAddress,\r
1064 MemoryProfileActionAllocatePages,\r
1065 AllocInfo->MemoryType,\r
1066 (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),\r
1067 (VOID *) (UINTN) AllocInfo->Buffer\r
1068 );\r
1069 }\r
1070 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {\r
1071 SmmCoreUpdateProfileAllocate (\r
1072 AllocInfo->CallerAddress,\r
1073 MemoryProfileActionAllocatePages,\r
1074 AllocInfo->MemoryType,\r
1075 (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),\r
1076 (VOID *) ((UINTN) Buffer + Size)\r
1077 );\r
1078 }\r
1079 }\r
1080\r
1081 //\r
1082 // Use SmmInternalFreePool() that will not update profile for this FreePool action.\r
1083 //\r
1084 SmmInternalFreePool (AllocInfoData);\r
1085\r
1086 return TRUE;\r
1087}\r
1088\r
1089/**\r
1090 Update SMRAM profile information.\r
1091\r
1092 @param CallerAddress Address of caller who call Allocate or Free.\r
1093 @param Action This Allocate or Free action.\r
1094 @param MemoryType Memory type.\r
1095 @param Size Buffer size.\r
1096 @param Buffer Buffer address.\r
1097\r
1098 @retval TRUE Profile udpate success.\r
1099 @retval FALSE Profile update fail.\r
1100\r
1101**/\r
1102BOOLEAN\r
1103SmmCoreUpdateProfile (\r
1104 IN PHYSICAL_ADDRESS CallerAddress,\r
1105 IN MEMORY_PROFILE_ACTION Action,\r
1106 IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool\r
1107 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool\r
1108 IN VOID *Buffer\r
1109 )\r
1110{\r
1111 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1112\r
1113 if (!IS_SMRAM_PROFILE_ENABLED) {\r
1114 return FALSE;\r
1115 }\r
1116\r
1117 if (!mSmramProfileRecordingStatus) {\r
1118 return FALSE;\r
1119 }\r
1120\r
1121 //\r
1122 // Free operations have no memory type information, so skip the check.\r
1123 //\r
1124 if ((Action == MemoryProfileActionAllocatePages) || (Action == MemoryProfileActionAllocatePool)) {\r
1125 //\r
1126 // Only record limited MemoryType.\r
1127 //\r
1128 if (!SmmCoreNeedRecordProfile (MemoryType)) {\r
1129 return FALSE;\r
1130 }\r
1131 }\r
1132\r
1133 ContextData = GetSmramProfileContext ();\r
1134 if (ContextData == NULL) {\r
1135 return FALSE;\r
1136 }\r
1137\r
1138 switch (Action) {\r
1139 case MemoryProfileActionAllocatePages:\r
1140 SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);\r
1141 break;\r
1142 case MemoryProfileActionFreePages:\r
1143 SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);\r
1144 break;\r
1145 case MemoryProfileActionAllocatePool:\r
1146 SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);\r
1147 break;\r
1148 case MemoryProfileActionFreePool:\r
1149 SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);\r
1150 break;\r
1151 default:\r
1152 ASSERT (FALSE);\r
1153 break;\r
1154 }\r
1155\r
1156 return TRUE;\r
1157}\r
1158\r
1159/**\r
1160 SMRAM profile ready to lock callback function.\r
1161\r
1162**/\r
1163VOID\r
1164SmramProfileReadyToLock (\r
1165 VOID\r
1166 )\r
1167{\r
1168 if (!IS_SMRAM_PROFILE_ENABLED) {\r
1169 return;\r
1170 }\r
1171\r
1172 DEBUG ((EFI_D_INFO, "SmramProfileReadyToLock\n"));\r
1173 mSmramReadyToLock = TRUE;\r
1174}\r
1175\r
1176////////////////////\r
1177\r
1178/**\r
1179 This function check if the address is in SMRAM.\r
1180\r
1181 @param Buffer the buffer address to be checked.\r
1182 @param Length the buffer length to be checked.\r
1183\r
1184 @retval TRUE this address is in SMRAM.\r
1185 @retval FALSE this address is NOT in SMRAM.\r
1186\r
1187**/\r
1188BOOLEAN\r
1189InternalIsAddressInSmram (\r
1190 IN PHYSICAL_ADDRESS Buffer,\r
1191 IN UINT64 Length\r
1192 )\r
1193{\r
1194 UINTN Index;\r
1195\r
1196 for (Index = 0; Index < mFullSmramRangeCount; Index ++) {\r
1197 if (((Buffer >= mFullSmramRanges[Index].CpuStart) && (Buffer < mFullSmramRanges[Index].CpuStart + mFullSmramRanges[Index].PhysicalSize)) ||\r
1198 ((mFullSmramRanges[Index].CpuStart >= Buffer) && (mFullSmramRanges[Index].CpuStart < Buffer + Length))) {\r
1199 return TRUE;\r
1200 }\r
1201 }\r
1202\r
1203 return FALSE;\r
1204}\r
1205\r
1206/**\r
1207 This function check if the address refered by Buffer and Length is valid.\r
1208\r
1209 @param Buffer the buffer address to be checked.\r
1210 @param Length the buffer length to be checked.\r
1211\r
1212 @retval TRUE this address is valid.\r
1213 @retval FALSE this address is NOT valid.\r
1214**/\r
1215BOOLEAN\r
1216InternalIsAddressValid (\r
1217 IN UINTN Buffer,\r
1218 IN UINTN Length\r
1219 )\r
1220{\r
1221 if (Buffer > (MAX_ADDRESS - Length)) {\r
1222 //\r
1223 // Overflow happen\r
1224 //\r
1225 return FALSE;\r
1226 }\r
1227 if (InternalIsAddressInSmram ((PHYSICAL_ADDRESS) Buffer, (UINT64)Length)) {\r
1228 return FALSE;\r
1229 }\r
1230 return TRUE;\r
1231}\r
1232\r
1233/**\r
1234 Get SMRAM profile data size.\r
1235\r
1236 @return SMRAM profile data size.\r
1237\r
1238**/\r
1239UINTN\r
1240SmramProfileGetDataSize (\r
1241 VOID\r
1242 )\r
1243{\r
1244 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1245 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1246 LIST_ENTRY *DriverInfoList;\r
1247 LIST_ENTRY *DriverLink;\r
1248 UINTN TotalSize;\r
1249 LIST_ENTRY *Node;\r
1250 LIST_ENTRY *FreePageList;\r
1251 LIST_ENTRY *FreePoolList;\r
1252 FREE_POOL_HEADER *Pool;\r
1253 UINTN PoolListIndex;\r
1254 UINTN Index;\r
1255\r
1256 ContextData = GetSmramProfileContext ();\r
1257 if (ContextData == NULL) {\r
1258 return 0;\r
1259 }\r
1260\r
1261 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);\r
1262 TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount;\r
1263\r
1264 DriverInfoList = ContextData->DriverInfoList;\r
1265 for (DriverLink = DriverInfoList->ForwardLink;\r
1266 DriverLink != DriverInfoList;\r
1267 DriverLink = DriverLink->ForwardLink) {\r
1268 DriverInfoData = CR (\r
1269 DriverLink,\r
1270 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1271 Link,\r
1272 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1273 );\r
1274 TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfoData->DriverInfo.AllocRecordCount;\r
1275 }\r
1276\r
1277\r
1278 Index = 0;\r
1279 FreePageList = &mSmmMemoryMap;\r
1280 for (Node = FreePageList->BackLink;\r
1281 Node != FreePageList;\r
1282 Node = Node->BackLink) {\r
1283 Index++;\r
1284 }\r
1285 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1286 FreePoolList = &mSmmPoolLists[PoolListIndex];\r
1287 for (Node = FreePoolList->BackLink;\r
1288 Node != FreePoolList;\r
1289 Node = Node->BackLink) {\r
1290 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1291 if (Pool->Header.Available) {\r
1292 Index++;\r
1293 }\r
1294 }\r
1295 }\r
1296\r
1297\r
1298 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));\r
1299 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));\r
1300\r
1301 return TotalSize;\r
1302}\r
1303\r
1304/**\r
1305 Copy SMRAM profile data.\r
1306\r
1307 @param ProfileBuffer The buffer to hold SMRAM profile data.\r
1308\r
1309**/\r
1310VOID\r
1311SmramProfileCopyData (\r
1312 IN VOID *ProfileBuffer\r
1313 )\r
1314{\r
1315 MEMORY_PROFILE_CONTEXT *Context;\r
1316 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
1317 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
1318 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1319 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1320 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
1321 LIST_ENTRY *DriverInfoList;\r
1322 LIST_ENTRY *DriverLink;\r
1323 LIST_ENTRY *AllocInfoList;\r
1324 LIST_ENTRY *AllocLink;\r
1325 LIST_ENTRY *Node;\r
1326 FREE_PAGE_LIST *Pages;\r
1327 LIST_ENTRY *FreePageList;\r
1328 LIST_ENTRY *FreePoolList;\r
1329 FREE_POOL_HEADER *Pool;\r
1330 UINTN PoolListIndex;\r
1331 UINT32 Index;\r
1332 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;\r
1333 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;\r
1334 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor;\r
1335\r
1336 ContextData = GetSmramProfileContext ();\r
1337 if (ContextData == NULL) {\r
1338 return ;\r
1339 }\r
1340\r
1341 Context = ProfileBuffer;\r
1342 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));\r
1343 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);\r
1344\r
1345 DriverInfoList = ContextData->DriverInfoList;\r
1346 for (DriverLink = DriverInfoList->ForwardLink;\r
1347 DriverLink != DriverInfoList;\r
1348 DriverLink = DriverLink->ForwardLink) {\r
1349 DriverInfoData = CR (\r
1350 DriverLink,\r
1351 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1352 Link,\r
1353 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1354 );\r
1355 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));\r
1356 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1);\r
1357\r
1358 AllocInfoList = DriverInfoData->AllocInfoList;\r
1359 for (AllocLink = AllocInfoList->ForwardLink;\r
1360 AllocLink != AllocInfoList;\r
1361 AllocLink = AllocLink->ForwardLink) {\r
1362 AllocInfoData = CR (\r
1363 AllocLink,\r
1364 MEMORY_PROFILE_ALLOC_INFO_DATA,\r
1365 Link,\r
1366 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
1367 );\r
1368 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));\r
1369 AllocInfo += 1;\r
1370 }\r
1371\r
1372 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount);\r
1373 }\r
1374\r
1375\r
1376 FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) DriverInfo;\r
1377 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));\r
1378 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (FreeMemory + 1);\r
1379 Index = 0;\r
1380 FreePageList = &mSmmMemoryMap;\r
1381 for (Node = FreePageList->BackLink;\r
1382 Node != FreePageList;\r
1383 Node = Node->BackLink) {\r
1384 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
1385 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1386 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1387 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1388 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages;\r
1389 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);\r
1390 MemoryProfileDescriptor++;\r
1391 Index++;\r
1392 }\r
1393 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1394 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];\r
1395 for (Node = FreePoolList->BackLink;\r
1396 Node != FreePoolList;\r
1397 Node = Node->BackLink) {\r
1398 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1399 if (Pool->Header.Available) {\r
1400 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1401 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1402 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1403 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool;\r
1404 MemoryProfileDescriptor->Size = Pool->Header.Size;\r
1405 MemoryProfileDescriptor++;\r
1406 Index++;\r
1407 }\r
1408 }\r
1409 }\r
1410 FreeMemory->FreeMemoryEntryCount = Index;\r
1411\r
1412 MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) MemoryProfileDescriptor;\r
1413 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;\r
1414 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);\r
1415 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;\r
1416 MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount;\r
1417 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (MemoryRange + 1);\r
1418 for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
1419 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1420 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1421 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1422 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;\r
1423 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;\r
1424 MemoryProfileDescriptor++; \r
1425 }\r
1426}\r
1427\r
1428/**\r
1429 SMRAM profile handler to get profile info.\r
1430\r
1431 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.\r
1432\r
1433**/\r
1434VOID\r
1435SmramProfileHandlerGetInfo (\r
1436 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo\r
1437 )\r
1438{\r
1439 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1440 BOOLEAN SmramProfileRecordingStatus;\r
1441\r
1442 ContextData = GetSmramProfileContext ();\r
1443 if (ContextData == NULL) {\r
1444 return ;\r
1445 }\r
1446\r
1447 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1448 mSmramProfileRecordingStatus = FALSE;\r
1449\r
1450 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();\r
1451 SmramProfileParameterGetInfo->Header.ReturnStatus = 0;\r
1452\r
1453 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1454}\r
1455\r
1456/**\r
1457 SMRAM profile handler to get profile data.\r
1458\r
1459 @param SmramProfileParameterGetData The parameter of SMM profile get data.\r
1460\r
1461**/\r
1462VOID\r
1463SmramProfileHandlerGetData (\r
1464 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData\r
1465 )\r
1466{\r
1467 UINT64 ProfileSize;\r
1468 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData;\r
1469 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1470 BOOLEAN SmramProfileRecordingStatus;\r
1471\r
1472 ContextData = GetSmramProfileContext ();\r
1473 if (ContextData == NULL) {\r
1474 return ;\r
1475 }\r
1476\r
1477 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1478 mSmramProfileRecordingStatus = FALSE;\r
1479\r
1480\r
1481 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));\r
1482\r
1483 ProfileSize = SmramProfileGetDataSize();\r
1484\r
1485 //\r
1486 // Sanity check\r
1487 //\r
1488 if (!InternalIsAddressValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {\r
1489 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));\r
1490 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1491 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;\r
1492 goto Done;\r
1493 }\r
1494\r
1495 if (SmramProfileGetData.ProfileSize < ProfileSize) {\r
1496 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1497 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL;\r
1498 goto Done;\r
1499 }\r
1500\r
1501 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1502 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer);\r
1503 SmramProfileParameterGetData->Header.ReturnStatus = 0;\r
1504\r
1505Done:\r
1506 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1507}\r
1508\r
1509/**\r
1510 SMRAM profile handler to register SMM image.\r
1511\r
1512 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.\r
1513\r
1514**/\r
1515VOID\r
1516SmramProfileHandlerRegisterImage (\r
1517 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage\r
1518 )\r
1519{\r
1520 EFI_STATUS Status;\r
1521 EFI_SMM_DRIVER_ENTRY DriverEntry;\r
1522 VOID *EntryPointInImage;\r
1523 BOOLEAN Ret;\r
1524\r
1525 ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
1526 CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));\r
1527 DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer;\r
1528 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage;\r
1529 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
1530 ASSERT_EFI_ERROR (Status);\r
1531 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
1532\r
1533 Ret = RegisterSmramProfileImage (&DriverEntry, FALSE);\r
1534 if (Ret) {\r
1535 SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;\r
1536 }\r
1537}\r
1538\r
1539/**\r
1540 SMRAM profile handler to unregister SMM image.\r
1541\r
1542 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.\r
1543\r
1544**/\r
1545VOID\r
1546SmramProfileHandlerUnregisterImage (\r
1547 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage\r
1548 )\r
1549{\r
1550 EFI_STATUS Status;\r
1551 EFI_SMM_DRIVER_ENTRY DriverEntry;\r
1552 VOID *EntryPointInImage;\r
1553 BOOLEAN Ret;\r
1554\r
1555 ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
1556 CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));\r
1557 DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer;\r
1558 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage;\r
1559 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
1560 ASSERT_EFI_ERROR (Status);\r
1561 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
1562\r
1563 Ret = UnregisterSmramProfileImage (&DriverEntry, FALSE);\r
1564 if (Ret) {\r
1565 SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;\r
1566 }\r
1567}\r
1568\r
1569/**\r
1570 Dispatch function for a Software SMI handler.\r
1571\r
1572 Caution: This function may receive untrusted input.\r
1573 Communicate buffer and buffer size are external input, so this function will do basic validation.\r
1574\r
1575 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
1576 @param Context Points to an optional handler context which was specified when the\r
1577 handler was registered.\r
1578 @param CommBuffer A pointer to a collection of data in memory that will\r
1579 be conveyed from a non-SMM environment into an SMM environment.\r
1580 @param CommBufferSize The size of the CommBuffer.\r
1581\r
1582 @retval EFI_SUCCESS Command is handled successfully.\r
1583\r
1584**/\r
1585EFI_STATUS\r
1586EFIAPI\r
1587SmramProfileHandler (\r
1588 IN EFI_HANDLE DispatchHandle,\r
1589 IN CONST VOID *Context OPTIONAL,\r
1590 IN OUT VOID *CommBuffer OPTIONAL,\r
1591 IN OUT UINTN *CommBufferSize OPTIONAL\r
1592 )\r
1593{\r
1594 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader;\r
1595 UINTN TempCommBufferSize;\r
1596\r
1597 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));\r
1598\r
1599 //\r
1600 // If input is invalid, stop processing this SMI\r
1601 //\r
1602 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
1603 return EFI_SUCCESS;\r
1604 }\r
1605\r
1606 TempCommBufferSize = *CommBufferSize;\r
1607\r
1608 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {\r
1609 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1610 return EFI_SUCCESS;\r
1611 }\r
1612\r
1613 if (mSmramReadyToLock && !InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
1614 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
1615 return EFI_SUCCESS;\r
1616 }\r
1617\r
1618 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer);\r
1619\r
1620 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;\r
1621\r
1622 if (GetSmramProfileContext () == NULL) {\r
1623 SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED;\r
1624 return EFI_SUCCESS;\r
1625 }\r
1626\r
1627 switch (SmramProfileParameterHeader->Command) {\r
1628 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:\r
1629 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n"));\r
1630 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {\r
1631 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1632 return EFI_SUCCESS;\r
1633 }\r
1634 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer);\r
1635 break;\r
1636 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:\r
1637 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n"));\r
1638 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {\r
1639 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1640 return EFI_SUCCESS;\r
1641 }\r
1642 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);\r
1643 break;\r
1644 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE:\r
1645 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n"));\r
1646 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) {\r
1647 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1648 return EFI_SUCCESS;\r
1649 }\r
1650 if (mSmramReadyToLock) {\r
1651 return EFI_SUCCESS;\r
1652 }\r
1653 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer);\r
1654 break;\r
1655 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE:\r
1656 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n"));\r
1657 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) {\r
1658 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1659 return EFI_SUCCESS;\r
1660 }\r
1661 if (mSmramReadyToLock) {\r
1662 return EFI_SUCCESS;\r
1663 }\r
1664 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);\r
1665 break;\r
1666 default:\r
1667 break;\r
1668 }\r
1669\r
1670 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n"));\r
1671\r
1672 return EFI_SUCCESS;\r
1673}\r
1674\r
1675/**\r
1676 Register SMRAM profile handler.\r
1677\r
1678**/\r
1679VOID\r
1680RegisterSmramProfileHandler (\r
1681 VOID\r
1682 )\r
1683{\r
1684 EFI_STATUS Status;\r
1685 EFI_HANDLE DispatchHandle;\r
1686\r
1687 if (!IS_SMRAM_PROFILE_ENABLED) {\r
1688 return;\r
1689 }\r
1690\r
1691 Status = SmiHandlerRegister (\r
1692 SmramProfileHandler,\r
1693 &gEdkiiMemoryProfileGuid,\r
1694 &DispatchHandle\r
1695 );\r
1696 ASSERT_EFI_ERROR (Status);\r
1697}\r
1698\r
1699////////////////////\r
1700\r
1701/**\r
1702 Dump SMRAM range.\r
1703\r
1704**/\r
1705VOID\r
1706DumpSmramRange (\r
1707 VOID\r
1708 )\r
1709{\r
1710 UINTN Index;\r
1711 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1712 BOOLEAN SmramProfileRecordingStatus;\r
1713\r
1714 ContextData = GetSmramProfileContext ();\r
1715 if (ContextData == NULL) {\r
1716 return ;\r
1717 }\r
1718\r
1719 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1720 mSmramProfileRecordingStatus = FALSE;\r
1721\r
1722 DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));\r
1723\r
1724 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1725\r
1726 DEBUG ((EFI_D_INFO, "FullSmramRange:\n"));\r
1727 for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
1728 DEBUG ((EFI_D_INFO, " FullSmramRange (0x%x)\n", Index));\r
1729 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));\r
1730 DEBUG ((EFI_D_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));\r
1731 DEBUG ((EFI_D_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));\r
1732 DEBUG ((EFI_D_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState));\r
1733 }\r
1734\r
1735 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1736\r
1737 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1738}\r
1739\r
1740/**\r
1741 Dump SMRAM free page list.\r
1742\r
1743**/\r
1744VOID\r
1745DumpFreePagesList (\r
1746 VOID\r
1747 )\r
1748{\r
1749 LIST_ENTRY *FreePageList;\r
1750 LIST_ENTRY *Node;\r
1751 FREE_PAGE_LIST *Pages;\r
1752 UINTN Index;\r
1753 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1754 BOOLEAN SmramProfileRecordingStatus;\r
1755\r
1756 ContextData = GetSmramProfileContext ();\r
1757 if (ContextData == NULL) {\r
1758 return ;\r
1759 }\r
1760\r
1761 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1762 mSmramProfileRecordingStatus = FALSE;\r
1763\r
1764 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1765\r
1766 DEBUG ((EFI_D_INFO, "FreePagesList:\n"));\r
1767 FreePageList = &mSmmMemoryMap;\r
1768 for (Node = FreePageList->BackLink, Index = 0;\r
1769 Node != FreePageList;\r
1770 Node = Node->BackLink, Index++) {\r
1771 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
1772 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));\r
1773 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages));\r
1774 DEBUG ((EFI_D_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages));\r
1775 }\r
1776\r
1777 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1778\r
1779 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1780}\r
1781\r
1782/**\r
1783 Dump SMRAM free pool list.\r
1784\r
1785**/\r
1786VOID\r
1787DumpFreePoolList (\r
1788 VOID\r
1789 )\r
1790{\r
1791 LIST_ENTRY *FreePoolList;\r
1792 LIST_ENTRY *Node;\r
1793 FREE_POOL_HEADER *Pool;\r
1794 UINTN Index;\r
1795 UINTN PoolListIndex;\r
1796 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1797 BOOLEAN SmramProfileRecordingStatus;\r
1798\r
1799 ContextData = GetSmramProfileContext ();\r
1800 if (ContextData == NULL) {\r
1801 return ;\r
1802 }\r
1803\r
1804 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1805 mSmramProfileRecordingStatus = FALSE;\r
1806\r
1807 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1808\r
1809 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1810 DEBUG ((EFI_D_INFO, "FreePoolList (%d):\n", PoolListIndex));\r
1811 FreePoolList = &mSmmPoolLists[PoolListIndex];\r
1812 for (Node = FreePoolList->BackLink, Index = 0;\r
1813 Node != FreePoolList;\r
1814 Node = Node->BackLink, Index++) {\r
1815 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1816 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));\r
1817 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool));\r
1818 DEBUG ((EFI_D_INFO, " Size - 0x%08x\n", Pool->Header.Size));\r
1819 DEBUG ((EFI_D_INFO, " Available - 0x%02x\n", Pool->Header.Available));\r
1820 }\r
1821 }\r
1822\r
1823 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1824\r
1825 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1826}\r
1827\r
1828GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = {\r
1829 L"Unknown",\r
1830 L"AllocatePages",\r
1831 L"FreePages",\r
1832 L"AllocatePool",\r
1833 L"FreePool",\r
1834};\r
1835\r
1836GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mMemoryTypeString[] = {\r
1837 L"EfiReservedMemoryType",\r
1838 L"EfiLoaderCode",\r
1839 L"EfiLoaderData",\r
1840 L"EfiBootServicesCode",\r
1841 L"EfiBootServicesData",\r
1842 L"EfiRuntimeServicesCode",\r
1843 L"EfiRuntimeServicesData",\r
1844 L"EfiConventionalMemory",\r
1845 L"EfiUnusableMemory",\r
1846 L"EfiACPIReclaimMemory",\r
1847 L"EfiACPIMemoryNVS",\r
1848 L"EfiMemoryMappedIO",\r
1849 L"EfiMemoryMappedIOPortSpace",\r
1850 L"EfiPalCode",\r
1851 L"EfiOSReserved",\r
1852};\r
1853\r
1854\r
1855/**\r
1856 Dump SMRAM profile.\r
1857\r
1858**/\r
1859VOID\r
1860DumpSmramProfile (\r
1861 VOID\r
1862 )\r
1863{\r
1864 MEMORY_PROFILE_CONTEXT *Context;\r
1865 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
1866 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
1867 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1868 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1869 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
1870 LIST_ENTRY *SmramDriverInfoList;\r
1871 UINTN DriverIndex;\r
1872 LIST_ENTRY *DriverLink;\r
1873 LIST_ENTRY *AllocInfoList;\r
1874 UINTN AllocIndex;\r
1875 LIST_ENTRY *AllocLink;\r
1876 BOOLEAN SmramProfileRecordingStatus;\r
1877 UINTN TypeIndex;\r
1878\r
1879 ContextData = GetSmramProfileContext ();\r
1880 if (ContextData == NULL) {\r
1881 return ;\r
1882 }\r
1883\r
1884 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1885 mSmramProfileRecordingStatus = FALSE;\r
1886\r
1887 Context = &ContextData->Context;\r
1888 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1889 DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n"));\r
1890\r
1891 DEBUG ((EFI_D_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage));\r
1892 DEBUG ((EFI_D_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage));\r
1893 for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {\r
1894 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||\r
1895 (Context->PeakTotalUsageByType[TypeIndex] != 0)) {\r
1896 DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
1897 DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
1898 }\r
1899 }\r
1900 DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize));\r
1901 DEBUG ((EFI_D_INFO, " ImageCount - 0x%08x\n", Context->ImageCount));\r
1902 DEBUG ((EFI_D_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount));\r
1903\r
1904 SmramDriverInfoList = ContextData->DriverInfoList;\r
1905 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;\r
1906 DriverLink != SmramDriverInfoList;\r
1907 DriverLink = DriverLink->ForwardLink, DriverIndex++) {\r
1908 DriverInfoData = CR (\r
1909 DriverLink,\r
1910 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1911 Link,\r
1912 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1913 );\r
1914 DriverInfo = &DriverInfoData->DriverInfo;\r
1915 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));\r
1916 DEBUG ((EFI_D_INFO, " FileName - %g\n", &DriverInfo->FileName));\r
1917 DEBUG ((EFI_D_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase));\r
1918 DEBUG ((EFI_D_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize));\r
1919 DEBUG ((EFI_D_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint));\r
1920 DEBUG ((EFI_D_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem));\r
1921 DEBUG ((EFI_D_INFO, " FileType - 0x%02x\n", DriverInfo->FileType));\r
1922 DEBUG ((EFI_D_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage));\r
1923 DEBUG ((EFI_D_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage));\r
1924 for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {\r
1925 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||\r
1926 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {\r
1927 DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
1928 DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
1929 }\r
1930 }\r
1931 DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount));\r
1932\r
1933 AllocInfoList = DriverInfoData->AllocInfoList;\r
1934 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;\r
1935 AllocLink != AllocInfoList;\r
1936 AllocLink = AllocLink->ForwardLink, AllocIndex++) {\r
1937 AllocInfoData = CR (\r
1938 AllocLink,\r
1939 MEMORY_PROFILE_ALLOC_INFO_DATA,\r
1940 Link,\r
1941 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
1942 );\r
1943 AllocInfo = &AllocInfoData->AllocInfo;\r
1944 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));\r
1945 DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));\r
1946 DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId));\r
1947 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]));\r
1948 DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x\n", AllocInfo->MemoryType));\r
1949 DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer));\r
1950 DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size));\r
1951 }\r
1952 }\r
1953\r
1954 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1955\r
1956 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1957}\r
1958\r
1959/**\r
1960 Dump SMRAM infromation.\r
1961\r
1962**/\r
1963VOID\r
1964DumpSmramInfo (\r
1965 VOID\r
1966 )\r
1967{\r
1968 DEBUG_CODE (\r
1969 if (IS_SMRAM_PROFILE_ENABLED) {\r
1970 DumpSmramProfile ();\r
1971 DumpFreePagesList ();\r
1972 DumpFreePoolList ();\r
1973 DumpSmramRange ();\r
1974 }\r
1975 );\r
1976}\r
1977\r