• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
GetVariableStatisticsData(IN OUT EFI_SMM_COMMUNICATE_HEADER * SmmCommunicateHeader,IN OUT UINTN * SmmCommunicateSize)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
PrintInfoFromSmm(VOID)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   RealCommSize = 0;
108   Status = EfiGetSystemConfigurationTable (
109              &gEdkiiPiSmmCommunicationRegionTableGuid,
110              (VOID **) &PiSmmCommunicationRegionTable
111              );
112   if (EFI_ERROR (Status)) {
113     return Status;
114   }
115   ASSERT (PiSmmCommunicationRegionTable != NULL);
116   Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);
117   Size = 0;
118   MaxSize = 0;
119   for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
120     if (Entry->Type == EfiConventionalMemory) {
121       Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);
122       if (Size > (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (VARIABLE_INFO_ENTRY))) {
123         if (Size > MaxSize) {
124           MaxSize = Size;
125           RealCommSize = MaxSize;
126           CommBuffer = (EFI_SMM_COMMUNICATE_HEADER *) (UINTN) Entry->PhysicalStart;
127         }
128       }
129     }
130     Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);
131   }
132   ASSERT (CommBuffer != NULL);
133   ZeroMem (CommBuffer, RealCommSize);
134 
135   Print (L"Non-Volatile SMM Variables:\n");
136   do {
137     CommSize = RealCommSize;
138     Status = GetVariableStatisticsData (CommBuffer, &CommSize);
139     if (Status == EFI_BUFFER_TOO_SMALL) {
140       Print (L"The generic SMM communication buffer provided by SmmCommunicationRegionTable is too small\n");
141       return Status;
142     }
143 
144     if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {
145       break;
146     }
147 
148     FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;
149     VariableInfo   = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;
150 
151     if (!VariableInfo->Volatile) {
152       Print (
153           L"%g R%03d(%03d) W%03d D%03d:%s\n",
154           &VariableInfo->VendorGuid,
155           VariableInfo->ReadCount,
156           VariableInfo->CacheCount,
157           VariableInfo->WriteCount,
158           VariableInfo->DeleteCount,
159           (CHAR16 *)(VariableInfo + 1)
160           );
161     }
162   } while (TRUE);
163 
164   Print (L"Volatile SMM Variables:\n");
165   ZeroMem (CommBuffer, RealCommSize);
166   do {
167     CommSize = RealCommSize;
168     Status = GetVariableStatisticsData (CommBuffer, &CommSize);
169     if (Status == EFI_BUFFER_TOO_SMALL) {
170       Print (L"The generic SMM communication buffer provided by SmmCommunicationRegionTable is too small\n");
171       return Status;
172     }
173 
174     if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {
175       break;
176     }
177 
178     FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;
179     VariableInfo   = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;
180 
181     if (VariableInfo->Volatile) {
182       Print (
183           L"%g R%03d(%03d) W%03d D%03d:%s\n",
184           &VariableInfo->VendorGuid,
185           VariableInfo->ReadCount,
186           VariableInfo->CacheCount,
187           VariableInfo->WriteCount,
188           VariableInfo->DeleteCount,
189           (CHAR16 *)(VariableInfo + 1)
190           );
191     }
192   } while (TRUE);
193 
194   return Status;
195 }
196 
197 /**
198   The user Entry Point for Application. The user code starts with this function
199   as the real entry point for the image goes into a library that calls this
200   function.
201 
202   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
203   @param[in] SystemTable    A pointer to the EFI System Table.
204 
205   @retval EFI_SUCCESS       The entry point is executed successfully.
206   @retval other             Some error occurs when executing this entry point.
207 
208 **/
209 EFI_STATUS
210 EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)211 UefiMain (
212   IN EFI_HANDLE        ImageHandle,
213   IN EFI_SYSTEM_TABLE  *SystemTable
214   )
215 {
216   EFI_STATUS            Status;
217   VARIABLE_INFO_ENTRY   *VariableInfo;
218   VARIABLE_INFO_ENTRY   *Entry;
219 
220   Status = EfiGetSystemConfigurationTable (&gEfiVariableGuid, (VOID **)&Entry);
221   if (EFI_ERROR (Status) || (Entry == NULL)) {
222     Status = EfiGetSystemConfigurationTable (&gEfiAuthenticatedVariableGuid, (VOID **)&Entry);
223   }
224 
225   if (EFI_ERROR (Status) || (Entry == NULL)) {
226     Status = PrintInfoFromSmm ();
227     if (!EFI_ERROR (Status)) {
228       return Status;
229     }
230   }
231 
232   if (!EFI_ERROR (Status) && (Entry != NULL)) {
233     Print (L"Non-Volatile EFI Variables:\n");
234     VariableInfo = Entry;
235     do {
236       if (!VariableInfo->Volatile) {
237         Print (
238           L"%g R%03d(%03d) W%03d D%03d:%s\n",
239           &VariableInfo->VendorGuid,
240           VariableInfo->ReadCount,
241           VariableInfo->CacheCount,
242           VariableInfo->WriteCount,
243           VariableInfo->DeleteCount,
244           VariableInfo->Name
245           );
246       }
247 
248       VariableInfo = VariableInfo->Next;
249     } while (VariableInfo != NULL);
250 
251     Print (L"Volatile EFI Variables:\n");
252     VariableInfo = Entry;
253     do {
254       if (VariableInfo->Volatile) {
255         Print (
256           L"%g R%03d(%03d) W%03d D%03d:%s\n",
257           &VariableInfo->VendorGuid,
258           VariableInfo->ReadCount,
259           VariableInfo->CacheCount,
260           VariableInfo->WriteCount,
261           VariableInfo->DeleteCount,
262           VariableInfo->Name
263           );
264       }
265       VariableInfo = VariableInfo->Next;
266     } while (VariableInfo != NULL);
267 
268   } else {
269     Print (L"Warning: Variable Dxe/Smm driver doesn't enable the feature of statistical information!\n");
270     Print (L"If you want to see this info, please:\n");
271     Print (L"  1. Set PcdVariableCollectStatistics as TRUE\n");
272     Print (L"  2. Rebuild Variable Dxe/Smm driver\n");
273     Print (L"  3. Run \"VariableInfo\" cmd again\n");
274   }
275 
276   return Status;
277 }
278