summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Universal/FirmwareVolume
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
commit878ddf1fc3540a715f63594ed22b6929e881afb4 (patch)
treec56c44dac138137b510e1fba7c3efe5e4d84bea2 /EdkModulePkg/Universal/FirmwareVolume
downloadedk2-878ddf1fc3540a715f63594ed22b6929e881afb4.zip
edk2-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.gz
edk2-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.bz2
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Universal/FirmwareVolume')
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c951
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs28
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h675
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd44
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa90
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c530
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c567
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c399
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c143
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c140
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c234
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs28
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h65
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd40
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa61
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c75
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h53
-rw-r--r--EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml47
19 files changed, 4217 insertions, 0 deletions
diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c
new file mode 100644
index 0000000..0d20e88
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c
@@ -0,0 +1,951 @@
+/*++
+
+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.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)) {
+ gBS->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)) {
+ gBS->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) {
+ gBS->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)) {
+ gBS->FreePool (MyBuffer);
+ gBS->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)) {
+ gBS->FreePool (MyBuffer);
+ gBS->FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += MyLength;
+ }
+ //
+ // Free MyBuffer
+ //
+ gBS->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)) {
+ gBS->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)) {
+ gBS->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)) {
+ gBS->FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += MyLength;
+ }
+ //
+ // All success.
+ //
+ gBS->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_FLASH_MAP_ENTRY_DATA *FlashMapEntry;
+ EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
+ UINT32 LbaIndex;
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ //
+ // 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->SpareAreaLength = 0;
+ FtwLiteDevice->WorkSpaceLength = 0;
+
+ GuidHob.Raw = GetHobList ();
+ while (NULL != (GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw))) {
+ FlashMapEntry = (EFI_FLASH_MAP_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid);
+ //
+ // Get the FTW work space Flash Map SUB area
+ //
+ if ((FlashMapEntry->AreaType == EFI_FLASH_AREA_FTW_STATE) && (FlashMapEntry->NumEntries == 1)) {
+ FtwLiteDevice->WorkSpaceAddress = FlashMapEntry->Entries[0].Base;
+ FtwLiteDevice->WorkSpaceLength = (UINTN) FlashMapEntry->Entries[0].Length;
+ }
+ //
+ // Get the FTW backup SUB area
+ //
+ if ((FlashMapEntry->AreaType == EFI_FLASH_AREA_FTW_BACKUP) && (FlashMapEntry->NumEntries == 1)) {
+ FtwLiteDevice->SpareAreaAddress = FlashMapEntry->Entries[0].Base;
+ FtwLiteDevice->SpareAreaLength = (UINTN) FlashMapEntry->Entries[0].Length;
+ }
+
+ GuidHob.Raw = GET_NEXT_HOB (GuidHob);
+ }
+
+ 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->FvBlockMap[0];
+ while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->BlockLength == 0))) {
+ for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
+ if (FtwLiteDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->BlockLength * LbaIndex)) {
+ FtwLiteDevice->FtwWorkSpaceLba = LbaIndex - 1;
+ //
+ // Get the Work space size and Base(Offset)
+ //
+ FtwLiteDevice->FtwWorkSpaceSize = FtwLiteDevice->WorkSpaceLength;
+ FtwLiteDevice->FtwWorkSpaceBase = (UINTN) (FtwLiteDevice->WorkSpaceAddress - (BaseAddress + FvbMapEntry->BlockLength * (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->FvBlockMap[0];
+ while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->BlockLength == 0))) {
+ for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
+ if (FtwLiteDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->BlockLength * LbaIndex)) {
+ //
+ // Get the NumberOfSpareBlock and SizeOfSpareBlock
+ //
+ FtwLiteDevice->FtwSpareLba = LbaIndex - 1;
+ FtwLiteDevice->SizeOfSpareBlock = FvbMapEntry->BlockLength;
+ 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/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs
new file mode 100644
index 0000000..f2a6221
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs
@@ -0,0 +1,28 @@
+/*++
+
+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 <AutoGen.h>
+#include <DxeDepex.h>
+
+
+DEPENDENCY_START
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID AND EFI_ALTERNATE_FV_BLOCK_GUID
+DEPENDENCY_END
diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h
new file mode 100644
index 0000000..8754827
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h
@@ -0,0 +1,675 @@
+/*++
+
+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_
+
+#include <Common/FlashMap.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/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd
new file mode 100644
index 0000000..a56e9de
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>FtwLite</BaseName>
+ <Guid>4C862FC6-0E54-4e36-8C8F-FF6F3167951F</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>
+ <Created>2006-03-22 14:11</Created>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>BaseLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>DxeHobLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+ <BuildOptions ToolChain="MSFT">
+ <ImageEntryPoint>_ModuleEntryPoint</ImageEntryPoint>
+ </BuildOptions>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa
new file mode 100644
index 0000000..06eb47c
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>FtwLite</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>4C862FC6-0E54-4e36-8C8F-FF6F3167951F</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for DiskIo module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>0</Specification>
+ <Created>2006-03-22 14:11</Created>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>FtwLite.c</Filename>
+ <Filename>FtwMisc.c</Filename>
+ <Filename>FtwWorkSpace.c</Filename>
+ <Filename>FtwLite.dxs</Filename>
+ <Arch ArchType="IA32">
+ <Filename>ia32\Ia32FtwMisc.c</Filename>
+ </Arch>
+ <Arch ArchType="X64">
+ <Filename>x64\x64FtwMisc.c</Filename>
+ </Arch>
+ <Arch ArchType="IPF">
+ <Filename>Ipf\IpfFtwMisc.c</Filename>
+ </Arch>
+ <Arch ArchType="EBC">
+ <Filename>ia32\Ia32FtwMisc.c</Filename>
+ </Arch>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="ALWAYS_PRODUCED">FaultTolerantWriteLite</Protocol>
+ <Protocol Usage="SOMETIMES_CONSUMED">PciRootBridgeIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">FirmwareVolumeBlock</Protocol>
+ </Protocols>
+ <Hobs>
+ <Hob Usage="ALWAYS_CONSUMED" HobType="GUID_EXTENSION">
+ <Name>FlashMapHob</Name>
+ <C_Name>gEfiFlashMapHobGuid</C_Name>
+ <Guid>0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59</Guid>
+ </Hob>
+ </Hobs>
+ <Guids>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>FlashMapHob</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>SystemNvDataFv</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>InitializeFtwLite</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c
new file mode 100644
index 0000000..025ec33
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c
@@ -0,0 +1,530 @@
+/*++
+
+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:
+
+ 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;
+ }
+ }
+
+ gBS->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)) {
+ gBS->FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Erase the target block
+ //
+ Status = FtwEraseBlock (FtwLiteDevice, FvBlock, Lba);
+ if (EFI_ERROR (Status)) {
+ gBS->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));
+ gBS->FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+
+ gBS->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)) {
+ gBS->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)) {
+ gBS->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)) {
+ gBS->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));
+ gBS->FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+ //
+ // Since the memory buffer will not be used, free memory Buffer.
+ //
+ gBS->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/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c
new file mode 100644
index 0000000..820655c
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c
@@ -0,0 +1,567 @@
+/*++
+
+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:
+
+ 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 |= 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;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ TempBufferSize,
+ (VOID **) &TempBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (TempBuffer, TempBufferSize);
+
+ 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)) {
+ gBS->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) {
+ gBS->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)) {
+ gBS->FreePool (TempBuffer);
+ gBS->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)) {
+ gBS->FreePool (TempBuffer);
+ gBS->FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+ //
+ // Free TempBuffer
+ //
+ gBS->FreePool (TempBuffer);
+
+ //
+ // Write the spare block to working block
+ //
+ Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);
+ if (EFI_ERROR (Status)) {
+ gBS->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)) {
+ gBS->FreePool (SpareBuffer);
+ return EFI_ABORTED;
+ }
+
+ Ptr += Length;
+ }
+
+ gBS->FreePool (SpareBuffer);
+
+ DEBUG ((EFI_D_FTW_LITE, "FtwLite: reclaim work space success\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c
new file mode 100644
index 0000000..80258f4
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c
@@ -0,0 +1,399 @@
+/*++
+
+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:
+
+ 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 (
+ if (TopSwap) {
+ DEBUG ((EFI_D_ERROR, "SAR: Set top swap\n"));
+ } else {
+ DEBUG ((EFI_D_ERROR, "SAR: Clear top swap\n"));
+ }
+ );
+
+ 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));
+ gBS->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)) {
+ gBS->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)) {
+ gBS->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)) {
+ gBS->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)) {
+ gBS->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));
+ gBS->FreePool (Buffer);
+ return Status;
+ }
+
+ Ptr += Count;
+ }
+
+ gBS->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/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c
new file mode 100644
index 0000000..d31883b
--- /dev/null
+++ b/EdkModulePkg/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/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml
new file mode 100644
index 0000000..0883c25
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="FtwLite"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Universal\FirmwareVolume\FaultTolerantWriteLite\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="FtwLite">
+ <GenBuild baseName="FtwLite" mbdFilename="${MODULE_DIR}\FtwLite.mbd" msaFilename="${MODULE_DIR}\FtwLite.msa"/>
+ </target>
+ <target depends="FtwLite_clean" name="clean"/>
+ <target depends="FtwLite_cleanall" name="cleanall"/>
+ <target name="FtwLite_clean">
+ <OutputDirSetup baseName="FtwLite" mbdFilename="${MODULE_DIR}\FtwLite.mbd" msaFilename="${MODULE_DIR}\FtwLite.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\FtwLite_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\FtwLite_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="FtwLite_cleanall">
+ <OutputDirSetup baseName="FtwLite" mbdFilename="${MODULE_DIR}\FtwLite.mbd" msaFilename="${MODULE_DIR}\FtwLite.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\FtwLite_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\FtwLite_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**FtwLite*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c
new file mode 100644
index 0000000..067bfcf
--- /dev/null
+++ b/EdkModulePkg/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/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c
new file mode 100644
index 0000000..dc7ed07
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c
@@ -0,0 +1,234 @@
+/*++
+
+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:
+
+ Crc32SectionExtract.c
+
+Abstract:
+
+ Implements GUIDed section extraction protocol interface with
+ a specific GUID: CRC32.
+
+ Please refer to the Tiano File Image Format Specification,
+ FV spec 0.3.6
+
+--*/
+
+
+#include <GuidedSection.h>
+#include <Crc32SectionExtract.h>
+
+EFI_STATUS
+InitializeCrc32GuidedSectionExtractionProtocol (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+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) {
+ gBS->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)) {
+ gBS->FreePool (Crc32GuidedSep);
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+UINT32
+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
+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;
+
+ Status = gBS->AllocatePool (EfiBootServicesData, *OutputSize, OutputBuffer);
+ if (EFI_ERROR (Status)) {
+ 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/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs
new file mode 100644
index 0000000..033ff94
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs
@@ -0,0 +1,28 @@
+/*++
+
+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 <AutoGen.h>
+#include "DxeDepex.h"
+
+DEPENDENCY_START
+ EFI_RUNTIME_ARCH_PROTOCOL_GUID
+DEPENDENCY_END
+
diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h
new file mode 100644
index 0000000..8e32d6d
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h
@@ -0,0 +1,65 @@
+/*++
+
+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:
+
+ Crc32SectionExtract.h
+
+Abstract:
+
+ Header file for Crc32SectionExtract.c
+ Please refer to Tiano File Image Format specification
+ FV spec 0.3.6
+
+--*/
+
+#ifndef _CRC32_GUIDED_SECTION_EXTRACTION_H
+#define _CRC32_GUIDED_SECTION_EXTRACTION_H
+
+typedef struct {
+ EFI_GUID_DEFINED_SECTION GuidedSectionHeader;
+ UINT32 CRC32Checksum;
+} CRC32_SECTION_HEADER;
+
+//
+// Function prototype declarations
+//
+STATIC
+EFI_STATUS
+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
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd
new file mode 100644
index 0000000..67ea3cd
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>Crc32SectionExtract</BaseName>
+ <Guid>51C9F40C-5243-4473-B265-B3C8FFAFF9FA</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:19</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa
new file mode 100644
index 0000000..da82d56
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>Crc32SectionExtract</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>51C9F40C-5243-4473-B265-B3C8FFAFF9FA</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for DiskIo module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, 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>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:19</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>Crc32SectionExtract.c</Filename>
+ <Filename>Crc32SectionExtract.h</Filename>
+ <Filename>GuidedSection.c</Filename>
+ <Filename>GuidedSection.h</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">SecurityPolicy</Protocol>
+ <Protocol Usage="ALWAYS_PRODUCED">Crc32GuidedSectionExtraction</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>InitializeCrc32GuidedSectionExtractionProtocol</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c
new file mode 100644
index 0000000..3c3f22f
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c
@@ -0,0 +1,75 @@
+/*++
+
+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:
+
+ 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.
+
+ Please refer to the Tiano File Image Format Specification,
+ FV spec 0.3.6
+
+ Acronyms used Meaning
+
+
+--*/
+
+
+#include "Common/FirmwareFileSystem.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
+{
+ EFI_STATUS Status;
+
+ *GuidedSep = NULL;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL),
+ (VOID **) GuidedSep
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (*GuidedSep)->ExtractSection = ExtractSection;
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h
new file mode 100644
index 0000000..1399edf
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h
@@ -0,0 +1,53 @@
+/*++
+
+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:
+
+ GuidedSection.h
+
+Abstract:
+
+ Header file for GuidedSection.c
+ Please refer to Tiano File Image Format specification
+ FV spec 0.3.6
+
+--*/
+
+#ifndef _GUIDED_SECTION_EXTRACTION_H
+#define _GUIDED_SECTION_EXTRACTION_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
diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml
new file mode 100644
index 0000000..7582701
--- /dev/null
+++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="Crc32SectionExtract"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Universal\FirmwareVolume\GuidedSectionExtraction\Crc32SectionExtract\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="Crc32SectionExtract">
+ <GenBuild baseName="Crc32SectionExtract" mbdFilename="${MODULE_DIR}\Crc32SectionExtract.mbd" msaFilename="${MODULE_DIR}\Crc32SectionExtract.msa"/>
+ </target>
+ <target depends="Crc32SectionExtract_clean" name="clean"/>
+ <target depends="Crc32SectionExtract_cleanall" name="cleanall"/>
+ <target name="Crc32SectionExtract_clean">
+ <OutputDirSetup baseName="Crc32SectionExtract" mbdFilename="${MODULE_DIR}\Crc32SectionExtract.mbd" msaFilename="${MODULE_DIR}\Crc32SectionExtract.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\Crc32SectionExtract_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\Crc32SectionExtract_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="Crc32SectionExtract_cleanall">
+ <OutputDirSetup baseName="Crc32SectionExtract" mbdFilename="${MODULE_DIR}\Crc32SectionExtract.mbd" msaFilename="${MODULE_DIR}\Crc32SectionExtract.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\Crc32SectionExtract_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\Crc32SectionExtract_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**Crc32SectionExtract*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file