summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/FirmwareVolume
diff options
context:
space:
mode:
authorqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>2007-06-27 14:52:40 +0000
committerqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>2007-06-27 14:52:40 +0000
commitd7dec593eaf18c9c2e197e92a4434e21c4f8e9b7 (patch)
tree67906b4ef10dfd247ddb977e09c85d0a6ad30e99 /MdeModulePkg/Universal/FirmwareVolume
parenteb5f1a7fc7fd6f2edb306ca001f19b218abf0d7d (diff)
downloadedk2-d7dec593eaf18c9c2e197e92a4434e21c4f8e9b7.zip
edk2-d7dec593eaf18c9c2e197e92a4434e21c4f8e9b7.tar.gz
edk2-d7dec593eaf18c9c2e197e92a4434e21c4f8e9b7.tar.bz2
Add EBC, FTW, Crc32SectionExtract, NullMemoryTest modules.
CrcSectionExtract cannot build for now for some missing definitions. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2813 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/FirmwareVolume')
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c931
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs27
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h695
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.inf133
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa103
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c530
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c561
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c403
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c143
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c140
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c230
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs26
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h112
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.inf88
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa66
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c61
-rw-r--r--MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h54
17 files changed, 4303 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c
new file mode 100644
index 0000000..38fe11d
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c
@@ -0,0 +1,931 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ FtwLite.c
+
+Abstract:
+
+ This is a simple fault tolerant write driver, based on PlatformFd library.
+ And it only supports write BufferSize <= SpareAreaLength.
+
+ This boot service only protocol provides fault tolerant write capability for
+ block devices. The protocol has internal non-volatile intermediate storage
+ of the data and private information. It should be able to recover
+ automatically from a critical fault, such as power failure.
+
+Notes:
+
+ The implementation uses an FTW Lite (Fault Tolerant Write) Work Space.
+ This work space is a memory copy of the work space on the Woring Block,
+ the size of the work space is the FTW_WORK_SPACE_SIZE bytes.
+
+--*/
+
+#include <FtwLite.h>
+
+//
+// In write function, we should check the target range to prevent the user
+// from writing Spare block and Working space directly.
+//
+//
+// Fault Tolerant Write Protocol API
+//
+EFI_STATUS
+EFIAPI
+FtwLiteWrite (
+ IN EFI_FTW_LITE_PROTOCOL *This,
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Starts a target block update. This function will record data about write
+ in fault tolerant storage and will complete the write in a recoverable
+ manner, ensuring at all times that either the original contents or
+ the modified contents are available.
+
+Arguments:
+ This - Calling context
+ FvbHandle - The handle of FVB protocol that provides services for
+ reading, writing, and erasing the target block.
+ Lba - The logical block address of the target block.
+ Offset - The offset within the target block to place the data.
+ NumBytes - The number of bytes to write to the target block.
+ Buffer - The data to write.
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_BAD_BUFFER_SIZE - The write would span a target block, which is not
+ a valid action.
+ EFI_ACCESS_DENIED - No writes have been allocated.
+ EFI_NOT_FOUND - Cannot find FVB by handle.
+ EFI_OUT_OF_RESOURCES - Cannot allocate memory.
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice;
+ EFI_FTW_LITE_RECORD *Record;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_PHYSICAL_ADDRESS FvbPhysicalAddress;
+ UINTN MyLength;
+ UINTN MyOffset;
+ UINTN MyBufferSize;
+ UINT8 *MyBuffer;
+ UINTN SpareBufferSize;
+ UINT8 *SpareBuffer;
+ UINTN Index;
+ UINT8 *Ptr;
+ EFI_DEV_PATH_PTR DevPtr;
+
+ //
+ // Refresh work space and get last record
+ //
+ FtwLiteDevice = FTW_LITE_CONTEXT_FROM_THIS (This);
+ Status = WorkSpaceRefresh (FtwLiteDevice);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ Record = FtwLiteDevice->FtwLastRecord;
+
+ //
+ // Check the flags of last write record
+ //
+ if ((Record->WriteAllocated == FTW_VALID_STATE) || (Record->SpareCompleted == FTW_VALID_STATE)) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // IF former record has completed, THEN use next record
+ //
+ if (Record->WriteCompleted == FTW_VALID_STATE) {
+ Record++;
+ FtwLiteDevice->FtwLastRecord = Record;
+ }
+
+ MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
+
+ //
+ // Check if the input data can fit within the target block
+ //
+ if ((Offset +*NumBytes) > FtwLiteDevice->SpareAreaLength) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ //
+ // Check if there is enough free space for allocate a record
+ //
+ if ((MyOffset + WRITE_TOTAL_SIZE) > FtwLiteDevice->FtwWorkSpaceSize) {
+ Status = FtwReclaimWorkSpace (FtwLiteDevice);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "FtwLite: Reclaim work space - %r", Status));
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Get the FVB protocol by handle
+ //
+ Status = FtwGetFvbByHandle (FvbHandle, &Fvb);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Allocate a write record in workspace.
+ // Update Header->WriteAllocated as VALID
+ //
+ Status = FtwUpdateFvState (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase + MyOffset,
+ WRITE_ALLOCATED
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Allocate record - %r\n", Status));
+ return EFI_ABORTED;
+ }
+
+ Record->WriteAllocated = FTW_VALID_STATE;
+
+ //
+ // Prepare data of write record, filling DevPath with memory mapped address.
+ //
+ DevPtr.MemMap = (MEMMAP_DEVICE_PATH *) &Record->DevPath;
+ DevPtr.MemMap->Header.Type = HARDWARE_DEVICE_PATH;
+ DevPtr.MemMap->Header.SubType = HW_MEMMAP_DP;
+ SetDevicePathNodeLength (&DevPtr.MemMap->Header, sizeof (MEMMAP_DEVICE_PATH));
+
+ Status = Fvb->GetPhysicalAddress (Fvb, &FvbPhysicalAddress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Get FVB physical address - %r\n", Status));
+ return EFI_ABORTED;
+ }
+
+ DevPtr.MemMap->MemoryType = EfiMemoryMappedIO;
+ DevPtr.MemMap->StartingAddress = FvbPhysicalAddress;
+ DevPtr.MemMap->EndingAddress = FvbPhysicalAddress +*NumBytes;
+ //
+ // ignored!
+ //
+ Record->Lba = Lba;
+ Record->Offset = Offset;
+ Record->NumBytes = *NumBytes;
+
+ //
+ // Write the record to the work space.
+ //
+ MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
+ MyLength = FTW_LITE_RECORD_SIZE;
+
+ Status = FtwLiteDevice->FtwFvBlock->Write (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase + MyOffset,
+ &MyLength,
+ (UINT8 *) Record
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Record has been written to working block, then write data.
+ //
+ //
+ // Allocate a memory buffer
+ //
+ MyBufferSize = FtwLiteDevice->SpareAreaLength;
+ MyBuffer = AllocatePool (MyBufferSize);
+ if (MyBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Starting at Lba, if the number of the rest blocks on Fvb is less
+ // than NumberOfSpareBlock.
+ //
+ //
+ // Read all original data from target block to memory buffer
+ //
+ if (IsInWorkingBlock (FtwLiteDevice, Fvb, Lba)) {
+ //
+ // If target block falls into working block, we must follow the process of
+ // updating working block.
+ //
+ Ptr = MyBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ MyLength = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwFvBlock->Read (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkBlockLba + Index,
+ 0,
+ &MyLength,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (MyBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += MyLength;
+ }
+ //
+ // Update Offset by adding the offset from the start LBA of working block to
+ // the target LBA. The target block can not span working block!
+ //
+ Offset = (((UINTN) (Lba - FtwLiteDevice->FtwWorkBlockLba)) * FtwLiteDevice->SizeOfSpareBlock + Offset);
+ ASSERT ((Offset +*NumBytes) <= FtwLiteDevice->SpareAreaLength);
+
+ } else {
+
+ Ptr = MyBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ MyLength = FtwLiteDevice->SizeOfSpareBlock;
+ Status = Fvb->Read (Fvb, Lba + Index, 0, &MyLength, Ptr);
+ if (EFI_ERROR (Status)) {
+ FreePool (MyBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += MyLength;
+ }
+ }
+ //
+ // Overwrite the updating range data with
+ // the input buffer content
+ //
+ CopyMem (MyBuffer + Offset, Buffer, *NumBytes);
+
+ //
+ // Try to keep the content of spare block
+ // Save spare block into a spare backup memory buffer (Sparebuffer)
+ //
+ SpareBufferSize = FtwLiteDevice->SpareAreaLength;
+ SpareBuffer = AllocatePool (SpareBufferSize);
+ if (SpareBuffer == NULL) {
+ FreePool (MyBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = SpareBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ MyLength = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Read (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &MyLength,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (MyBuffer);
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += MyLength;
+ }
+ //
+ // Write the memory buffer to spare block
+ // Don't forget to erase Flash first.
+ //
+ Status = FtwEraseSpareBlock (FtwLiteDevice);
+ Ptr = MyBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ MyLength = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Write (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &MyLength,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (MyBuffer);
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += MyLength;
+ }
+ //
+ // Free MyBuffer
+ //
+ FreePool (MyBuffer);
+
+ //
+ // Set the SpareCompleteD in the FTW record,
+ //
+ MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
+ Status = FtwUpdateFvState (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase + MyOffset,
+ SPARE_COMPLETED
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Record->SpareCompleted = FTW_VALID_STATE;
+
+ //
+ // Since the content has already backuped in spare block, the write is
+ // guaranteed to be completed with fault tolerant manner.
+ //
+ Status = FtwWriteRecord (FtwLiteDevice, Fvb);
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Record++;
+ FtwLiteDevice->FtwLastRecord = Record;
+
+ //
+ // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
+ //
+ Status = FtwEraseSpareBlock (FtwLiteDevice);
+ Ptr = SpareBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ MyLength = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Write (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &MyLength,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += MyLength;
+ }
+ //
+ // All success.
+ //
+ FreePool (SpareBuffer);
+
+ DEBUG (
+ (EFI_D_FTW_LITE,
+ "FtwLite: Write() success, (Lba:Offset)=(%lx:0x%x), NumBytes: 0x%x\n",
+ Lba,
+ Offset,
+ *NumBytes)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FtwWriteRecord (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb
+ )
+/*++
+
+Routine Description:
+ Write a record with fault tolerant mannaer.
+ Since the content has already backuped in spare block, the write is
+ guaranteed to be completed with fault tolerant manner.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+ Fvb - The FVB protocol that provides services for
+ reading, writing, and erasing the target block.
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FTW_LITE_RECORD *Record;
+ EFI_LBA WorkSpaceLbaOffset;
+ UINTN Offset;
+
+ //
+ // Spare Complete but Destination not complete,
+ // Recover the targt block with the spare block.
+ //
+ Record = FtwLiteDevice->FtwLastRecord;
+
+ //
+ // IF target block is working block, THEN Flush Spare Block To Working Block;
+ // ELSE IF target block is boot block, THEN Flush Spare Block To boot Block;
+ // ELSE flush spare block to normal target block.ENDIF
+ //
+ if (IsInWorkingBlock (FtwLiteDevice, Fvb, Record->Lba)) {
+ //
+ // If target block is working block, Attention:
+ // it's required to set SPARE_COMPLETED to spare block.
+ //
+ WorkSpaceLbaOffset = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba;
+ Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
+ Status = FtwUpdateFvState (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + WorkSpaceLbaOffset,
+ FtwLiteDevice->FtwWorkSpaceBase + Offset,
+ SPARE_COMPLETED
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);
+ } else if (IsBootBlock (FtwLiteDevice, Fvb, Record->Lba)) {
+ //
+ // Update boot block
+ //
+ Status = FlushSpareBlockToBootBlock (FtwLiteDevice);
+ } else {
+ //
+ // Update blocks other than working block or boot block
+ //
+ Status = FlushSpareBlockToTargetBlock (FtwLiteDevice, Fvb, Record->Lba);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set WriteCompleted flag in record
+ //
+ Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
+ Status = FtwUpdateFvState (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase + Offset,
+ WRITE_COMPLETED
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Record->WriteCompleted = FTW_VALID_STATE;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FtwRestart (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Restarts a previously interrupted write. The caller must provide the
+ block protocol needed to complete the interrupted write.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+ FvbHandle - The handle of FVB protocol that provides services for
+ reading, writing, and erasing the target block.
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ACCESS_DENIED - No pending writes exist
+ EFI_NOT_FOUND - FVB protocol not found by the handle
+ EFI_ABORTED - The function could not complete successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FTW_LITE_RECORD *Record;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_DEV_PATH_PTR DevPathPtr;
+
+ //
+ // Spare Completed but Destination not complete,
+ // Recover the targt block with the spare block.
+ //
+ Record = FtwLiteDevice->FtwLastRecord;
+
+ //
+ // Only support memory mapped FVB device path by now.
+ //
+ DevPathPtr.MemMap = (MEMMAP_DEVICE_PATH *) &Record->DevPath;
+ if (!((DevPathPtr.MemMap->Header.Type == HARDWARE_DEVICE_PATH) && (DevPathPtr.MemMap->Header.SubType == HW_MEMMAP_DP))
+ ) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Device Path is not memory mapped\n"));
+ return EFI_ABORTED;
+ }
+
+ Status = GetFvbByAddress (DevPathPtr.MemMap->StartingAddress, &Fvb);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Since the content has already backuped in spare block, the write is
+ // guaranteed to be completed with fault tolerant manner.
+ //
+ Status = FtwWriteRecord (FtwLiteDevice, Fvb);
+ DEBUG ((EFI_D_FTW_INFO, "FtwLite: Restart() - %r\n", Status));
+
+ Record++;
+ FtwLiteDevice->FtwLastRecord = Record;
+
+ //
+ // Erase Spare block
+ // This is restart, no need to keep spareblock content.
+ //
+ FtwEraseSpareBlock (FtwLiteDevice);
+
+ return Status;
+}
+
+
+EFI_STATUS
+FtwAbort (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Aborts all previous allocated writes.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully.
+ EFI_NOT_FOUND - No allocated writes exist.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+
+ if (FtwLiteDevice->FtwLastRecord->WriteCompleted == FTW_VALID_STATE) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Update the complete state of the header as VALID and abort.
+ //
+ Offset = (UINT8 *) FtwLiteDevice->FtwLastRecord - FtwLiteDevice->FtwWorkSpace;
+ Status = FtwUpdateFvState (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase + Offset,
+ WRITE_COMPLETED
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ FtwLiteDevice->FtwLastRecord->WriteCompleted = FTW_VALID_STATE;
+
+ Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord);
+
+ //
+ // Erase the spare block
+ //
+ Status = FtwEraseSpareBlock (FtwLiteDevice);
+
+ DEBUG ((EFI_D_FTW_INFO, "FtwLite: Abort() success \n"));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+InitializeFtwLite (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+ Routine Description:
+ This function is the entry point of the Fault Tolerant Write driver.
+
+ Arguments:
+ ImageHandle - EFI_HANDLE: A handle for the image that is initializing
+ this driver
+ SystemTable - EFI_SYSTEM_TABLE: A pointer to the EFI system table
+
+ Returns:
+ EFI_SUCCESS - FTW has finished the initialization
+ EFI_ABORTED - FTW initialization error
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ UINTN Index;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice;
+ EFI_FTW_LITE_RECORD *Record;
+ UINTN Length;
+ EFI_STATUS Status;
+ UINTN Offset;
+ EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
+ UINT32 LbaIndex;
+
+ //
+ // Allocate Private data of this driver,
+ // INCLUDING THE FtwWorkSpace[FTW_WORK_SPACE_SIZE].
+ //
+ FtwLiteDevice = NULL;
+ FtwLiteDevice = AllocatePool (sizeof (EFI_FTW_LITE_DEVICE) + FTW_WORK_SPACE_SIZE);
+ if (FtwLiteDevice != NULL) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem (FtwLiteDevice, sizeof (EFI_FTW_LITE_DEVICE));
+ FtwLiteDevice->Signature = FTW_LITE_DEVICE_SIGNATURE;
+
+ //
+ // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
+ //
+ FtwLiteDevice->FtwWorkSpace = (UINT8 *) (FtwLiteDevice + 1);
+ FtwLiteDevice->FtwWorkSpaceSize = FTW_WORK_SPACE_SIZE;
+ SetMem (
+ FtwLiteDevice->FtwWorkSpace,
+ FtwLiteDevice->FtwWorkSpaceSize,
+ FTW_ERASED_BYTE
+ );
+ FtwLiteDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwLiteDevice->FtwWorkSpace;
+
+ FtwLiteDevice->FtwLastRecord = NULL;
+
+ FtwLiteDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
+ FtwLiteDevice->WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+
+ FtwLiteDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);
+ FtwLiteDevice->SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+
+ ASSERT ((FtwLiteDevice->WorkSpaceLength != 0) && (FtwLiteDevice->SpareAreaLength != 0));
+
+ //
+ // Locate FVB protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ASSERT (HandleCount > 0);
+
+ FtwLiteDevice->FtwFvBlock = NULL;
+ FtwLiteDevice->FtwBackupFvb = NULL;
+ FtwLiteDevice->FtwWorkSpaceLba = (EFI_LBA) (-1);
+ FtwLiteDevice->FtwSpareLba = (EFI_LBA) (-1);
+ for (Index = 0; Index < HandleCount; Index += 1) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ (VOID **) &Fvb
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) BaseAddress);
+
+ if ((FtwLiteDevice->WorkSpaceAddress >= BaseAddress) &&
+ (FtwLiteDevice->WorkSpaceAddress <= (BaseAddress + FwVolHeader->FvLength))
+ ) {
+ FtwLiteDevice->FtwFvBlock = Fvb;
+ //
+ // To get the LBA of work space
+ //
+ if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
+ //
+ // FV may have multiple types of BlockLength
+ //
+ FvbMapEntry = &FwVolHeader->BlockMap[0];
+ while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->Length == 0))) {
+ for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
+ if (FtwLiteDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex)) {
+ FtwLiteDevice->FtwWorkSpaceLba = LbaIndex - 1;
+ //
+ // Get the Work space size and Base(Offset)
+ //
+ FtwLiteDevice->FtwWorkSpaceSize = FtwLiteDevice->WorkSpaceLength;
+ FtwLiteDevice->FtwWorkSpaceBase = (UINTN) (FtwLiteDevice->WorkSpaceAddress - (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
+ break;
+ }
+ }
+ //
+ // end for
+ //
+ FvbMapEntry++;
+ }
+ //
+ // end while
+ //
+ }
+ }
+
+ if ((FtwLiteDevice->SpareAreaAddress >= BaseAddress) &&
+ (FtwLiteDevice->SpareAreaAddress <= (BaseAddress + FwVolHeader->FvLength))
+ ) {
+ FtwLiteDevice->FtwBackupFvb = Fvb;
+ //
+ // To get the LBA of spare
+ //
+ if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
+ //
+ // FV may have multiple types of BlockLength
+ //
+ FvbMapEntry = &FwVolHeader->BlockMap[0];
+ while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->Length == 0))) {
+ for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
+ if (FtwLiteDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex)) {
+ //
+ // Get the NumberOfSpareBlock and SizeOfSpareBlock
+ //
+ FtwLiteDevice->FtwSpareLba = LbaIndex - 1;
+ FtwLiteDevice->SizeOfSpareBlock = FvbMapEntry->Length;
+ FtwLiteDevice->NumberOfSpareBlock = FtwLiteDevice->SpareAreaLength / FtwLiteDevice->SizeOfSpareBlock;
+ //
+ // Check the range of spare area to make sure that it's in FV range
+ //
+ ASSERT ((FtwLiteDevice->FtwSpareLba + FtwLiteDevice->NumberOfSpareBlock) <= FvbMapEntry->NumBlocks);
+ break;
+ }
+ }
+
+ FvbMapEntry++;
+ }
+ //
+ // end while
+ //
+ }
+ }
+ }
+ //
+ // Calculate the start LBA of working block. Working block is an area which
+ // contains working space in its last block and has the same size as spare
+ // block, unless there are not enough blocks before the block that contains
+ // working space.
+ //
+ FtwLiteDevice->FtwWorkBlockLba = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->NumberOfSpareBlock + 1;
+ if ((INT64) (FtwLiteDevice->FtwWorkBlockLba) < 0) {
+ FtwLiteDevice->FtwWorkBlockLba = 0;
+ }
+
+ if ((FtwLiteDevice->FtwFvBlock == NULL) ||
+ (FtwLiteDevice->FtwBackupFvb == NULL) ||
+ (FtwLiteDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) ||
+ (FtwLiteDevice->FtwSpareLba == (EFI_LBA) (-1))
+ ) {
+ DEBUG ((EFI_D_ERROR, "FtwLite: Working or spare FVB not ready\n"));
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // Refresh workspace data from working block
+ //
+ Status = WorkSpaceRefresh (FtwLiteDevice);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // If the working block workspace is not valid, try the spare block
+ //
+ if (!IsValidWorkSpace (FtwLiteDevice->FtwWorkSpaceHeader)) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace invalid, read from backup\n"));
+ //
+ // Read from spare block
+ //
+ Length = FtwLiteDevice->FtwWorkSpaceSize;
+ Status = FtwLiteDevice->FtwBackupFvb->Read (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba,
+ FtwLiteDevice->FtwWorkSpaceBase,
+ &Length,
+ FtwLiteDevice->FtwWorkSpace
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // If spare block is valid, then replace working block content.
+ //
+ if (IsValidWorkSpace (FtwLiteDevice->FtwWorkSpaceHeader)) {
+ Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart working block in Init() - %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+
+ FtwAbort (FtwLiteDevice);
+ //
+ // Refresh work space.
+ //
+ Status = WorkSpaceRefresh (FtwLiteDevice);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ } else {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Both are invalid, init workspace\n"));
+ //
+ // If both are invalid, then initialize work space.
+ //
+ SetMem (
+ FtwLiteDevice->FtwWorkSpace,
+ FtwLiteDevice->FtwWorkSpaceSize,
+ FTW_ERASED_BYTE
+ );
+ InitWorkSpaceHeader (FtwLiteDevice->FtwWorkSpaceHeader);
+ //
+ // Write to work space on the working block
+ //
+ Length = FtwLiteDevice->FtwWorkSpaceSize;
+ Status = FtwLiteDevice->FtwFvBlock->Write (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase,
+ &Length,
+ FtwLiteDevice->FtwWorkSpace
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ }
+ }
+ //
+ // Hook the protocol API
+ //
+ FtwLiteDevice->FtwLiteInstance.Write = FtwLiteWrite;
+
+ //
+ // Install protocol interface
+ //
+ Status = gBS->InstallProtocolInterface (
+ &FtwLiteDevice->Handle,
+ &gEfiFaultTolerantWriteLiteProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &FtwLiteDevice->FtwLiteInstance
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // If (!SpareCompleted) THEN Abort to rollback.
+ //
+ if ((FtwLiteDevice->FtwLastRecord->WriteAllocated == FTW_VALID_STATE) &&
+ (FtwLiteDevice->FtwLastRecord->SpareCompleted != FTW_VALID_STATE)
+ ) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Init.. record not SpareCompleted, abort()\n"));
+ FtwAbort (FtwLiteDevice);
+ }
+ //
+ // if (SpareCompleted) THEN Restart to fault tolerant write.
+ //
+ if ((FtwLiteDevice->FtwLastRecord->SpareCompleted == FTW_VALID_STATE) &&
+ (FtwLiteDevice->FtwLastRecord->WriteCompleted != FTW_VALID_STATE)
+ ) {
+
+ Status = FtwRestart (FtwLiteDevice);
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart last write - %r\n", Status));
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // To check the workspace buffer behind last records is EMPTY or not.
+ // If it's not EMPTY, FTW_LITE also need to call reclaim().
+ //
+ Record = FtwLiteDevice->FtwLastRecord;
+ Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
+ if (FtwLiteDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
+ Offset += WRITE_TOTAL_SIZE;
+ }
+
+ if (!IsErasedFlashBuffer (
+ FTW_ERASE_POLARITY,
+ FtwLiteDevice->FtwWorkSpace + Offset,
+ FtwLiteDevice->FtwWorkSpaceSize - Offset
+ )) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace is dirty, call reclaim...\n"));
+ Status = FtwReclaimWorkSpace (FtwLiteDevice);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace reclaim - %r\n", Status));
+ return EFI_ABORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs
new file mode 100644
index 0000000..93aa216
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ FtwLite.dxs
+
+Abstract:
+
+ Dependency expression source file.
+
+--*/
+#include <DxeDepex.h>
+
+
+DEPENDENCY_START
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID AND EFI_ALTERNATE_FV_BLOCK_GUID
+DEPENDENCY_END
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h
new file mode 100644
index 0000000..8bc122d
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h
@@ -0,0 +1,695 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ FtwLite.h
+
+Abstract:
+
+ This is a simple fault tolerant write driver, based on PlatformFd library.
+ And it only supports write BufferSize <= SpareAreaLength.
+
+ This boot service only protocol provides fault tolerant write capability for
+ block devices. The protocol has internal non-volatile intermediate storage
+ of the data and private information. It should be able to recover
+ automatically from a critical fault, such as power failure.
+
+--*/
+
+#ifndef _EFI_FAULT_TOLERANT_WRITE_LITE_H_
+#define _EFI_FAULT_TOLERANT_WRITE_LITE_H_
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/PciRootBridgeIo.h>
+#include <Guid/SystemNvDataGuid.h>
+#include <Protocol/FaultTolerantWriteLite.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Common/WorkingBlockHeader.h>
+
+#define EFI_D_FTW_LITE EFI_D_ERROR
+#define EFI_D_FTW_INFO EFI_D_INFO
+
+//
+// Flash erase polarity is 1
+//
+#define FTW_ERASE_POLARITY 1
+
+#define FTW_VALID_STATE 0
+#define FTW_INVALID_STATE 1
+
+#define FTW_ERASED_BYTE ((UINT8) (255))
+#define FTW_POLARITY_REVERT ((UINT8) (255))
+
+typedef struct {
+ UINT8 WriteAllocated : 1;
+ UINT8 SpareCompleted : 1;
+ UINT8 WriteCompleted : 1;
+ UINT8 Reserved : 5;
+#define WRITE_ALLOCATED 0x1
+#define SPARE_COMPLETED 0x2
+#define WRITE_COMPLETED 0x4
+
+ EFI_DEV_PATH DevPath;
+ EFI_LBA Lba;
+ UINTN Offset;
+ UINTN NumBytes;
+ //
+ // UINTN SpareAreaOffset;
+ //
+} EFI_FTW_LITE_RECORD;
+
+#define FTW_LITE_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('F', 'T', 'W', 'L')
+
+//
+// MACRO for Block size.
+// Flash Erasing will do in block granularity.
+//
+#ifdef FV_BLOCK_SIZE
+#define FTW_BLOCK_SIZE FV_BLOCK_SIZE
+#else
+#define FV_BLOCK_SIZE 0x10000
+#define FTW_BLOCK_SIZE FV_BLOCK_SIZE
+#endif
+//
+// MACRO for FTW WORK SPACE Base & Size
+//
+#ifdef EFI_FTW_WORKING_OFFSET
+#define FTW_WORK_SPACE_BASE EFI_FTW_WORKING_OFFSET
+#else
+#define FTW_WORK_SPACE_BASE 0x00E000
+#endif
+
+#ifdef EFI_FTW_WORKING_LENGTH
+#define FTW_WORK_SPACE_SIZE EFI_FTW_WORKING_LENGTH
+#else
+#define FTW_WORK_SPACE_SIZE 0x002000
+#endif
+//
+// MACRO for FTW header and record
+//
+#define FTW_WORKING_QUEUE_SIZE (FTW_WORK_SPACE_SIZE - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER))
+#define FTW_LITE_RECORD_SIZE (sizeof (EFI_FTW_LITE_RECORD))
+#define WRITE_TOTAL_SIZE FTW_LITE_RECORD_SIZE
+
+//
+// EFI Fault tolerant protocol private data structure
+//
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_FTW_LITE_PROTOCOL FtwLiteInstance;
+ EFI_PHYSICAL_ADDRESS WorkSpaceAddress;
+ UINTN WorkSpaceLength;
+ EFI_PHYSICAL_ADDRESS SpareAreaAddress;
+ UINTN SpareAreaLength;
+ UINTN NumberOfSpareBlock; // Number of the blocks in spare block
+ UINTN SizeOfSpareBlock; // Block size in bytes of the blocks in spare block
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader;
+ EFI_FTW_LITE_RECORD *FtwLastRecord;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FtwFvBlock; // FVB of working block
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FtwBackupFvb; // FVB of spare block
+ EFI_LBA FtwSpareLba;
+ EFI_LBA FtwWorkBlockLba; // Start LBA of working block
+ EFI_LBA FtwWorkSpaceLba; // Start LBA of working space
+ UINTN FtwWorkSpaceBase; // Offset from LBA start addr
+ UINTN FtwWorkSpaceSize;
+ UINT8 *FtwWorkSpace;
+ //
+ // Following a buffer of FtwWorkSpace[FTW_WORK_SPACE_SIZE],
+ // Allocated with EFI_FTW_LITE_DEVICE.
+ //
+} EFI_FTW_LITE_DEVICE;
+
+#define FTW_LITE_CONTEXT_FROM_THIS(a) CR (a, EFI_FTW_LITE_DEVICE, FtwLiteInstance, FTW_LITE_DEVICE_SIGNATURE)
+
+//
+// Driver entry point
+//
+EFI_STATUS
+EFIAPI
+InitializeFtwLite (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This function is the entry point of the Fault Tolerant Write driver.
+
+Arguments:
+ ImageHandle - EFI_HANDLE: A handle for the image that is initializing
+ this driver
+ SystemTable - EFI_SYSTEM_TABLE: A pointer to the EFI system table
+
+Returns:
+ EFI_SUCCESS - FTW has finished the initialization
+ EFI_ABORTED - FTW initialization error
+
+--*/
+;
+
+//
+// Fault Tolerant Write Protocol API
+//
+EFI_STATUS
+EFIAPI
+FtwLiteWrite (
+ IN EFI_FTW_LITE_PROTOCOL *This,
+ IN EFI_HANDLE FvbHandle,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN *NumBytes,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Starts a target block update. This function will record data about write
+ in fault tolerant storage and will complete the write in a recoverable
+ manner, ensuring at all times that either the original contents or
+ the modified contents are available.
+
+Arguments:
+ This - Calling context
+ FvbHandle - The handle of FVB protocol that provides services for
+ reading, writing, and erasing the target block.
+ Lba - The logical block address of the target block.
+ Offset - The offset within the target block to place the data.
+ NumBytes - The number of bytes to write to the target block.
+ Buffer - The data to write.
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_BAD_BUFFER_SIZE - The write would span a target block, which is not
+ a valid action.
+ EFI_ACCESS_DENIED - No writes have been allocated.
+ EFI_NOT_FOUND - Cannot find FVB by handle.
+ EFI_OUT_OF_RESOURCES - Cannot allocate memory.
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+;
+
+//
+// Internal functions
+//
+EFI_STATUS
+FtwRestart (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Restarts a previously interrupted write. The caller must provide the
+ block protocol needed to complete the interrupted write.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+ FvbHandle - The handle of FVB protocol that provides services for
+ reading, writing, and erasing the target block.
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ACCESS_DENIED - No pending writes exist
+ EFI_NOT_FOUND - FVB protocol not found by the handle
+ EFI_ABORTED - The function could not complete successfully
+
+--*/
+;
+
+EFI_STATUS
+FtwAbort (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Aborts all previous allocated writes.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully.
+ EFI_NOT_FOUND - No allocated writes exist.
+
+--*/
+;
+
+
+EFI_STATUS
+FtwWriteRecord (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb
+ )
+/*++
+
+Routine Description:
+ Write a record with fault tolerant mannaer.
+ Since the content has already backuped in spare block, the write is
+ guaranteed to be completed with fault tolerant manner.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+ Fvb - The FVB protocol that provides services for
+ reading, writing, and erasing the target block.
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully
+
+--*/
+;
+
+EFI_STATUS
+FtwEraseBlock (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+ To Erase one block. The size is FTW_BLOCK_SIZE
+
+Arguments:
+ FtwLiteDevice - Calling context
+ FvBlock - FVB Protocol interface
+ Lba - Lba of the firmware block
+
+Returns:
+ EFI_SUCCESS - Block LBA is Erased successfully
+ Others - Error occurs
+
+--*/
+;
+
+EFI_STATUS
+FtwEraseSpareBlock (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+
+ Erase spare block.
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+
+Returns:
+
+ Status code
+
+--*/
+;
+
+EFI_STATUS
+FtwGetFvbByHandle (
+ IN EFI_HANDLE FvBlockHandle,
+ OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
+ )
+/*++
+
+Routine Description:
+ Retrive the proper FVB protocol interface by HANDLE.
+
+Arguments:
+ FvBlockHandle - The handle of FVB protocol that provides services for
+ reading, writing, and erasing the target block.
+ FvBlock - The interface of FVB protocol
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully
+--*/
+;
+
+EFI_STATUS
+GetFvbByAddress (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
+ )
+/*++
+
+Routine Description:
+
+ Get firmware block by address.
+
+Arguments:
+
+ Address - Address specified the block
+ FvBlock - The block caller wanted
+
+Returns:
+
+ Status code
+
+ EFI_NOT_FOUND - Block not found
+
+--*/
+;
+
+BOOLEAN
+IsInWorkingBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ Is it in working block?
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ FvBlock - Fvb protocol instance
+ Lba - The block specified
+
+Returns:
+
+ In working block or not
+
+--*/
+;
+
+BOOLEAN
+IsBootBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ Check whether the block is a boot block.
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ FvBlock - Fvb protocol instance
+ Lba - Lba value
+
+Returns:
+
+ Is a boot block or not
+
+--*/
+;
+
+EFI_STATUS
+FlushSpareBlockToTargetBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+ Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwLiteDevice->FtwSpareLba.
+ Target block is accessed by FvBlock protocol interface. LBA is Lba.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+ FvBlock - FVB Protocol interface to access target block
+ Lba - Lba of the target block
+
+Returns:
+ EFI_SUCCESS - Spare block content is copied to target block
+ EFI_INVALID_PARAMETER - Input parameter error
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+--*/
+;
+
+EFI_STATUS
+FlushSpareBlockToWorkingBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwLiteDevice->FtwSpareLba.
+ Working block is accessed by FTW working FVB protocol interface. LBA is
+ FtwLiteDevice->FtwWorkBlockLba.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+
+Returns:
+ EFI_SUCCESS - Spare block content is copied to target block
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+Notes:
+ Since the working block header is important when FTW initializes, the
+ state of the operation should be handled carefully. The Crc value is
+ calculated without STATE element.
+
+--*/
+;
+
+EFI_STATUS
+FlushSpareBlockToBootBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwLiteDevice->FtwSpareLba.
+ Boot block is accessed by BootFvb protocol interface. LBA is 0.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+
+Returns:
+ EFI_SUCCESS - Spare block content is copied to boot block
+ EFI_INVALID_PARAMETER - Input parameter error
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+Notes:
+
+--*/
+;
+
+EFI_STATUS
+FtwUpdateFvState (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINT8 NewBit
+ )
+/*++
+
+Routine Description:
+ Update a bit of state on a block device. The location of the bit is
+ calculated by the (Lba, Offset, bit). Here bit is determined by the
+ the name of a certain bit.
+
+Arguments:
+ FvBlock - FVB Protocol interface to access SrcBlock and DestBlock
+ Lba - Lba of a block
+ Offset - Offset on the Lba
+ NewBit - New value that will override the old value if it can be change
+
+Returns:
+ EFI_SUCCESS - A state bit has been updated successfully
+ Others - Access block device error.
+
+Notes:
+ Assume all bits of State are inside the same BYTE.
+
+ EFI_ABORTED - Read block fail
+--*/
+;
+
+EFI_STATUS
+FtwGetLastRecord (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ OUT EFI_FTW_LITE_RECORD **FtwLastRecord
+ )
+/*++
+
+Routine Description:
+ Get the last Write record pointer.
+ The last record is the record whose 'complete' state hasn't been set.
+ After all, this header may be a EMPTY header entry for next Allocate.
+
+Arguments:
+ FtwLiteDevice - Private data of this driver
+ FtwLastRecord - Pointer to retrieve the last write record
+
+Returns:
+ EFI_SUCCESS - Get the last write record successfully
+ EFI_ABORTED - The FTW work space is damaged
+
+--*/
+;
+
+BOOLEAN
+IsErasedFlashBuffer (
+ IN BOOLEAN Polarity,
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Check whether a flash buffer is erased.
+
+Arguments:
+
+ Polarity - All 1 or all 0
+ Buffer - Buffer to check
+ BufferSize - Size of the buffer
+
+Returns:
+
+ Erased or not.
+
+--*/
+;
+
+EFI_STATUS
+InitWorkSpaceHeader (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
+ )
+/*++
+
+Routine Description:
+ Initialize a work space when there is no work space.
+
+Arguments:
+ WorkingHeader - Pointer of working block header
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+;
+
+EFI_STATUS
+WorkSpaceRefresh (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Read from working block to refresh the work space in memory.
+
+Arguments:
+ FtwLiteDevice - Point to private data of FTW driver
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+;
+
+BOOLEAN
+IsValidWorkSpace (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
+ )
+/*++
+
+Routine Description:
+ Check to see if it is a valid work space.
+
+Arguments:
+ WorkingHeader - Pointer of working block header
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+;
+
+EFI_STATUS
+CleanupWorkSpace (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ IN OUT UINT8 *BlockBuffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+ Reclaim the work space. Get rid of all the completed write records
+ and write records in the Fault Tolerant work space.
+
+Arguments:
+ FtwLiteDevice - Point to private data of FTW driver
+ FtwSpaceBuffer - Buffer to contain the reclaimed clean data
+ BufferSize - Size of the FtwSpaceBuffer
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_BUFFER_TOO_SMALL - The FtwSpaceBuffer is too small
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+;
+
+EFI_STATUS
+FtwReclaimWorkSpace (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Reclaim the work space on the working block.
+
+Arguments:
+ FtwLiteDevice - Point to private data of FTW driver
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+--*/
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.inf b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.inf
new file mode 100644
index 0000000..39422f2
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.inf
@@ -0,0 +1,133 @@
+#/** @file
+# Component description file for FtwLite module.
+#
+# This driver provides fault tolerant write capability for block devices.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FtwLite
+ FILE_GUID = 4C862FC6-0E54-4e36-8C8F-FF6F3167951F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeFtwLite
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ FtwLite.dxs
+ FtwWorkSpace.c
+ FtwMisc.c
+ FtwLite.c
+ FtwLite.h
+
+[Sources.Ia32]
+ Ia32/Ia32FtwMisc.c
+
+[Sources.X64]
+ x64/x64FtwMisc.c
+
+[Sources.IPF]
+ Ipf/IpfFtwMisc.c
+
+[Sources.EBC]
+ Ia32/Ia32FtwMisc.c
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ DebugLib
+ PcdLib
+
+
+################################################################################
+#
+# Guid C Name Section - list of Guids that this module uses or produces.
+#
+################################################################################
+
+[Guids]
+ gEfiSystemNvDataFvGuid # ALWAYS_CONSUMED
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFaultTolerantWriteLiteProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[Protocols.IA32]
+ gEfiPciRootBridgeIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Protocols.EBC]
+ gEfiPciRootBridgeIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+
+################################################################################
+#
+# Pcd DYNAMIC - list of PCDs that this module is coded for.
+#
+################################################################################
+
+[PcdsDynamic.common]
+ PcdFlashNvStorageFtwWorkingSize|gEfiGenericPlatformTokenSpaceGuid
+ PcdFlashNvStorageFtwWorkingBase|gEfiGenericPlatformTokenSpaceGuid
+ PcdFlashNvStorageFtwSpareSize|gEfiGenericPlatformTokenSpaceGuid
+ PcdFlashNvStorageFtwSpareBase|gEfiGenericPlatformTokenSpaceGuid
+
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa
new file mode 100644
index 0000000..7362f47
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>FtwLite</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>4C862FC6-0E54-4e36-8C8F-FF6F3167951F</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for FtwLite module.</Abstract>
+ <Description>This driver provides fault tolerant write capability for block devices.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>FtwLite</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PcdLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>FtwLite.h</Filename>
+ <Filename>FtwLite.c</Filename>
+ <Filename>FtwMisc.c</Filename>
+ <Filename>FtwWorkSpace.c</Filename>
+ <Filename>FtwLite.dxs</Filename>
+ <Filename SupArchList="IA32 EBC">Ia32/Ia32FtwMisc.c</Filename>
+ <Filename SupArchList="X64">x64/x64FtwMisc.c</Filename>
+ <Filename SupArchList="IPF">Ipf/IpfFtwMisc.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="1E73767F-8F52-4603-AEB4-F29B510B6766"/>
+ <Package PackageGuid="BA0D78D6-2CAF-414b-BD4D-B6762A894288"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_PRODUCED">
+ <ProtocolCName>gEfiFaultTolerantWriteLiteProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED" SupArchList="IA32 EBC">
+ <ProtocolCName>gEfiPciRootBridgeIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFirmwareVolumeBlockProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Guids>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiSystemNvDataFvGuid</GuidCName>
+ </GuidCNames>
+ </Guids>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>InitializeFtwLite</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+ <PcdCoded>
+ <PcdEntry PcdItemType="DYNAMIC" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdFlashNvStorageFtwSpareBase</C_Name>
+ <TokenSpaceGuidCName>gEfiGenericPlatformTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>To get base address of the FTW spare block section in NV firmware volume.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="DYNAMIC" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdFlashNvStorageFtwSpareSize</C_Name>
+ <TokenSpaceGuidCName>gEfiGenericPlatformTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>To get size of the FTW spare block section in NV firmware volume.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="DYNAMIC" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdFlashNvStorageFtwWorkingBase</C_Name>
+ <TokenSpaceGuidCName>gEfiGenericPlatformTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>To get base address of the FTW working block section in NV firmware volume.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="DYNAMIC" Usage="ALWAYS_CONSUMED">
+ <C_Name>PcdFlashNvStorageFtwWorkingSize</C_Name>
+ <TokenSpaceGuidCName>gEfiGenericPlatformTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>To get size of the FTW working block section in NV firmware volume.</HelpText>
+ </PcdEntry>
+ </PcdCoded>
+</ModuleSurfaceArea>
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c
new file mode 100644
index 0000000..eb334ea
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c
@@ -0,0 +1,530 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FtwMisc.c
+
+Abstract:
+
+ Internal functions to support fault tolerant write.
+
+Revision History
+
+--*/
+
+#include <FtwLite.h>
+
+BOOLEAN
+IsErasedFlashBuffer (
+ IN BOOLEAN Polarity,
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Check whether a flash buffer is erased.
+
+Arguments:
+
+ Polarity - All 1 or all 0
+ Buffer - Buffer to check
+ BufferSize - Size of the buffer
+
+Returns:
+
+ Erased or not.
+
+--*/
+{
+ UINT8 ErasedValue;
+ UINT8 *Ptr;
+
+ if (Polarity) {
+ ErasedValue = 0xFF;
+ } else {
+ ErasedValue = 0;
+ }
+
+ Ptr = Buffer;
+ while (BufferSize--) {
+ if (*Ptr++ != ErasedValue) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+EFI_STATUS
+FtwEraseBlock (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+ To Erase one block. The size is FTW_BLOCK_SIZE
+
+Arguments:
+ FtwLiteDevice - Calling context
+ FvBlock - FVB Protocol interface
+ Lba - Lba of the firmware block
+
+Returns:
+ EFI_SUCCESS - Block LBA is Erased successfully
+ Others - Error occurs
+
+--*/
+{
+ return FvBlock->EraseBlocks (
+ FvBlock,
+ Lba,
+ FtwLiteDevice->NumberOfSpareBlock,
+ EFI_LBA_LIST_TERMINATOR
+ );
+}
+
+EFI_STATUS
+FtwEraseSpareBlock (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+
+ Erase spare block.
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+
+Returns:
+
+ Status code
+
+--*/
+{
+ return FtwLiteDevice->FtwBackupFvb->EraseBlocks (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba,
+ FtwLiteDevice->NumberOfSpareBlock,
+ EFI_LBA_LIST_TERMINATOR
+ );
+}
+
+EFI_STATUS
+FtwGetFvbByHandle (
+ IN EFI_HANDLE FvBlockHandle,
+ OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
+ )
+/*++
+
+Routine Description:
+ Retrive the proper FVB protocol interface by HANDLE.
+
+Arguments:
+ FvBlockHandle - The handle of FVB protocol that provides services for
+ reading, writing, and erasing the target block.
+ FvBlock - The interface of FVB protocol
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully
+--*/
+{
+ //
+ // To get the FVB protocol interface on the handle
+ //
+ return gBS->HandleProtocol (
+ FvBlockHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ (VOID **) FvBlock
+ );
+}
+
+EFI_STATUS
+GetFvbByAddress (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
+ )
+/*++
+
+Routine Description:
+
+ Get firmware block by address.
+
+Arguments:
+
+ Address - Address specified the block
+ FvBlock - The block caller wanted
+
+Returns:
+
+ Status code
+
+ EFI_NOT_FOUND - Block not found
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS FvbBaseAddress;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+
+ *FvBlock = NULL;
+ //
+ // Locate all handles of Fvb protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Search all FVB until find the right one
+ //
+ for (Index = 0; Index < HandleCount; Index += 1) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ (VOID **) &Fvb
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+ //
+ // Compare the address and select the right one
+ //
+ Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
+ if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + (FwVolHeader->FvLength - 1)))) {
+ *FvBlock = Fvb;
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+
+ FreePool (HandleBuffer);
+ return Status;
+}
+
+BOOLEAN
+IsInWorkingBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ Is it in working block?
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ FvBlock - Fvb protocol instance
+ Lba - The block specified
+
+Returns:
+
+ In working block or not
+
+--*/
+{
+ //
+ // If matching the following condition, the target block is in working block.
+ // 1. Target block is on the FV of working block (Using the same FVB protocol instance).
+ // 2. Lba falls into the range of working block.
+ //
+ return (BOOLEAN)
+ (
+ (FvBlock == FtwLiteDevice->FtwFvBlock) &&
+ (Lba >= FtwLiteDevice->FtwWorkBlockLba) &&
+ (Lba <= FtwLiteDevice->FtwWorkSpaceLba)
+ );
+}
+
+EFI_STATUS
+FlushSpareBlockToTargetBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+ Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwLiteDevice->FtwSpareLba.
+ Target block is accessed by FvBlock protocol interface. LBA is Lba.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+ FvBlock - FVB Protocol interface to access target block
+ Lba - Lba of the target block
+
+Returns:
+ EFI_SUCCESS - Spare block content is copied to target block
+ EFI_INVALID_PARAMETER - Input parameter error
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Buffer;
+ UINTN Count;
+ UINT8 *Ptr;
+ UINTN Index;
+
+ if ((FtwLiteDevice == NULL) || (FvBlock == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Allocate a memory buffer
+ //
+ Length = FtwLiteDevice->SpareAreaLength;
+ Buffer = AllocatePool (Length);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Read all content of spare block to memory buffer
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Read (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Erase the target block
+ //
+ Status = FtwEraseBlock (FtwLiteDevice, FvBlock, Lba);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Write memory buffer to block, using the FvbBlock protocol interface
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write block - %r\n", Status));
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+
+ FreePool (Buffer);
+
+ return Status;
+}
+
+EFI_STATUS
+FlushSpareBlockToWorkingBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwLiteDevice->FtwSpareLba.
+ Working block is accessed by FTW working FVB protocol interface. LBA is
+ FtwLiteDevice->FtwWorkBlockLba.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+
+Returns:
+ EFI_SUCCESS - Spare block content is copied to target block
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+Notes:
+ Since the working block header is important when FTW initializes, the
+ state of the operation should be handled carefully. The Crc value is
+ calculated without STATE element.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Buffer;
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
+ EFI_LBA WorkSpaceLbaOffset;
+ UINTN Count;
+ UINT8 *Ptr;
+ UINTN Index;
+
+ //
+ // Allocate a memory buffer
+ //
+ Length = FtwLiteDevice->SpareAreaLength;
+ Buffer = AllocatePool (Length);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // To guarantee that the WorkingBlockValid is set on spare block
+ //
+ WorkSpaceLbaOffset = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba;
+ FtwUpdateFvState (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + WorkSpaceLbaOffset,
+ FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
+ WORKING_BLOCK_VALID
+ );
+ //
+ // Read from spare block to memory buffer
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Read (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Clear the CRC and STATE, copy data from spare to working block.
+ //
+ WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (Buffer + (UINTN) WorkSpaceLbaOffset * FtwLiteDevice->SizeOfSpareBlock + FtwLiteDevice->FtwWorkSpaceBase);
+ InitWorkSpaceHeader (WorkingBlockHeader);
+ WorkingBlockHeader->WorkingBlockValid = FTW_ERASE_POLARITY;
+ WorkingBlockHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;
+
+ //
+ // target block is working block, then
+ // Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
+ // before erase the working block.
+ //
+ // Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
+ // WorkingBlockInvalid);
+ // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
+ //
+ Status = FtwUpdateFvState (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
+ WORKING_BLOCK_INVALID
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+
+ FtwLiteDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;
+
+ //
+ // Erase the working block
+ //
+ Status = FtwEraseBlock (
+ FtwLiteDevice,
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkBlockLba
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Write memory buffer to working block, using the FvbBlock protocol interface
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwFvBlock->Write (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkBlockLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write block - %r\n", Status));
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Since the memory buffer will not be used, free memory Buffer.
+ //
+ FreePool (Buffer);
+
+ //
+ // Update the VALID of the working block
+ //
+ // Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
+ // WorkingBlockValid);
+ // Hardcode offset sizeof(EFI_GUID)+sizeof(UINT32), to skip Signature and Crc
+ //
+ Status = FtwUpdateFvState (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
+ WORKING_BLOCK_VALID
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ FtwLiteDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c
new file mode 100644
index 0000000..00d7d8e
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c
@@ -0,0 +1,561 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FtwWorkSpace.c
+
+Abstract:
+
+Revision History
+
+--*/
+
+
+#include <FtwLite.h>
+
+BOOLEAN
+IsValidWorkSpace (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
+ )
+/*++
+
+Routine Description:
+ Check to see if it is a valid work space.
+
+Arguments:
+ WorkingHeader - Pointer of working block header
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER WorkingBlockHeader;
+
+ ASSERT (WorkingHeader != NULL);
+ if (WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) {
+ return FALSE;
+ }
+ //
+ // Check signature with gEfiSystemNvDataFvGuid
+ //
+ if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) {
+ return FALSE;
+ }
+ //
+ // Check the CRC of header
+ //
+ CopyMem (
+ &WorkingBlockHeader,
+ WorkingHeader,
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
+ );
+
+ //
+ // Filter out the Crc and State fields
+ //
+ SetMem (
+ &WorkingBlockHeader.Crc,
+ sizeof (UINT32),
+ FTW_ERASED_BYTE
+ );
+ WorkingBlockHeader.WorkingBlockValid = FTW_ERASE_POLARITY;
+ WorkingBlockHeader.WorkingBlockInvalid = FTW_ERASE_POLARITY;
+
+ //
+ // Calculate the Crc of woking block header
+ //
+ Status = gBS->CalculateCrc32 (
+ (UINT8 *) &WorkingBlockHeader,
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
+ &WorkingBlockHeader.Crc
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (WorkingBlockHeader.Crc != WorkingHeader->Crc) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Work block header CRC check error\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+EFI_STATUS
+InitWorkSpaceHeader (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
+ )
+/*++
+
+Routine Description:
+ Initialize a work space when there is no work space.
+
+Arguments:
+ WorkingHeader - Pointer of working block header
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ ASSERT (WorkingHeader != NULL);
+
+ //
+ // Here using gEfiSystemNvDataFvGuid as the signature.
+ //
+ CopyMem (
+ &WorkingHeader->Signature,
+ &gEfiSystemNvDataFvGuid,
+ sizeof (EFI_GUID)
+ );
+ WorkingHeader->WriteQueueSize = FTW_WORKING_QUEUE_SIZE;
+
+ //
+ // Crc is calculated with all the fields except Crc and STATE
+ //
+ WorkingHeader->WorkingBlockValid = FTW_ERASE_POLARITY;
+ WorkingHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;
+ SetMem (&WorkingHeader->Crc, sizeof (UINT32), FTW_ERASED_BYTE);
+
+ //
+ // Calculate the CRC value
+ //
+ Status = gBS->CalculateCrc32 (
+ (UINT8 *) WorkingHeader,
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
+ &WorkingHeader->Crc
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Restore the WorkingBlockValid flag to VALID state
+ //
+ WorkingHeader->WorkingBlockValid = FTW_VALID_STATE;
+ WorkingHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FtwUpdateFvState (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINT8 NewBit
+ )
+/*++
+
+Routine Description:
+ Update a bit of state on a block device. The location of the bit is
+ calculated by the (Lba, Offset, bit). Here bit is determined by the
+ the name of a certain bit.
+
+Arguments:
+ FvBlock - FVB Protocol interface to access SrcBlock and DestBlock
+ Lba - Lba of a block
+ Offset - Offset on the Lba
+ NewBit - New value that will override the old value if it can be change
+
+Returns:
+ EFI_SUCCESS - A state bit has been updated successfully
+ Others - Access block device error.
+
+Notes:
+ Assume all bits of State are inside the same BYTE.
+
+ EFI_ABORTED - Read block fail
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 State;
+ UINTN Length;
+
+ //
+ // Read state from device, assume State is only one byte.
+ //
+ Length = sizeof (UINT8);
+ Status = FvBlock->Read (FvBlock, Lba, Offset, &Length, &State);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ State ^= FTW_POLARITY_REVERT;
+ State = (UINT8) (State | NewBit);
+ State ^= FTW_POLARITY_REVERT;
+
+ //
+ // Write state back to device
+ //
+ Length = sizeof (UINT8);
+ Status = FvBlock->Write (FvBlock, Lba, Offset, &Length, &State);
+
+ return Status;
+}
+
+EFI_STATUS
+FtwGetLastRecord (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ OUT EFI_FTW_LITE_RECORD **FtwLastRecord
+ )
+/*++
+
+Routine Description:
+ Get the last Write record pointer.
+ The last record is the record whose 'complete' state hasn't been set.
+ After all, this header may be a EMPTY header entry for next Allocate.
+
+Arguments:
+ FtwLiteDevice - Private data of this driver
+ FtwLastRecord - Pointer to retrieve the last write record
+
+Returns:
+ EFI_SUCCESS - Get the last write record successfully
+ EFI_ABORTED - The FTW work space is damaged
+
+--*/
+{
+ EFI_FTW_LITE_RECORD *Record;
+
+ Record = (EFI_FTW_LITE_RECORD *) (FtwLiteDevice->FtwWorkSpaceHeader + 1);
+ while (Record->WriteCompleted == FTW_VALID_STATE) {
+ //
+ // If Offset exceed the FTW work space boudary, return error.
+ //
+ if ((UINTN) ((UINT8 *) Record - FtwLiteDevice->FtwWorkSpace) > FtwLiteDevice->FtwWorkSpaceSize) {
+ return EFI_ABORTED;
+ }
+
+ Record++;
+ }
+ //
+ // Last write record is found
+ //
+ *FtwLastRecord = Record;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WorkSpaceRefresh (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Read from working block to refresh the work space in memory.
+
+Arguments:
+ FtwLiteDevice - Point to private data of FTW driver
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINTN Offset;
+ EFI_FTW_LITE_RECORD *Record;
+
+ //
+ // Initialize WorkSpace as FTW_ERASED_BYTE
+ //
+ SetMem (
+ FtwLiteDevice->FtwWorkSpace,
+ FtwLiteDevice->FtwWorkSpaceSize,
+ FTW_ERASED_BYTE
+ );
+
+ //
+ // Read from working block
+ //
+ Length = FtwLiteDevice->FtwWorkSpaceSize;
+ Status = FtwLiteDevice->FtwFvBlock->Read (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkSpaceLba,
+ FtwLiteDevice->FtwWorkSpaceBase,
+ &Length,
+ FtwLiteDevice->FtwWorkSpace
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Refresh the FtwLastRecord
+ //
+ Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord);
+
+ Record = FtwLiteDevice->FtwLastRecord;
+ Offset = (UINTN) (UINT8 *) Record - (UINTN) FtwLiteDevice->FtwWorkSpace;
+
+ //
+ // IF work space has error or Record is out of the workspace limit, THEN
+ // call reclaim.
+ //
+ if (EFI_ERROR (Status) || (Offset + WRITE_TOTAL_SIZE >= FtwLiteDevice->FtwWorkSpaceSize)) {
+ //
+ // reclaim work space in working block.
+ //
+ Status = FtwReclaimWorkSpace (FtwLiteDevice);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: Reclaim workspace - %r\n", Status));
+ return EFI_ABORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CleanupWorkSpace (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ IN OUT UINT8 *FtwSpaceBuffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+ Reclaim the work space. Get rid of all the completed write records
+ and write records in the Fault Tolerant work space.
+
+Arguments:
+ FtwLiteDevice - Point to private data of FTW driver
+ FtwSpaceBuffer - Buffer to contain the reclaimed clean data
+ BufferSize - Size of the FtwSpaceBuffer
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_BUFFER_TOO_SMALL - The FtwSpaceBuffer is too small
+ EFI_ABORTED - The function could not complete successfully.
+
+--*/
+{
+ UINTN Length;
+ EFI_FTW_LITE_RECORD *Record;
+
+ //
+ // To check if the buffer is large enough
+ //
+ Length = FtwLiteDevice->FtwWorkSpaceSize;
+ if (BufferSize < Length) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // Clear the content of buffer that will save the new work space data
+ //
+ SetMem (FtwSpaceBuffer, Length, FTW_ERASED_BYTE);
+
+ //
+ // Copy EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER to buffer
+ //
+ CopyMem (
+ FtwSpaceBuffer,
+ FtwLiteDevice->FtwWorkSpaceHeader,
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
+ );
+
+ //
+ // Get the last record
+ //
+ Record = FtwLiteDevice->FtwLastRecord;
+ if ((Record != NULL) && (Record->WriteAllocated == FTW_VALID_STATE) && (Record->WriteCompleted != FTW_VALID_STATE)) {
+ CopyMem (
+ (UINT8 *) FtwSpaceBuffer + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
+ Record,
+ WRITE_TOTAL_SIZE
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FtwReclaimWorkSpace (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Reclaim the work space on the working block.
+
+Arguments:
+ FtwLiteDevice - Point to private data of FTW driver
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 *TempBuffer;
+ UINTN TempBufferSize;
+ UINT8 *Ptr;
+ UINTN Length;
+ UINTN Index;
+ UINTN SpareBufferSize;
+ UINT8 *SpareBuffer;
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
+
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: start to reclaim work space\n"));
+
+ //
+ // Read all original data from working block to a memory buffer
+ //
+ TempBufferSize = FtwLiteDevice->SpareAreaLength;
+ TempBuffer = AllocateZeroPool (TempBufferSize);
+ if (TempBuffer != NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = TempBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Length = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwFvBlock->Read (
+ FtwLiteDevice->FtwFvBlock,
+ FtwLiteDevice->FtwWorkBlockLba + Index,
+ 0,
+ &Length,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (TempBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+ //
+ // Clean up the workspace, remove all the completed records.
+ //
+ Ptr = TempBuffer +
+ ((UINTN) (FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba)) *
+ FtwLiteDevice->SizeOfSpareBlock + FtwLiteDevice->FtwWorkSpaceBase;
+
+ Status = CleanupWorkSpace (
+ FtwLiteDevice,
+ Ptr,
+ FtwLiteDevice->FtwWorkSpaceSize
+ );
+
+ CopyMem (
+ FtwLiteDevice->FtwWorkSpace,
+ Ptr,
+ FtwLiteDevice->FtwWorkSpaceSize
+ );
+
+ Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord);
+
+ //
+ // Set the WorkingBlockValid and WorkingBlockInvalid as INVALID
+ //
+ WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) Ptr;
+ WorkingBlockHeader->WorkingBlockValid = FTW_INVALID_STATE;
+ WorkingBlockHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
+
+ //
+ // Try to keep the content of spare block
+ // Save spare block into a spare backup memory buffer (Sparebuffer)
+ //
+ SpareBufferSize = FtwLiteDevice->SpareAreaLength;
+ SpareBuffer = AllocatePool (SpareBufferSize);
+ if (SpareBuffer == NULL) {
+ FreePool (TempBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = SpareBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Length = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Read (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &Length,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (TempBuffer);
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+ //
+ // Write the memory buffer to spare block
+ //
+ Status = FtwEraseSpareBlock (FtwLiteDevice);
+ Ptr = TempBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Length = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Write (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &Length,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (TempBuffer);
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+ //
+ // Free TempBuffer
+ //
+ FreePool (TempBuffer);
+
+ //
+ // Write the spare block to working block
+ //
+ Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return Status;
+ }
+ //
+ // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
+ //
+ Status = FtwEraseSpareBlock (FtwLiteDevice);
+ Ptr = SpareBuffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Length = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Write (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &Length,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+
+ FreePool (SpareBuffer);
+
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: reclaim work space success\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c
new file mode 100644
index 0000000..6425f29
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c
@@ -0,0 +1,403 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Ia32FtwMisc.c
+
+Abstract:
+
+ Ia32 platform related code to support FtwLite..
+
+Revision History
+
+--*/
+
+
+#include <FtwLite.h>
+
+//
+// MACROs for boot block update
+//
+#define BOOT_BLOCK_BASE 0xFFFF0000
+
+//
+// (LPC -- D31:F0)
+//
+#define LPC_BUS_NUMBER 0x00
+#define LPC_DEVICE_NUMBER 0x1F
+#define LPC_IF 0xF0
+//
+// Top swap
+//
+#define GEN_STATUS 0xD4
+#define TOP_SWAP_BIT (1 << 13)
+
+STATIC
+UINT32
+ReadPciRegister (
+ IN UINT32 Offset
+ )
+/*++
+
+Routine Description:
+
+ Read PCI register value.
+
+Arguments:
+
+ Offset - Offset of the register
+
+Returns:
+
+ The value.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 Value;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ Value = 0;
+ Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID **) &PciRootBridgeIo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "FtwLite: Locate PCI root bridge io protocol - %r", Status));
+ return 0;
+ }
+
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ EFI_PCI_ADDRESS (
+ LPC_BUS_NUMBER,
+ LPC_DEVICE_NUMBER,
+ LPC_IF,
+ Offset
+ ),
+ 1,
+ &Value
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Value;
+}
+
+STATIC
+EFI_STATUS
+GetSwapState (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ OUT BOOLEAN *SwapState
+ )
+/*++
+
+Routine Description:
+
+ Get swap state
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ SwapState - Swap state
+
+Returns:
+
+ EFI_SUCCESS - State successfully got
+
+--*/
+{
+ //
+ // Top swap status is 13 bit
+ //
+ *SwapState = (BOOLEAN) ((ReadPciRegister (GEN_STATUS) & TOP_SWAP_BIT) != 0);
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+SetSwapState (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ IN BOOLEAN TopSwap
+ )
+/*++
+
+Routine Description:
+ Set swap state.
+
+Arguments:
+ FtwLiteDevice - Indicates a pointer to the calling context.
+ TopSwap - New swap state
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+
+Note:
+ the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
+ software will not be able to clear the Top-Swap bit until the system is
+ rebooted without GNT[A]# being pulled down.
+
+--*/
+{
+ UINT32 GenStatus;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_STATUS Status;
+
+ //
+ // Top-Swap bit (bit 13, D31: F0, Offset D4h)
+ //
+ GenStatus = ReadPciRegister (GEN_STATUS);
+
+ //
+ // Set 13 bit, according to input NewSwapState
+ //
+ if (TopSwap) {
+ GenStatus |= TOP_SWAP_BIT;
+ } else {
+ GenStatus &= ~TOP_SWAP_BIT;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID **) &PciRootBridgeIo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "FtwLite: Locate PCI root bridge io protocol - %r", Status));
+ return Status;
+ }
+ //
+ // Write back the GenStatus register
+ //
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ EFI_PCI_ADDRESS (
+ LPC_BUS_NUMBER,
+ LPC_DEVICE_NUMBER,
+ LPC_IF,
+ GEN_STATUS
+ ),
+ 1,
+ &GenStatus
+ );
+
+ DEBUG_CODE_BEGIN ();
+ if (TopSwap) {
+ DEBUG ((EFI_D_ERROR, "SAR: Set top swap\n"));
+ } else {
+ DEBUG ((EFI_D_ERROR, "SAR: Clear top swap\n"));
+ }
+ DEBUG_CODE_END ();
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsBootBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ Check whether the block is a boot block.
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ FvBlock - Fvb protocol instance
+ Lba - Lba value
+
+Returns:
+
+ Is a boot block or not
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
+
+ Status = GetFvbByAddress (BOOT_BLOCK_BASE, &BootFvb);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ //
+ // Compare the Fvb
+ //
+ return (BOOLEAN) (FvBlock == BootFvb);
+}
+
+EFI_STATUS
+FlushSpareBlockToBootBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwLiteDevice->FtwSpareLba.
+ Boot block is accessed by BootFvb protocol interface. LBA is 0.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+
+Returns:
+ EFI_SUCCESS - Spare block content is copied to boot block
+ EFI_INVALID_PARAMETER - Input parameter error
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+Notes:
+ FTW will do extra work on boot block update.
+ FTW should depend on a protocol of EFI_ADDRESS_RANGE_SWAP_PROTOCOL,
+ which is produced by a chipset driver.
+
+ FTW updating boot block steps:
+ 1. Erase top swap block (0xFFFE-0xFFFEFFFF) and write data to it ready
+ 2. Read data from top swap block to memory buffer
+ 3. SetSwapState(EFI_SWAPPED)
+ 4. Erasing boot block (0xFFFF-0xFFFFFFFF)
+ 5. Programming boot block until the boot block is ok.
+ 6. SetSwapState(UNSWAPPED)
+
+ Notes:
+ 1. Since the SwapState bit is saved in CMOS, FTW can restore and continue
+ even in the scenario of power failure.
+ 2. FTW shall not allow to update boot block when battery state is error.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Buffer;
+ UINTN Count;
+ UINT8 *Ptr;
+ UINTN Index;
+ BOOLEAN TopSwap;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
+ EFI_LBA BootLba;
+
+ //
+ // Allocate a memory buffer
+ //
+ Length = FtwLiteDevice->SpareAreaLength;
+ Buffer = AllocatePool (Length);
+ if (Buffer == NULL) {
+ }
+ //
+ // Get TopSwap bit state
+ //
+ Status = GetSwapState (FtwLiteDevice, &TopSwap);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "FtwLite: Get Top Swapped status - %r\n", Status));
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+
+ if (TopSwap) {
+ //
+ // Get FVB of current boot block
+ //
+ Status = GetFvbByAddress (FtwLiteDevice->SpareAreaAddress + FTW_BLOCK_SIZE, &BootFvb);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+ //
+ // Read data from current boot block
+ //
+ BootLba = 0;
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwLiteDevice->SizeOfSpareBlock;
+ Status = BootFvb->Read (
+ BootFvb,
+ BootLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+
+ } else {
+ //
+ // Read data from spare block
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Read (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Set TopSwap bit
+ //
+ Status = SetSwapState (FtwLiteDevice, TRUE);
+ DEBUG ((EFI_D_ERROR, "FtwLite: Set Swap State - %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // Erase boot block. After setting TopSwap bit, it's spare block now!
+ //
+ Status = FtwEraseSpareBlock (FtwLiteDevice);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Write memory buffer to currenet spare block
+ //
+ Ptr = Buffer;
+ for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
+ Count = FtwLiteDevice->SizeOfSpareBlock;
+ Status = FtwLiteDevice->FtwBackupFvb->Write (
+ FtwLiteDevice->FtwBackupFvb,
+ FtwLiteDevice->FtwSpareLba + Index,
+ 0,
+ &Count,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write boot block - %r\n", Status));
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+
+ FreePool (Buffer);
+
+ //
+ // Clear TopSwap bit
+ //
+ Status = SetSwapState (FtwLiteDevice, FALSE);
+ DEBUG ((EFI_D_ERROR, "FtwLite: Clear Swap State - %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c
new file mode 100644
index 0000000..d31883b
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c
@@ -0,0 +1,143 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ IpfFtwMisc.c
+
+Abstract:
+
+ Ipf platform related code to support FtwLite..
+
+Revision History
+
+--*/
+
+
+#include <FtwLite.h>
+
+//
+// MACROs for boot block update
+//
+#define BOOT_BLOCK_BASE
+
+STATIC
+EFI_STATUS
+GetSwapState (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ OUT BOOLEAN *SwapState
+ )
+/*++
+
+Routine Description:
+
+ Get swap state
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ SwapState - Swap state
+
+Returns:
+
+ EFI_SUCCESS - State successfully got
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+SetSwapState (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ IN BOOLEAN TopSwap
+ )
+/*++
+
+Routine Description:
+ Set swap state.
+
+Arguments:
+ FtwLiteDevice - Indicates a pointer to the calling context.
+ TopSwap - New swap state
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+
+Note:
+ the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
+ software will not be able to clear the Top-Swap bit until the system is
+ rebooted without GNT[A]# being pulled down.
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsBootBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ Check whether the block is a boot block.
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ FvBlock - Fvb protocol instance
+ Lba - Lba value
+
+Returns:
+
+ Is a boot block or not
+
+--*/
+{
+ //
+ // IPF doesn't support safe bootblock update
+ // so treat bootblock as normal block
+ //
+ return FALSE;
+}
+
+EFI_STATUS
+FlushSpareBlockToBootBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwLiteDevice->FtwSpareLba.
+ Boot block is accessed by BootFvb protocol interface. LBA is 0.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+
+Returns:
+ EFI_SUCCESS - Spare block content is copied to boot block
+ EFI_INVALID_PARAMETER - Input parameter error
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+Notes:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c
new file mode 100644
index 0000000..d8e3a03
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c
@@ -0,0 +1,140 @@
+
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ x64FtwMisc.c
+
+Abstract:
+
+ X64 platform related code to support FtwLite..
+
+Revision History
+
+--*/
+
+
+#include <FtwLite.h>
+
+//
+// MACROs for boot block update
+//
+#define BOOT_BLOCK_BASE
+
+// STATIC
+EFI_STATUS
+GetSwapState (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ OUT BOOLEAN *SwapState
+ )
+/*++
+
+Routine Description:
+
+ Get swap state
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ SwapState - Swap state
+
+Returns:
+
+ EFI_SUCCESS - State successfully got
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+// STATIC
+EFI_STATUS
+SetSwapState (
+ IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ IN BOOLEAN TopSwap
+ )
+/*++
+
+Routine Description:
+ Set swap state.
+
+Arguments:
+ FtwLiteDevice - Indicates a pointer to the calling context.
+ TopSwap - New swap state
+
+Returns:
+ EFI_SUCCESS - The function completed successfully
+
+Note:
+ the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
+ software will not be able to clear the Top-Swap bit until the system is
+ rebooted without GNT[A]# being pulled down.
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsBootBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice,
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
+ EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ Check whether the block is a boot block.
+
+Arguments:
+
+ FtwLiteDevice - Calling context
+ FvBlock - Fvb protocol instance
+ Lba - Lba value
+
+Returns:
+
+ Is a boot block or not
+
+--*/
+{
+ return FALSE;
+}
+
+EFI_STATUS
+FlushSpareBlockToBootBlock (
+ EFI_FTW_LITE_DEVICE *FtwLiteDevice
+ )
+/*++
+
+Routine Description:
+ Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
+ Spare block is accessed by FTW backup FVB protocol interface. LBA is
+ FtwLiteDevice->FtwSpareLba.
+ Boot block is accessed by BootFvb protocol interface. LBA is 0.
+
+Arguments:
+ FtwLiteDevice - The private data of FTW_LITE driver
+
+Returns:
+ EFI_SUCCESS - Spare block content is copied to boot block
+ EFI_INVALID_PARAMETER - Input parameter error
+ EFI_OUT_OF_RESOURCES - Allocate memory error
+ EFI_ABORTED - The function could not complete successfully
+
+Notes:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c
new file mode 100644
index 0000000..de9ba83
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c
@@ -0,0 +1,230 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Crc32SectionExtract.c
+
+Abstract:
+
+ Implements GUIDed section extraction protocol interface with
+ a specific GUID: CRC32.
+
+ Please refer to the Framewokr Firmware Volume Specification 0.9.
+
+--*/
+
+
+#include <GuidedSection.h>
+#include <Crc32SectionExtract.h>
+
+EFI_STATUS
+EFIAPI
+InitializeCrc32GuidedSectionExtractionProtocol (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Entry point of the CRC32 GUIDed section extraction protocol.
+ Creates and initializes an instance of the GUIDed section
+ extraction protocol with CRC32 GUID.
+
+Arguments:
+
+ ImageHandle EFI_HANDLE: A handle for the image that is initializing
+ this driver
+ SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table
+
+Returns:
+
+ EFI_SUCCESS: Driver initialized successfully
+ EFI_LOAD_ERROR: Failed to Initialize or has been loaded
+ EFI_OUT_OF_RESOURCES: Could not allocate needed resources
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *Crc32GuidedSep;
+ EFI_HANDLE Handle;
+
+ //
+ // Call all constructors per produced protocols
+ //
+ Status = GuidedSectionExtractionProtocolConstructor (
+ &Crc32GuidedSep,
+ (EFI_EXTRACT_GUIDED_SECTION) Crc32ExtractSection
+ );
+ if (EFI_ERROR (Status)) {
+ if (Crc32GuidedSep != NULL) {
+ FreePool (Crc32GuidedSep);
+ }
+
+ return Status;
+ }
+ //
+ // Pass in a NULL to install to a new handle
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiCrc32GuidedSectionExtractionProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ Crc32GuidedSep
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Crc32GuidedSep);
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+UINT32
+EFIAPI
+GetSectionLength (
+ IN EFI_COMMON_SECTION_HEADER *CommonHeader
+ )
+/*++
+
+ Routine Description:
+ Get a length of section.
+
+ Parameters:
+ CommonHeader - Pointer to the common section header.
+
+ Return Value:
+ The length of the section, including the section header.
+
+--*/
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: CommonHeader - add argument and description to function comment
+{
+ UINT32 Size;
+
+ Size = *(UINT32 *) CommonHeader->Size & 0x00FFFFFF;
+
+ return Size;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+Crc32ExtractSection (
+ IN EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
+ IN VOID *InputSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+ Routine Description:
+ This function reads and extracts contents of a section from an
+ encapsulating section.
+
+ Parameters:
+ This - Indicates the calling context.
+ InputSection - Buffer containing the input GUIDed section
+ to be processed.
+ OutputBuffer - *OutputBuffer is allocated from boot services
+ pool memory and containing the new section
+ stream. The caller is responsible for freeing
+ this buffer.
+ AuthenticationStatus - Pointer to a caller allocated UINT32 that
+ indicates the authentication status of the
+ output buffer
+
+ Return Value:
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES
+ EFI_INVALID_PARAMETER
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: This - add argument and description to function comment
+// TODO: InputSection - add argument and description to function comment
+// TODO: OutputBuffer - add argument and description to function comment
+// TODO: OutputSize - add argument and description to function comment
+// TODO: AuthenticationStatus - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ CRC32_SECTION_HEADER *Crc32SectionHeader;
+ EFI_GUID_DEFINED_SECTION *GuidedSectionHeader;
+ UINT8 *Image;
+ UINT32 Crc32Checksum;
+ VOID *DummyInterface;
+
+ if (OutputBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *OutputBuffer = NULL;
+
+ //
+ // Points to the section header
+ //
+ Crc32SectionHeader = (CRC32_SECTION_HEADER *) InputSection;
+ GuidedSectionHeader = (EFI_GUID_DEFINED_SECTION *) InputSection;
+
+ //
+ // Check if the GUID is a CRC32 section GUID
+ //
+ if (!CompareGuid (
+ &(GuidedSectionHeader->SectionDefinitionGuid),
+ &gEfiCrc32GuidedSectionExtractionProtocolGuid
+ )) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Image = (UINT8 *) InputSection + (UINT32) (GuidedSectionHeader->DataOffset);
+ *OutputSize = GetSectionLength ((EFI_COMMON_SECTION_HEADER *) InputSection) - (UINT32) GuidedSectionHeader->DataOffset;
+
+ *OutputBuffer = AllocatePool (*OutputSize);
+ if (*OutputBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Implictly CRC32 GUIDed section should have STATUS_VALID bit set
+ //
+ ASSERT (GuidedSectionHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID);
+ *AuthenticationStatus = EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_AGGREGATE_AUTH_STATUS_IMAGE_SIGNED;
+
+ //
+ // Check whether there exists EFI_SECURITY_POLICY_PROTOCOL_GUID.
+ //
+ Status = gBS->LocateProtocol (&gEfiSecurityPolicyProtocolGuid, NULL, &DummyInterface);
+ if (!EFI_ERROR (Status)) {
+ *AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_PLATFORM_OVERRIDE | EFI_AGGREGATE_AUTH_STATUS_PLATFORM_OVERRIDE;
+ } else {
+ //
+ // Calculate CRC32 Checksum of Image
+ //
+ gBS->CalculateCrc32 (Image, *OutputSize, &Crc32Checksum);
+ if (Crc32Checksum != Crc32SectionHeader->CRC32Checksum) {
+ *AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_TEST_FAILED | EFI_AGGREGATE_AUTH_STATUS_TEST_FAILED;
+ }
+ }
+
+ CopyMem (*OutputBuffer, Image, *OutputSize);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs
new file mode 100644
index 0000000..d42975a
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs
@@ -0,0 +1,26 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Crc32SectionExtraction.dxs
+
+Abstract:
+
+ Dependency expression file.
+
+--*/
+#include "DxeDepex.h"
+
+DEPENDENCY_START
+ EFI_RUNTIME_ARCH_PROTOCOL_GUID
+DEPENDENCY_END
+
diff --git a/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h
new file mode 100644
index 0000000..37af840
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h
@@ -0,0 +1,112 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Crc32SectionExtract.h
+
+Abstract:
+
+ Header file for Crc32SectionExtract.c
+ Please refer to the Framewokr Firmware Volume Specification 0.9.
+
+--*/
+
+#ifndef _CRC32_GUIDED_SECTION_EXTRACTION_H
+#define _CRC32_GUIDED_SECTION_EXTRACTION_H
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/SecurityPolicy.h>
+#include <Protocol/GuidedSectionExtaction.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+typedef struct {
+ EFI_GUID_DEFINED_SECTION GuidedSectionHeader;
+ UINT32 CRC32Checksum;
+} CRC32_SECTION_HEADER;
+
+//
+// Function prototype declarations
+//
+STATIC
+EFI_STATUS
+EFIAPI
+Crc32ExtractSection (
+ IN EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This,
+ IN VOID *InputSection,
+ OUT VOID **OutputBuffer,
+ OUT UINTN *OutputSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ InputSection - TODO: add argument description
+ OutputBuffer - TODO: add argument description
+ OutputSize - TODO: add argument description
+ AuthenticationStatus - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+InitializeCrc32GuidedSectionExtractionProtocol (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Entry point of the CRC32 GUIDed section extraction protocol.
+ Creates and initializes an instance of the GUIDed section
+ extraction protocol with CRC32 GUID.
+
+Arguments:
+
+ ImageHandle EFI_HANDLE: A handle for the image that is initializing
+ this driver
+ SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table
+
+Returns:
+
+ EFI_SUCCESS: Driver initialized successfully
+ EFI_LOAD_ERROR: Failed to Initialize or has been loaded
+ EFI_OUT_OF_RESOURCES: Could not allocate needed resources
+
+--*/
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.inf b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.inf
new file mode 100644
index 0000000..69becb8
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.inf
@@ -0,0 +1,88 @@
+#/** @file
+# Component description file for Crc32SectionExtract module.
+#
+# This driver implements CRC32 GUIDed section extraction protocol interface.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Crc32SectionExtract
+ FILE_GUID = 51C9F40C-5243-4473-B265-B3C8FFAFF9FA
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeCrc32GuidedSectionExtractionProtocol
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ Crc32SectionExtract.dxs
+ GuidedSection.h
+ GuidedSection.c
+ Crc32SectionExtract.h
+ Crc32SectionExtract.c
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ DebugLib
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gEfiSecurityPolicyProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+ gEfiCrc32GuidedSectionExtractionProtocolGuid # PROTOCOL ALWAYS_PRODUCED
diff --git a/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa
new file mode 100644
index 0000000..a4ab182
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>Crc32SectionExtract</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>51C9F40C-5243-4473-B265-B3C8FFAFF9FA</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for Crc32SectionExtract module.</Abstract>
+ <Description>This driver implements CRC32 GUIDed section extraction protocol interface.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>Crc32SectionExtract</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>Crc32SectionExtract.c</Filename>
+ <Filename>Crc32SectionExtract.h</Filename>
+ <Filename>GuidedSection.c</Filename>
+ <Filename>GuidedSection.h</Filename>
+ <Filename>Crc32SectionExtract.dxs</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="1E73767F-8F52-4603-AEB4-F29B510B6766"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="SOMETIMES_CONSUMED">
+ <ProtocolCName>gEfiSecurityPolicyProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_PRODUCED">
+ <ProtocolCName>gEfiCrc32GuidedSectionExtractionProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>InitializeCrc32GuidedSectionExtractionProtocol</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c
new file mode 100644
index 0000000..87605cc
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c
@@ -0,0 +1,61 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GuidedSection.c
+
+Abstract:
+
+ GUIDed section extraction protocol implementation.
+ This contains the common constructor of GUIDed section
+ extraction protocol. GUID specific implementation of each
+ GUIDed section extraction protocol can be found in other
+ files under the same directory.
+
+--*/
+
+#include "GuidedSection.h"
+
+EFI_STATUS
+GuidedSectionExtractionProtocolConstructor (
+ OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL **GuidedSep,
+ IN EFI_EXTRACT_GUIDED_SECTION ExtractSection
+ )
+/*++
+
+Routine Description:
+
+ Constructor for the GUIDed section extraction protocol. Initializes
+ instance data.
+
+Arguments:
+
+ This Instance to construct
+
+Returns:
+
+ EFI_SUCCESS: Instance initialized.
+
+--*/
+// TODO: GuidedSep - add argument and description to function comment
+// TODO: ExtractSection - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+{
+ *GuidedSep = AllocatePool (sizeof (EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL));
+ if (*GuidedSep == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (*GuidedSep)->ExtractSection = ExtractSection;
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h
new file mode 100644
index 0000000..d6613b0
--- /dev/null
+++ b/MdeModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GuidedSection.h
+
+Abstract:
+
+ Header file for GuidedSection.c
+ Please refer to the Framewokr Firmware Volume Specification 0.9.
+
+--*/
+
+#ifndef _GUIDED_SECTION_EXTRACTION_H
+#define _GUIDED_SECTION_EXTRACTION_H
+
+#include "Crc32SectionExtract.h"
+
+//
+// Function prototype declarations
+//
+EFI_STATUS
+GuidedSectionExtractionProtocolConstructor (
+ OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL **GuidedSep,
+ IN EFI_EXTRACT_GUIDED_SECTION ExtractSection
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ GuidedSep - TODO: add argument description
+ ExtractSection - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif