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