]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c
Change IPF version AuthVariable driver to support multiple-platform feature.
[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
6Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
7This program and the accompanying materials \r
8are licensed and made available under the terms and conditions of the BSD License \r
9which accompanies this distribution. The full text of the license may be found at \r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include <PiDxe.h>\r
18#include <Protocol/VariableWrite.h>\r
19#include <Protocol/Variable.h>\r
20#include <Protocol/SmmCommunication.h>\r
21#include <Protocol/SmmVariable.h>\r
22\r
23#include <Library/UefiBootServicesTableLib.h>\r
24#include <Library/UefiRuntimeServicesTableLib.h>\r
25#include <Library/MemoryAllocationLib.h>\r
26#include <Library/UefiDriverEntryPoint.h>\r
27#include <Library/UefiRuntimeLib.h>\r
28#include <Library/BaseMemoryLib.h>\r
29#include <Library/DebugLib.h>\r
30#include <Library/PcdLib.h>\r
31#include <Library/UefiLib.h>\r
32#include <Library/BaseLib.h>\r
33\r
34#include <Guid/EventGroup.h>\r
35#include <Guid/AuthenticatedVariableFormat.h>\r
36#include <Guid/SmmVariableCommon.h>\r
37\r
38EFI_HANDLE mHandle = NULL; \r
39EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;\r
40EFI_EVENT mVirtualAddressChangeEvent = NULL;\r
41EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;\r
42UINT8 *mVariableBuffer = NULL;\r
43UINT8 *mVariableBufferPhysical = NULL;\r
44UINTN mVariableBufferSize;\r
45\r
46\r
47/**\r
48 Initialize the communicate buffer using DataSize and Function.\r
49\r
50 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +\r
51 DataSize.\r
52\r
53 @param[out] DataPtr Points to the data in the communicate buffer.\r
54 @param[in] DataSize The data size to send to SMM.\r
55 @param[in] Function The function number to initialize the communicate header.\r
56 \r
57 @retval EFI_INVALID_PARAMETER The data size is too big.\r
58 @retval EFI_SUCCESS Find the specified variable.\r
59\r
60**/\r
61EFI_STATUS\r
62InitCommunicateBuffer (\r
63 OUT VOID **DataPtr OPTIONAL,\r
64 IN UINTN DataSize,\r
65 IN UINTN Function\r
66 )\r
67{\r
68 EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; \r
69 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader; \r
70\r
71 \r
72 if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {\r
73 return EFI_INVALID_PARAMETER;\r
74 }\r
75\r
76 SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;\r
77 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
78 SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
79 \r
80 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
81 SmmVariableFunctionHeader->Function = Function;\r
82 if (DataPtr != NULL) {\r
83 *DataPtr = SmmVariableFunctionHeader->Data;\r
84 }\r
85\r
86 return EFI_SUCCESS;\r
87}\r
88\r
89\r
90/**\r
91 Send the data in communicate buffer to SMM.\r
92\r
93 @param[in] DataSize This size of the function header and the data.\r
94\r
95 @retval EFI_SUCCESS Success is returned from the functin in SMM.\r
96 @retval Others Failure is returned from the function in SMM. \r
97 \r
98**/\r
99EFI_STATUS\r
100SendCommunicateBuffer (\r
101 IN UINTN DataSize\r
102 )\r
103{\r
104 EFI_STATUS Status;\r
105 UINTN CommSize;\r
106 EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; \r
107 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
108 \r
109 CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
110 Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);\r
111 ASSERT_EFI_ERROR (Status);\r
112\r
113 SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;\r
114 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;\r
115 return SmmVariableFunctionHeader->ReturnStatus;\r
116}\r
117\r
118\r
119/**\r
120 This code finds variable in storage blocks (Volatile or Non-Volatile).\r
121\r
122 @param[in] VariableName Name of Variable to be found.\r
123 @param[in] VendorGuid Variable vendor GUID.\r
124 @param[out] Attributes Attribute value of the variable found.\r
125 @param[in, out] DataSize Size of Data found. If size is less than the\r
126 data, this value contains the required size.\r
127 @param[out] Data Data pointer.\r
128 \r
129 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
130 @retval EFI_SUCCESS Find the specified variable.\r
131 @retval EFI_NOT_FOUND Not found.\r
132 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
133\r
134**/\r
135EFI_STATUS\r
136EFIAPI\r
137RuntimeServiceGetVariable (\r
138 IN CHAR16 *VariableName,\r
139 IN EFI_GUID *VendorGuid,\r
140 OUT UINT32 *Attributes OPTIONAL,\r
141 IN OUT UINTN *DataSize,\r
142 OUT VOID *Data\r
143 )\r
144{\r
145 EFI_STATUS Status;\r
146 UINTN PayloadSize;\r
147 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
148\r
149 if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
150 return EFI_INVALID_PARAMETER;\r
151 }\r
152\r
153 if ((*DataSize != 0) && (Data == NULL)) {\r
154 return EFI_INVALID_PARAMETER;\r
155 }\r
156 \r
157 //\r
158 // Init the communicate buffer. The buffer data size is:\r
159 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
160 //\r
161 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName);\r
162 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);\r
163 if (EFI_ERROR (Status)) {\r
164 return Status;\r
165 }\r
166 ASSERT (SmmVariableHeader != NULL);\r
167\r
168 CopyGuid (&SmmVariableHeader->Guid, VendorGuid);\r
169 SmmVariableHeader->DataSize = *DataSize;\r
170 SmmVariableHeader->NameSize = StrSize (VariableName);\r
171 if (Attributes == NULL) {\r
172 SmmVariableHeader->Attributes = 0;\r
173 } else {\r
174 SmmVariableHeader->Attributes = *Attributes;\r
175 }\r
176 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);\r
177\r
178 //\r
179 // Send data to SMM.\r
180 //\r
181 Status = SendCommunicateBuffer (PayloadSize);\r
182\r
183 //\r
184 // Get data from SMM.\r
185 //\r
186 *DataSize = SmmVariableHeader->DataSize;\r
187 if (Attributes != NULL) {\r
188 *Attributes = SmmVariableHeader->Attributes;\r
189 }\r
190\r
191 if (EFI_ERROR (Status)) {\r
192 return Status;\r
193 }\r
194\r
195 CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);\r
196\r
197 return Status;\r
198}\r
199\r
200\r
201/**\r
202 This code Finds the Next available variable.\r
203\r
204 @param[in, out] VariableNameSize Size of the variable name.\r
205 @param[in, out] VariableName Pointer to variable name.\r
206 @param[in, out] VendorGuid Variable Vendor Guid.\r
207\r
208 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
209 @retval EFI_SUCCESS Find the specified variable.\r
210 @retval EFI_NOT_FOUND Not found.\r
211 @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
212\r
213**/\r
214EFI_STATUS\r
215EFIAPI\r
216RuntimeServiceGetNextVariableName (\r
217 IN OUT UINTN *VariableNameSize,\r
218 IN OUT CHAR16 *VariableName,\r
219 IN OUT EFI_GUID *VendorGuid\r
220 )\r
221{\r
222 EFI_STATUS Status;\r
223 UINTN PayloadSize;\r
224 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;\r
225\r
226 if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
227 return EFI_INVALID_PARAMETER;\r
228 }\r
229 \r
230 //\r
231 // Init the communicate buffer. The buffer data size is:\r
232 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
233 //\r
234 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize; \r
235 Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);\r
236 if (EFI_ERROR (Status)) {\r
237 return Status;\r
238 }\r
239 ASSERT (SmmGetNextVariableName != NULL);\r
240\r
241 SmmGetNextVariableName->NameSize = *VariableNameSize;\r
242 CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);\r
243 CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize);\r
244\r
245 //\r
246 // Send data to SMM\r
247 //\r
248 Status = SendCommunicateBuffer (PayloadSize);\r
249\r
250 //\r
251 // Get data from SMM.\r
252 //\r
253 *VariableNameSize = SmmGetNextVariableName->NameSize; \r
254 if (EFI_ERROR (Status)) {\r
255 return Status;\r
256 }\r
257 \r
258 CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);\r
259 CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize); \r
260\r
261 return Status;\r
262}\r
263\r
264/**\r
265 This code sets variable in storage blocks (Volatile or Non-Volatile).\r
266\r
267 @param[in] VariableName Name of Variable to be found.\r
268 @param[in] VendorGuid Variable vendor GUID.\r
269 @param[in] Attributes Attribute value of the variable found\r
270 @param[in] DataSize Size of Data found. If size is less than the\r
271 data, this value contains the required size.\r
272 @param[in] Data Data pointer.\r
273\r
274 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
275 @retval EFI_SUCCESS Set successfully.\r
276 @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.\r
277 @retval EFI_NOT_FOUND Not found.\r
278 @retval EFI_WRITE_PROTECTED Variable is read-only.\r
279\r
280**/\r
281EFI_STATUS\r
282EFIAPI\r
283RuntimeServiceSetVariable (\r
284 IN CHAR16 *VariableName,\r
285 IN EFI_GUID *VendorGuid,\r
286 IN UINT32 Attributes,\r
287 IN UINTN DataSize,\r
288 IN VOID *Data\r
289 )\r
290{\r
291 EFI_STATUS Status;\r
292 UINTN PayloadSize; \r
293 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
294 \r
295 //\r
296 // Check input parameters.\r
297 //\r
298 if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
299 return EFI_INVALID_PARAMETER;\r
300 } \r
301\r
302 if (DataSize != 0 && Data == NULL) {\r
303 return EFI_INVALID_PARAMETER;\r
304 }\r
305 \r
306 //\r
307 // Init the communicate buffer. The buffer data size is:\r
308 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
309 //\r
310 PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;\r
311 Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);\r
312 if (EFI_ERROR (Status)) {\r
313 return Status;\r
314 }\r
315 ASSERT (SmmVariableHeader != NULL);\r
316\r
317 CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);\r
318 SmmVariableHeader->DataSize = DataSize;\r
319 SmmVariableHeader->NameSize = StrSize (VariableName);\r
320 SmmVariableHeader->Attributes = Attributes;\r
321 CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);\r
322 CopyMem ((UINT8 *) SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);\r
323\r
324 //\r
325 // Send data to SMM.\r
326 //\r
327 Status = SendCommunicateBuffer (PayloadSize);\r
328 \r
329 return Status;\r
330}\r
331\r
332\r
333/**\r
334 This code returns information about the EFI variables.\r
335\r
336 @param[in] Attributes Attributes bitmask to specify the type of variables\r
337 on which to return information.\r
338 @param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available\r
339 for the EFI variables associated with the attributes specified.\r
340 @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available\r
341 for EFI variables associated with the attributes specified.\r
342 @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables\r
343 associated with the attributes specified.\r
344\r
345 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.\r
346 @retval EFI_SUCCESS Query successfully.\r
347 @retval EFI_UNSUPPORTED The attribute is not supported on this platform.\r
348\r
349**/\r
350EFI_STATUS\r
351EFIAPI\r
352RuntimeServiceQueryVariableInfo (\r
353 IN UINT32 Attributes,\r
354 OUT UINT64 *MaximumVariableStorageSize,\r
355 OUT UINT64 *RemainingVariableStorageSize,\r
356 OUT UINT64 *MaximumVariableSize\r
357 )\r
358{\r
359 EFI_STATUS Status;\r
360 UINTN PayloadSize;\r
361 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;\r
362\r
363 if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
364 return EFI_INVALID_PARAMETER;\r
365 }\r
366 \r
367 //\r
368 // Init the communicate buffer. The buffer data size is:\r
369 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;\r
370 //\r
371 PayloadSize = sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);\r
372 Status = InitCommunicateBuffer ((VOID **)&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);\r
373 if (EFI_ERROR (Status)) {\r
374 return Status;\r
375 }\r
376 ASSERT (SmmQueryVariableInfo != NULL);\r
377\r
378 SmmQueryVariableInfo->Attributes = Attributes;\r
379\r
380 //\r
381 // Send data to SMM.\r
382 //\r
383 Status = SendCommunicateBuffer (PayloadSize);\r
384 if (EFI_ERROR (Status)) {\r
385 return Status;\r
386 }\r
387\r
388 //\r
389 // Get data from SMM.\r
390 //\r
391 *MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;\r
392 *MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;\r
393 *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize; \r
394 \r
395 return EFI_SUCCESS;\r
396}\r
397\r
398\r
399/**\r
400 Exit Boot Services Event notification handler.\r
401\r
402 Notify SMM variable driver about the event.\r
403\r
404 @param[in] Event Event whose notification function is being invoked.\r
405 @param[in] Context Pointer to the notification function's context.\r
406\r
407**/\r
408VOID\r
409EFIAPI\r
410OnExitBootServices (\r
411 IN EFI_EVENT Event,\r
412 IN VOID *Context\r
413 )\r
414{\r
415 //\r
416 // Init the communicate buffer. The buffer data size is:\r
417 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
418 //\r
419 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE); \r
420\r
421 //\r
422 // Send data to SMM.\r
423 //\r
424 SendCommunicateBuffer (0);\r
425}\r
426\r
427\r
428/**\r
429 On Ready To Boot Services Event notification handler.\r
430\r
431 Notify SMM variable driver about the event.\r
432\r
433 @param[in] Event Event whose notification function is being invoked\r
434 @param[in] Context Pointer to the notification function's context\r
435\r
436**/\r
437VOID\r
438EFIAPI\r
439OnReadyToBoot (\r
440 IN EFI_EVENT Event,\r
441 IN VOID *Context\r
442 )\r
443{\r
444 //\r
445 // Init the communicate buffer. The buffer data size is:\r
446 // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
447 //\r
448 InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);\r
449 \r
450 //\r
451 // Send data to SMM.\r
452 //\r
453 SendCommunicateBuffer (0);\r
454}\r
455\r
456\r
457/**\r
458 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.\r
459\r
460 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
461 It convers pointer to new virtual address.\r
462\r
463 @param[in] Event Event whose notification function is being invoked.\r
464 @param[in] Context Pointer to the notification function's context.\r
465\r
466**/\r
467VOID\r
468EFIAPI\r
469VariableAddressChangeEvent (\r
470 IN EFI_EVENT Event,\r
471 IN VOID *Context\r
472 )\r
473{\r
474 EfiConvertPointer (0x0, (VOID **) &mVariableBuffer);\r
475 EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);\r
476}\r
477\r
478\r
479/**\r
480 Initialize variable service and install Variable Architectural protocol.\r
481\r
482 @param[in] Event Event whose notification function is being invoked.\r
483 @param[in] Context Pointer to the notification function's context.\r
484 \r
485**/\r
486VOID\r
487EFIAPI\r
488SmmVariableReady (\r
489 IN EFI_EVENT Event,\r
490 IN VOID *Context\r
491 )\r
492{\r
493 EFI_STATUS Status;\r
494\r
495 Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);\r
496 if (EFI_ERROR (Status)) {\r
497 return;\r
498 }\r
499 \r
500 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);\r
501 ASSERT_EFI_ERROR (Status);\r
502 \r
503 //\r
504 // Allocate memory for variable store.\r
505 //\r
506 mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
507 mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));\r
508 mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);\r
509 ASSERT (mVariableBuffer != NULL);\r
510\r
511 //\r
512 // Save the buffer physical address used for SMM conmunication.\r
513 //\r
514 mVariableBufferPhysical = mVariableBuffer;\r
515\r
516 gRT->GetVariable = RuntimeServiceGetVariable;\r
517 gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;\r
518 gRT->SetVariable = RuntimeServiceSetVariable;\r
519 gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;\r
520 \r
521 //\r
522 // Install the Variable Architectural Protocol on a new handle.\r
523 //\r
524 Status = gBS->InstallProtocolInterface (\r
525 &mHandle,\r
526 &gEfiVariableArchProtocolGuid, \r
527 EFI_NATIVE_INTERFACE,\r
528 NULL\r
529 );\r
530 ASSERT_EFI_ERROR (Status);\r
531}\r
532\r
533\r
534/**\r
535 SMM Non-Volatile variable write service is ready notify event handler.\r
536\r
537 @param[in] Event Event whose notification function is being invoked.\r
538 @param[in] Context Pointer to the notification function's context.\r
539 \r
540**/\r
541VOID\r
542EFIAPI\r
543SmmVariableWriteReady (\r
544 IN EFI_EVENT Event,\r
545 IN VOID *Context\r
546 )\r
547{\r
548 EFI_STATUS Status;\r
549 VOID *ProtocolOps;\r
550\r
551 //\r
552 // Check whether the protocol is installed or not.\r
553 //\r
554 Status = gBS->LocateProtocol (&gSmmVariableWriteGuid, NULL, (VOID **) &ProtocolOps);\r
555 if (EFI_ERROR (Status)) {\r
556 return;\r
557 }\r
558 \r
559 Status = gBS->InstallProtocolInterface (\r
560 &mHandle,\r
561 &gEfiVariableWriteArchProtocolGuid, \r
562 EFI_NATIVE_INTERFACE,\r
563 NULL\r
564 );\r
565 ASSERT_EFI_ERROR (Status); \r
566}\r
567\r
568\r
569/**\r
570 Variable Driver main entry point. The Variable driver places the 4 EFI\r
571 runtime services in the EFI System Table and installs arch protocols \r
572 for variable read and write services being available. It also registers\r
573 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
574\r
575 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
576 @param[in] SystemTable A pointer to the EFI System Table.\r
577 \r
578 @retval EFI_SUCCESS Variable service successfully initialized.\r
579\r
580**/\r
581EFI_STATUS\r
582EFIAPI\r
583VariableSmmRuntimeInitialize (\r
584 IN EFI_HANDLE ImageHandle,\r
585 IN EFI_SYSTEM_TABLE *SystemTable\r
586 )\r
587{\r
588 VOID *SmmVariableRegistration;\r
589 VOID *SmmVariableWriteRegistration;\r
590 EFI_EVENT OnReadyToBootEvent;\r
591 EFI_EVENT ExitBootServiceEvent;\r
592 \r
593 //\r
594 // Smm variable service is ready\r
595 //\r
596 EfiCreateProtocolNotifyEvent (\r
597 &gEfiSmmVariableProtocolGuid, \r
598 TPL_CALLBACK, \r
599 SmmVariableReady, \r
600 NULL, \r
601 &SmmVariableRegistration\r
602 );\r
603\r
604 //\r
605 // Smm Non-Volatile variable write service is ready\r
606 //\r
607 EfiCreateProtocolNotifyEvent (\r
608 &gSmmVariableWriteGuid, \r
609 TPL_CALLBACK, \r
610 SmmVariableWriteReady, \r
611 NULL, \r
612 &SmmVariableWriteRegistration\r
613 );\r
614\r
615 //\r
616 // Register the event to reclaim variable for OS usage.\r
617 //\r
618 EfiCreateEventReadyToBootEx (\r
619 TPL_NOTIFY, \r
620 OnReadyToBoot, \r
621 NULL, \r
622 &OnReadyToBootEvent\r
623 ); \r
624\r
625 //\r
626 // Register the event to inform SMM variable that it is at runtime.\r
627 //\r
628 gBS->CreateEventEx (\r
629 EVT_NOTIFY_SIGNAL,\r
630 TPL_NOTIFY,\r
631 OnExitBootServices,\r
632 NULL,\r
633 &gEfiEventExitBootServicesGuid,\r
634 &ExitBootServiceEvent\r
635 ); \r
636\r
637 //\r
638 // Register the event to convert the pointer for runtime.\r
639 //\r
640 gBS->CreateEventEx (\r
641 EVT_NOTIFY_SIGNAL,\r
642 TPL_NOTIFY,\r
643 VariableAddressChangeEvent,\r
644 NULL,\r
645 &gEfiEventVirtualAddressChangeGuid,\r
646 &mVirtualAddressChangeEvent\r
647 );\r
648 \r
649 return EFI_SUCCESS;\r
650}\r
651\r