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