MdeModulePkg/Variable: Add a file for NV variable functions
[mirror_edk2.git] / MdeModulePkg / Application / VariableInfo / VariableInfo.c
CommitLineData
33a5a666 1/** @file\r
627e117a
SZ
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
faf3de9b 6 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
9d510e61 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
33a5a666
A
8\r
9**/\r
10\r
11#include <Uefi.h>\r
33a5a666
A
12#include <Library/UefiLib.h>\r
13#include <Library/UefiApplicationEntryPoint.h>\r
627e117a
SZ
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
3709c4cd 20#include <Guid/VariableFormat.h>\r
627e117a 21#include <Guid/SmmVariableCommon.h>\r
faf3de9b 22#include <Guid/PiSmmCommunicationRegionTable.h>\r
627e117a
SZ
23#include <Protocol/SmmCommunication.h>\r
24#include <Protocol/SmmVariable.h>\r
25\r
26EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = 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_SMM_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_SMM_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
33a5a666 56\r
627e117a
SZ
57 Status = mSmmCommunication->Communicate (mSmmCommunication, SmmCommunicateHeader, SmmCommunicateSize);\r
58 ASSERT_EFI_ERROR (Status);\r
59\r
60 Status = SmmVariableFunctionHeader->ReturnStatus;\r
61 return Status;\r
62}\r
63\r
64/**\r
65\r
66 This function get and print the variable statistics data from SMM variable driver.\r
67\r
68 @retval EFI_SUCCESS Print the statistics information successfully.\r
69 @retval EFI_NOT_FOUND Not found the statistics information.\r
70\r
71**/\r
72EFI_STATUS\r
73PrintInfoFromSmm (\r
74 VOID\r
75 )\r
76{\r
77 EFI_STATUS Status;\r
78 VARIABLE_INFO_ENTRY *VariableInfo;\r
79 EFI_SMM_COMMUNICATE_HEADER *CommBuffer;\r
80 UINTN RealCommSize;\r
81 UINTN CommSize;\r
82 SMM_VARIABLE_COMMUNICATE_HEADER *FunctionHeader;\r
83 EFI_SMM_VARIABLE_PROTOCOL *Smmvariable;\r
faf3de9b
SZ
84 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;\r
85 UINT32 Index;\r
86 EFI_MEMORY_DESCRIPTOR *Entry;\r
87 UINTN Size;\r
88 UINTN MaxSize;\r
627e117a
SZ
89\r
90 Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **) &Smmvariable);\r
91 if (EFI_ERROR (Status)) {\r
92 return Status;\r
93 }\r
94\r
95 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);\r
96 if (EFI_ERROR (Status)) {\r
97 return Status;\r
98 }\r
99\r
faf3de9b 100 CommBuffer = NULL;\r
05b39efb 101 RealCommSize = 0;\r
faf3de9b
SZ
102 Status = EfiGetSystemConfigurationTable (\r
103 &gEdkiiPiSmmCommunicationRegionTableGuid,\r
104 (VOID **) &PiSmmCommunicationRegionTable\r
105 );\r
106 if (EFI_ERROR (Status)) {\r
107 return Status;\r
108 }\r
109 ASSERT (PiSmmCommunicationRegionTable != NULL);\r
110 Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);\r
111 Size = 0;\r
112 MaxSize = 0;\r
113 for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
114 if (Entry->Type == EfiConventionalMemory) {\r
115 Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);\r
116 if (Size > (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (VARIABLE_INFO_ENTRY))) {\r
117 if (Size > MaxSize) {\r
118 MaxSize = Size;\r
119 RealCommSize = MaxSize;\r
120 CommBuffer = (EFI_SMM_COMMUNICATE_HEADER *) (UINTN) Entry->PhysicalStart;\r
121 }\r
122 }\r
123 }\r
124 Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
125 }\r
627e117a 126 ASSERT (CommBuffer != NULL);\r
faf3de9b 127 ZeroMem (CommBuffer, RealCommSize);\r
627e117a
SZ
128\r
129 Print (L"Non-Volatile SMM Variables:\n");\r
130 do {\r
faf3de9b 131 CommSize = RealCommSize;\r
627e117a
SZ
132 Status = GetVariableStatisticsData (CommBuffer, &CommSize);\r
133 if (Status == EFI_BUFFER_TOO_SMALL) {\r
faf3de9b
SZ
134 Print (L"The generic SMM communication buffer provided by SmmCommunicationRegionTable is too small\n");\r
135 return Status;\r
627e117a
SZ
136 }\r
137\r
138 if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {\r
139 break;\r
140 }\r
141\r
627e117a
SZ
142 FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;\r
143 VariableInfo = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;\r
144\r
145 if (!VariableInfo->Volatile) {\r
146 Print (\r
147 L"%g R%03d(%03d) W%03d D%03d:%s\n",\r
148 &VariableInfo->VendorGuid,\r
149 VariableInfo->ReadCount,\r
150 VariableInfo->CacheCount,\r
151 VariableInfo->WriteCount,\r
152 VariableInfo->DeleteCount,\r
153 (CHAR16 *)(VariableInfo + 1)\r
154 );\r
155 }\r
156 } while (TRUE);\r
157\r
158 Print (L"Volatile SMM Variables:\n");\r
faf3de9b 159 ZeroMem (CommBuffer, RealCommSize);\r
627e117a 160 do {\r
faf3de9b 161 CommSize = RealCommSize;\r
627e117a
SZ
162 Status = GetVariableStatisticsData (CommBuffer, &CommSize);\r
163 if (Status == EFI_BUFFER_TOO_SMALL) {\r
faf3de9b
SZ
164 Print (L"The generic SMM communication buffer provided by SmmCommunicationRegionTable is too small\n");\r
165 return Status;\r
627e117a
SZ
166 }\r
167\r
168 if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {\r
169 break;\r
170 }\r
171\r
627e117a
SZ
172 FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;\r
173 VariableInfo = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;\r
174\r
175 if (VariableInfo->Volatile) {\r
176 Print (\r
177 L"%g R%03d(%03d) W%03d D%03d:%s\n",\r
178 &VariableInfo->VendorGuid,\r
179 VariableInfo->ReadCount,\r
180 VariableInfo->CacheCount,\r
181 VariableInfo->WriteCount,\r
182 VariableInfo->DeleteCount,\r
183 (CHAR16 *)(VariableInfo + 1)\r
184 );\r
185 }\r
186 } while (TRUE);\r
187\r
627e117a
SZ
188 return Status;\r
189}\r
33a5a666
A
190\r
191/**\r
192 The user Entry Point for Application. The user code starts with this function\r
627e117a 193 as the real entry point for the image goes into a library that calls this\r
33a5a666
A
194 function.\r
195\r
627e117a 196 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
33a5a666 197 @param[in] SystemTable A pointer to the EFI System Table.\r
627e117a 198\r
33a5a666
A
199 @retval EFI_SUCCESS The entry point is executed successfully.\r
200 @retval other Some error occurs when executing this entry point.\r
201\r
202**/\r
203EFI_STATUS\r
204EFIAPI\r
205UefiMain (\r
206 IN EFI_HANDLE ImageHandle,\r
207 IN EFI_SYSTEM_TABLE *SystemTable\r
208 )\r
209{\r
210 EFI_STATUS Status;\r
211 VARIABLE_INFO_ENTRY *VariableInfo;\r
212 VARIABLE_INFO_ENTRY *Entry;\r
213\r
3709c4cd 214 Status = EfiGetSystemConfigurationTable (&gEfiVariableGuid, (VOID **)&Entry);\r
627e117a
SZ
215 if (EFI_ERROR (Status) || (Entry == NULL)) {\r
216 Status = EfiGetSystemConfigurationTable (&gEfiAuthenticatedVariableGuid, (VOID **)&Entry);\r
217 }\r
218\r
219 if (EFI_ERROR (Status) || (Entry == NULL)) {\r
220 Status = PrintInfoFromSmm ();\r
221 if (!EFI_ERROR (Status)) {\r
222 return Status;\r
223 }\r
224 }\r
225\r
33a5a666
A
226 if (!EFI_ERROR (Status) && (Entry != NULL)) {\r
227 Print (L"Non-Volatile EFI Variables:\n");\r
228 VariableInfo = Entry;\r
229 do {\r
230 if (!VariableInfo->Volatile) {\r
231 Print (\r
627e117a
SZ
232 L"%g R%03d(%03d) W%03d D%03d:%s\n",\r
233 &VariableInfo->VendorGuid,\r
33a5a666
A
234 VariableInfo->ReadCount,\r
235 VariableInfo->CacheCount,\r
236 VariableInfo->WriteCount,\r
237 VariableInfo->DeleteCount,\r
238 VariableInfo->Name\r
239 );\r
240 }\r
241\r
242 VariableInfo = VariableInfo->Next;\r
243 } while (VariableInfo != NULL);\r
244\r
245 Print (L"Volatile EFI Variables:\n");\r
246 VariableInfo = Entry;\r
247 do {\r
248 if (VariableInfo->Volatile) {\r
249 Print (\r
627e117a
SZ
250 L"%g R%03d(%03d) W%03d D%03d:%s\n",\r
251 &VariableInfo->VendorGuid,\r
33a5a666
A
252 VariableInfo->ReadCount,\r
253 VariableInfo->CacheCount,\r
254 VariableInfo->WriteCount,\r
255 VariableInfo->DeleteCount,\r
256 VariableInfo->Name\r
257 );\r
258 }\r
259 VariableInfo = VariableInfo->Next;\r
260 } while (VariableInfo != NULL);\r
261\r
5e895e6a 262 } else {\r
faf3de9b 263 Print (L"Warning: Variable Dxe/Smm driver doesn't enable the feature of statistical information!\n");\r
5e895e6a 264 Print (L"If you want to see this info, please:\n");\r
265 Print (L" 1. Set PcdVariableCollectStatistics as TRUE\n");\r
faf3de9b 266 Print (L" 2. Rebuild Variable Dxe/Smm driver\n");\r
5e895e6a 267 Print (L" 3. Run \"VariableInfo\" cmd again\n");\r
33a5a666
A
268 }\r
269\r
133e09da 270 return Status;\r
33a5a666 271}\r