]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
SecurityPkg Variable: Implement variable quota management.
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / RuntimeDxe / VariableSmm.c
CommitLineData
0c18794e 1/** @file\r
2 The sample implementation for SMM variable protocol. And this driver \r
3 implements an SMI handler to communicate with the DXE runtime driver \r
4 to provide variable services.\r
5\r
dc204d5a
JY
6 Caution: This module requires additional review when modified.\r
7 This driver will have external input - variable data and communicate buffer in SMM mode.\r
8 This external input must be validated carefully to avoid security issue like\r
9 buffer overflow, integer overflow.\r
10\r
11 SmmVariableHandler() will receive untrusted input and do basic validation.\r
12\r
13 Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(), \r
14 VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(), \r
15 SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
16\r
17409b7a 17Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
0c18794e 18This program and the accompanying materials \r
19are licensed and made available under the terms and conditions of the BSD License \r
20which accompanies this distribution. The full text of the license may be found at \r
21http://opensource.org/licenses/bsd-license.php\r
22\r
23THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
24WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
25\r
26**/\r
27\r
28#include <Protocol/SmmVariable.h>\r
29#include <Protocol/SmmFirmwareVolumeBlock.h>\r
30#include <Protocol/SmmFaultTolerantWrite.h>\r
25a4e71a 31#include <Protocol/SmmAccess2.h>\r
6ab9f441 32#include <Protocol/SmmEndOfDxe.h>\r
17409b7a 33#include <Protocol/SmmVarCheck.h>\r
25a4e71a 34\r
0c18794e 35#include <Library/SmmServicesTableLib.h>\r
36\r
37#include <Guid/AuthenticatedVariableFormat.h>\r
38#include <Guid/SmmVariableCommon.h>\r
39#include "Variable.h"\r
40\r
25a4e71a 41EFI_SMRAM_DESCRIPTOR *mSmramRanges;\r
42UINTN mSmramRangeCount;\r
43\r
0c18794e 44extern VARIABLE_INFO_ENTRY *gVariableInfo;\r
45EFI_HANDLE mSmmVariableHandle = NULL;\r
46EFI_HANDLE mVariableHandle = NULL;\r
47BOOLEAN mAtRuntime = FALSE;\r
48EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
5e5bb2a9
SZ
49UINT8 *mVariableBufferPayload = NULL;\r
50UINTN mVariableBufferPayloadSize;\r
6ab9f441
RN
51extern BOOLEAN mEndOfDxe;\r
52extern BOOLEAN mEnableLocking;\r
53\r
c1d93242
JY
54/**\r
55 SecureBoot Hook for SetVariable.\r
56\r
57 @param[in] VariableName Name of Variable to be found.\r
58 @param[in] VendorGuid Variable vendor GUID.\r
59\r
60**/\r
61VOID\r
62EFIAPI\r
63SecureBootHook (\r
64 IN CHAR16 *VariableName,\r
65 IN EFI_GUID *VendorGuid\r
66 )\r
67{\r
68 return ;\r
69}\r
70\r
6ab9f441
RN
71/**\r
72\r
73 This code sets variable in storage blocks (Volatile or Non-Volatile).\r
74\r
75 @param VariableName Name of Variable to be found.\r
76 @param VendorGuid Variable vendor GUID.\r
77 @param Attributes Attribute value of the variable found\r
78 @param DataSize Size of Data found. If size is less than the\r
79 data, this value contains the required size.\r
80 @param Data Data pointer.\r
81\r
82 @return EFI_INVALID_PARAMETER Invalid parameter.\r
83 @return EFI_SUCCESS Set successfully.\r
84 @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.\r
85 @return EFI_NOT_FOUND Not found.\r
86 @return EFI_WRITE_PROTECTED Variable is read-only.\r
87\r
88**/\r
89EFI_STATUS\r
90EFIAPI\r
91SmmVariableSetVariable (\r
92 IN CHAR16 *VariableName,\r
93 IN EFI_GUID *VendorGuid,\r
94 IN UINT32 Attributes,\r
95 IN UINTN DataSize,\r
96 IN VOID *Data\r
97 )\r
98{\r
99 EFI_STATUS Status;\r
100\r
101 //\r
102 // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.\r
103 //\r
104 mEnableLocking = FALSE;\r
105 Status = VariableServiceSetVariable (\r
106 VariableName,\r
107 VendorGuid,\r
108 Attributes,\r
109 DataSize,\r
110 Data\r
111 );\r
112 mEnableLocking = TRUE;\r
113 return Status;\r
114}\r
5e5bb2a9 115\r
0c18794e 116EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {\r
117 VariableServiceGetVariable,\r
118 VariableServiceGetNextVariableName,\r
6ab9f441 119 SmmVariableSetVariable,\r
0c18794e 120 VariableServiceQueryVariableInfo\r
121};\r
122\r
17409b7a
SZ
123EDKII_SMM_VAR_CHECK_PROTOCOL mSmmVarCheck = { VarCheckRegisterSetVariableCheckHandler,\r
124 VarCheckVariablePropertySet,\r
125 VarCheckVariablePropertyGet };\r
126\r
0c18794e 127/**\r
128 Return TRUE if ExitBootServices () has been called.\r
129 \r
130 @retval TRUE If ExitBootServices () has been called.\r
131**/\r
132BOOLEAN\r
133AtRuntime (\r
134 VOID\r
135 )\r
136{\r
137 return mAtRuntime;\r
138}\r
139\r
25a4e71a 140/**\r
141 This function check if the address is in SMRAM.\r
142\r
143 @param Buffer the buffer address to be checked.\r
144 @param Length the buffer length to be checked.\r
145\r
146 @retval TRUE this address is in SMRAM.\r
147 @retval FALSE this address is NOT in SMRAM.\r
148**/\r
149BOOLEAN\r
150InternalIsAddressInSmram (\r
151 IN EFI_PHYSICAL_ADDRESS Buffer,\r
152 IN UINT64 Length\r
153 )\r
154{\r
155 UINTN Index;\r
156\r
157 for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
158 if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||\r
159 ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {\r
160 return TRUE;\r
161 }\r
162 }\r
163\r
164 return FALSE;\r
165}\r
166\r
9d00d20e
SZ
167/**\r
168 This function check if the address refered by Buffer and Length is valid.\r
169\r
170 @param Buffer the buffer address to be checked.\r
171 @param Length the buffer length to be checked.\r
172\r
173 @retval TRUE this address is valid.\r
174 @retval FALSE this address is NOT valid.\r
175**/\r
176BOOLEAN\r
177InternalIsAddressValid (\r
178 IN UINTN Buffer,\r
179 IN UINTN Length\r
180 )\r
181{\r
182 if (Buffer > (MAX_ADDRESS - Length)) {\r
183 //\r
184 // Overflow happen\r
185 //\r
186 return FALSE;\r
187 }\r
188 if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)Buffer, (UINT64)Length)) {\r
189 return FALSE;\r
190 }\r
191 return TRUE;\r
192}\r
25a4e71a 193\r
0c18794e 194/**\r
195 Initializes a basic mutual exclusion lock.\r
196\r
197 This function initializes a basic mutual exclusion lock to the released state \r
198 and returns the lock. Each lock provides mutual exclusion access at its task \r
199 priority level. Since there is no preemption or multiprocessor support in EFI,\r
200 acquiring the lock only consists of raising to the locks TPL.\r
201 If Lock is NULL, then ASSERT().\r
202 If Priority is not a valid TPL value, then ASSERT().\r
203\r
204 @param Lock A pointer to the lock data structure to initialize.\r
205 @param Priority EFI TPL is associated with the lock.\r
206\r
207 @return The lock.\r
208\r
209**/\r
210EFI_LOCK *\r
211InitializeLock (\r
212 IN OUT EFI_LOCK *Lock,\r
213 IN EFI_TPL Priority\r
214 )\r
215{\r
216 return Lock;\r
217}\r
218\r
219/**\r
220 Acquires lock only at boot time. Simply returns at runtime.\r
221\r
222 This is a temperary function that will be removed when\r
223 EfiAcquireLock() in UefiLib can handle the call in UEFI\r
224 Runtimer driver in RT phase.\r
225 It calls EfiAcquireLock() at boot time, and simply returns\r
226 at runtime.\r
227\r
228 @param Lock A pointer to the lock to acquire.\r
229\r
230**/\r
231VOID\r
232AcquireLockOnlyAtBootTime (\r
233 IN EFI_LOCK *Lock\r
234 )\r
235{\r
236\r
237}\r
238\r
239\r
240/**\r
241 Releases lock only at boot time. Simply returns at runtime.\r
242\r
243 This is a temperary function which will be removed when\r
244 EfiReleaseLock() in UefiLib can handle the call in UEFI\r
245 Runtimer driver in RT phase.\r
246 It calls EfiReleaseLock() at boot time and simply returns\r
247 at runtime.\r
248\r
249 @param Lock A pointer to the lock to release.\r
250\r
251**/\r
252VOID\r
253ReleaseLockOnlyAtBootTime (\r
254 IN EFI_LOCK *Lock\r
255 )\r
256{\r
257\r
258}\r
259\r
260/**\r
261 Retrive the SMM Fault Tolerent Write protocol interface.\r
262\r
263 @param[out] FtwProtocol The interface of SMM Ftw protocol\r
264\r
265 @retval EFI_SUCCESS The SMM FTW protocol instance was found and returned in FtwProtocol.\r
266 @retval EFI_NOT_FOUND The SMM FTW protocol instance was not found.\r
267 @retval EFI_INVALID_PARAMETER SarProtocol is NULL.\r
268\r
269**/\r
270EFI_STATUS\r
271GetFtwProtocol (\r
272 OUT VOID **FtwProtocol\r
273 )\r
274{\r
275 EFI_STATUS Status;\r
276\r
277 //\r
278 // Locate Smm Fault Tolerent Write protocol\r
279 //\r
280 Status = gSmst->SmmLocateProtocol (\r
281 &gEfiSmmFaultTolerantWriteProtocolGuid, \r
282 NULL, \r
283 FtwProtocol\r
284 );\r
285 return Status;\r
286}\r
287\r
288\r
289/**\r
290 Retrive the SMM FVB protocol interface by HANDLE.\r
291\r
292 @param[in] FvBlockHandle The handle of SMM FVB protocol that provides services for\r
293 reading, writing, and erasing the target block.\r
294 @param[out] FvBlock The interface of SMM FVB protocol\r
295\r
296 @retval EFI_SUCCESS The interface information for the specified protocol was returned.\r
297 @retval EFI_UNSUPPORTED The device does not support the SMM FVB protocol.\r
298 @retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.\r
299\r
300**/\r
301EFI_STATUS\r
302GetFvbByHandle (\r
303 IN EFI_HANDLE FvBlockHandle,\r
304 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock\r
305 )\r
306{\r
307 //\r
308 // To get the SMM FVB protocol interface on the handle\r
309 //\r
310 return gSmst->SmmHandleProtocol (\r
311 FvBlockHandle,\r
312 &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
313 (VOID **) FvBlock\r
314 );\r
315}\r
316\r
317\r
318/**\r
319 Function returns an array of handles that support the SMM FVB protocol\r
320 in a buffer allocated from pool. \r
321\r
322 @param[out] NumberHandles The number of handles returned in Buffer.\r
323 @param[out] Buffer A pointer to the buffer to return the requested\r
324 array of handles that support SMM FVB protocol.\r
325\r
326 @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of\r
327 handles in Buffer was returned in NumberHandles.\r
328 @retval EFI_NOT_FOUND No SMM FVB handle was found.\r
329 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.\r
330 @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.\r
331\r
332**/\r
333EFI_STATUS\r
334GetFvbCountAndBuffer (\r
335 OUT UINTN *NumberHandles,\r
336 OUT EFI_HANDLE **Buffer\r
337 )\r
338{\r
339 EFI_STATUS Status;\r
340 UINTN BufferSize;\r
341\r
342 if ((NumberHandles == NULL) || (Buffer == NULL)) {\r
343 return EFI_INVALID_PARAMETER;\r
344 }\r
345\r
346 BufferSize = 0;\r
347 *NumberHandles = 0;\r
348 *Buffer = NULL;\r
349 Status = gSmst->SmmLocateHandle (\r
350 ByProtocol,\r
351 &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
352 NULL,\r
353 &BufferSize,\r
354 *Buffer\r
355 );\r
356 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
357 return EFI_NOT_FOUND;\r
358 }\r
359\r
360 *Buffer = AllocatePool (BufferSize);\r
361 if (*Buffer == NULL) {\r
362 return EFI_OUT_OF_RESOURCES;\r
363 }\r
364\r
365 Status = gSmst->SmmLocateHandle (\r
366 ByProtocol,\r
367 &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
368 NULL,\r
369 &BufferSize,\r
370 *Buffer\r
371 );\r
372\r
373 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
374 if (EFI_ERROR(Status)) {\r
375 *NumberHandles = 0;\r
5e5bb2a9
SZ
376 FreePool (*Buffer);\r
377 *Buffer = NULL;\r
0c18794e 378 }\r
379\r
380 return Status;\r
381}\r
382\r
383\r
384/**\r
385 Get the variable statistics information from the information buffer pointed by gVariableInfo.\r
386\r
dc204d5a
JY
387 Caution: This function may be invoked at SMM runtime.\r
388 InfoEntry and InfoSize are external input. Care must be taken to make sure not security issue at runtime.\r
389\r
648f98d1 390 @param[in, out] InfoEntry A pointer to the buffer of variable information entry.\r
391 On input, point to the variable information returned last time. if \r
392 InfoEntry->VendorGuid is zero, return the first information.\r
393 On output, point to the next variable information.\r
394 @param[in, out] InfoSize On input, the size of the variable information buffer.\r
395 On output, the returned variable information size.\r
396\r
397 @retval EFI_SUCCESS The variable information is found and returned successfully.\r
398 @retval EFI_UNSUPPORTED No variable inoformation exists in variable driver. The \r
399 PcdVariableCollectStatistics should be set TRUE to support it.\r
400 @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the next variable information.\r
401 @retval EFI_INVALID_PARAMETER Input parameter is invalid.\r
0c18794e 402\r
403**/\r
404EFI_STATUS\r
405SmmVariableGetStatistics (\r
406 IN OUT VARIABLE_INFO_ENTRY *InfoEntry,\r
407 IN OUT UINTN *InfoSize\r
408 )\r
409{\r
410 VARIABLE_INFO_ENTRY *VariableInfo;\r
411 UINTN NameLength;\r
412 UINTN StatisticsInfoSize;\r
413 CHAR16 *InfoName;\r
5e5bb2a9 414 EFI_GUID VendorGuid;\r
0c18794e 415 \r
648f98d1 416 if (InfoEntry == NULL) {\r
417 return EFI_INVALID_PARAMETER;\r
418 }\r
419 \r
0c18794e 420 VariableInfo = gVariableInfo; \r
421 if (VariableInfo == NULL) {\r
422 return EFI_UNSUPPORTED;\r
423 }\r
424\r
425 StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);\r
12373f2c 426 if (*InfoSize < StatisticsInfoSize) {\r
0c18794e 427 *InfoSize = StatisticsInfoSize;\r
428 return EFI_BUFFER_TOO_SMALL;\r
429 }\r
430 InfoName = (CHAR16 *)(InfoEntry + 1);\r
431\r
5e5bb2a9
SZ
432 CopyGuid (&VendorGuid, &InfoEntry->VendorGuid);\r
433\r
434 if (CompareGuid (&VendorGuid, &mZeroGuid)) {\r
0c18794e 435 //\r
436 // Return the first variable info\r
437 //\r
438 CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
439 CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
440 *InfoSize = StatisticsInfoSize;\r
441 return EFI_SUCCESS;\r
442 }\r
443\r
444 //\r
445 // Get the next variable info\r
446 //\r
447 while (VariableInfo != NULL) {\r
5e5bb2a9 448 if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) {\r
0c18794e 449 NameLength = StrSize (VariableInfo->Name);\r
450 if (NameLength == StrSize (InfoName)) {\r
451 if (CompareMem (VariableInfo->Name, InfoName, NameLength) == 0) {\r
452 //\r
453 // Find the match one\r
454 //\r
455 VariableInfo = VariableInfo->Next;\r
456 break;\r
457 }\r
458 }\r
459 }\r
460 VariableInfo = VariableInfo->Next;\r
461 };\r
462 \r
463 if (VariableInfo == NULL) {\r
464 *InfoSize = 0;\r
465 return EFI_SUCCESS;\r
466 }\r
467\r
468 //\r
469 // Output the new variable info\r
470 //\r
471 StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);\r
472 if (*InfoSize < StatisticsInfoSize) {\r
473 *InfoSize = StatisticsInfoSize;\r
474 return EFI_BUFFER_TOO_SMALL;\r
475 }\r
476\r
477 CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
478 CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
479 *InfoSize = StatisticsInfoSize;\r
480 \r
481 return EFI_SUCCESS;\r
482}\r
483\r
484\r
485/**\r
486 Communication service SMI Handler entry.\r
487\r
488 This SMI handler provides services for the variable wrapper driver.\r
489\r
dc204d5a
JY
490 Caution: This function may receive untrusted input.\r
491 This variable data and communicate buffer are external input, so this function will do basic validation.\r
492 Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(), \r
493 VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(), \r
494 SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
495\r
0c18794e 496 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
497 @param[in] RegisterContext Points to an optional handler context which was specified when the\r
498 handler was registered.\r
499 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
500 be conveyed from a non-SMM environment into an SMM environment.\r
501 @param[in, out] CommBufferSize The size of the CommBuffer.\r
502\r
503 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers \r
504 should still be called.\r
505 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should \r
506 still be called.\r
507 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still \r
508 be called.\r
509 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
648f98d1 510\r
0c18794e 511**/\r
512EFI_STATUS\r
513EFIAPI\r
514SmmVariableHandler (\r
515 IN EFI_HANDLE DispatchHandle,\r
516 IN CONST VOID *RegisterContext,\r
517 IN OUT VOID *CommBuffer,\r
518 IN OUT UINTN *CommBufferSize\r
519 )\r
520{\r
521 EFI_STATUS Status;\r
522 SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
523 SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
524 SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;\r
525 SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;\r
526 VARIABLE_INFO_ENTRY *VariableInfo;\r
6ab9f441 527 SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
17409b7a 528 SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
0c18794e 529 UINTN InfoSize;\r
9d00d20e 530 UINTN NameBufferSize;\r
5e5bb2a9 531 UINTN CommBufferPayloadSize;\r
164a9b67 532 UINTN TempCommBufferSize;\r
0c18794e 533\r
25a4e71a 534 //\r
535 // If input is invalid, stop processing this SMI\r
536 //\r
537 if (CommBuffer == NULL || CommBufferSize == NULL) {\r
538 return EFI_SUCCESS;\r
648f98d1 539 }\r
0c18794e 540\r
164a9b67
SZ
541 TempCommBufferSize = *CommBufferSize;\r
542\r
543 if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
5e5bb2a9
SZ
544 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));\r
545 return EFI_SUCCESS;\r
546 }\r
164a9b67 547 CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
5e5bb2a9
SZ
548 if (CommBufferPayloadSize > mVariableBufferPayloadSize) {\r
549 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));\r
25a4e71a 550 return EFI_SUCCESS;\r
551 }\r
552\r
164a9b67 553 if (!InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
5e5bb2a9 554 DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
25a4e71a 555 return EFI_SUCCESS;\r
556 }\r
557 \r
0c18794e 558 SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;\r
25a4e71a 559 \r
0c18794e 560 switch (SmmVariableFunctionHeader->Function) {\r
561 case SMM_VARIABLE_FUNCTION_GET_VARIABLE:\r
5e5bb2a9
SZ
562 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
563 DEBUG ((EFI_D_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));\r
564 return EFI_SUCCESS;\r
565 }\r
566 //\r
567 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
568 //\r
569 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
570 SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;\r
9d00d20e
SZ
571 if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
572 ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {\r
573 //\r
574 // Prevent InfoSize overflow happen\r
575 //\r
576 Status = EFI_ACCESS_DENIED;\r
577 goto EXIT;\r
578 }\r
25a4e71a 579 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) \r
580 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
581\r
582 //\r
583 // SMRAM range check already covered before\r
584 //\r
5e5bb2a9
SZ
585 if (InfoSize > CommBufferPayloadSize) {\r
586 DEBUG ((EFI_D_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));\r
25a4e71a 587 Status = EFI_ACCESS_DENIED;\r
588 goto EXIT;\r
589 }\r
590\r
9d00d20e
SZ
591 if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
592 //\r
593 // Make sure VariableName is A Null-terminated string.\r
594 //\r
595 Status = EFI_ACCESS_DENIED;\r
596 goto EXIT;\r
597 }\r
598\r
0c18794e 599 Status = VariableServiceGetVariable (\r
600 SmmVariableHeader->Name,\r
601 &SmmVariableHeader->Guid,\r
602 &SmmVariableHeader->Attributes,\r
603 &SmmVariableHeader->DataSize,\r
604 (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize\r
605 );\r
5e5bb2a9 606 CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
0c18794e 607 break;\r
608 \r
609 case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:\r
5e5bb2a9
SZ
610 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
611 DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));\r
612 return EFI_SUCCESS;\r
613 }\r
614 //\r
615 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
616 //\r
617 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
618 GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) mVariableBufferPayload;\r
9d00d20e
SZ
619 if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
620 //\r
621 // Prevent InfoSize overflow happen\r
622 //\r
623 Status = EFI_ACCESS_DENIED;\r
624 goto EXIT;\r
625 }\r
25a4e71a 626 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;\r
627\r
628 //\r
629 // SMRAM range check already covered before\r
630 //\r
5e5bb2a9
SZ
631 if (InfoSize > CommBufferPayloadSize) {\r
632 DEBUG ((EFI_D_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));\r
25a4e71a 633 Status = EFI_ACCESS_DENIED;\r
634 goto EXIT;\r
635 }\r
636\r
5e5bb2a9 637 NameBufferSize = CommBufferPayloadSize - OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
9d00d20e
SZ
638 if (NameBufferSize < sizeof (CHAR16) || GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0') {\r
639 //\r
640 // Make sure input VariableName is A Null-terminated string.\r
641 //\r
642 Status = EFI_ACCESS_DENIED;\r
643 goto EXIT;\r
644 }\r
645\r
0c18794e 646 Status = VariableServiceGetNextVariableName (\r
647 &GetNextVariableName->NameSize,\r
648 GetNextVariableName->Name,\r
649 &GetNextVariableName->Guid\r
650 );\r
5e5bb2a9 651 CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
0c18794e 652 break;\r
653 \r
654 case SMM_VARIABLE_FUNCTION_SET_VARIABLE:\r
5e5bb2a9
SZ
655 if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
656 DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));\r
657 return EFI_SUCCESS;\r
658 }\r
659 //\r
660 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
661 //\r
662 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
663 SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;\r
9d00d20e
SZ
664 if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
665 ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {\r
666 //\r
667 // Prevent InfoSize overflow happen\r
668 //\r
669 Status = EFI_ACCESS_DENIED;\r
670 goto EXIT;\r
671 }\r
d17c4eac 672 InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
673 + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
674\r
675 //\r
676 // SMRAM range check already covered before\r
677 // Data buffer should not contain SMM range\r
678 //\r
5e5bb2a9
SZ
679 if (InfoSize > CommBufferPayloadSize) {\r
680 DEBUG ((EFI_D_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));\r
d17c4eac 681 Status = EFI_ACCESS_DENIED;\r
682 goto EXIT;\r
683 }\r
684\r
9d00d20e
SZ
685 if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
686 //\r
687 // Make sure VariableName is A Null-terminated string.\r
688 //\r
689 Status = EFI_ACCESS_DENIED;\r
690 goto EXIT;\r
691 }\r
692\r
0c18794e 693 Status = VariableServiceSetVariable (\r
694 SmmVariableHeader->Name,\r
695 &SmmVariableHeader->Guid,\r
696 SmmVariableHeader->Attributes,\r
697 SmmVariableHeader->DataSize,\r
698 (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize\r
699 );\r
700 break;\r
701 \r
702 case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:\r
5e5bb2a9
SZ
703 if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {\r
704 DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));\r
705 return EFI_SUCCESS;\r
25a4e71a 706 }\r
5e5bb2a9 707 QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;\r
25a4e71a 708 \r
0c18794e 709 Status = VariableServiceQueryVariableInfo (\r
710 QueryVariableInfo->Attributes,\r
711 &QueryVariableInfo->MaximumVariableStorageSize,\r
712 &QueryVariableInfo->RemainingVariableStorageSize,\r
713 &QueryVariableInfo->MaximumVariableSize\r
714 );\r
715 break;\r
716\r
717 case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:\r
6ab9f441 718 mEndOfDxe = TRUE;\r
952ba83c
SZ
719 //\r
720 // The initialization for variable quota.\r
721 //\r
722 InitializeVariableQuota ();\r
876ac395 723 if (AtRuntime()) {\r
724 Status = EFI_UNSUPPORTED;\r
725 break;\r
726 }\r
0c18794e 727 ReclaimForOS ();\r
728 Status = EFI_SUCCESS;\r
729 break;\r
730 \r
731 case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE:\r
732 mAtRuntime = TRUE;\r
733 Status = EFI_SUCCESS;\r
734 break;\r
735\r
736 case SMM_VARIABLE_FUNCTION_GET_STATISTICS:\r
737 VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;\r
164a9b67 738 InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
25a4e71a 739\r
740 //\r
741 // Do not need to check SmmVariableFunctionHeader->Data in SMRAM here. \r
742 // It is covered by previous CommBuffer check \r
743 //\r
744 \r
745 if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {\r
5e5bb2a9 746 DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));\r
25a4e71a 747 Status = EFI_ACCESS_DENIED;\r
748 goto EXIT;\r
749 } \r
750\r
0c18794e 751 Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);\r
3f5c168f 752 *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
0c18794e 753 break;\r
754\r
6ab9f441
RN
755 case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:\r
756 if (mEndOfDxe) {\r
757 Status = EFI_ACCESS_DENIED;\r
758 } else {\r
759 VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;\r
760 Status = VariableLockRequestToLock (\r
761 NULL,\r
762 VariableToLock->Name,\r
763 &VariableToLock->Guid\r
764 );\r
765 }\r
766 break;\r
17409b7a
SZ
767 case SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET:\r
768 if (mEndOfDxe) {\r
769 Status = EFI_ACCESS_DENIED;\r
770 } else {\r
771 CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *) SmmVariableFunctionHeader->Data;\r
772 Status = VarCheckVariablePropertySet (\r
773 CommVariableProperty->Name,\r
774 &CommVariableProperty->Guid,\r
775 &CommVariableProperty->VariableProperty\r
776 );\r
777 }\r
778 break;\r
779 case SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET:\r
780 if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
781 DEBUG ((EFI_D_ERROR, "VarCheckVariablePropertyGet: SMM communication buffer size invalid!\n"));\r
782 return EFI_SUCCESS;\r
783 }\r
784 //\r
785 // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
786 //\r
787 CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
788 CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *) mVariableBufferPayload;\r
789 if ((UINTN) (~0) - CommVariableProperty->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
790 //\r
791 // Prevent InfoSize overflow happen\r
792 //\r
793 Status = EFI_ACCESS_DENIED;\r
794 goto EXIT;\r
795 }\r
796 InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + CommVariableProperty->NameSize;\r
797\r
798 //\r
799 // SMRAM range check already covered before\r
800 //\r
801 if (InfoSize > CommBufferPayloadSize) {\r
802 DEBUG ((EFI_D_ERROR, "VarCheckVariablePropertyGet: Data size exceed communication buffer size limit!\n"));\r
803 Status = EFI_ACCESS_DENIED;\r
804 goto EXIT;\r
805 }\r
806\r
807 if (CommVariableProperty->NameSize < sizeof (CHAR16) || CommVariableProperty->Name[CommVariableProperty->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
808 //\r
809 // Make sure VariableName is A Null-terminated string.\r
810 //\r
811 Status = EFI_ACCESS_DENIED;\r
812 goto EXIT;\r
813 }\r
814\r
815 Status = VarCheckVariablePropertyGet (\r
816 CommVariableProperty->Name,\r
817 &CommVariableProperty->Guid,\r
818 &CommVariableProperty->VariableProperty\r
819 );\r
820 CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
821 break;\r
6ab9f441 822\r
0c18794e 823 default:\r
0c18794e 824 Status = EFI_UNSUPPORTED;\r
825 }\r
826\r
25a4e71a 827EXIT:\r
0c18794e 828\r
25a4e71a 829 SmmVariableFunctionHeader->ReturnStatus = Status;\r
0c18794e 830 return EFI_SUCCESS;\r
831}\r
832\r
6ab9f441
RN
833/**\r
834 SMM END_OF_DXE protocol notification event handler.\r
835\r
836 @param Protocol Points to the protocol's unique identifier\r
837 @param Interface Points to the interface instance\r
838 @param Handle The handle on which the interface was installed\r
839\r
840 @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully\r
841\r
842**/\r
843EFI_STATUS\r
844EFIAPI\r
845SmmEndOfDxeCallback (\r
846 IN CONST EFI_GUID *Protocol,\r
847 IN VOID *Interface,\r
848 IN EFI_HANDLE Handle\r
849 )\r
850{\r
851 DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));\r
852 mEndOfDxe = TRUE;\r
952ba83c
SZ
853 //\r
854 // The initialization for variable quota.\r
855 //\r
856 InitializeVariableQuota ();\r
6ab9f441
RN
857 return EFI_SUCCESS;\r
858}\r
0c18794e 859\r
860/**\r
861 SMM Fault Tolerant Write protocol notification event handler.\r
862\r
863 Non-Volatile variable write may needs FTW protocol to reclaim when \r
864 writting variable.\r
865 \r
866 @param Protocol Points to the protocol's unique identifier\r
867 @param Interface Points to the interface instance\r
868 @param Handle The handle on which the interface was installed\r
869\r
870 @retval EFI_SUCCESS SmmEventCallback runs successfully\r
871 @retval EFI_NOT_FOUND The Fvb protocol for variable is not found.\r
872 \r
873 **/\r
874EFI_STATUS\r
875EFIAPI\r
876SmmFtwNotificationEvent (\r
877 IN CONST EFI_GUID *Protocol,\r
878 IN VOID *Interface,\r
879 IN EFI_HANDLE Handle\r
880 )\r
881{\r
882 EFI_STATUS Status;\r
883 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
884 EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;\r
885 EFI_PHYSICAL_ADDRESS NvStorageVariableBase;\r
41982ebb 886 UINTN FtwMaxBlockSize;\r
0c18794e 887 \r
888 if (mVariableModuleGlobal->FvbInstance != NULL) {\r
889 return EFI_SUCCESS;\r
890 }\r
891\r
892 //\r
893 // Ensure SMM FTW protocol is installed.\r
894 //\r
895 Status = GetFtwProtocol ((VOID **)&FtwProtocol);\r
896 if (EFI_ERROR (Status)) {\r
897 return Status;\r
898 }\r
899\r
41982ebb
SZ
900 Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);\r
901 if (!EFI_ERROR (Status)) {\r
902 ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);\r
903 }\r
904\r
0c18794e 905 //\r
906 // Find the proper FVB protocol for variable.\r
907 //\r
908 NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
909 if (NvStorageVariableBase == 0) {\r
910 NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
911 }\r
912 Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);\r
913 if (EFI_ERROR (Status)) {\r
914 return EFI_NOT_FOUND;\r
915 }\r
916\r
917 mVariableModuleGlobal->FvbInstance = FvbProtocol;\r
918 \r
919 Status = VariableWriteServiceInitialize ();\r
25da08c8
DG
920 if (EFI_ERROR (Status)) {\r
921 DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));\r
922 }\r
0c18794e 923 \r
924 //\r
925 // Notify the variable wrapper driver the variable write service is ready\r
926 //\r
927 Status = gBS->InstallProtocolInterface (\r
928 &mSmmVariableHandle,\r
929 &gSmmVariableWriteGuid,\r
930 EFI_NATIVE_INTERFACE,\r
931 NULL\r
932 );\r
933 ASSERT_EFI_ERROR (Status);\r
934 \r
935 return EFI_SUCCESS;\r
936}\r
937\r
938\r
939/**\r
940 Variable Driver main entry point. The Variable driver places the 4 EFI\r
941 runtime services in the EFI System Table and installs arch protocols \r
942 for variable read and write services being available. It also registers\r
943 a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
944\r
945 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
946 @param[in] SystemTable A pointer to the EFI System Table.\r
947 \r
948 @retval EFI_SUCCESS Variable service successfully initialized.\r
949\r
950**/\r
951EFI_STATUS\r
952EFIAPI\r
953VariableServiceInitialize (\r
954 IN EFI_HANDLE ImageHandle,\r
955 IN EFI_SYSTEM_TABLE *SystemTable\r
956 )\r
957{\r
958 EFI_STATUS Status;\r
959 EFI_HANDLE VariableHandle;\r
960 VOID *SmmFtwRegistration;\r
25a4e71a 961 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
962 UINTN Size;\r
6ab9f441 963 VOID *SmmEndOfDxeRegistration;\r
25a4e71a 964\r
0c18794e 965 //\r
966 // Variable initialize.\r
967 //\r
968 Status = VariableCommonInitialize ();\r
969 ASSERT_EFI_ERROR (Status);\r
970\r
971 //\r
972 // Install the Smm Variable Protocol on a new handle.\r
973 //\r
974 VariableHandle = NULL;\r
975 Status = gSmst->SmmInstallProtocolInterface (\r
976 &VariableHandle,\r
977 &gEfiSmmVariableProtocolGuid,\r
978 EFI_NATIVE_INTERFACE,\r
979 &gSmmVariable\r
980 );\r
981 ASSERT_EFI_ERROR (Status);\r
982\r
17409b7a
SZ
983 Status = gSmst->SmmInstallProtocolInterface (\r
984 &VariableHandle,\r
985 &gEdkiiSmmVarCheckProtocolGuid,\r
986 EFI_NATIVE_INTERFACE,\r
987 &mSmmVarCheck\r
988 );\r
989 ASSERT_EFI_ERROR (Status);\r
990\r
25a4e71a 991 //\r
992 // Get SMRAM information\r
993 //\r
994 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);\r
995 ASSERT_EFI_ERROR (Status);\r
996\r
997 Size = 0;\r
998 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
999 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
1000\r
1001 Status = gSmst->SmmAllocatePool (\r
1002 EfiRuntimeServicesData,\r
1003 Size,\r
1004 (VOID **)&mSmramRanges\r
1005 );\r
1006 ASSERT_EFI_ERROR (Status);\r
1007\r
1008 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);\r
1009 ASSERT_EFI_ERROR (Status);\r
1010\r
1011 mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
1012\r
5e5bb2a9 1013 mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +\r
17409b7a 1014 OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - sizeof (VARIABLE_HEADER);\r
5e5bb2a9
SZ
1015\r
1016 Status = gSmst->SmmAllocatePool (\r
1017 EfiRuntimeServicesData,\r
1018 mVariableBufferPayloadSize,\r
1019 (VOID **)&mVariableBufferPayload\r
1020 );\r
1021 ASSERT_EFI_ERROR (Status);\r
1022\r
0c18794e 1023 ///\r
1024 /// Register SMM variable SMI handler\r
1025 ///\r
1026 VariableHandle = NULL;\r
1027 Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
1028 ASSERT_EFI_ERROR (Status);\r
1029 \r
1030 //\r
1031 // Notify the variable wrapper driver the variable service is ready\r
1032 //\r
1033 Status = SystemTable->BootServices->InstallProtocolInterface (\r
1034 &mVariableHandle,\r
1035 &gEfiSmmVariableProtocolGuid,\r
1036 EFI_NATIVE_INTERFACE,\r
1037 &gSmmVariable\r
1038 );\r
1039 ASSERT_EFI_ERROR (Status);\r
1040 \r
6ab9f441
RN
1041 //\r
1042 // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.\r
1043 //\r
1044 Status = gSmst->SmmRegisterProtocolNotify (\r
1045 &gEfiSmmEndOfDxeProtocolGuid,\r
1046 SmmEndOfDxeCallback,\r
1047 &SmmEndOfDxeRegistration\r
1048 );\r
1049 ASSERT_EFI_ERROR (Status);\r
1050\r
0c18794e 1051 //\r
1052 // Register FtwNotificationEvent () notify function.\r
1053 // \r
1054 Status = gSmst->SmmRegisterProtocolNotify (\r
1055 &gEfiSmmFaultTolerantWriteProtocolGuid,\r
1056 SmmFtwNotificationEvent,\r
1057 &SmmFtwRegistration\r
1058 );\r
1059 ASSERT_EFI_ERROR (Status);\r
1060\r
1061 SmmFtwNotificationEvent (NULL, NULL, NULL);\r
1062 \r
1063 return EFI_SUCCESS;\r
1064}\r
1065\r
1066\r