+++ /dev/null
-/** @file\r
-\r
- Internal generic functions to operate flash block.\r
-\r
-Copyright (c) 2006 - 2008, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-**/\r
-\r
-#include "FtwLite.h"\r
-\r
-/**\r
-\r
- Check whether a flash buffer is erased.\r
-\r
-\r
- @param Polarity All 1 or all 0\r
- @param Buffer Buffer to check\r
- @param BufferSize Size of the buffer\r
-\r
- @return A BOOLEAN value indicating erased or not.\r
-\r
-**/\r
-BOOLEAN\r
-IsErasedFlashBuffer (\r
- IN BOOLEAN Polarity,\r
- IN UINT8 *Buffer,\r
- IN UINTN BufferSize\r
- )\r
-{\r
- UINT8 ErasedValue;\r
- UINT8 *Ptr;\r
-\r
- if (Polarity) {\r
- ErasedValue = 0xFF;\r
- } else {\r
- ErasedValue = 0;\r
- }\r
-\r
- Ptr = Buffer;\r
- while ((BufferSize--) != 0) {\r
- if (*Ptr++ != ErasedValue) {\r
- return FALSE;\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-/**\r
- To erase the block with the spare block size.\r
-\r
-\r
- @param FtwLiteDevice Calling context\r
- @param FvBlock FVB Protocol interface\r
- @param Lba Lba of the firmware block\r
-\r
- @retval EFI_SUCCESS Block LBA is Erased successfully\r
- @retval Others Error occurs\r
-\r
-**/\r
-EFI_STATUS\r
-FtwEraseBlock (\r
- IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,\r
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,\r
- EFI_LBA Lba\r
- )\r
-{\r
- return FvBlock->EraseBlocks (\r
- FvBlock,\r
- Lba,\r
- FtwLiteDevice->NumberOfSpareBlock,\r
- EFI_LBA_LIST_TERMINATOR\r
- );\r
-}\r
-\r
-/**\r
-\r
- Erase spare block.\r
-\r
-\r
- @param FtwLiteDevice Calling context\r
-\r
- @retval EFI_SUCCESS The erase request was successfully\r
- completed.\r
- \r
- @retval EFI_ACCESS_DENIED The firmware volume is in the\r
- WriteDisabled state.\r
- @retval EFI_DEVICE_ERROR The block device is not functioning\r
- correctly and could not be written.\r
- The firmware device may have been\r
- partially erased.\r
- @retval EFI_INVALID_PARAMETER One or more of the LBAs listed\r
- in the variable argument list do\r
- not exist in the firmware volume. \r
-\r
-\r
-**/\r
-EFI_STATUS\r
-FtwEraseSpareBlock (\r
- IN EFI_FTW_LITE_DEVICE *FtwLiteDevice\r
- )\r
-{\r
- return FtwLiteDevice->FtwBackupFvb->EraseBlocks (\r
- FtwLiteDevice->FtwBackupFvb,\r
- FtwLiteDevice->FtwSpareLba,\r
- FtwLiteDevice->NumberOfSpareBlock,\r
- EFI_LBA_LIST_TERMINATOR\r
- );\r
-}\r
-\r
-/**\r
- Retrive the proper FVB protocol interface by HANDLE.\r
-\r
-\r
- @param FvBlockHandle The handle of FVB protocol that provides services for\r
- reading, writing, and erasing the target block.\r
- @param FvBlock The interface of FVB protocol\r
-\r
- @retval EFI_SUCCESS The function completed successfully\r
- @retval EFI_ABORTED The function could not complete successfully\r
-\r
-**/\r
-EFI_STATUS\r
-FtwGetFvbByHandle (\r
- IN EFI_HANDLE FvBlockHandle,\r
- OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock\r
- )\r
-{\r
- //\r
- // To get the FVB protocol interface on the handle\r
- //\r
- return gBS->HandleProtocol (\r
- FvBlockHandle,\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- (VOID **) FvBlock\r
- );\r
-}\r
-\r
-/**\r
-\r
- Get firmware block by address.\r
-\r
-\r
- @param Address Address specified the block\r
- @param FvBlock The block caller wanted\r
-\r
- @retval EFI_SUCCESS The protocol instance if found.\r
- @retval EFI_NOT_FOUND Block not found\r
-\r
-**/\r
-EFI_STATUS\r
-GetFvbByAddress (\r
- IN EFI_PHYSICAL_ADDRESS Address,\r
- OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN HandleCount;\r
- UINTN Index;\r
- EFI_PHYSICAL_ADDRESS FvbBaseAddress;\r
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
-\r
- *FvBlock = NULL;\r
- //\r
- // Locate all handles of Fvb protocol\r
- //\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- NULL,\r
- &HandleCount,\r
- &HandleBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_NOT_FOUND;\r
- }\r
- //\r
- // Search all FVB until find the right one\r
- //\r
- for (Index = 0; Index < HandleCount; Index += 1) {\r
- Status = gBS->HandleProtocol (\r
- HandleBuffer[Index],\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- (VOID **) &Fvb\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_NOT_FOUND;\r
- break;\r
- }\r
- //\r
- // Compare the address and select the right one\r
- //\r
- Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
- if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + (FwVolHeader->FvLength - 1)))) {\r
- *FvBlock = Fvb;\r
- Status = EFI_SUCCESS;\r
- break;\r
- }\r
- }\r
-\r
- FreePool (HandleBuffer);\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
- Is it in working block?\r
-\r
-\r
- @param FtwLiteDevice Calling context\r
- @param FvBlock Fvb protocol instance\r
- @param Lba The block specified\r
-\r
- @return A BOOLEAN value indicating in working block or not.\r
-\r
-**/\r
-BOOLEAN\r
-IsInWorkingBlock (\r
- EFI_FTW_LITE_DEVICE *FtwLiteDevice,\r
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,\r
- EFI_LBA Lba\r
- )\r
-{\r
- //\r
- // If matching the following condition, the target block is in working block.\r
- // 1. Target block is on the FV of working block (Using the same FVB protocol instance).\r
- // 2. Lba falls into the range of working block.\r
- //\r
- return (BOOLEAN)\r
- (\r
- (FvBlock == FtwLiteDevice->FtwFvBlock) &&\r
- (Lba >= FtwLiteDevice->FtwWorkBlockLba) &&\r
- (Lba <= FtwLiteDevice->FtwWorkSpaceLba)\r
- );\r
-}\r
-\r
-/**\r
- Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.\r
- Spare block is accessed by FTW backup FVB protocol interface. LBA is\r
- FtwLiteDevice->FtwSpareLba.\r
- Target block is accessed by FvBlock protocol interface. LBA is Lba.\r
-\r
-\r
- @param FtwLiteDevice The private data of FTW_LITE driver\r
- @param FvBlock FVB Protocol interface to access target block\r
- @param Lba Lba of the target block\r
-\r
- @retval EFI_SUCCESS Spare block content is copied to target block\r
- @retval EFI_INVALID_PARAMETER Input parameter error\r
- @retval EFI_OUT_OF_RESOURCES Allocate memory error\r
- @retval EFI_ABORTED The function could not complete successfully\r
-\r
-**/\r
-EFI_STATUS\r
-FlushSpareBlockToTargetBlock (\r
- EFI_FTW_LITE_DEVICE *FtwLiteDevice,\r
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,\r
- EFI_LBA Lba\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Length;\r
- UINT8 *Buffer;\r
- UINTN Count;\r
- UINT8 *Ptr;\r
- UINTN Index;\r
-\r
- if ((FtwLiteDevice == NULL) || (FvBlock == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Allocate a memory buffer\r
- //\r
- Length = FtwLiteDevice->SpareAreaLength;\r
- Buffer = AllocatePool (Length);\r
- if (Buffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Read all content of spare block to memory buffer\r
- //\r
- Ptr = Buffer;\r
- for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
- Count = FtwLiteDevice->BlockSize;\r
- Status = FtwLiteDevice->FtwBackupFvb->Read (\r
- FtwLiteDevice->FtwBackupFvb,\r
- FtwLiteDevice->FtwSpareLba + Index,\r
- 0,\r
- &Count,\r
- Ptr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (Buffer);\r
- return Status;\r
- }\r
-\r
- Ptr += Count;\r
- }\r
- //\r
- // Erase the target block\r
- //\r
- Status = FtwEraseBlock (FtwLiteDevice, FvBlock, Lba);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (Buffer);\r
- return EFI_ABORTED;\r
- }\r
- //\r
- // Write memory buffer to block, using the FvbBlock protocol interface\r
- //\r
- Ptr = Buffer;\r
- for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
- Count = FtwLiteDevice->BlockSize;\r
- Status = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "FtwLite: FVB Write block - %r\n", Status));\r
- FreePool (Buffer);\r
- return Status;\r
- }\r
-\r
- Ptr += Count;\r
- }\r
-\r
- FreePool (Buffer);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.\r
- Spare block is accessed by FTW backup FVB protocol interface. LBA is\r
- FtwLiteDevice->FtwSpareLba.\r
- Working block is accessed by FTW working FVB protocol interface. LBA is\r
- FtwLiteDevice->FtwWorkBlockLba.\r
-\r
-\r
- @param FtwLiteDevice The private data of FTW_LITE driver\r
-\r
- @retval EFI_SUCCESS Spare block content is copied to target block\r
- @retval EFI_OUT_OF_RESOURCES Allocate memory error\r
- @retval EFI_ABORTED The function could not complete successfully\r
- Notes:\r
- Since the working block header is important when FTW initializes, the\r
- state of the operation should be handled carefully. The Crc value is\r
- calculated without STATE element.\r
-\r
-**/\r
-EFI_STATUS\r
-FlushSpareBlockToWorkingBlock (\r
- EFI_FTW_LITE_DEVICE *FtwLiteDevice\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Length;\r
- UINT8 *Buffer;\r
- EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;\r
- EFI_LBA WorkSpaceLbaOffset;\r
- UINTN Count;\r
- UINT8 *Ptr;\r
- UINTN Index;\r
-\r
- //\r
- // Allocate a memory buffer\r
- //\r
- Length = FtwLiteDevice->SpareAreaLength;\r
- Buffer = AllocatePool (Length);\r
- if (Buffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // To guarantee that the WorkingBlockValid is set on spare block\r
- //\r
- // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,\r
- // WorkingBlockValid);\r
- // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).\r
- //\r
- WorkSpaceLbaOffset = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba;\r
- FtwUpdateFvState (\r
- FtwLiteDevice->FtwBackupFvb,\r
- FtwLiteDevice->FtwSpareLba + WorkSpaceLbaOffset,\r
- FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
- WORKING_BLOCK_VALID\r
- );\r
- //\r
- // Read from spare block to memory buffer\r
- //\r
- Ptr = Buffer;\r
- for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
- Count = FtwLiteDevice->BlockSize;\r
- Status = FtwLiteDevice->FtwBackupFvb->Read (\r
- FtwLiteDevice->FtwBackupFvb,\r
- FtwLiteDevice->FtwSpareLba + Index,\r
- 0,\r
- &Count,\r
- Ptr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (Buffer);\r
- return Status;\r
- }\r
-\r
- Ptr += Count;\r
- }\r
- //\r
- // Clear the CRC and STATE, copy data from spare to working block.\r
- //\r
- WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (Buffer + (UINTN) WorkSpaceLbaOffset * FtwLiteDevice->BlockSize + FtwLiteDevice->FtwWorkSpaceBase);\r
- InitWorkSpaceHeader (WorkingBlockHeader);\r
- WorkingBlockHeader->WorkingBlockValid = FTW_ERASE_POLARITY;\r
- WorkingBlockHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;\r
-\r
- //\r
- // target block is working block, then\r
- // Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER\r
- // before erase the working block.\r
- //\r
- // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,\r
- // WorkingBlockInvalid);\r
- // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).\r
- //\r
- Status = FtwUpdateFvState (\r
- FtwLiteDevice->FtwFvBlock,\r
- FtwLiteDevice->FtwWorkSpaceLba,\r
- FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
- WORKING_BLOCK_INVALID\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (Buffer);\r
- return EFI_ABORTED;\r
- }\r
-\r
- FtwLiteDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;\r
-\r
- //\r
- // Erase the working block\r
- //\r
- Status = FtwEraseBlock (\r
- FtwLiteDevice,\r
- FtwLiteDevice->FtwFvBlock,\r
- FtwLiteDevice->FtwWorkBlockLba\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (Buffer);\r
- return EFI_ABORTED;\r
- }\r
- //\r
- // Write memory buffer to working block, using the FvbBlock protocol interface\r
- //\r
- Ptr = Buffer;\r
- for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
- Count = FtwLiteDevice->BlockSize;\r
- Status = FtwLiteDevice->FtwFvBlock->Write (\r
- FtwLiteDevice->FtwFvBlock,\r
- FtwLiteDevice->FtwWorkBlockLba + Index,\r
- 0,\r
- &Count,\r
- Ptr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "FtwLite: FVB Write block - %r\n", Status));\r
- FreePool (Buffer);\r
- return Status;\r
- }\r
-\r
- Ptr += Count;\r
- }\r
- //\r
- // Since the memory buffer will not be used, free memory Buffer.\r
- //\r
- FreePool (Buffer);\r
-\r
- //\r
- // Update the VALID of the working block\r
- //\r
- // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,\r
- // WorkingBlockValid);\r
- // Hardcode offset sizeof(EFI_GUID)+sizeof(UINT32), to skip Signature and Crc\r
- //\r
- Status = FtwUpdateFvState (\r
- FtwLiteDevice->FtwFvBlock,\r
- FtwLiteDevice->FtwWorkSpaceLba,\r
- FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
- WORKING_BLOCK_VALID\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- FtwLiteDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;\r
-\r
- return EFI_SUCCESS;\r
-}\r