TianoCore EDK2 master
Loading...
Searching...
No Matches
MmVariablePei.c
1
9#include "MmVariablePei.h"
10
11#define MM_VARIABLE_COMM_BUFFER_OFFSET (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)
12
13//
14// Module globals
15//
16EFI_PEI_READ_ONLY_VARIABLE2_PPI mPeiSecureVariableRead = {
17 PeiMmGetVariable,
18 PeiMmGetNextVariableName
19};
20
21EFI_PEI_PPI_DESCRIPTOR mPeiMmVariablePpi = {
22 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
23 &gEfiPeiReadOnlyVariable2PpiGuid,
24 &mPeiSecureVariableRead
25};
26
38EFIAPI
39PeiMmVariableInitialize (
40 IN EFI_PEI_FILE_HANDLE FileHandle,
41 IN CONST EFI_PEI_SERVICES **PeiServices
42 )
43{
44 return PeiServicesInstallPpi (&mPeiMmVariablePpi);
45}
46
61PopulateHeaderAndCommunicate (
62 IN OUT UINT8 *CommunicateBuffer,
63 IN UINTN CommunicateBufferSize,
64 IN UINTN Function
65 )
66{
67 EFI_STATUS Status;
68 EFI_PEI_MM_COMMUNICATION_PPI *MmCommunicationPpi;
69 EFI_MM_COMMUNICATE_HEADER *MmCommunicateHeader;
70 SMM_VARIABLE_COMMUNICATE_HEADER *MmVarCommsHeader;
71
72 // Minimal sanity check
73 if ((CommunicateBuffer == NULL) ||
74 (CommunicateBufferSize < MM_VARIABLE_COMM_BUFFER_OFFSET))
75 {
76 Status = EFI_INVALID_PARAMETER;
77 DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize));
78 goto Exit;
79 }
80
81 if ((Function != SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) &&
82 (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE))
83 {
84 Status = EFI_INVALID_PARAMETER;
85 DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n", __func__, Function));
86 goto Exit;
87 }
88
89 Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0, NULL, (VOID **)&MmCommunicationPpi);
90 if (EFI_ERROR (Status)) {
91 DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication PPI: %r\n", __func__, Status));
92 goto Exit;
93 }
94
95 // Zero the entire Communication Buffer Header
96 MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommunicateBuffer;
97
98 ZeroMem (MmCommunicateHeader, SMM_COMMUNICATE_HEADER_SIZE);
99
100 // Use gEfiSmmVariableProtocolGuid to request the MM variable service in Standalone MM
101 CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid, sizeof (GUID));
102
103 // Program the MM header size
104 MmCommunicateHeader->MessageLength = CommunicateBufferSize - SMM_COMMUNICATE_HEADER_SIZE;
105
106 MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE);
107
108 // We are only supporting GetVariable and GetNextVariableName
109 MmVarCommsHeader->Function = Function;
110
111 // Send the MM request using MmCommunicationPei
112 Status = MmCommunicationPpi->Communicate (MmCommunicationPpi, CommunicateBuffer, &CommunicateBufferSize);
113 if (EFI_ERROR (Status)) {
114 // Received an error from MM interface.
115 DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", __func__, Status));
116 goto Exit;
117 }
118
119 // MM request was successfully handled by the framework.
120 // Set status to the Variable Service Status Code
121 Status = MmVarCommsHeader->ReturnStatus;
122 if (EFI_ERROR (Status)) {
123 // We received an error from Variable Service.
124 // We cant do anymore so return Status
125 if (Status != EFI_BUFFER_TOO_SMALL) {
126 DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n", __func__, Status));
127 }
128
129 goto Exit;
130 }
131
132Exit:
133 return Status;
134}
135
164EFIAPI
165PeiMmGetVariable (
167 IN CONST CHAR16 *VariableName,
168 IN CONST EFI_GUID *VariableGuid,
169 OUT UINT32 *Attributes, OPTIONAL
170 IN OUT UINTN *DataSize,
171 OUT VOID *Data OPTIONAL
172 )
173{
174 EFI_STATUS Status;
175 UINTN MessageSize;
177 UINT8 *MmCommunicateBuffer;
178 UINTN RequiredPages;
179
180 // Check input parameters
181 if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize == NULL)) {
182 return EFI_INVALID_PARAMETER;
183 }
184
185 if (VariableName[0] == 0) {
186 return EFI_NOT_FOUND;
187 }
188
189 if ((*DataSize > 0) && (Data == NULL)) {
190 return EFI_INVALID_PARAMETER;
191 }
192
193 // Allocate required pages to send MM request
194 MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
196 StrSize (VariableName) + *DataSize;
197
198 RequiredPages = EFI_SIZE_TO_PAGES (MessageSize);
199 MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
200
201 if (MmCommunicateBuffer == NULL) {
202 Status = EFI_OUT_OF_RESOURCES;
203 DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", __func__, Status));
204 return Status;
205 }
206
207 // Zero the entire Communication Buffer
208 ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
209
210 //
211 // Program all payload structure contents
212 //
213 MmVarAccessHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
214
215 // Variable GUID
216 CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof (GUID));
217
218 // Program the max amount of data we accept.
219 MmVarAccessHeader->DataSize = *DataSize;
220
221 // Get size of the variable name
222 MmVarAccessHeader->NameSize = StrSize (VariableName);
223
224 // Populate incoming variable name
225 CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName, MmVarAccessHeader->NameSize);
226
227 Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
228 if (EFI_ERROR (Status)) {
229 // We received an error from either communicate or Variable Service.
230 if (Status != EFI_BUFFER_TOO_SMALL) {
231 DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable service errored: %r\n", __func__, Status));
232 }
233
234 goto Exit;
235 }
236
237 Status = EFI_SUCCESS;
238
239 // User provided buffer is too small
240 if (*DataSize < MmVarAccessHeader->DataSize) {
241 Status = EFI_BUFFER_TOO_SMALL;
242 }
243
244Exit:
245 // Check if we need to set Attributes
246 if (Attributes != NULL) {
247 *Attributes = MmVarAccessHeader->Attributes;
248 }
249
250 *DataSize = MmVarAccessHeader->DataSize;
251
252 if (Status == EFI_SUCCESS) {
253 CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name + MmVarAccessHeader->NameSize, *DataSize);
254 }
255
256 // Free the Communication Buffer
257 if (MmCommunicateBuffer != NULL) {
258 FreePages (MmCommunicateBuffer, RequiredPages);
259 }
260
261 return Status;
262}
263
294EFIAPI
295PeiMmGetNextVariableName (
297 IN OUT UINTN *VariableNameSize,
298 IN OUT CHAR16 *VariableName,
299 IN OUT EFI_GUID *VariableGuid
300 )
301{
302 EFI_STATUS Status;
303 UINTN MessageSize;
304 UINT8 *MmCommunicateBuffer;
306 UINTN RequiredPages;
307
308 // Check input parameters
309 if ((VariableName == NULL) ||
310 (VariableGuid == NULL) ||
311 (VariableNameSize == NULL) ||
312 (*VariableNameSize == 0))
313 {
314 return EFI_INVALID_PARAMETER;
315 }
316
317 // Allocate required pages to send MM request
318 MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
320 StrSize (VariableName) + *VariableNameSize;
321
322 RequiredPages = EFI_SIZE_TO_PAGES (MessageSize);
323 MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
324
325 if (MmCommunicateBuffer == NULL) {
326 Status = EFI_OUT_OF_RESOURCES;
327 DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", __func__, Status));
328 return Status;
329 }
330
331 // Zero the entire Communication Buffer
332 ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
333
334 //
335 // Program all payload structure contents
336 //
337 MmVarGetNextVarHeader = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
338
339 // Variable GUID
340 CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid, sizeof (GUID));
341
342 // Program the maximal length of name we can accept.
343 MmVarGetNextVarHeader->NameSize = *VariableNameSize;
344
345 // Populate incoming variable name
346 CopyMem ((VOID *)&MmVarGetNextVarHeader->Name, VariableName, MmVarGetNextVarHeader->NameSize);
347
348 // Send the MM request using MmCommunicationPei
349 Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
350 if (EFI_ERROR (Status)) {
351 // We received an error from either communicate or Variable Service.
352 if (Status != EFI_BUFFER_TOO_SMALL) {
353 DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable service errored: %r\n", __func__, Status));
354 }
355
356 goto Exit;
357 }
358
359 Status = EFI_SUCCESS;
360
361 // User provided buffer is too small
362 if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) {
363 Status = EFI_BUFFER_TOO_SMALL;
364 }
365
366Exit:
367 // Update the name size to be returned
368 *VariableNameSize = MmVarGetNextVarHeader->NameSize;
369
370 if (Status == EFI_SUCCESS) {
371 CopyMem ((VOID *)VariableName, (UINT8 *)MmVarGetNextVarHeader->Name, *VariableNameSize);
372 CopyMem ((VOID *)VariableGuid, (UINT8 *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID));
373 }
374
375 // Free the Communication Buffer
376 if (MmCommunicateBuffer != NULL) {
377 FreePages (MmCommunicateBuffer, RequiredPages);
378 }
379
380 return Status;
381}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
EFI_STATUS EFIAPI PeiServicesLocatePpi(IN CONST EFI_GUID *Guid, IN UINTN Instance, IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, IN OUT VOID **Ppi)
EFI_STATUS EFIAPI PeiServicesInstallPpi(IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID * EFI_PEI_FILE_HANDLE
Definition: PiPeiCis.h:26
VOID *EFIAPI AllocatePages(IN UINTN Pages)
#define SMM_COMMUNICATE_HEADER_SIZE
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
Definition: Base.h:213