]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
Use SmmMemLib to check communication buffer.
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmramProfileRecord.c
CommitLineData
84edd20b
SZ
1/** @file\r
2 Support routines for SMRAM profile.\r
3\r
842b1242 4 Copyright (c) 2014 - 2015, 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 "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
84edd20b
SZ
1178/**\r
1179 Get SMRAM profile data size.\r
1180\r
1181 @return SMRAM profile data size.\r
1182\r
1183**/\r
1184UINTN\r
1185SmramProfileGetDataSize (\r
1186 VOID\r
1187 )\r
1188{\r
1189 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1190 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1191 LIST_ENTRY *DriverInfoList;\r
1192 LIST_ENTRY *DriverLink;\r
1193 UINTN TotalSize;\r
1194 LIST_ENTRY *Node;\r
1195 LIST_ENTRY *FreePageList;\r
1196 LIST_ENTRY *FreePoolList;\r
1197 FREE_POOL_HEADER *Pool;\r
1198 UINTN PoolListIndex;\r
1199 UINTN Index;\r
1200\r
1201 ContextData = GetSmramProfileContext ();\r
1202 if (ContextData == NULL) {\r
1203 return 0;\r
1204 }\r
1205\r
1206 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);\r
1207 TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount;\r
1208\r
1209 DriverInfoList = ContextData->DriverInfoList;\r
1210 for (DriverLink = DriverInfoList->ForwardLink;\r
1211 DriverLink != DriverInfoList;\r
1212 DriverLink = DriverLink->ForwardLink) {\r
1213 DriverInfoData = CR (\r
1214 DriverLink,\r
1215 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1216 Link,\r
1217 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1218 );\r
1219 TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfoData->DriverInfo.AllocRecordCount;\r
1220 }\r
1221\r
1222\r
1223 Index = 0;\r
1224 FreePageList = &mSmmMemoryMap;\r
1225 for (Node = FreePageList->BackLink;\r
1226 Node != FreePageList;\r
1227 Node = Node->BackLink) {\r
1228 Index++;\r
1229 }\r
1230 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1231 FreePoolList = &mSmmPoolLists[PoolListIndex];\r
1232 for (Node = FreePoolList->BackLink;\r
1233 Node != FreePoolList;\r
1234 Node = Node->BackLink) {\r
1235 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1236 if (Pool->Header.Available) {\r
1237 Index++;\r
1238 }\r
1239 }\r
1240 }\r
1241\r
1242\r
1243 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));\r
1244 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));\r
1245\r
1246 return TotalSize;\r
1247}\r
1248\r
1249/**\r
1250 Copy SMRAM profile data.\r
1251\r
1252 @param ProfileBuffer The buffer to hold SMRAM profile data.\r
1253\r
1254**/\r
1255VOID\r
1256SmramProfileCopyData (\r
1257 IN VOID *ProfileBuffer\r
1258 )\r
1259{\r
1260 MEMORY_PROFILE_CONTEXT *Context;\r
1261 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
1262 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
1263 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1264 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1265 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
1266 LIST_ENTRY *DriverInfoList;\r
1267 LIST_ENTRY *DriverLink;\r
1268 LIST_ENTRY *AllocInfoList;\r
1269 LIST_ENTRY *AllocLink;\r
1270 LIST_ENTRY *Node;\r
1271 FREE_PAGE_LIST *Pages;\r
1272 LIST_ENTRY *FreePageList;\r
1273 LIST_ENTRY *FreePoolList;\r
1274 FREE_POOL_HEADER *Pool;\r
1275 UINTN PoolListIndex;\r
1276 UINT32 Index;\r
1277 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;\r
1278 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;\r
1279 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor;\r
1280\r
1281 ContextData = GetSmramProfileContext ();\r
1282 if (ContextData == NULL) {\r
1283 return ;\r
1284 }\r
1285\r
1286 Context = ProfileBuffer;\r
1287 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));\r
1288 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);\r
1289\r
1290 DriverInfoList = ContextData->DriverInfoList;\r
1291 for (DriverLink = DriverInfoList->ForwardLink;\r
1292 DriverLink != DriverInfoList;\r
1293 DriverLink = DriverLink->ForwardLink) {\r
1294 DriverInfoData = CR (\r
1295 DriverLink,\r
1296 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1297 Link,\r
1298 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1299 );\r
1300 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));\r
1301 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1);\r
1302\r
1303 AllocInfoList = DriverInfoData->AllocInfoList;\r
1304 for (AllocLink = AllocInfoList->ForwardLink;\r
1305 AllocLink != AllocInfoList;\r
1306 AllocLink = AllocLink->ForwardLink) {\r
1307 AllocInfoData = CR (\r
1308 AllocLink,\r
1309 MEMORY_PROFILE_ALLOC_INFO_DATA,\r
1310 Link,\r
1311 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
1312 );\r
1313 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));\r
1314 AllocInfo += 1;\r
1315 }\r
1316\r
1317 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount);\r
1318 }\r
1319\r
1320\r
1321 FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) DriverInfo;\r
1322 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));\r
1323 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (FreeMemory + 1);\r
1324 Index = 0;\r
1325 FreePageList = &mSmmMemoryMap;\r
1326 for (Node = FreePageList->BackLink;\r
1327 Node != FreePageList;\r
1328 Node = Node->BackLink) {\r
1329 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
1330 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1331 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1332 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1333 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages;\r
1334 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);\r
1335 MemoryProfileDescriptor++;\r
1336 Index++;\r
1337 }\r
1338 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1339 FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];\r
1340 for (Node = FreePoolList->BackLink;\r
1341 Node != FreePoolList;\r
1342 Node = Node->BackLink) {\r
1343 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1344 if (Pool->Header.Available) {\r
1345 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1346 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1347 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1348 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool;\r
1349 MemoryProfileDescriptor->Size = Pool->Header.Size;\r
1350 MemoryProfileDescriptor++;\r
1351 Index++;\r
1352 }\r
1353 }\r
1354 }\r
1355 FreeMemory->FreeMemoryEntryCount = Index;\r
1356\r
1357 MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) MemoryProfileDescriptor;\r
1358 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;\r
1359 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);\r
1360 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;\r
1361 MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount;\r
1362 MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (MemoryRange + 1);\r
1363 for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
1364 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
1365 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
1366 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
1367 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;\r
1368 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;\r
1369 MemoryProfileDescriptor++; \r
1370 }\r
1371}\r
1372\r
1373/**\r
1374 SMRAM profile handler to get profile info.\r
1375\r
1376 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.\r
1377\r
1378**/\r
1379VOID\r
1380SmramProfileHandlerGetInfo (\r
1381 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo\r
1382 )\r
1383{\r
1384 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1385 BOOLEAN SmramProfileRecordingStatus;\r
1386\r
1387 ContextData = GetSmramProfileContext ();\r
1388 if (ContextData == NULL) {\r
1389 return ;\r
1390 }\r
1391\r
1392 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1393 mSmramProfileRecordingStatus = FALSE;\r
1394\r
1395 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();\r
1396 SmramProfileParameterGetInfo->Header.ReturnStatus = 0;\r
1397\r
1398 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1399}\r
1400\r
1401/**\r
1402 SMRAM profile handler to get profile data.\r
1403\r
1404 @param SmramProfileParameterGetData The parameter of SMM profile get data.\r
1405\r
1406**/\r
1407VOID\r
1408SmramProfileHandlerGetData (\r
1409 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData\r
1410 )\r
1411{\r
1412 UINT64 ProfileSize;\r
1413 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData;\r
1414 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1415 BOOLEAN SmramProfileRecordingStatus;\r
1416\r
1417 ContextData = GetSmramProfileContext ();\r
1418 if (ContextData == NULL) {\r
1419 return ;\r
1420 }\r
1421\r
1422 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1423 mSmramProfileRecordingStatus = FALSE;\r
1424\r
1425\r
1426 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));\r
1427\r
1428 ProfileSize = SmramProfileGetDataSize();\r
1429\r
1430 //\r
1431 // Sanity check\r
1432 //\r
842b1242 1433 if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {\r
84edd20b
SZ
1434 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));\r
1435 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1436 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;\r
1437 goto Done;\r
1438 }\r
1439\r
1440 if (SmramProfileGetData.ProfileSize < ProfileSize) {\r
1441 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1442 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL;\r
1443 goto Done;\r
1444 }\r
1445\r
1446 SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
1447 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer);\r
1448 SmramProfileParameterGetData->Header.ReturnStatus = 0;\r
1449\r
1450Done:\r
1451 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1452}\r
1453\r
1454/**\r
1455 SMRAM profile handler to register SMM image.\r
1456\r
1457 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.\r
1458\r
1459**/\r
1460VOID\r
1461SmramProfileHandlerRegisterImage (\r
1462 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage\r
1463 )\r
1464{\r
1465 EFI_STATUS Status;\r
1466 EFI_SMM_DRIVER_ENTRY DriverEntry;\r
1467 VOID *EntryPointInImage;\r
1468 BOOLEAN Ret;\r
1469\r
1470 ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
1471 CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));\r
1472 DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer;\r
1473 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage;\r
1474 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
1475 ASSERT_EFI_ERROR (Status);\r
1476 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
1477\r
1478 Ret = RegisterSmramProfileImage (&DriverEntry, FALSE);\r
1479 if (Ret) {\r
1480 SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;\r
1481 }\r
1482}\r
1483\r
1484/**\r
1485 SMRAM profile handler to unregister SMM image.\r
1486\r
1487 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.\r
1488\r
1489**/\r
1490VOID\r
1491SmramProfileHandlerUnregisterImage (\r
1492 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage\r
1493 )\r
1494{\r
1495 EFI_STATUS Status;\r
1496 EFI_SMM_DRIVER_ENTRY DriverEntry;\r
1497 VOID *EntryPointInImage;\r
1498 BOOLEAN Ret;\r
1499\r
1500 ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
1501 CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));\r
1502 DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer;\r
1503 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage;\r
1504 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
1505 ASSERT_EFI_ERROR (Status);\r
1506 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
1507\r
1508 Ret = UnregisterSmramProfileImage (&DriverEntry, FALSE);\r
1509 if (Ret) {\r
1510 SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;\r
1511 }\r
1512}\r
1513\r
1514/**\r
1515 Dispatch function for a Software SMI handler.\r
1516\r
1517 Caution: This function may receive untrusted input.\r
1518 Communicate buffer and buffer size are external input, so this function will do basic validation.\r
1519\r
1520 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
1521 @param Context Points to an optional handler context which was specified when the\r
1522 handler was registered.\r
1523 @param CommBuffer A pointer to a collection of data in memory that will\r
1524 be conveyed from a non-SMM environment into an SMM environment.\r
1525 @param CommBufferSize The size of the CommBuffer.\r
1526\r
1527 @retval EFI_SUCCESS Command is handled successfully.\r
1528\r
1529**/\r
1530EFI_STATUS\r
1531EFIAPI\r
1532SmramProfileHandler (\r
1533 IN EFI_HANDLE DispatchHandle,\r
1534 IN CONST VOID *Context OPTIONAL,\r
1535 IN OUT VOID *CommBuffer OPTIONAL,\r
1536 IN OUT UINTN *CommBufferSize OPTIONAL\r
1537 )\r
1538{\r
1539 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader;\r
1540 UINTN TempCommBufferSize;\r
1541\r
1542 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));\r
1543\r
1544 //\r
1545 // If input is invalid, stop processing this SMI\r
1546 //\r
1547 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
1548 return EFI_SUCCESS;\r
1549 }\r
1550\r
1551 TempCommBufferSize = *CommBufferSize;\r
1552\r
1553 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {\r
1554 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1555 return EFI_SUCCESS;\r
1556 }\r
1557\r
842b1242 1558 if (mSmramReadyToLock && !SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
84edd20b
SZ
1559 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
1560 return EFI_SUCCESS;\r
1561 }\r
1562\r
1563 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer);\r
1564\r
1565 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;\r
1566\r
1567 if (GetSmramProfileContext () == NULL) {\r
1568 SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED;\r
1569 return EFI_SUCCESS;\r
1570 }\r
1571\r
1572 switch (SmramProfileParameterHeader->Command) {\r
1573 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:\r
1574 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n"));\r
1575 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {\r
1576 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1577 return EFI_SUCCESS;\r
1578 }\r
1579 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer);\r
1580 break;\r
1581 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:\r
1582 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n"));\r
1583 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {\r
1584 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1585 return EFI_SUCCESS;\r
1586 }\r
1587 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);\r
1588 break;\r
1589 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE:\r
1590 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n"));\r
1591 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) {\r
1592 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1593 return EFI_SUCCESS;\r
1594 }\r
1595 if (mSmramReadyToLock) {\r
1596 return EFI_SUCCESS;\r
1597 }\r
1598 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer);\r
1599 break;\r
1600 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE:\r
1601 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n"));\r
1602 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) {\r
1603 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
1604 return EFI_SUCCESS;\r
1605 }\r
1606 if (mSmramReadyToLock) {\r
1607 return EFI_SUCCESS;\r
1608 }\r
1609 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);\r
1610 break;\r
1611 default:\r
1612 break;\r
1613 }\r
1614\r
1615 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n"));\r
1616\r
1617 return EFI_SUCCESS;\r
1618}\r
1619\r
1620/**\r
1621 Register SMRAM profile handler.\r
1622\r
1623**/\r
1624VOID\r
1625RegisterSmramProfileHandler (\r
1626 VOID\r
1627 )\r
1628{\r
1629 EFI_STATUS Status;\r
1630 EFI_HANDLE DispatchHandle;\r
1631\r
1632 if (!IS_SMRAM_PROFILE_ENABLED) {\r
1633 return;\r
1634 }\r
1635\r
1636 Status = SmiHandlerRegister (\r
1637 SmramProfileHandler,\r
1638 &gEdkiiMemoryProfileGuid,\r
1639 &DispatchHandle\r
1640 );\r
1641 ASSERT_EFI_ERROR (Status);\r
1642}\r
1643\r
1644////////////////////\r
1645\r
1646/**\r
1647 Dump SMRAM range.\r
1648\r
1649**/\r
1650VOID\r
1651DumpSmramRange (\r
1652 VOID\r
1653 )\r
1654{\r
1655 UINTN Index;\r
1656 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1657 BOOLEAN SmramProfileRecordingStatus;\r
1658\r
1659 ContextData = GetSmramProfileContext ();\r
1660 if (ContextData == NULL) {\r
1661 return ;\r
1662 }\r
1663\r
1664 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1665 mSmramProfileRecordingStatus = FALSE;\r
1666\r
1667 DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));\r
1668\r
1669 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1670\r
1671 DEBUG ((EFI_D_INFO, "FullSmramRange:\n"));\r
1672 for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
1673 DEBUG ((EFI_D_INFO, " FullSmramRange (0x%x)\n", Index));\r
1674 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));\r
1675 DEBUG ((EFI_D_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));\r
1676 DEBUG ((EFI_D_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));\r
1677 DEBUG ((EFI_D_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState));\r
1678 }\r
1679\r
1680 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1681\r
1682 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1683}\r
1684\r
1685/**\r
1686 Dump SMRAM free page list.\r
1687\r
1688**/\r
1689VOID\r
1690DumpFreePagesList (\r
1691 VOID\r
1692 )\r
1693{\r
1694 LIST_ENTRY *FreePageList;\r
1695 LIST_ENTRY *Node;\r
1696 FREE_PAGE_LIST *Pages;\r
1697 UINTN Index;\r
1698 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1699 BOOLEAN SmramProfileRecordingStatus;\r
1700\r
1701 ContextData = GetSmramProfileContext ();\r
1702 if (ContextData == NULL) {\r
1703 return ;\r
1704 }\r
1705\r
1706 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1707 mSmramProfileRecordingStatus = FALSE;\r
1708\r
1709 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1710\r
1711 DEBUG ((EFI_D_INFO, "FreePagesList:\n"));\r
1712 FreePageList = &mSmmMemoryMap;\r
1713 for (Node = FreePageList->BackLink, Index = 0;\r
1714 Node != FreePageList;\r
1715 Node = Node->BackLink, Index++) {\r
1716 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
1717 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));\r
1718 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages));\r
1719 DEBUG ((EFI_D_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages));\r
1720 }\r
1721\r
1722 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1723\r
1724 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1725}\r
1726\r
1727/**\r
1728 Dump SMRAM free pool list.\r
1729\r
1730**/\r
1731VOID\r
1732DumpFreePoolList (\r
1733 VOID\r
1734 )\r
1735{\r
1736 LIST_ENTRY *FreePoolList;\r
1737 LIST_ENTRY *Node;\r
1738 FREE_POOL_HEADER *Pool;\r
1739 UINTN Index;\r
1740 UINTN PoolListIndex;\r
1741 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1742 BOOLEAN SmramProfileRecordingStatus;\r
1743\r
1744 ContextData = GetSmramProfileContext ();\r
1745 if (ContextData == NULL) {\r
1746 return ;\r
1747 }\r
1748\r
1749 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1750 mSmramProfileRecordingStatus = FALSE;\r
1751\r
1752 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1753\r
1754 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
1755 DEBUG ((EFI_D_INFO, "FreePoolList (%d):\n", PoolListIndex));\r
1756 FreePoolList = &mSmmPoolLists[PoolListIndex];\r
1757 for (Node = FreePoolList->BackLink, Index = 0;\r
1758 Node != FreePoolList;\r
1759 Node = Node->BackLink, Index++) {\r
1760 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
1761 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index));\r
1762 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool));\r
1763 DEBUG ((EFI_D_INFO, " Size - 0x%08x\n", Pool->Header.Size));\r
1764 DEBUG ((EFI_D_INFO, " Available - 0x%02x\n", Pool->Header.Available));\r
1765 }\r
1766 }\r
1767\r
1768 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1769\r
1770 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1771}\r
1772\r
1773GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = {\r
1774 L"Unknown",\r
1775 L"AllocatePages",\r
1776 L"FreePages",\r
1777 L"AllocatePool",\r
1778 L"FreePool",\r
1779};\r
1780\r
1781GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mMemoryTypeString[] = {\r
1782 L"EfiReservedMemoryType",\r
1783 L"EfiLoaderCode",\r
1784 L"EfiLoaderData",\r
1785 L"EfiBootServicesCode",\r
1786 L"EfiBootServicesData",\r
1787 L"EfiRuntimeServicesCode",\r
1788 L"EfiRuntimeServicesData",\r
1789 L"EfiConventionalMemory",\r
1790 L"EfiUnusableMemory",\r
1791 L"EfiACPIReclaimMemory",\r
1792 L"EfiACPIMemoryNVS",\r
1793 L"EfiMemoryMappedIO",\r
1794 L"EfiMemoryMappedIOPortSpace",\r
1795 L"EfiPalCode",\r
1796 L"EfiOSReserved",\r
1797};\r
1798\r
1799\r
1800/**\r
1801 Dump SMRAM profile.\r
1802\r
1803**/\r
1804VOID\r
1805DumpSmramProfile (\r
1806 VOID\r
1807 )\r
1808{\r
1809 MEMORY_PROFILE_CONTEXT *Context;\r
1810 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;\r
1811 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;\r
1812 MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
1813 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData;\r
1814 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData;\r
1815 LIST_ENTRY *SmramDriverInfoList;\r
1816 UINTN DriverIndex;\r
1817 LIST_ENTRY *DriverLink;\r
1818 LIST_ENTRY *AllocInfoList;\r
1819 UINTN AllocIndex;\r
1820 LIST_ENTRY *AllocLink;\r
1821 BOOLEAN SmramProfileRecordingStatus;\r
1822 UINTN TypeIndex;\r
1823\r
1824 ContextData = GetSmramProfileContext ();\r
1825 if (ContextData == NULL) {\r
1826 return ;\r
1827 }\r
1828\r
1829 SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
1830 mSmramProfileRecordingStatus = FALSE;\r
1831\r
1832 Context = &ContextData->Context;\r
1833 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
1834 DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n"));\r
1835\r
1836 DEBUG ((EFI_D_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage));\r
1837 DEBUG ((EFI_D_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage));\r
1838 for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {\r
1839 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||\r
1840 (Context->PeakTotalUsageByType[TypeIndex] != 0)) {\r
1841 DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
1842 DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
1843 }\r
1844 }\r
1845 DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize));\r
1846 DEBUG ((EFI_D_INFO, " ImageCount - 0x%08x\n", Context->ImageCount));\r
1847 DEBUG ((EFI_D_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount));\r
1848\r
1849 SmramDriverInfoList = ContextData->DriverInfoList;\r
1850 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;\r
1851 DriverLink != SmramDriverInfoList;\r
1852 DriverLink = DriverLink->ForwardLink, DriverIndex++) {\r
1853 DriverInfoData = CR (\r
1854 DriverLink,\r
1855 MEMORY_PROFILE_DRIVER_INFO_DATA,\r
1856 Link,\r
1857 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
1858 );\r
1859 DriverInfo = &DriverInfoData->DriverInfo;\r
1860 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));\r
1861 DEBUG ((EFI_D_INFO, " FileName - %g\n", &DriverInfo->FileName));\r
1862 DEBUG ((EFI_D_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase));\r
1863 DEBUG ((EFI_D_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize));\r
1864 DEBUG ((EFI_D_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint));\r
1865 DEBUG ((EFI_D_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem));\r
1866 DEBUG ((EFI_D_INFO, " FileType - 0x%02x\n", DriverInfo->FileType));\r
1867 DEBUG ((EFI_D_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage));\r
1868 DEBUG ((EFI_D_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage));\r
1869 for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {\r
1870 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||\r
1871 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {\r
1872 DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
1873 DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
1874 }\r
1875 }\r
1876 DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount));\r
1877\r
1878 AllocInfoList = DriverInfoData->AllocInfoList;\r
1879 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;\r
1880 AllocLink != AllocInfoList;\r
1881 AllocLink = AllocLink->ForwardLink, AllocIndex++) {\r
1882 AllocInfoData = CR (\r
1883 AllocLink,\r
1884 MEMORY_PROFILE_ALLOC_INFO_DATA,\r
1885 Link,\r
1886 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
1887 );\r
1888 AllocInfo = &AllocInfoData->AllocInfo;\r
1889 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));\r
1890 DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));\r
1891 DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId));\r
1892 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]));\r
1893 DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x\n", AllocInfo->MemoryType));\r
1894 DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer));\r
1895 DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size));\r
1896 }\r
1897 }\r
1898\r
1899 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
1900\r
1901 mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
1902}\r
1903\r
1904/**\r
1905 Dump SMRAM infromation.\r
1906\r
1907**/\r
1908VOID\r
1909DumpSmramInfo (\r
1910 VOID\r
1911 )\r
1912{\r
1913 DEBUG_CODE (\r
1914 if (IS_SMRAM_PROFILE_ENABLED) {\r
1915 DumpSmramProfile ();\r
1916 DumpFreePagesList ();\r
1917 DumpFreePoolList ();\r
1918 DumpSmramRange ();\r
1919 }\r
1920 );\r
1921}\r
1922\r