]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
MdeModulePkg: Variable: Update PCR[7] measure for new TCG spec
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VariableSmmRuntimeDxe.c
CommitLineData
8a2d4996 1/** @file\r
8a2d4996 2 Implement all four UEFI Runtime Variable services for the nonvolatile\r
3 and volatile storage space and install variable architecture protocol\r
4 based on SMM variable module.\r
5\r
18a7dbbc
SZ
6 Caution: This module requires additional review when modified.\r
7 This driver will have external input - variable data.\r
8 This external input must be validated carefully to avoid security issue like\r
9 buffer overflow, integer overflow.\r
10\r
11 RuntimeServiceGetVariable() and RuntimeServiceSetVariable() are external API\r
12 to receive data buffer. The size should be checked carefully.\r
13\r
14 InitCommunicateBuffer() is really function to check the variable data size.\r
15\r
dc9bd6ed 16Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>\r
fa0737a8
SZ
17This program and the accompanying materials\r
18are licensed and made available under the terms and conditions of the BSD License\r
19which accompanies this distribution. The full text of the license may be found at\r
20http://opensource.org/licenses/bsd-license.php\r
8a2d4996 21\r
fa0737a8
SZ
22THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
23WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
8a2d4996 24\r
25**/\r
d00ed85e 26#include <PiDxe.h>\r
8a2d4996 27#include <Protocol/VariableWrite.h>\r
28#include <Protocol/Variable.h>\r
29#include <Protocol/SmmCommunication.h>\r
d00ed85e 30#include <Protocol/SmmVariable.h>\r
ff843847 31#include <Protocol/VariableLock.h>\r
efb01a10 32#include <Protocol/VarCheck.h>\r
8a2d4996 33\r
34#include <Library/UefiBootServicesTableLib.h>\r
35#include <Library/UefiRuntimeServicesTableLib.h>\r
36#include <Library/MemoryAllocationLib.h>\r
37#include <Library/UefiDriverEntryPoint.h>\r
38#include <Library/UefiRuntimeLib.h>\r
39#include <Library/BaseMemoryLib.h>\r
40#include <Library/DebugLib.h>\r
8a2d4996 41#include <Library/UefiLib.h>\r
42#include <Library/BaseLib.h>\r
43\r
44#include <Guid/EventGroup.h>\r
d00ed85e 45#include <Guid/SmmVariableCommon.h>\r
8a2d4996 46\r
fa0737a8 47EFI_HANDLE mHandle = NULL;\r
8a2d4996 48EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;\r
49EFI_EVENT mVirtualAddressChangeEvent = NULL;\r
50EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;\r
51UINT8 *mVariableBuffer = NULL;\r
52UINT8 *mVariableBufferPhysical = NULL;\r
8a2d4996 53UINTN mVariableBufferSize;\r
5e5bb2a9 54UINTN mVariableBufferPayloadSize;\r
6ed1ec59 55EFI_LOCK mVariableServicesLock;\r
ff843847 56EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;\r
efb01a10 57EDKII_VAR_CHECK_PROTOCOL mVarCheck;\r
8a2d4996 58\r
fa0737a8
SZ
59/**\r
60 SecureBoot Hook for SetVariable.\r
61\r
62 @param[in] VariableName Name of Variable to be found.\r
63 @param[in] VendorGuid Variable vendor GUID.\r
64\r
65**/\r
66VOID\r
67EFIAPI\r
68SecureBootHook (\r
69 IN CHAR16 *VariableName,\r
70 IN EFI_GUID *VendorGuid\r
71 );\r
72\r
dc9bd6ed
ZC
73/**\r
74 Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).\r
75 Record their initial State when variable write service is ready.\r
76\r
77**/\r
78VOID\r
79EFIAPI\r
80RecordSecureBootPolicyVarData(\r
81 VOID\r
82 );\r
83\r
6ed1ec59
SZ
84/**\r
85 Acquires lock only at boot time. Simply returns at runtime.\r
86\r
87 This is a temperary function that will be removed when\r
88 EfiAcquireLock() in UefiLib can handle the call in UEFI\r
89 Runtimer driver in RT phase.\r
90 It calls EfiAcquireLock() at boot time, and simply returns\r
91 at runtime.\r
92\r
93 @param Lock A pointer to the lock to acquire.\r
94\r
95**/\r
96VOID\r
97AcquireLockOnlyAtBootTime (\r
98 IN EFI_LOCK *Lock\r
99 )\r
100{\r
101 if (!EfiAtRuntime ()) {\r
102 EfiAcquireLock (Lock);\r
103 }\r
104}\r
105\r
106/**\r
107 Releases lock only at boot time. Simply returns at runtime.\r
108\r
109 This is a temperary function which will be removed when\r
110 EfiReleaseLock() in UefiLib can handle the call in UEFI\r
111 Runtimer driver in RT phase.\r
112 It calls EfiReleaseLock() at boot time and simply returns\r
113 at runtime.\r
114\r
115 @param Lock A pointer to the lock to release.\r
116\r
117**/\r
118VOID\r
119ReleaseLockOnlyAtBootTime (\r
120 IN EFI_LOCK *Lock\r
121 )\r
122{\r
123 if (!EfiAtRuntime ()) {\r
124 EfiReleaseLock (Lock);\r
125 }\r
126}\r
8a2d4996 127\r
128/**\r
129 Initialize the communicate buffer using DataSize and Function.\r
130\r
131 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +\r
132 DataSize.\r
133\r
18a7dbbc
SZ
134 Caution: This function may receive untrusted input.\r
135 The data size external input, so this function will validate it carefully to avoid buffer overflow.\r
136\r
8a2d4996 137 @param[out] DataPtr Points to the data in the communicate buffer.\r
138 @param[in] DataSize The data size to send to SMM.\r
139 @param[in] Function The function number to initialize the communicate header.\r
fa0737a8 140\r
8a2d4996 141 @retval EFI_INVALID_PARAMETER The data size is too big.\r
142 @retval EFI_SUCCESS Find the specified variable.\r
143\r
144**/\r
145EFI_STATUS\r
146InitCommunicateBuffer (\r
147 OUT VOID **DataPtr OPTIONAL,\r
148 IN UINTN DataSize,\r
149 IN UINTN Function\r
150 )\r
151{\r
fa0737a8
SZ
152 EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
153 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
154\r
8a2d4996 155\r
8a2d4996 156 if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {\r
157 return EFI_INVALID_PARAMETER;\r
158 }\r
159\r
160 SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;\r
161 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
162 SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
fa0737a8 163\r
8a2d4996 164 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
165 SmmVariableFunctionHeader->Function = Function;\r
166 if (DataPtr != NULL) {\r
167 *DataPtr = SmmVariableFunctionHeader->Data;\r
168 }\r
169\r
170 return EFI_SUCCESS;\r
171}\r
172\r
173\r
174/**\r
175 Send the data in communicate buffer to SMM.\r
176\r
177 @param[in] DataSize This size of the function header and the data.\r
178\r
32732a33 179 @retval EFI_SUCCESS Success is returned from the functin in SMM.\r
fa0737a8
SZ
180 @retval Others Failure is returned from the function in SMM.\r
181\r
8a2d4996 182**/\r
183EFI_STATUS\r
184SendCommunicateBuffer (\r
185 IN UINTN DataSize\r
186 )\r
187{\r
188 EFI_STATUS Status;\r
189 UINTN CommSize;\r
fa0737a8 190 EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
8a2d4996 191 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
fa0737a8 192\r
8a2d4996 193 CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
194 Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);\r
195 ASSERT_EFI_ERROR (Status);\r
196\r
197 SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;\r
198 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;\r
199 return SmmVariableFunctionHeader->ReturnStatus;\r
200}\r
201\r
ff843847
RN
202/**\r
203 Mark a variable that will become read-only after leaving the DXE phase of execution.\r
204\r
205 @param[in] This The VARIABLE_LOCK_PROTOCOL instance.\r
206 @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.\r
207 @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.\r
208\r
209 @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked\r
210 as pending to be read-only.\r
211 @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.\r
212 Or VariableName is an empty string.\r
213 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
214 already been signaled.\r
215 @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.\r
216**/\r
217EFI_STATUS\r
218EFIAPI\r
219VariableLockRequestToLock (\r
220 IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,\r
221 IN CHAR16 *VariableName,\r
222 IN EFI_GUID *VendorGuid\r
223 )\r
224{\r
225 EFI_STATUS Status;\r
51547bb8 226 UINTN VariableNameSize;\r
ff843847
RN
227 UINTN PayloadSize;\r
228 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
229\r
230 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
231 return EFI_INVALID_PARAMETER;\r
232 }\r
233\r
51547bb8 234 VariableNameSize = StrSize (VariableName);\r
4e1005ec 235 VariableToLock = NULL;\r
51547bb8
RN
236\r
237 //\r
238 // If VariableName exceeds SMM payload limit. Return failure\r
239 //\r
240 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {\r
241 return EFI_INVALID_PARAMETER;\r
242 }\r
243\r
ff843847
RN
244 AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
245\r
246 //\r
247 // Init the communicate buffer. The buffer data size is:\r
248 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
249 //\r
51547bb8 250 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;\r
ff843847
RN
251 Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);\r
252 if (EFI_ERROR (Status)) {\r
253 goto Done;\r
254 }\r
255 ASSERT (VariableToLock != NULL);\r
256\r
257 CopyGuid (&VariableToLock->Guid, VendorGuid);\r
51547bb8 258 VariableToLock->NameSize = VariableNameSize;\r
ff843847
RN
259 CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);\r
260\r
261 //\r
262 // Send data to SMM.\r
263 //\r
264 Status = SendCommunicateBuffer (PayloadSize);\r
265\r
266Done:\r
267 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
268 return Status;\r
269}\r
8a2d4996 270\r
efb01a10
SZ
271/**\r
272 Register SetVariable check handler.\r
273\r
274 @param[in] Handler Pointer to check handler.\r
275\r
276 @retval EFI_SUCCESS The SetVariable check handler was registered successfully.\r
277 @retval EFI_INVALID_PARAMETER Handler is NULL.\r
278 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
279 already been signaled.\r
280 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the SetVariable check handler register request.\r
281 @retval EFI_UNSUPPORTED This interface is not implemented.\r
282 For example, it is unsupported in VarCheck protocol if both VarCheck and SmmVarCheck protocols are present.\r
283\r
284**/\r
285EFI_STATUS\r
286EFIAPI\r
287VarCheckRegisterSetVariableCheckHandler (\r
288 IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler\r
289 )\r
290{\r
291 return EFI_UNSUPPORTED;\r
292}\r
293\r
294/**\r
295 Variable property set.\r
296\r
297 @param[in] Name Pointer to the variable name.\r
298 @param[in] Guid Pointer to the vendor GUID.\r
299 @param[in] VariableProperty Pointer to the input variable property.\r
300\r
301 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was set successfully.\r
302 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,\r
303 or the fields of VariableProperty are not valid.\r
304 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
305 already been signaled.\r
306 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the variable property set request.\r
307\r
308**/\r
309EFI_STATUS\r
310EFIAPI\r
311VarCheckVariablePropertySet (\r
312 IN CHAR16 *Name,\r
313 IN EFI_GUID *Guid,\r
314 IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty\r
315 )\r
316{\r
317 EFI_STATUS Status;\r
318 UINTN VariableNameSize;\r
319 UINTN PayloadSize;\r
320 SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
321\r
322 if (Name == NULL || Name[0] == 0 || Guid == NULL) {\r
323 return EFI_INVALID_PARAMETER;\r
324 }\r
325\r
326 if (VariableProperty == NULL) {\r
327 return EFI_INVALID_PARAMETER;\r
328 }\r
329\r
330 if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {\r
331 return EFI_INVALID_PARAMETER;\r
332 }\r
333\r
334 VariableNameSize = StrSize (Name);\r
335 CommVariableProperty = NULL;\r
336\r
337 //\r
338 // If VariableName exceeds SMM payload limit. Return failure\r
339 //\r
340 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
341 return EFI_INVALID_PARAMETER;\r
342 }\r
343\r
344 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
345\r
346 //\r
347 // Init the communicate buffer. The buffer data size is:\r
348 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
349 //\r
350 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + VariableNameSize;\r
351 Status = InitCommunicateBuffer ((VOID **) &CommVariableProperty, PayloadSize, SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET);\r
352 if (EFI_ERROR (Status)) {\r
353 goto Done;\r
354 }\r
355 ASSERT (CommVariableProperty != NULL);\r
356\r
357 CopyGuid (&CommVariableProperty->Guid, Guid);\r
358 CopyMem (&CommVariableProperty->VariableProperty, VariableProperty, sizeof (*VariableProperty));\r
359 CommVariableProperty->NameSize = VariableNameSize;\r
360 CopyMem (CommVariableProperty->Name, Name, CommVariableProperty->NameSize);\r
361\r
362 //\r
363 // Send data to SMM.\r
364 //\r
365 Status = SendCommunicateBuffer (PayloadSize);\r
366\r
367Done:\r
368 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
369 return Status;\r
370}\r
371\r
372/**\r
373 Variable property get.\r
374\r
375 @param[in] Name Pointer to the variable name.\r
376 @param[in] Guid Pointer to the vendor GUID.\r
377 @param[out] VariableProperty Pointer to the output variable property.\r
378\r
379 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was got successfully.\r
380 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.\r
381 @retval EFI_NOT_FOUND The property of variable specified by the Name and Guid was not found.\r
382\r
383**/\r
384EFI_STATUS\r
385EFIAPI\r
386VarCheckVariablePropertyGet (\r
387 IN CHAR16 *Name,\r
388 IN EFI_GUID *Guid,\r
389 OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty\r
390 )\r
391{\r
392 EFI_STATUS Status;\r
393 UINTN VariableNameSize;\r
394 UINTN PayloadSize;\r
395 SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
396\r
397 if (Name == NULL || Name[0] == 0 || Guid == NULL) {\r
398 return EFI_INVALID_PARAMETER;\r
399 }\r
400\r
401 if (VariableProperty == NULL) {\r
402 return EFI_INVALID_PARAMETER;\r
403 }\r
404\r
405 VariableNameSize = StrSize (Name);\r
406 CommVariableProperty = NULL;\r
407\r
408 //\r
409 // If VariableName exceeds SMM payload limit. Return failure\r
410 //\r
411 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
412 return EFI_INVALID_PARAMETER;\r
413 }\r
414\r
415 AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
416\r
417 //\r
418 // Init the communicate buffer. The buffer data size is:\r
419 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
420 //\r
421 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + VariableNameSize;\r
422 Status = InitCommunicateBuffer ((VOID **) &CommVariableProperty, PayloadSize, SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET);\r
423 if (EFI_ERROR (Status)) {\r
424 goto Done;\r
425 }\r
426 ASSERT (CommVariableProperty != NULL);\r
427\r
428 CopyGuid (&CommVariableProperty->Guid, Guid);\r
429 CommVariableProperty->NameSize = VariableNameSize;\r
430 CopyMem (CommVariableProperty->Name, Name, CommVariableProperty->NameSize);\r
431\r
432 //\r
433 // Send data to SMM.\r
434 //\r
435 Status = SendCommunicateBuffer (PayloadSize);\r
436 if (Status == EFI_SUCCESS) {\r
437 CopyMem (VariableProperty, &CommVariableProperty->VariableProperty, sizeof (*VariableProperty));\r
438 }\r
439\r
440Done:\r
441 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
442 return Status;\r
443}\r
444\r
8a2d4996 445/**\r
446 This code finds variable in storage blocks (Volatile or Non-Volatile).\r
447\r
18a7dbbc
SZ
448 Caution: This function may receive untrusted input.\r
449 The data size is external input, so this function will validate it carefully to avoid buffer overflow.\r
450\r
8a2d4996 451 @param[in] VariableName Name of Variable to be found.\r
452 @param[in] VendorGuid Variable vendor GUID.\r
453 @param[out] Attributes Attribute value of the variable found.\r
454 @param[in, out] DataSize Size of Data found. If size is less than the\r
455 data, this value contains the required size.\r
456 @param[out] Data Data pointer.\r
fa0737a8 457\r
8a2d4996 458 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
459 @retval EFI_SUCCESS Find the specified variable.\r
460 @retval EFI_NOT_FOUND Not found.\r
461 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
462\r
463**/\r
464EFI_STATUS\r
465EFIAPI\r
466RuntimeServiceGetVariable (\r
467 IN CHAR16 *VariableName,\r
468 IN EFI_GUID *VendorGuid,\r
469 OUT UINT32 *Attributes OPTIONAL,\r
470 IN OUT UINTN *DataSize,\r
471 OUT VOID *Data\r
472 )\r
473{\r
474 EFI_STATUS Status;\r
475 UINTN PayloadSize;\r
476 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
3a146f2a 477 UINTN TempDataSize;\r
9d00d20e 478 UINTN VariableNameSize;\r
8a2d4996 479\r
480 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
481 return EFI_INVALID_PARAMETER;\r
482 }\r
483\r
3a146f2a 484 TempDataSize = *DataSize;\r
9d00d20e 485 VariableNameSize = StrSize (VariableName);\r
4e1005ec 486 SmmVariableHeader = NULL;\r
3a146f2a 487\r
488 //\r
489 // If VariableName exceeds SMM payload limit. Return failure\r
490 //\r
5e5bb2a9 491 if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
3588bb35
SZ
492 return EFI_INVALID_PARAMETER;\r
493 }\r
494\r
6ed1ec59
SZ
495 AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
496\r
8a2d4996 497 //\r
498 // Init the communicate buffer. The buffer data size is:\r
6ed1ec59 499 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
8a2d4996 500 //\r
5e5bb2a9 501 if (TempDataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) {\r
3a146f2a 502 //\r
503 // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size\r
504 //\r
5e5bb2a9 505 TempDataSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize;\r
3a146f2a 506 }\r
9d00d20e 507 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize;\r
3a146f2a 508\r
5c7fa429 509 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);\r
8a2d4996 510 if (EFI_ERROR (Status)) {\r
6ed1ec59 511 goto Done;\r
8a2d4996 512 }\r
513 ASSERT (SmmVariableHeader != NULL);\r
514\r
515 CopyGuid (&SmmVariableHeader->Guid, VendorGuid);\r
3a146f2a 516 SmmVariableHeader->DataSize = TempDataSize;\r
9d00d20e 517 SmmVariableHeader->NameSize = VariableNameSize;\r
8a2d4996 518 if (Attributes == NULL) {\r
519 SmmVariableHeader->Attributes = 0;\r
520 } else {\r
521 SmmVariableHeader->Attributes = *Attributes;\r
522 }\r
523 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);\r
524\r
525 //\r
526 // Send data to SMM.\r
527 //\r
528 Status = SendCommunicateBuffer (PayloadSize);\r
529\r
530 //\r
531 // Get data from SMM.\r
532 //\r
3a146f2a 533 if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {\r
534 //\r
535 // SMM CommBuffer DataSize can be a trimed value\r
536 // Only update DataSize when needed\r
537 //\r
538 *DataSize = SmmVariableHeader->DataSize;\r
539 }\r
8a2d4996 540 if (Attributes != NULL) {\r
541 *Attributes = SmmVariableHeader->Attributes;\r
542 }\r
543\r
544 if (EFI_ERROR (Status)) {\r
6ed1ec59 545 goto Done;\r
8a2d4996 546 }\r
547\r
82e47eb2
SZ
548 if (Data != NULL) {\r
549 CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);\r
550 } else {\r
551 Status = EFI_INVALID_PARAMETER;\r
552 }\r
8a2d4996 553\r
6ed1ec59
SZ
554Done:\r
555 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
8a2d4996 556 return Status;\r
557}\r
558\r
559\r
560/**\r
561 This code Finds the Next available variable.\r
562\r
563 @param[in, out] VariableNameSize Size of the variable name.\r
564 @param[in, out] VariableName Pointer to variable name.\r
565 @param[in, out] VendorGuid Variable Vendor Guid.\r
566\r
567 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
568 @retval EFI_SUCCESS Find the specified variable.\r
569 @retval EFI_NOT_FOUND Not found.\r
570 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
571\r
572**/\r
573EFI_STATUS\r
574EFIAPI\r
575RuntimeServiceGetNextVariableName (\r
576 IN OUT UINTN *VariableNameSize,\r
577 IN OUT CHAR16 *VariableName,\r
578 IN OUT EFI_GUID *VendorGuid\r
579 )\r
580{\r
581 EFI_STATUS Status;\r
582 UINTN PayloadSize;\r
583 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;\r
9d00d20e
SZ
584 UINTN OutVariableNameSize;\r
585 UINTN InVariableNameSize;\r
8a2d4996 586\r
587 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
588 return EFI_INVALID_PARAMETER;\r
589 }\r
6ed1ec59 590\r
9d00d20e
SZ
591 OutVariableNameSize = *VariableNameSize;\r
592 InVariableNameSize = StrSize (VariableName);\r
4e1005ec 593 SmmGetNextVariableName = NULL;\r
0c55190f 594\r
595 //\r
596 // If input string exceeds SMM payload limit. Return failure\r
597 //\r
5e5bb2a9 598 if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
3588bb35
SZ
599 return EFI_INVALID_PARAMETER;\r
600 }\r
601\r
6ed1ec59
SZ
602 AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
603\r
8a2d4996 604 //\r
605 // Init the communicate buffer. The buffer data size is:\r
606 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
607 //\r
5e5bb2a9 608 if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
0c55190f 609 //\r
610 // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size\r
611 //\r
5e5bb2a9 612 OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
0c55190f 613 }\r
614 //\r
615 // Payload should be Guid + NameSize + MAX of Input & Output buffer\r
616 //\r
9d00d20e 617 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);\r
0c55190f 618\r
5c7fa429 619 Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);\r
8a2d4996 620 if (EFI_ERROR (Status)) {\r
6ed1ec59 621 goto Done;\r
8a2d4996 622 }\r
623 ASSERT (SmmGetNextVariableName != NULL);\r
624\r
0c55190f 625 //\r
626 // SMM comm buffer->NameSize is buffer size for return string\r
627 //\r
9d00d20e 628 SmmGetNextVariableName->NameSize = OutVariableNameSize;\r
0c55190f 629\r
8a2d4996 630 CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);\r
0c55190f 631 //\r
632 // Copy whole string\r
633 //\r
9d00d20e
SZ
634 CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize);\r
635 if (OutVariableNameSize > InVariableNameSize) {\r
636 ZeroMem ((UINT8 *) SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize);\r
637 }\r
8a2d4996 638\r
639 //\r
640 // Send data to SMM\r
641 //\r
642 Status = SendCommunicateBuffer (PayloadSize);\r
643\r
644 //\r
645 // Get data from SMM.\r
646 //\r
9d00d20e
SZ
647 if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {\r
648 //\r
649 // SMM CommBuffer NameSize can be a trimed value\r
650 // Only update VariableNameSize when needed\r
651 //\r
652 *VariableNameSize = SmmGetNextVariableName->NameSize;\r
653 }\r
8a2d4996 654 if (EFI_ERROR (Status)) {\r
6ed1ec59 655 goto Done;\r
8a2d4996 656 }\r
fa0737a8 657\r
8a2d4996 658 CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);\r
fa0737a8 659 CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);\r
8a2d4996 660\r
6ed1ec59
SZ
661Done:\r
662 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
8a2d4996 663 return Status;\r
664}\r
665\r
666/**\r
667 This code sets variable in storage blocks (Volatile or Non-Volatile).\r
668\r
18a7dbbc
SZ
669 Caution: This function may receive untrusted input.\r
670 The data size and data are external input, so this function will validate it carefully to avoid buffer overflow.\r
671\r
8a2d4996 672 @param[in] VariableName Name of Variable to be found.\r
673 @param[in] VendorGuid Variable vendor GUID.\r
674 @param[in] Attributes Attribute value of the variable found\r
675 @param[in] DataSize Size of Data found. If size is less than the\r
676 data, this value contains the required size.\r
677 @param[in] Data Data pointer.\r
678\r
679 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
680 @retval EFI_SUCCESS Set successfully.\r
681 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.\r
682 @retval EFI_NOT_FOUND Not found.\r
683 @retval EFI_WRITE_PROTECTED Variable is read-only.\r
684\r
685**/\r
686EFI_STATUS\r
687EFIAPI\r
688RuntimeServiceSetVariable (\r
689 IN CHAR16 *VariableName,\r
690 IN EFI_GUID *VendorGuid,\r
691 IN UINT32 Attributes,\r
692 IN UINTN DataSize,\r
693 IN VOID *Data\r
694 )\r
695{\r
696 EFI_STATUS Status;\r
fa0737a8 697 UINTN PayloadSize;\r
8a2d4996 698 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
9d00d20e 699 UINTN VariableNameSize;\r
fa0737a8 700\r
8a2d4996 701 //\r
702 // Check input parameters.\r
703 //\r
704 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
705 return EFI_INVALID_PARAMETER;\r
fa0737a8 706 }\r
8a2d4996 707\r
708 if (DataSize != 0 && Data == NULL) {\r
709 return EFI_INVALID_PARAMETER;\r
710 }\r
6ed1ec59 711\r
9d00d20e 712 VariableNameSize = StrSize (VariableName);\r
4e1005ec 713 SmmVariableHeader = NULL;\r
3588bb35 714\r
5e5bb2a9
SZ
715 //\r
716 // If VariableName or DataSize exceeds SMM payload limit. Return failure\r
717 //\r
718 if ((VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
719 (DataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize)){\r
56251c66 720 return EFI_INVALID_PARAMETER;\r
721 }\r
722\r
6ed1ec59 723 AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
fa0737a8 724\r
8a2d4996 725 //\r
726 // Init the communicate buffer. The buffer data size is:\r
727 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
728 //\r
9d00d20e 729 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize;\r
5c7fa429 730 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);\r
8a2d4996 731 if (EFI_ERROR (Status)) {\r
6ed1ec59 732 goto Done;\r
8a2d4996 733 }\r
734 ASSERT (SmmVariableHeader != NULL);\r
735\r
736 CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);\r
737 SmmVariableHeader->DataSize = DataSize;\r
9d00d20e 738 SmmVariableHeader->NameSize = VariableNameSize;\r
8a2d4996 739 SmmVariableHeader->Attributes = Attributes;\r
740 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);\r
741 CopyMem ((UINT8 *) SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);\r
742\r
743 //\r
744 // Send data to SMM.\r
745 //\r
746 Status = SendCommunicateBuffer (PayloadSize);\r
6ed1ec59
SZ
747\r
748Done:\r
749 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
fa0737a8
SZ
750\r
751 if (!EfiAtRuntime ()) {\r
752 if (!EFI_ERROR (Status)) {\r
753 SecureBootHook (\r
754 VariableName,\r
755 VendorGuid\r
756 );\r
757 }\r
758 }\r
8a2d4996 759 return Status;\r
760}\r
761\r
762\r
763/**\r
764 This code returns information about the EFI variables.\r
765\r
766 @param[in] Attributes Attributes bitmask to specify the type of variables\r
767 on which to return information.\r
768 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available\r
769 for the EFI variables associated with the attributes specified.\r
770 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available\r
771 for EFI variables associated with the attributes specified.\r
772 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables\r
773 associated with the attributes specified.\r
774\r
775 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.\r
776 @retval EFI_SUCCESS Query successfully.\r
777 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.\r
778\r
779**/\r
780EFI_STATUS\r
781EFIAPI\r
782RuntimeServiceQueryVariableInfo (\r
783 IN UINT32 Attributes,\r
784 OUT UINT64 *MaximumVariableStorageSize,\r
785 OUT UINT64 *RemainingVariableStorageSize,\r
786 OUT UINT64 *MaximumVariableSize\r
787 )\r
788{\r
789 EFI_STATUS Status;\r
790 UINTN PayloadSize;\r
791 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;\r
792\r
4e1005ec
ED
793 SmmQueryVariableInfo = NULL;\r
794\r
8a2d4996 795 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
796 return EFI_INVALID_PARAMETER;\r
797 }\r
6ed1ec59
SZ
798\r
799 AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
800\r
8a2d4996 801 //\r
802 // Init the communicate buffer. The buffer data size is:\r
803 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;\r
804 //\r
d00ed85e 805 PayloadSize = sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);\r
5c7fa429 806 Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);\r
8a2d4996 807 if (EFI_ERROR (Status)) {\r
6ed1ec59 808 goto Done;\r
8a2d4996 809 }\r
810 ASSERT (SmmQueryVariableInfo != NULL);\r
811\r
812 SmmQueryVariableInfo->Attributes = Attributes;\r
813\r
814 //\r
815 // Send data to SMM.\r
816 //\r
817 Status = SendCommunicateBuffer (PayloadSize);\r
818 if (EFI_ERROR (Status)) {\r
6ed1ec59 819 goto Done;\r
8a2d4996 820 }\r
821\r
822 //\r
823 // Get data from SMM.\r
824 //\r
825 *MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;\r
826 *MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;\r
fa0737a8 827 *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;\r
6ed1ec59
SZ
828\r
829Done:\r
830 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
aab9212f 831 return Status;\r
8a2d4996 832}\r
833\r
834\r
835/**\r
836 Exit Boot Services Event notification handler.\r
837\r
838 Notify SMM variable driver about the event.\r
839\r
840 @param[in] Event Event whose notification function is being invoked.\r
841 @param[in] Context Pointer to the notification function's context.\r
842\r
843**/\r
844VOID\r
845EFIAPI\r
846OnExitBootServices (\r
847 IN EFI_EVENT Event,\r
848 IN VOID *Context\r
849 )\r
850{\r
851 //\r
852 // Init the communicate buffer. The buffer data size is:\r
853 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
854 //\r
fa0737a8 855 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);\r
8a2d4996 856\r
857 //\r
858 // Send data to SMM.\r
859 //\r
860 SendCommunicateBuffer (0);\r
861}\r
862\r
863\r
864/**\r
865 On Ready To Boot Services Event notification handler.\r
866\r
867 Notify SMM variable driver about the event.\r
868\r
869 @param[in] Event Event whose notification function is being invoked\r
870 @param[in] Context Pointer to the notification function's context\r
871\r
872**/\r
873VOID\r
874EFIAPI\r
875OnReadyToBoot (\r
876 IN EFI_EVENT Event,\r
877 IN VOID *Context\r
878 )\r
879{\r
880 //\r
881 // Init the communicate buffer. The buffer data size is:\r
882 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
883 //\r
884 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);\r
fa0737a8 885\r
8a2d4996 886 //\r
887 // Send data to SMM.\r
888 //\r
889 SendCommunicateBuffer (0);\r
fa0737a8
SZ
890\r
891 gBS->CloseEvent (Event);\r
8a2d4996 892}\r
893\r
894\r
895/**\r
896 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.\r
897\r
898 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
899 It convers pointer to new virtual address.\r
900\r
901 @param[in] Event Event whose notification function is being invoked.\r
902 @param[in] Context Pointer to the notification function's context.\r
903\r
904**/\r
905VOID\r
906EFIAPI\r
907VariableAddressChangeEvent (\r
908 IN EFI_EVENT Event,\r
909 IN VOID *Context\r
910 )\r
911{\r
912 EfiConvertPointer (0x0, (VOID **) &mVariableBuffer);\r
913 EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);\r
914}\r
915\r
fa0737a8
SZ
916/**\r
917 This code gets variable payload size.\r
918\r
919 @param[out] VariablePayloadSize Output pointer to variable payload size.\r
920\r
921 @retval EFI_SUCCESS Get successfully.\r
922 @retval Others Get unsuccessfully.\r
923\r
924**/\r
925EFI_STATUS\r
926EFIAPI\r
927GetVariablePayloadSize (\r
928 OUT UINTN *VariablePayloadSize\r
929 )\r
930{\r
931 EFI_STATUS Status;\r
932 SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *SmmGetPayloadSize;\r
933 EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
934 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
935 UINTN CommSize;\r
936 UINT8 *CommBuffer;\r
937\r
938 SmmGetPayloadSize = NULL;\r
939 CommBuffer = NULL;\r
940\r
941 if(VariablePayloadSize == NULL) {\r
942 return EFI_INVALID_PARAMETER;\r
943 }\r
944\r
945 AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
946\r
947 //\r
948 // Init the communicate buffer. The buffer data size is:\r
949 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
950 //\r
951 CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
952 CommBuffer = AllocateZeroPool (CommSize);\r
953 if (CommBuffer == NULL) {\r
954 Status = EFI_OUT_OF_RESOURCES;\r
955 goto Done;\r
956 }\r
957\r
958 SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) CommBuffer;\r
959 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
960 SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
961\r
962 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
963 SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;\r
964 SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;\r
965\r
966 //\r
967 // Send data to SMM.\r
968 //\r
969 Status = mSmmCommunication->Communicate (mSmmCommunication, CommBuffer, &CommSize);\r
970 ASSERT_EFI_ERROR (Status);\r
971\r
972 Status = SmmVariableFunctionHeader->ReturnStatus;\r
973 if (EFI_ERROR (Status)) {\r
974 goto Done;\r
975 }\r
976\r
977 //\r
978 // Get data from SMM.\r
979 //\r
980 *VariablePayloadSize = SmmGetPayloadSize->VariablePayloadSize;\r
981\r
982Done:\r
983 if (CommBuffer != NULL) {\r
984 FreePool (CommBuffer);\r
985 }\r
986 ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
987 return Status;\r
988}\r
8a2d4996 989\r
990/**\r
991 Initialize variable service and install Variable Architectural protocol.\r
992\r
993 @param[in] Event Event whose notification function is being invoked.\r
994 @param[in] Context Pointer to the notification function's context.\r
fa0737a8 995\r
8a2d4996 996**/\r
997VOID\r
998EFIAPI\r
999SmmVariableReady (\r
1000 IN EFI_EVENT Event,\r
1001 IN VOID *Context\r
1002 )\r
1003{\r
1004 EFI_STATUS Status;\r
1005\r
1006 Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);\r
1007 if (EFI_ERROR (Status)) {\r
1008 return;\r
1009 }\r
fa0737a8 1010\r
8a2d4996 1011 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);\r
1012 ASSERT_EFI_ERROR (Status);\r
fa0737a8 1013\r
8a2d4996 1014 //\r
5e5bb2a9 1015 // Allocate memory for variable communicate buffer.\r
8a2d4996 1016 //\r
fa0737a8
SZ
1017 Status = GetVariablePayloadSize (&mVariableBufferPayloadSize);\r
1018 ASSERT_EFI_ERROR (Status);\r
5e5bb2a9 1019 mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;\r
8a2d4996 1020 mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);\r
1021 ASSERT (mVariableBuffer != NULL);\r
1022\r
1023 //\r
1024 // Save the buffer physical address used for SMM conmunication.\r
1025 //\r
1026 mVariableBufferPhysical = mVariableBuffer;\r
1027\r
1028 gRT->GetVariable = RuntimeServiceGetVariable;\r
1029 gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;\r
1030 gRT->SetVariable = RuntimeServiceSetVariable;\r
1031 gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;\r
fa0737a8 1032\r
8a2d4996 1033 //\r
1034 // Install the Variable Architectural Protocol on a new handle.\r
1035 //\r
1036 Status = gBS->InstallProtocolInterface (\r
1037 &mHandle,\r
fa0737a8 1038 &gEfiVariableArchProtocolGuid,\r
8a2d4996 1039 EFI_NATIVE_INTERFACE,\r
1040 NULL\r
1041 );\r
1042 ASSERT_EFI_ERROR (Status);\r
aa2868b3
SZ
1043\r
1044 mVariableLock.RequestToLock = VariableLockRequestToLock;\r
1045 Status = gBS->InstallMultipleProtocolInterfaces (\r
1046 &mHandle,\r
1047 &gEdkiiVariableLockProtocolGuid,\r
1048 &mVariableLock,\r
1049 NULL\r
1050 );\r
1051 ASSERT_EFI_ERROR (Status);\r
1052\r
1053 mVarCheck.RegisterSetVariableCheckHandler = VarCheckRegisterSetVariableCheckHandler;\r
1054 mVarCheck.VariablePropertySet = VarCheckVariablePropertySet;\r
1055 mVarCheck.VariablePropertyGet = VarCheckVariablePropertyGet;\r
1056 Status = gBS->InstallMultipleProtocolInterfaces (\r
1057 &mHandle,\r
1058 &gEdkiiVarCheckProtocolGuid,\r
1059 &mVarCheck,\r
1060 NULL\r
1061 );\r
1062 ASSERT_EFI_ERROR (Status);\r
fa0737a8
SZ
1063\r
1064 gBS->CloseEvent (Event);\r
8a2d4996 1065}\r
1066\r
1067\r
1068/**\r
1069 SMM Non-Volatile variable write service is ready notify event handler.\r
1070\r
1071 @param[in] Event Event whose notification function is being invoked.\r
1072 @param[in] Context Pointer to the notification function's context.\r
fa0737a8 1073\r
8a2d4996 1074**/\r
1075VOID\r
1076EFIAPI\r
1077SmmVariableWriteReady (\r
1078 IN EFI_EVENT Event,\r
1079 IN VOID *Context\r
1080 )\r
1081{\r
1082 EFI_STATUS Status;\r
1083 VOID *ProtocolOps;\r
1084\r
1085 //\r
1086 // Check whether the protocol is installed or not.\r
1087 //\r
d00ed85e 1088 Status = gBS->LocateProtocol (&gSmmVariableWriteGuid, NULL, (VOID **) &ProtocolOps);\r
8a2d4996 1089 if (EFI_ERROR (Status)) {\r
1090 return;\r
1091 }\r
fa0737a8 1092\r
dc9bd6ed
ZC
1093 //\r
1094 // Some Secure Boot Policy Var (SecureBoot, etc) updates following other\r
1095 // Secure Boot Policy Variable change. Record their initial value.\r
1096 //\r
1097 RecordSecureBootPolicyVarData();\r
1098\r
8a2d4996 1099 Status = gBS->InstallProtocolInterface (\r
1100 &mHandle,\r
fa0737a8 1101 &gEfiVariableWriteArchProtocolGuid,\r
8a2d4996 1102 EFI_NATIVE_INTERFACE,\r
1103 NULL\r
1104 );\r
fa0737a8
SZ
1105 ASSERT_EFI_ERROR (Status);\r
1106\r
1107 gBS->CloseEvent (Event);\r
8a2d4996 1108}\r
1109\r
1110\r
1111/**\r
1112 Variable Driver main entry point. The Variable driver places the 4 EFI\r
fa0737a8 1113 runtime services in the EFI System Table and installs arch protocols\r
d00ed85e 1114 for variable read and write services being available. It also registers\r
8a2d4996 1115 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
1116\r
fa0737a8 1117 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
8a2d4996 1118 @param[in] SystemTable A pointer to the EFI System Table.\r
fa0737a8 1119\r
8a2d4996 1120 @retval EFI_SUCCESS Variable service successfully initialized.\r
1121\r
1122**/\r
1123EFI_STATUS\r
1124EFIAPI\r
1125VariableSmmRuntimeInitialize (\r
1126 IN EFI_HANDLE ImageHandle,\r
1127 IN EFI_SYSTEM_TABLE *SystemTable\r
1128 )\r
1129{\r
1130 VOID *SmmVariableRegistration;\r
1131 VOID *SmmVariableWriteRegistration;\r
1132 EFI_EVENT OnReadyToBootEvent;\r
1133 EFI_EVENT ExitBootServiceEvent;\r
d3460bcb 1134 EFI_EVENT LegacyBootEvent;\r
6ed1ec59
SZ
1135\r
1136 EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);\r
1137\r
8a2d4996 1138 //\r
1139 // Smm variable service is ready\r
1140 //\r
1141 EfiCreateProtocolNotifyEvent (\r
fa0737a8
SZ
1142 &gEfiSmmVariableProtocolGuid,\r
1143 TPL_CALLBACK,\r
1144 SmmVariableReady,\r
1145 NULL,\r
8a2d4996 1146 &SmmVariableRegistration\r
1147 );\r
1148\r
1149 //\r
1150 // Smm Non-Volatile variable write service is ready\r
1151 //\r
1152 EfiCreateProtocolNotifyEvent (\r
fa0737a8
SZ
1153 &gSmmVariableWriteGuid,\r
1154 TPL_CALLBACK,\r
1155 SmmVariableWriteReady,\r
1156 NULL,\r
8a2d4996 1157 &SmmVariableWriteRegistration\r
1158 );\r
1159\r
1160 //\r
1161 // Register the event to reclaim variable for OS usage.\r
1162 //\r
1163 EfiCreateEventReadyToBootEx (\r
fa0737a8
SZ
1164 TPL_NOTIFY,\r
1165 OnReadyToBoot,\r
1166 NULL,\r
8a2d4996 1167 &OnReadyToBootEvent\r
fa0737a8 1168 );\r
8a2d4996 1169\r
1170 //\r
1171 // Register the event to inform SMM variable that it is at runtime.\r
1172 //\r
1173 gBS->CreateEventEx (\r
1174 EVT_NOTIFY_SIGNAL,\r
1175 TPL_NOTIFY,\r
1176 OnExitBootServices,\r
1177 NULL,\r
1178 &gEfiEventExitBootServicesGuid,\r
1179 &ExitBootServiceEvent\r
fa0737a8 1180 );\r
8a2d4996 1181\r
d3460bcb
SZ
1182 //\r
1183 // Register the event to inform SMM variable that it is at runtime for legacy boot.\r
1184 // Reuse OnExitBootServices() here.\r
1185 //\r
1186 EfiCreateEventLegacyBootEx(\r
1187 TPL_NOTIFY,\r
1188 OnExitBootServices,\r
1189 NULL,\r
1190 &LegacyBootEvent\r
1191 );\r
1192\r
8a2d4996 1193 //\r
1194 // Register the event to convert the pointer for runtime.\r
1195 //\r
1196 gBS->CreateEventEx (\r
1197 EVT_NOTIFY_SIGNAL,\r
1198 TPL_NOTIFY,\r
1199 VariableAddressChangeEvent,\r
1200 NULL,\r
1201 &gEfiEventVirtualAddressChangeGuid,\r
1202 &mVirtualAddressChangeEvent\r
1203 );\r
fa0737a8 1204\r
8a2d4996 1205 return EFI_SUCCESS;\r
1206}\r
1207\r