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