TianoCore EDK2 master
Loading...
Searching...
No Matches
FaultTolerantWriteSmmDxe.c
Go to the documentation of this file.
1
12
14EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication2 = NULL;
15UINTN mPrivateDataSize = 0;
16
17EFI_FAULT_TOLERANT_WRITE_PROTOCOL mFaultTolerantWriteDriver = {
24};
25
35VOID
37 OUT VOID **CommunicateBuffer,
38 OUT VOID **DataPtr,
39 IN UINTN DataSize,
40 IN UINTN Function
41 )
42{
43 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
44 SMM_FTW_COMMUNICATE_FUNCTION_HEADER *SmmFtwFunctionHeader;
45
46 //
47 // The whole buffer size: SMM_COMMUNICATE_HEADER_SIZE + SMM_FTW_COMMUNICATE_HEADER_SIZE + DataSize.
48 //
50 ASSERT (SmmCommunicateHeader != NULL);
51
52 //
53 // Prepare data buffer.
54 //
55 CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmFaultTolerantWriteProtocolGuid);
56 SmmCommunicateHeader->MessageLength = DataSize + SMM_FTW_COMMUNICATE_HEADER_SIZE;
57
58 SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *)SmmCommunicateHeader->Data;
59 SmmFtwFunctionHeader->Function = Function;
60
61 *CommunicateBuffer = SmmCommunicateHeader;
62 if (DataPtr != NULL) {
63 *DataPtr = SmmFtwFunctionHeader->Data;
64 }
65}
66
76 IN OUT EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader,
77 IN UINTN DataSize
78 )
79{
80 EFI_STATUS Status;
81 UINTN CommSize;
82 SMM_FTW_COMMUNICATE_FUNCTION_HEADER *SmmFtwFunctionHeader;
83
85 Status = mMmCommunication2->Communicate (
86 mMmCommunication2,
87 SmmCommunicateHeader,
88 SmmCommunicateHeader,
89 &CommSize
90 );
91 ASSERT_EFI_ERROR (Status);
92
93 SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *)SmmCommunicateHeader->Data;
94 return SmmFtwFunctionHeader->ReturnStatus;
95}
96
110 IN EFI_HANDLE FvbHandle,
111 OUT EFI_PHYSICAL_ADDRESS *FvbBaseAddress,
112 OUT EFI_FVB_ATTRIBUTES_2 *FvbAttributes
113 )
114{
115 EFI_STATUS Status;
117
118 Status = gBS->HandleProtocol (FvbHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
119 if (EFI_ERROR (Status)) {
120 return Status;
121 }
122
123 Status = Fvb->GetPhysicalAddress (Fvb, FvbBaseAddress);
124 if (EFI_ERROR (Status)) {
125 return Status;
126 }
127
128 Status = Fvb->GetAttributes (Fvb, FvbAttributes);
129 return Status;
130}
131
145EFIAPI
148 OUT UINTN *BlockSize
149 )
150{
151 EFI_STATUS Status;
152 UINTN PayloadSize;
153 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
154 SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *SmmFtwBlockSizeHeader;
155
156 //
157 // Initialize the communicate buffer.
158 //
159 PayloadSize = sizeof (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER);
160 InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwBlockSizeHeader, PayloadSize, FTW_FUNCTION_GET_MAX_BLOCK_SIZE);
161
162 //
163 // Send data to SMM.
164 //
165 Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
166
167 //
168 // Get data from SMM
169 //
170 *BlockSize = SmmFtwBlockSizeHeader->BlockSize;
171 FreePool (SmmCommunicateHeader);
172
173 return Status;
174}
175
198EFIAPI
201 IN EFI_GUID *CallerId,
202 IN UINTN PrivateDataSize,
203 IN UINTN NumberOfWrites
204 )
205{
206 EFI_STATUS Status;
207 UINTN PayloadSize;
208 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
209 SMM_FTW_ALLOCATE_HEADER *SmmFtwAllocateHeader;
210
211 //
212 // Initialize the communicate buffer.
213 //
214 PayloadSize = sizeof (SMM_FTW_ALLOCATE_HEADER);
215 InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwAllocateHeader, PayloadSize, FTW_FUNCTION_ALLOCATE);
216 CopyGuid (&SmmFtwAllocateHeader->CallerId, CallerId);
217 SmmFtwAllocateHeader->PrivateDataSize = PrivateDataSize;
218 SmmFtwAllocateHeader->NumberOfWrites = NumberOfWrites;
219
220 //
221 // Send data to SMM.
222 //
223 Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
224 if (!EFI_ERROR (Status)) {
225 mPrivateDataSize = PrivateDataSize;
226 }
227
228 FreePool (SmmCommunicateHeader);
229 return Status;
230}
231
260EFIAPI
263 IN EFI_LBA Lba,
264 IN UINTN Offset,
265 IN UINTN Length,
266 IN VOID *PrivateData,
267 IN EFI_HANDLE FvBlockHandle,
268 IN VOID *Buffer
269 )
270{
271 EFI_STATUS Status;
272 UINTN PayloadSize;
273 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
274 SMM_FTW_WRITE_HEADER *SmmFtwWriteHeader;
275
276 //
277 // Initialize the communicate buffer.
278 //
279 PayloadSize = OFFSET_OF (SMM_FTW_WRITE_HEADER, Data) + Length;
280 if (PrivateData != NULL) {
281 //
282 // The private data buffer size should be the same one in FtwAllocate API.
283 //
284 PayloadSize += mPrivateDataSize;
285 }
286
287 InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwWriteHeader, PayloadSize, FTW_FUNCTION_WRITE);
288
289 //
290 // FvBlockHandle can not be used in SMM environment. Here we get the FVB protocol first, then get FVB base address
291 // and its attribute. Send these information to SMM handler, the SMM handler will find the proper FVB to write data.
292 //
293 Status = ConvertFvbHandle (FvBlockHandle, &SmmFtwWriteHeader->FvbBaseAddress, &SmmFtwWriteHeader->FvbAttributes);
294 if (EFI_ERROR (Status)) {
295 FreePool (SmmCommunicateHeader);
296 return EFI_ABORTED;
297 }
298
299 SmmFtwWriteHeader->Lba = Lba;
300 SmmFtwWriteHeader->Offset = Offset;
301 SmmFtwWriteHeader->Length = Length;
302 CopyMem (SmmFtwWriteHeader->Data, Buffer, Length);
303 if (PrivateData == NULL) {
304 SmmFtwWriteHeader->PrivateDataSize = 0;
305 } else {
306 SmmFtwWriteHeader->PrivateDataSize = mPrivateDataSize;
307 CopyMem (&SmmFtwWriteHeader->Data[Length], PrivateData, mPrivateDataSize);
308 }
309
310 //
311 // Send data to SMM.
312 //
313 Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
314 FreePool (SmmCommunicateHeader);
315 return Status;
316}
317
331EFIAPI
334 IN EFI_HANDLE FvBlockHandle
335 )
336{
337 EFI_STATUS Status;
338 UINTN PayloadSize;
339 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
340 SMM_FTW_RESTART_HEADER *SmmFtwRestartHeader;
341
342 //
343 // Initialize the communicate buffer.
344 //
345 PayloadSize = sizeof (SMM_FTW_RESTART_HEADER);
346 InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwRestartHeader, PayloadSize, FTW_FUNCTION_RESTART);
347
348 //
349 // FvBlockHandle can not be used in SMM environment. Here we get the FVB protocol first, then get FVB base address
350 // and its attribute. Send these information to SMM handler, the SMM handler will find the proper FVB to write data.
351 //
352 Status = ConvertFvbHandle (FvBlockHandle, &SmmFtwRestartHeader->FvbBaseAddress, &SmmFtwRestartHeader->FvbAttributes);
353 if (EFI_ERROR (Status)) {
354 FreePool (SmmCommunicateHeader);
355 return EFI_ABORTED;
356 }
357
358 //
359 // Send data to SMM.
360 //
361 Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
362 FreePool (SmmCommunicateHeader);
363 return Status;
364}
365
377EFIAPI
380 )
381{
382 EFI_STATUS Status;
383 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
384
385 //
386 // Initialize the communicate buffer.
387 //
388 InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, NULL, 0, FTW_FUNCTION_ABORT);
389
390 //
391 // Send data to SMM.
392 //
393 Status = SendCommunicateBuffer (SmmCommunicateHeader, 0);
394
395 FreePool (SmmCommunicateHeader);
396 return Status;
397}
398
425EFIAPI
428 OUT EFI_GUID *CallerId,
429 OUT EFI_LBA *Lba,
430 OUT UINTN *Offset,
431 OUT UINTN *Length,
432 IN OUT UINTN *PrivateDataSize,
433 OUT VOID *PrivateData,
434 OUT BOOLEAN *Complete
435 )
436{
437 EFI_STATUS Status;
438 UINTN PayloadSize;
439 EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
440 SMM_FTW_GET_LAST_WRITE_HEADER *SmmFtwGetLastWriteHeader;
441
442 //
443 // Initialize the communicate buffer.
444 //
445 PayloadSize = OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data) + *PrivateDataSize;
446 InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwGetLastWriteHeader, PayloadSize, FTW_FUNCTION_GET_LAST_WRITE);
447 SmmFtwGetLastWriteHeader->PrivateDataSize = *PrivateDataSize;
448
449 //
450 // Send data to SMM.
451 //
452 Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
453
454 //
455 // Get data from SMM
456 //
457 *PrivateDataSize = SmmFtwGetLastWriteHeader->PrivateDataSize;
458 if ((Status == EFI_SUCCESS) || (Status == EFI_BUFFER_TOO_SMALL)) {
459 *Lba = SmmFtwGetLastWriteHeader->Lba;
460 *Offset = SmmFtwGetLastWriteHeader->Offset;
461 *Length = SmmFtwGetLastWriteHeader->Length;
462 *Complete = SmmFtwGetLastWriteHeader->Complete;
463 CopyGuid (CallerId, &SmmFtwGetLastWriteHeader->CallerId);
464 if (Status == EFI_SUCCESS) {
465 CopyMem (PrivateData, SmmFtwGetLastWriteHeader->Data, *PrivateDataSize);
466 }
467 } else if (Status == EFI_NOT_FOUND) {
468 *Complete = SmmFtwGetLastWriteHeader->Complete;
469 }
470
471 FreePool (SmmCommunicateHeader);
472 return Status;
473}
474
483VOID
484EFIAPI
486 IN EFI_EVENT Event,
487 IN VOID *Context
488 )
489{
490 EFI_STATUS Status;
492
493 //
494 // Just return to avoid install SMM FaultTolerantWriteProtocol again
495 // if Fault Tolerant Write protocol had been installed.
496 //
497 Status = gBS->LocateProtocol (&gEfiFaultTolerantWriteProtocolGuid, NULL, (VOID **)&FtwProtocol);
498 if (!EFI_ERROR (Status)) {
499 return;
500 }
501
502 Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **)&mMmCommunication2);
503 ASSERT_EFI_ERROR (Status);
504
505 //
506 // Install protocol interface
507 //
508 Status = gBS->InstallProtocolInterface (
509 &mHandle,
510 &gEfiFaultTolerantWriteProtocolGuid,
512 &mFaultTolerantWriteDriver
513 );
514 ASSERT_EFI_ERROR (Status);
515
516 Status = gBS->CloseEvent (Event);
517 ASSERT_EFI_ERROR (Status);
518}
519
532EFIAPI
534 IN EFI_HANDLE ImageHandle,
535 IN EFI_SYSTEM_TABLE *SystemTable
536 )
537{
538 VOID *SmmFtwRegistration;
539
540 //
541 // Smm FTW driver is ready
542 //
544 &gEfiSmmFaultTolerantWriteProtocolGuid,
545 TPL_CALLBACK,
547 NULL,
548 &SmmFtwRegistration
549 );
550
551 return EFI_SUCCESS;
552}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define SMM_FTW_COMMUNICATE_HEADER_SIZE
EFI_STATUS EFIAPI FaultTolerantWriteSmmInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
VOID InitCommunicateBuffer(OUT VOID **CommunicateBuffer, OUT VOID **DataPtr, IN UINTN DataSize, IN UINTN Function)
EFI_STATUS EFIAPI FtwGetMaxBlockSize(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, OUT UINTN *BlockSize)
VOID EFIAPI SmmFtwReady(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI FtwRestart(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, IN EFI_HANDLE FvBlockHandle)
EFI_STATUS SendCommunicateBuffer(IN OUT EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader, IN UINTN DataSize)
EFI_STATUS EFIAPI FtwAllocate(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, IN EFI_GUID *CallerId, IN UINTN PrivateDataSize, IN UINTN NumberOfWrites)
EFI_STATUS EFIAPI FtwWrite(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN UINTN Length, IN VOID *PrivateData, IN EFI_HANDLE FvBlockHandle, IN VOID *Buffer)
EFI_STATUS ConvertFvbHandle(IN EFI_HANDLE FvbHandle, OUT EFI_PHYSICAL_ADDRESS *FvbBaseAddress, OUT EFI_FVB_ATTRIBUTES_2 *FvbAttributes)
EFI_STATUS EFIAPI FtwGetLastWrite(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, OUT EFI_GUID *CallerId, OUT EFI_LBA *Lba, OUT UINTN *Offset, OUT UINTN *Length, IN OUT UINTN *PrivateDataSize, OUT VOID *PrivateData, OUT BOOLEAN *Complete)
EFI_HANDLE mHandle
EFI_STATUS EFIAPI FtwAbort(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This)
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
UINT32 EFI_FVB_ATTRIBUTES_2
#define SMM_COMMUNICATE_HEADER_SIZE
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_EVENT EFIAPI EfiCreateProtocolNotifyEvent(IN EFI_GUID *ProtocolGuid, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext OPTIONAL, OUT VOID **Registration)
Definition: UefiLib.c:134
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
Definition: Base.h:213