]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Application/VariableInfo/VariableInfo.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Application / VariableInfo / VariableInfo.c
... / ...
CommitLineData
1/** @file\r
2 If the Variable services have PcdVariableCollectStatistics set to TRUE then\r
3 this utility will print out the statistics information. You can use console\r
4 redirection to capture the data.\r
5\r
6 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
8\r
9**/\r
10\r
11#include <Uefi.h>\r
12#include <Library/UefiLib.h>\r
13#include <Library/UefiApplicationEntryPoint.h>\r
14#include <Library/BaseMemoryLib.h>\r
15#include <Library/BaseLib.h>\r
16#include <Library/MemoryAllocationLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/UefiBootServicesTableLib.h>\r
19\r
20#include <Guid/VariableFormat.h>\r
21#include <Guid/SmmVariableCommon.h>\r
22#include <Guid/PiSmmCommunicationRegionTable.h>\r
23#include <Protocol/MmCommunication2.h>\r
24#include <Protocol/SmmVariable.h>\r
25\r
26EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication2 = NULL;\r
27\r
28/**\r
29 This function get the variable statistics data from SMM variable driver.\r
30\r
31 @param[in, out] SmmCommunicateHeader In input, a pointer to a collection of data that will\r
32 be passed into an SMM environment. In output, a pointer\r
33 to a collection of data that comes from an SMM environment.\r
34 @param[in, out] SmmCommunicateSize The size of the SmmCommunicateHeader.\r
35\r
36 @retval EFI_SUCCESS Get the statistics data information.\r
37 @retval EFI_NOT_FOUND Not found.\r
38 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
39\r
40**/\r
41EFI_STATUS\r
42EFIAPI\r
43GetVariableStatisticsData (\r
44 IN OUT EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader,\r
45 IN OUT UINTN *SmmCommunicateSize\r
46 )\r
47{\r
48 EFI_STATUS Status;\r
49 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
50\r
51 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
52 SmmCommunicateHeader->MessageLength = *SmmCommunicateSize - OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);\r
53\r
54 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) &SmmCommunicateHeader->Data[0];\r
55 SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_STATISTICS;\r
56\r
57 Status = mMmCommunication2->Communicate (mMmCommunication2,\r
58 SmmCommunicateHeader,\r
59 SmmCommunicateHeader,\r
60 SmmCommunicateSize);\r
61 ASSERT_EFI_ERROR (Status);\r
62\r
63 Status = SmmVariableFunctionHeader->ReturnStatus;\r
64 return Status;\r
65}\r
66\r
67/**\r
68\r
69 This function get and print the variable statistics data from SMM variable driver.\r
70\r
71 @retval EFI_SUCCESS Print the statistics information successfully.\r
72 @retval EFI_NOT_FOUND Not found the statistics information.\r
73\r
74**/\r
75EFI_STATUS\r
76PrintInfoFromSmm (\r
77 VOID\r
78 )\r
79{\r
80 EFI_STATUS Status;\r
81 VARIABLE_INFO_ENTRY *VariableInfo;\r
82 EFI_MM_COMMUNICATE_HEADER *CommBuffer;\r
83 UINTN RealCommSize;\r
84 UINTN CommSize;\r
85 SMM_VARIABLE_COMMUNICATE_HEADER *FunctionHeader;\r
86 EFI_SMM_VARIABLE_PROTOCOL *Smmvariable;\r
87 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;\r
88 UINT32 Index;\r
89 EFI_MEMORY_DESCRIPTOR *Entry;\r
90 UINTN Size;\r
91 UINTN MaxSize;\r
92\r
93 Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **) &Smmvariable);\r
94 if (EFI_ERROR (Status)) {\r
95 return Status;\r
96 }\r
97\r
98 Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **) &mMmCommunication2);\r
99 if (EFI_ERROR (Status)) {\r
100 return Status;\r
101 }\r
102\r
103 CommBuffer = NULL;\r
104 RealCommSize = 0;\r
105 Status = EfiGetSystemConfigurationTable (\r
106 &gEdkiiPiSmmCommunicationRegionTableGuid,\r
107 (VOID **) &PiSmmCommunicationRegionTable\r
108 );\r
109 if (EFI_ERROR (Status)) {\r
110 return Status;\r
111 }\r
112 ASSERT (PiSmmCommunicationRegionTable != NULL);\r
113 Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);\r
114 Size = 0;\r
115 MaxSize = 0;\r
116 for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
117 if (Entry->Type == EfiConventionalMemory) {\r
118 Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);\r
119 if (Size > (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (VARIABLE_INFO_ENTRY))) {\r
120 if (Size > MaxSize) {\r
121 MaxSize = Size;\r
122 RealCommSize = MaxSize;\r
123 CommBuffer = (EFI_MM_COMMUNICATE_HEADER *) (UINTN) Entry->PhysicalStart;\r
124 }\r
125 }\r
126 }\r
127 Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
128 }\r
129 ASSERT (CommBuffer != NULL);\r
130 ZeroMem (CommBuffer, RealCommSize);\r
131\r
132 Print (L"SMM Driver Non-Volatile Variables:\n");\r
133 do {\r
134 CommSize = RealCommSize;\r
135 Status = GetVariableStatisticsData (CommBuffer, &CommSize);\r
136 if (Status == EFI_BUFFER_TOO_SMALL) {\r
137 Print (L"The generic SMM communication buffer provided by SmmCommunicationRegionTable is too small\n");\r
138 return Status;\r
139 }\r
140\r
141 if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {\r
142 break;\r
143 }\r
144\r
145 FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;\r
146 VariableInfo = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;\r
147\r
148 if (!VariableInfo->Volatile) {\r
149 Print (\r
150 L"%g R%03d(%03d) W%03d D%03d:%s\n",\r
151 &VariableInfo->VendorGuid,\r
152 VariableInfo->ReadCount,\r
153 VariableInfo->CacheCount,\r
154 VariableInfo->WriteCount,\r
155 VariableInfo->DeleteCount,\r
156 (CHAR16 *)(VariableInfo + 1)\r
157 );\r
158 }\r
159 } while (TRUE);\r
160\r
161 Print (L"SMM Driver Volatile Variables:\n");\r
162 ZeroMem (CommBuffer, RealCommSize);\r
163 do {\r
164 CommSize = RealCommSize;\r
165 Status = GetVariableStatisticsData (CommBuffer, &CommSize);\r
166 if (Status == EFI_BUFFER_TOO_SMALL) {\r
167 Print (L"The generic SMM communication buffer provided by SmmCommunicationRegionTable is too small\n");\r
168 return Status;\r
169 }\r
170\r
171 if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {\r
172 break;\r
173 }\r
174\r
175 FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;\r
176 VariableInfo = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;\r
177\r
178 if (VariableInfo->Volatile) {\r
179 Print (\r
180 L"%g R%03d(%03d) W%03d D%03d:%s\n",\r
181 &VariableInfo->VendorGuid,\r
182 VariableInfo->ReadCount,\r
183 VariableInfo->CacheCount,\r
184 VariableInfo->WriteCount,\r
185 VariableInfo->DeleteCount,\r
186 (CHAR16 *)(VariableInfo + 1)\r
187 );\r
188 }\r
189 } while (TRUE);\r
190\r
191 return Status;\r
192}\r
193\r
194/**\r
195 The user Entry Point for Application. The user code starts with this function\r
196 as the real entry point for the image goes into a library that calls this\r
197 function.\r
198\r
199 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
200 @param[in] SystemTable A pointer to the EFI System Table.\r
201\r
202 @retval EFI_SUCCESS The entry point is executed successfully.\r
203 @retval other Some error occurs when executing this entry point.\r
204\r
205**/\r
206EFI_STATUS\r
207EFIAPI\r
208UefiMain (\r
209 IN EFI_HANDLE ImageHandle,\r
210 IN EFI_SYSTEM_TABLE *SystemTable\r
211 )\r
212{\r
213 EFI_STATUS RuntimeDxeStatus;\r
214 EFI_STATUS SmmStatus;\r
215 VARIABLE_INFO_ENTRY *VariableInfo;\r
216 VARIABLE_INFO_ENTRY *Entry;\r
217\r
218 RuntimeDxeStatus = EfiGetSystemConfigurationTable (&gEfiVariableGuid, (VOID **) &Entry);\r
219 if (EFI_ERROR (RuntimeDxeStatus) || (Entry == NULL)) {\r
220 RuntimeDxeStatus = EfiGetSystemConfigurationTable (&gEfiAuthenticatedVariableGuid, (VOID **) &Entry);\r
221 }\r
222\r
223 if (!EFI_ERROR (RuntimeDxeStatus) && (Entry != NULL)) {\r
224 Print (L"Runtime DXE Driver Non-Volatile EFI Variables:\n");\r
225 VariableInfo = Entry;\r
226 do {\r
227 if (!VariableInfo->Volatile) {\r
228 Print (\r
229 L"%g R%03d(%03d) W%03d D%03d:%s\n",\r
230 &VariableInfo->VendorGuid,\r
231 VariableInfo->ReadCount,\r
232 VariableInfo->CacheCount,\r
233 VariableInfo->WriteCount,\r
234 VariableInfo->DeleteCount,\r
235 VariableInfo->Name\r
236 );\r
237 }\r
238\r
239 VariableInfo = VariableInfo->Next;\r
240 } while (VariableInfo != NULL);\r
241\r
242 Print (L"Runtime DXE Driver Volatile EFI Variables:\n");\r
243 VariableInfo = Entry;\r
244 do {\r
245 if (VariableInfo->Volatile) {\r
246 Print (\r
247 L"%g R%03d(%03d) W%03d D%03d:%s\n",\r
248 &VariableInfo->VendorGuid,\r
249 VariableInfo->ReadCount,\r
250 VariableInfo->CacheCount,\r
251 VariableInfo->WriteCount,\r
252 VariableInfo->DeleteCount,\r
253 VariableInfo->Name\r
254 );\r
255 }\r
256 VariableInfo = VariableInfo->Next;\r
257 } while (VariableInfo != NULL);\r
258 }\r
259\r
260 SmmStatus = PrintInfoFromSmm ();\r
261\r
262 if (EFI_ERROR (RuntimeDxeStatus) && EFI_ERROR (SmmStatus)) {\r
263 Print (L"Warning: Variable Dxe/Smm driver doesn't enable the feature of statistical information!\n");\r
264 Print (L"If you want to see this info, please:\n");\r
265 Print (L" 1. Set PcdVariableCollectStatistics as TRUE\n");\r
266 Print (L" 2. Rebuild Variable Dxe/Smm driver\n");\r
267 Print (L" 3. Run \"VariableInfo\" cmd again\n");\r
268\r
269 return EFI_NOT_FOUND;\r
270 }\r
271\r
272 return EFI_SUCCESS;\r
273}\r