]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Application/VariableInfo/VariableInfo.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 (
58 mMmCommunication2,
59 SmmCommunicateHeader,
60 SmmCommunicateHeader,
61 SmmCommunicateSize
62 );
63 ASSERT_EFI_ERROR (Status);
64
65 Status = SmmVariableFunctionHeader->ReturnStatus;
66 return Status;
67 }
68
69 /**
70
71 This function get and print the variable statistics data from SMM variable driver.
72
73 @retval EFI_SUCCESS Print the statistics information successfully.
74 @retval EFI_NOT_FOUND Not found the statistics information.
75
76 **/
77 EFI_STATUS
78 PrintInfoFromSmm (
79 VOID
80 )
81 {
82 EFI_STATUS Status;
83 VARIABLE_INFO_ENTRY *VariableInfo;
84 EFI_MM_COMMUNICATE_HEADER *CommBuffer;
85 UINTN RealCommSize;
86 UINTN CommSize;
87 SMM_VARIABLE_COMMUNICATE_HEADER *FunctionHeader;
88 EFI_SMM_VARIABLE_PROTOCOL *Smmvariable;
89 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
90 UINT32 Index;
91 EFI_MEMORY_DESCRIPTOR *Entry;
92 UINTN Size;
93 UINTN MaxSize;
94
95 Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&Smmvariable);
96 if (EFI_ERROR (Status)) {
97 return Status;
98 }
99
100 Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **)&mMmCommunication2);
101 if (EFI_ERROR (Status)) {
102 return Status;
103 }
104
105 CommBuffer = NULL;
106 RealCommSize = 0;
107 Status = EfiGetSystemConfigurationTable (
108 &gEdkiiPiSmmCommunicationRegionTableGuid,
109 (VOID **)&PiSmmCommunicationRegionTable
110 );
111 if (EFI_ERROR (Status)) {
112 return Status;
113 }
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_MM_COMMUNICATE_HEADER *)(UINTN)Entry->PhysicalStart;
127 }
128 }
129 }
130
131 Entry = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Entry + PiSmmCommunicationRegionTable->DescriptorSize);
132 }
133
134 ASSERT (CommBuffer != NULL);
135 ZeroMem (CommBuffer, RealCommSize);
136
137 Print (L"SMM Driver Non-Volatile Variables:\n");
138 do {
139 CommSize = RealCommSize;
140 Status = GetVariableStatisticsData (CommBuffer, &CommSize);
141 if (Status == EFI_BUFFER_TOO_SMALL) {
142 Print (L"The generic SMM communication buffer provided by SmmCommunicationRegionTable is too small\n");
143 return Status;
144 }
145
146 if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {
147 break;
148 }
149
150 FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer->Data;
151 VariableInfo = (VARIABLE_INFO_ENTRY *)FunctionHeader->Data;
152
153 if (!VariableInfo->Volatile) {
154 Print (
155 L"%g R%03d(%03d) W%03d D%03d:%s\n",
156 &VariableInfo->VendorGuid,
157 VariableInfo->ReadCount,
158 VariableInfo->CacheCount,
159 VariableInfo->WriteCount,
160 VariableInfo->DeleteCount,
161 (CHAR16 *)(VariableInfo + 1)
162 );
163 }
164 } while (TRUE);
165
166 Print (L"SMM Driver Volatile Variables:\n");
167 ZeroMem (CommBuffer, RealCommSize);
168 do {
169 CommSize = RealCommSize;
170 Status = GetVariableStatisticsData (CommBuffer, &CommSize);
171 if (Status == EFI_BUFFER_TOO_SMALL) {
172 Print (L"The generic SMM communication buffer provided by SmmCommunicationRegionTable is too small\n");
173 return Status;
174 }
175
176 if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {
177 break;
178 }
179
180 FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer->Data;
181 VariableInfo = (VARIABLE_INFO_ENTRY *)FunctionHeader->Data;
182
183 if (VariableInfo->Volatile) {
184 Print (
185 L"%g R%03d(%03d) W%03d D%03d:%s\n",
186 &VariableInfo->VendorGuid,
187 VariableInfo->ReadCount,
188 VariableInfo->CacheCount,
189 VariableInfo->WriteCount,
190 VariableInfo->DeleteCount,
191 (CHAR16 *)(VariableInfo + 1)
192 );
193 }
194 } while (TRUE);
195
196 return Status;
197 }
198
199 /**
200 The user Entry Point for Application. The user code starts with this function
201 as the real entry point for the image goes into a library that calls this
202 function.
203
204 @param[in] ImageHandle The firmware allocated handle for the EFI image.
205 @param[in] SystemTable A pointer to the EFI System Table.
206
207 @retval EFI_SUCCESS The entry point is executed successfully.
208 @retval other Some error occurs when executing this entry point.
209
210 **/
211 EFI_STATUS
212 EFIAPI
213 UefiMain (
214 IN EFI_HANDLE ImageHandle,
215 IN EFI_SYSTEM_TABLE *SystemTable
216 )
217 {
218 EFI_STATUS RuntimeDxeStatus;
219 EFI_STATUS SmmStatus;
220 VARIABLE_INFO_ENTRY *VariableInfo;
221 VARIABLE_INFO_ENTRY *Entry;
222
223 RuntimeDxeStatus = EfiGetSystemConfigurationTable (&gEfiVariableGuid, (VOID **)&Entry);
224 if (EFI_ERROR (RuntimeDxeStatus) || (Entry == NULL)) {
225 RuntimeDxeStatus = EfiGetSystemConfigurationTable (&gEfiAuthenticatedVariableGuid, (VOID **)&Entry);
226 }
227
228 if (!EFI_ERROR (RuntimeDxeStatus) && (Entry != NULL)) {
229 Print (L"Runtime DXE Driver Non-Volatile EFI Variables:\n");
230 VariableInfo = Entry;
231 do {
232 if (!VariableInfo->Volatile) {
233 Print (
234 L"%g R%03d(%03d) W%03d D%03d:%s\n",
235 &VariableInfo->VendorGuid,
236 VariableInfo->ReadCount,
237 VariableInfo->CacheCount,
238 VariableInfo->WriteCount,
239 VariableInfo->DeleteCount,
240 VariableInfo->Name
241 );
242 }
243
244 VariableInfo = VariableInfo->Next;
245 } while (VariableInfo != NULL);
246
247 Print (L"Runtime DXE Driver Volatile EFI Variables:\n");
248 VariableInfo = Entry;
249 do {
250 if (VariableInfo->Volatile) {
251 Print (
252 L"%g R%03d(%03d) W%03d D%03d:%s\n",
253 &VariableInfo->VendorGuid,
254 VariableInfo->ReadCount,
255 VariableInfo->CacheCount,
256 VariableInfo->WriteCount,
257 VariableInfo->DeleteCount,
258 VariableInfo->Name
259 );
260 }
261
262 VariableInfo = VariableInfo->Next;
263 } while (VariableInfo != NULL);
264 }
265
266 SmmStatus = PrintInfoFromSmm ();
267
268 if (EFI_ERROR (RuntimeDxeStatus) && EFI_ERROR (SmmStatus)) {
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 return EFI_NOT_FOUND;
276 }
277
278 return EFI_SUCCESS;
279 }