From 878ddf1fc3540a715f63594ed22b6929e881afb4 Mon Sep 17 00:00:00 2001 From: bbahnsen Date: Fri, 21 Apr 2006 22:54:32 +0000 Subject: Initial import. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524 --- .../FaultTolerantWriteLite/Dxe/FtwLite.c | 951 +++++++++++++++++++++ .../FaultTolerantWriteLite/Dxe/FtwLite.dxs | 28 + .../FaultTolerantWriteLite/Dxe/FtwLite.h | 675 +++++++++++++++ .../FaultTolerantWriteLite/Dxe/FtwLite.mbd | 44 + .../FaultTolerantWriteLite/Dxe/FtwLite.msa | 90 ++ .../FaultTolerantWriteLite/Dxe/FtwMisc.c | 530 ++++++++++++ .../FaultTolerantWriteLite/Dxe/FtwWorkSpace.c | 567 ++++++++++++ .../FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c | 399 +++++++++ .../FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c | 143 ++++ .../FaultTolerantWriteLite/Dxe/build.xml | 47 + .../FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c | 140 +++ .../Crc32SectionExtract/Dxe/Crc32SectionExtract.c | 234 +++++ .../Dxe/Crc32SectionExtract.dxs | 28 + .../Crc32SectionExtract/Dxe/Crc32SectionExtract.h | 65 ++ .../Dxe/Crc32SectionExtract.mbd | 40 + .../Dxe/Crc32SectionExtract.msa | 61 ++ .../Crc32SectionExtract/Dxe/GuidedSection.c | 75 ++ .../Crc32SectionExtract/Dxe/GuidedSection.h | 53 ++ .../Crc32SectionExtract/Dxe/build.xml | 47 + 19 files changed, 4217 insertions(+) create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml create mode 100644 EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c create mode 100644 EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c create mode 100644 EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs create mode 100644 EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h create mode 100644 EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd create mode 100644 EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa create mode 100644 EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c create mode 100644 EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h create mode 100644 EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml (limited to 'EdkModulePkg/Universal/FirmwareVolume') diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c new file mode 100644 index 0000000000..0d20e88058 --- /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 + +// +// 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 0000000000..f2a6221b5d --- /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 +#include + + +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 0000000000..8754827e2d --- /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 +#include + +#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 0000000000..a56e9defc0 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd @@ -0,0 +1,44 @@ + + + + + FtwLite + 4C862FC6-0E54-4e36-8C8F-FF6F3167951F + 0 + FIX ME! + Copyright (c) 2004-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. + + 2006-03-22 14:11 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + DxeHobLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa new file mode 100644 index 0000000000..06eb47c2a2 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa @@ -0,0 +1,90 @@ + + + + + FtwLite + DXE_DRIVER + BS_DRIVER + 4C862FC6-0E54-4e36-8C8F-FF6F3167951F + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-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. + + 0 + 2006-03-22 14:11 + + + DebugLib + UefiDriverEntryPoint + UefiLib + BaseLib + HobLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + FtwLite.c + FtwMisc.c + FtwWorkSpace.c + FtwLite.dxs + + ia32\Ia32FtwMisc.c + + + x64\x64FtwMisc.c + + + Ipf\IpfFtwMisc.c + + + ia32\Ia32FtwMisc.c + + + + MdePkg + EdkModulePkg + + + FaultTolerantWriteLite + PciRootBridgeIo + FirmwareVolumeBlock + + + + FlashMapHob + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + + + FlashMapHob + + + SystemNvDataFv + + + + + InitializeFtwLite + + + diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c new file mode 100644 index 0000000000..025ec33f7b --- /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 + +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 0000000000..820655c76b --- /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 + +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 0000000000..80258f4cc3 --- /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 + +// +// 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 0000000000..d31883b2ee --- /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 + +// +// 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 0000000000..0883c25cba --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 0000000000..067bfcf179 --- /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 + +// +// 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 0000000000..dc7ed07baa --- /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 +#include + +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 0000000000..033ff94ac3 --- /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 +#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 0000000000..8e32d6d7bb --- /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 0000000000..67ea3cd4b9 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd @@ -0,0 +1,40 @@ + + + + + Crc32SectionExtract + 51C9F40C-5243-4473-B265-B3C8FFAFF9FA + 0 + FIX ME! + Copyright (c) 2004-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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + + 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 0000000000..da82d561a0 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa @@ -0,0 +1,61 @@ + + + + + Crc32SectionExtract + DXE_DRIVER + BS_DRIVER + 51C9F40C-5243-4473-B265-B3C8FFAFF9FA + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + + + Crc32SectionExtract.c + Crc32SectionExtract.h + GuidedSection.c + GuidedSection.h + + + MdePkg + EdkModulePkg + + + SecurityPolicy + Crc32GuidedSectionExtraction + + + + InitializeCrc32GuidedSectionExtractionProtocol + + + 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 0000000000..3c3f22f760 --- /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 0000000000..1399edf4f6 --- /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 0000000000..7582701719 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3