+++ /dev/null
-/** @file\r
- Firmware Volume Block Driver for Lakeport Platform.\r
-\r
- Firmware volume block driver for FWH or SPI device.\r
- It depends on which Flash Device Library to be linked with this driver.\r
-\r
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
- \r\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
- \r\r
-\r
-**/\r
-\r
-#include "FvbService.h"\r
-\r
-//\r
-// Global variable for this FVB driver which contains\r
-// the private data of all firmware volume block instances.\r
-//\r
-FWB_GLOBAL mFvbModuleGlobal;\r
-\r
-//\r
-// This platform driver knows there are 3 FVs on\r
-// FD, which are FvRecovery, FvMain and FvNvStorage.\r
-//\r
-UINT32 mPlatformFvBaseAddress[] = {\r
- FixedPcdGet32(PcdFlashNvStorageVariableBase),\r
-};\r
-\r
-FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {\r
- {\r
- {\r
- HARDWARE_DEVICE_PATH,\r
- HW_MEMMAP_DP,\r
- {\r
- (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),\r
- (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)\r
- }\r
- },\r
- EfiMemoryMappedIO,\r
- (EFI_PHYSICAL_ADDRESS) 0,\r
- (EFI_PHYSICAL_ADDRESS) 0,\r
- },\r
- {\r
- END_DEVICE_PATH_TYPE,\r
- END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
- {\r
- END_DEVICE_PATH_LENGTH,\r
- 0\r
- }\r
- }\r
-};\r
-\r
-FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {\r
- {\r
- {\r
- MEDIA_DEVICE_PATH,\r
- MEDIA_PIWG_FW_VOL_DP,\r
- {\r
- (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),\r
- (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)\r
- }\r
- },\r
- { 0 }\r
- },\r
- {\r
- END_DEVICE_PATH_TYPE,\r
- END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
- {\r
- END_DEVICE_PATH_LENGTH,\r
- 0\r
- }\r
- }\r
-};\r
-\r
-//\r
-// Template structure used when installing FVB protocol.\r
-//\r
-EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {\r
- FVB_DEVICE_SIGNATURE,\r
- NULL,\r
- 0, // Instance\r
- {\r
- FvbProtocolGetAttributes,\r
- FvbProtocolSetAttributes,\r
- FvbProtocolGetPhysicalAddress,\r
- FvbProtocolGetBlockSize,\r
- FvbProtocolRead,\r
- FvbProtocolWrite,\r
- FvbProtocolEraseBlocks,\r
- NULL\r
- } // FwVolBlockInstance\r
-};\r
-\r
-\r
-/**\r
- Get the pointer to EFI_FW_VOL_INSTANCE from the buffer pointed\r
- by mFvbModuleGlobal.FvInstance based on a index.\r
- Each EFI_FW_VOL_INSTANCE is with variable length as\r
- we have a block map at the end of the EFI_FIRMWARE_VOLUME_HEADER.\r
-\r
- @param[in] Instance The index of the EFI_FW_VOL_INSTANCE.\r
-\r
- @return A pointer to EFI_FW_VOL_INSTANCE.\r
-\r
-**/\r
-EFI_FW_VOL_INSTANCE *\r
-GetFvbInstance (\r
- IN UINTN Instance\r
- )\r
-{\r
- EFI_FW_VOL_INSTANCE *FwhRecord;\r
-\r
- if ( Instance >= mFvbModuleGlobal.NumFv ) {\r
- ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);\r
- return NULL;\r
- }\r
-\r
- //\r
- // Find the right instance of the FVB private data.\r
- //\r
- FwhRecord = mFvbModuleGlobal.FvInstance;\r
- while ( Instance > 0 ) {\r
- FwhRecord = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhRecord) +\r
- FwhRecord->VolumeHeader.HeaderLength +\r
- (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));\r
- Instance --;\r
- }\r
-\r
- return FwhRecord;\r
-\r
-}\r
-\r
-\r
-/**\r
- Get the EFI_FVB_ATTRIBUTES_2 of a FV.\r
-\r
- @param[in] The index of the EFI_FW_VOL_INSTANCE.\r
-\r
- @return EFI_FVB_ATTRIBUTES_2 of the FV identified by Instance.\r
-\r
-**/\r
-STATIC\r
-EFI_FVB_ATTRIBUTES_2\r
-FvbGetVolumeAttributes (\r
- IN UINTN Instance\r
- )\r
-{\r
- EFI_FW_VOL_INSTANCE * FwInstance = NULL;\r
- FwInstance = GetFvbInstance(Instance);\r
- ASSERT (FwInstance != NULL);\r
-\r
- if ( FwInstance != NULL ) {\r
- return FwInstance->VolumeHeader.Attributes;\r
- } else {\r
- return 0;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Retrieves the starting address of an LBA in an FV. It also\r
- return a few other attribut of the FV.\r
-\r
- @param[in] Instance The index of the EFI_FW_VOL_INSTANCE.\r
- @param[in] Lba The logical block address.\r
- @param[out] LbaAddress On output, contains the physical starting address\r
- of the Lba.\r
- @param[out] LbaLength On output, contains the length of the block.\r
- @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the\r
- number of consecutive blocks starting with Lba is\r
- returned. All blocks in this range have a size of\r
- BlockSize.\r
-\r
- @retval EFI_SUCCESS Successfully returns.\r
- @retval EFI_INVALID_PARAMETER Instance not found.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-FvbGetLbaAddress (\r
- IN UINTN Instance,\r
- IN EFI_LBA Lba,\r
- OUT UINTN *LbaAddress,\r
- OUT UINTN *LbaLength,\r
- OUT UINTN *NumOfBlocks\r
- )\r
-{\r
- UINT32 NumBlocks = 0;\r
- UINT32 BlockLength = 0;\r
- UINTN Offset;\r
- EFI_LBA StartLba;\r
- EFI_LBA NextLba;\r
- EFI_FW_VOL_INSTANCE *FwhInstance;\r
- EFI_FV_BLOCK_MAP_ENTRY *BlockMap = NULL;\r
-\r
- //\r
- // Find the right instance of the FVB private data.\r
- //\r
- FwhInstance = GetFvbInstance (Instance);\r
-\r
- StartLba = 0;\r
- Offset = 0;\r
- BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]);\r
- ASSERT (BlockMap != NULL);\r
-\r
- //\r
- // Parse the blockmap of the FV to find which map entry the Lba belongs to.\r
- //\r
- while (TRUE) {\r
- if ( BlockMap != NULL) {\r
- NumBlocks = BlockMap->NumBlocks;\r
- BlockLength = BlockMap->Length;\r
- }\r
-\r
- if ( NumBlocks == 0 || BlockLength == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- NextLba = StartLba + NumBlocks;\r
-\r
- //\r
- // The map entry found.\r
- //\r
- if (Lba >= StartLba && Lba < NextLba) {\r
- Offset = Offset + (UINTN)MultU64x32((Lba - StartLba), BlockLength);\r
- if ( LbaAddress && FwhInstance ) {\r
- *LbaAddress = FwhInstance->FvBase + Offset;\r
- }\r
-\r
- if (LbaLength ) {\r
- *LbaLength = BlockLength;\r
- }\r
-\r
- if (NumOfBlocks ) {\r
- *NumOfBlocks = (UINTN)(NextLba - Lba);\r
- }\r
- return EFI_SUCCESS;\r
- }\r
-\r
- StartLba = NextLba;\r
- Offset = Offset + NumBlocks * BlockLength;\r
- BlockMap++;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Reads specified number of bytes into a buffer from the specified block.\r
-\r
- @param[in] Instance The FV instance to be read from.\r
- @param[in] Lba The logical block address to be read from.\r
- @param[in] BlockOffset Offset into the block at which to begin reading.\r
- @param[in] NumBytes Pointer that on input contains the total size of\r
- the buffer. On output, it contains the total number\r
- of bytes read.\r
- @param[in] Buffer Pointer to a caller allocated buffer that will be\r
- used to hold the data read.\r
-\r
-\r
- @retval EFI_SUCCESS The firmware volume was read successfully and\r
- contents are in Buffer.\r
- @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output,\r
- NumBytes contains the total number of bytes returned\r
- in Buffer.\r
- @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.\r
- @retval EFI_DEVICE_ERROR The block device is not functioning correctly and\r
- could not be read.\r
- @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-FvbReadBlock (\r
- IN UINTN Instance,\r
- IN EFI_LBA Lba,\r
- IN UINTN BlockOffset,\r
- IN OUT UINTN *NumBytes,\r
- IN UINT8 *Buffer\r
- )\r
-{\r
- EFI_FVB_ATTRIBUTES_2 Attributes;\r
- UINTN LbaAddress;\r
- UINTN LbaLength;\r
- EFI_STATUS Status;\r
-\r
- if ( (NumBytes == NULL) || (Buffer == NULL)) {\r
- return (EFI_INVALID_PARAMETER);\r
- }\r
- if (*NumBytes == 0) {\r
- return (EFI_INVALID_PARAMETER);\r
- }\r
-\r
- Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- Attributes = FvbGetVolumeAttributes (Instance);\r
-\r
- if ( (Attributes & EFI_FVB2_READ_STATUS) == 0) {\r
- return (EFI_ACCESS_DENIED);\r
- }\r
-\r
- if (BlockOffset > LbaLength) {\r
- return (EFI_INVALID_PARAMETER);\r
- }\r
-\r
- if (LbaLength < ( *NumBytes + BlockOffset ) ) {\r
- *NumBytes = (UINT32) (LbaLength - BlockOffset);\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- }\r
-\r
- LibFvbFlashDeviceRead (LbaAddress + BlockOffset, NumBytes, Buffer);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Writes specified number of bytes from the input buffer to the block.\r
-\r
- @param[in] Instance The FV instance to be written to.\r
- @param[in] Lba The starting logical block index to write to.\r
- @param[in] BlockOffset Offset into the block at which to begin writing.\r
- @param[in] NumBytes Pointer that on input contains the total size of\r
- the buffer. On output, it contains the total number\r
- of bytes actually written.\r
- @param[in] Buffer Pointer to a caller allocated buffer that contains\r
- the source for the write.\r
- @retval EFI_SUCCESS The firmware volume was written successfully.\r
- @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output,\r
- NumBytes contains the total number of bytes\r
- actually writte.\r
- @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.\r
- @retval EFI_DEVICE_ERROR The block device is not functioning correctly and\r
- could not be written.\r
- @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-FvbWriteBlock (\r
- IN UINTN Instance,\r
- IN EFI_LBA Lba,\r
- IN UINTN BlockOffset,\r
- IN OUT UINTN *NumBytes,\r
- IN UINT8 *Buffer\r
- )\r
-{\r
- EFI_FVB_ATTRIBUTES_2 Attributes;\r
- UINTN LbaAddress;\r
- UINTN LbaLength;\r
- EFI_STATUS Status;\r
- EFI_STATUS Status1;\r
-\r
- if ( (NumBytes == NULL) || (Buffer == NULL)) {\r
- return (EFI_INVALID_PARAMETER);\r
- }\r
- if (*NumBytes == 0) {\r
- return (EFI_INVALID_PARAMETER);\r
- }\r
-\r
- Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Check if the FV is write enabled.\r
- //\r
- Attributes = FvbGetVolumeAttributes (Instance);\r
- if ( (Attributes & EFI_FVB2_WRITE_STATUS) == 0) {\r
- return (EFI_ACCESS_DENIED);\r
- }\r
-\r
- //\r
- // Perform boundary checks and adjust NumBytes.\r
- //\r
- if (BlockOffset > LbaLength) {\r
- return (EFI_INVALID_PARAMETER);\r
- }\r
-\r
- if ( LbaLength < ( *NumBytes + BlockOffset ) ) {\r
- DEBUG ((EFI_D_ERROR,\r
- "FvWriteBlock: Reducing Numbytes from 0x%x to 0x%x\n",\r
- *NumBytes,\r
- (UINT32)(LbaLength-BlockOffset))\r
- );\r
- *NumBytes = (UINT32) (LbaLength - BlockOffset);\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- }\r
-\r
- LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE);\r
-\r
- Status1 = LibFvbFlashDeviceWrite (LbaAddress + BlockOffset, NumBytes, Buffer);\r
-\r
- LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE);\r
- WriteBackInvalidateDataCacheRange ((VOID *) (LbaAddress + BlockOffset), *NumBytes);\r
-\r
- if ( EFI_ERROR (Status1) ) {\r
- return Status1;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Erases and initializes a firmware volume block.\r
-\r
- @param[in] Instance The FV instance to be erased.\r
- @param[in] Lba The logical block index to be erased.\r
-\r
- @retval EFI_SUCCESS The erase request was successfully completed.\r
- @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.\r
- @retval EFI_DEVICE_ERROR The block device is not functioning correctly and\r
- could not be written. Firmware device may have been\r
- partially erased.\r
- @retval EFI_INVALID_PARAMETER Instance not found.\r
-\r
-**/\r
-EFI_STATUS\r
-FvbEraseBlock (\r
- IN UINTN Instance,\r
- IN EFI_LBA Lba\r
- )\r
-{\r
- EFI_FVB_ATTRIBUTES_2 Attributes;\r
- UINTN LbaAddress;\r
- UINTN LbaLength;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Check if the FV is write enabled.\r
- //\r
- Attributes = FvbGetVolumeAttributes (Instance);\r
-\r
- if( (Attributes & EFI_FVB2_WRITE_STATUS) == 0) {\r
- return (EFI_ACCESS_DENIED);\r
- }\r
-\r
- //\r
- // Get the starting address of the block for erase.\r
- //\r
- Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE);\r
-\r
- Status = LibFvbFlashDeviceBlockErase (LbaAddress, LbaLength);\r
-\r
- LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE);\r
-\r
- WriteBackInvalidateDataCacheRange ((VOID *) LbaAddress, LbaLength);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Modifies the current settings of the firmware volume according to the\r
- input parameter, and returns the new setting of the volume.\r
-\r
- @param[in] Instance The FV instance whose attributes is going to be\r
- modified.\r
- @param[in] Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES_2\r
- containing the desired firmware volume settings.\r
- On successful return, it contains the new settings\r
- of the firmware volume.\r
-\r
- @retval EFI_SUCCESS Successfully returns.\r
- @retval EFI_ACCESS_DENIED The volume setting is locked and cannot be modified.\r
- @retval EFI_INVALID_PARAMETER Instance not found, or The attributes requested are\r
- in conflict with the capabilities as declared in the\r
- firmware volume header.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-FvbSetVolumeAttributes (\r
- IN UINTN Instance,\r
- IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes\r
- )\r
-{\r
- EFI_FW_VOL_INSTANCE *FwhInstance = NULL;\r
- EFI_FVB_ATTRIBUTES_2 OldAttributes = 0;\r
- EFI_FVB_ATTRIBUTES_2 *AttribPtr = NULL;\r
- EFI_FVB_ATTRIBUTES_2 UnchangedAttributes;\r
- UINT32 Capabilities;\r
- UINT32 OldStatus, NewStatus;\r
-\r
- //\r
- // Find the right instance of the FVB private data.\r
- //\r
- FwhInstance = GetFvbInstance (Instance);\r
-\r
- AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) & (FwhInstance->VolumeHeader.Attributes);\r
- ASSERT (AttribPtr != NULL);\r
-\r
- if ( AttribPtr != NULL) {\r
- OldAttributes = *AttribPtr;\r
- }\r
-\r
- Capabilities = OldAttributes & EFI_FVB2_CAPABILITIES;\r
- OldStatus = OldAttributes & EFI_FVB2_STATUS;\r
- NewStatus = *Attributes & EFI_FVB2_STATUS;\r
-\r
- UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \\r
- EFI_FVB2_READ_ENABLED_CAP | \\r
- EFI_FVB2_WRITE_DISABLED_CAP | \\r
- EFI_FVB2_WRITE_ENABLED_CAP | \\r
- EFI_FVB2_LOCK_CAP | \\r
- EFI_FVB2_STICKY_WRITE | \\r
- EFI_FVB2_MEMORY_MAPPED | \\r
- EFI_FVB2_ERASE_POLARITY | \\r
- EFI_FVB2_READ_LOCK_CAP | \\r
- EFI_FVB2_WRITE_LOCK_CAP | \\r
- EFI_FVB2_ALIGNMENT;\r
-\r
- //\r
- // Some attributes of FV is read only can *not* be set.\r
- //\r
- if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // If firmware volume is locked, no status bit can be updated.\r
- //\r
- if ( OldAttributes & EFI_FVB2_LOCK_STATUS ) {\r
- if ( OldStatus ^ NewStatus ) {\r
- return EFI_ACCESS_DENIED;\r
- }\r
- }\r
-\r
- //\r
- // Test read disable.\r
- //\r
- if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {\r
- if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- //\r
- // Test read enable.\r
- //\r
- if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {\r
- if (NewStatus & EFI_FVB2_READ_STATUS) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- //\r
- // Test write disable.\r
- //\r
- if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {\r
- if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- //\r
- // Test write enable.\r
- //\r
- if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {\r
- if (NewStatus & EFI_FVB2_WRITE_STATUS) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- //\r
- // Test lock.\r
- //\r
- if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {\r
- if (NewStatus & EFI_FVB2_LOCK_STATUS) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));\r
- *AttribPtr = (*AttribPtr) | NewStatus;\r
- *Attributes = *AttribPtr;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-//\r
-// FVB protocol APIs.\r
-//\r
-/**\r
- Retrieves the physical address of the device.\r
-\r
- @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL.\r
- @param[out] Address Output buffer containing the address.\r
-\r
- retval EFI_SUCCESS The function always return successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FvbProtocolGetPhysicalAddress (\r
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
- OUT EFI_PHYSICAL_ADDRESS *Address\r
- )\r
-{\r
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
- EFI_FW_VOL_INSTANCE *FvInstance;\r
-\r
- FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
- FvInstance = GetFvbInstance(FvbDevice->Instance);\r
-\r
- if (FvInstance != NULL) {\r
- *Address = FvInstance->FvBase;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Retrieve the size of a logical block.\r
-\r
- @param[in] This Calling context.\r
- @param[in] Lba Indicates which block to return the size for.\r
- @param[out] BlockSize A pointer to a caller allocated UINTN in which\r
- the size of the block is returned.\r
- @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the\r
- number of consecutive blocks starting with Lba is\r
- returned. All blocks in this range have a size of\r
- BlockSize.\r
-\r
- @retval EFI_SUCCESS The function always return successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FvbProtocolGetBlockSize (\r
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
- IN EFI_LBA Lba,\r
- OUT UINTN *BlockSize,\r
- OUT UINTN *NumOfBlocks\r
- )\r
-{\r
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
-\r
- DEBUG((EFI_D_INFO,\r
- "FvbProtocolGetBlockSize: Lba: 0x%lx BlockSize: 0x%x NumOfBlocks: 0x%x\n",\r
- Lba,\r
- BlockSize,\r
- NumOfBlocks)\r
- );\r
-\r
- FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
-\r
- return FvbGetLbaAddress (\r
- FvbDevice->Instance,\r
- Lba,\r
- NULL,\r
- BlockSize,\r
- NumOfBlocks\r
- );\r
-}\r
-\r
-\r
-/**\r
- Retrieves Volume attributes. No polarity translations are done.\r
-\r
- @param[in] This Calling context.\r
- @param[out] Attributes Output buffer which contains attributes.\r
-\r
- @retval EFI_SUCCESS The function always return successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FvbProtocolGetAttributes (\r
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
- OUT EFI_FVB_ATTRIBUTES_2 *Attributes\r
- )\r
-{\r
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
-\r
- FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
-\r
- *Attributes = FvbGetVolumeAttributes (FvbDevice->Instance);\r
-\r
- DEBUG ((EFI_D_INFO,\r
- "FvbProtocolGetAttributes: This: 0x%x Attributes: 0x%x\n",\r
- This,\r
- *Attributes)\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Sets Volume attributes. No polarity translations are done.\r
-\r
- @param[in] This Calling context.\r
- @param[out] Attributes Output buffer which contains attributes.\r
-\r
- @retval EFI_SUCCESS The function always return successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FvbProtocolSetAttributes (\r
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
- IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
-\r
- DEBUG((EFI_D_INFO,\r
- "FvbProtocolSetAttributes: Before SET - This: 0x%x Attributes: 0x%x\n",\r
- This,\r
- *Attributes)\r
- );\r
-\r
- FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
-\r
- Status = FvbSetVolumeAttributes (FvbDevice->Instance, Attributes);\r
-\r
- DEBUG((EFI_D_INFO,\r
- "FvbProtocolSetAttributes: After SET - This: 0x%x Attributes: 0x%x\n",\r
- This,\r
- *Attributes)\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- The EraseBlock() function erases one or more blocks as denoted by the\r
- variable argument list. The entire parameter list of blocks must be verified\r
- prior to erasing any blocks. If a block is requested that does not exist\r
- within the associated firmware volume (it has a larger index than the last\r
- block of the firmware volume), the EraseBlock() function must return\r
- EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.\r
-\r
- @param[in] This Calling context.\r
- @param[in] ... Starting LBA followed by Number of Lba to erase.\r
- a -1 to terminate the list.\r
-\r
- @retval EFI_SUCCESS The erase request was successfully completed.\r
- @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.\r
- @retval EFI_DEVICE_ERROR The block device is not functioning correctly and\r
- could not be written. Firmware device may have been\r
- partially erased.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FvbProtocolEraseBlocks (\r
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
- ...\r
- )\r
-{\r
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
- EFI_FW_VOL_INSTANCE *FwhInstance;\r
- UINTN NumOfBlocks = 0;\r
- VA_LIST args;\r
- EFI_LBA StartingLba;\r
- UINTN NumOfLba;\r
- EFI_STATUS Status;\r
-\r
- DEBUG((EFI_D_INFO, "FvbProtocolEraseBlocks: \n"));\r
- FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
-\r
- FwhInstance = GetFvbInstance (FvbDevice->Instance);\r
-\r
- if (FwhInstance != NULL) {\r
- NumOfBlocks = FwhInstance->NumOfBlocks;\r
- }\r
-\r
- VA_START (args, This);\r
-\r
- do {\r
- StartingLba = VA_ARG (args, EFI_LBA);\r
- if ( StartingLba == EFI_LBA_LIST_TERMINATOR ) {\r
- break;\r
- }\r
-\r
- NumOfLba = VA_ARG (args, UINTN);\r
-\r
- //\r
- // Check input parameters.\r
- //\r
- if (NumOfLba == 0) {\r
- VA_END (args);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ( ( StartingLba + NumOfLba ) > NumOfBlocks ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- } while ( 1 );\r
-\r
- VA_END (args);\r
-\r
- VA_START (args, This);\r
- do {\r
- StartingLba = VA_ARG (args, EFI_LBA);\r
- if (StartingLba == EFI_LBA_LIST_TERMINATOR) {\r
- break;\r
- }\r
-\r
- NumOfLba = VA_ARG (args, UINTN);\r
-\r
- while ( NumOfLba > 0 ) {\r
- Status = FvbEraseBlock (FvbDevice->Instance, StartingLba);\r
- if ( EFI_ERROR(Status)) {\r
- VA_END (args);\r
- return Status;\r
- }\r
- StartingLba ++;\r
- NumOfLba --;\r
- }\r
-\r
- } while ( 1 );\r
-\r
- VA_END (args);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Writes data beginning at Lba:Offset from FV. The write terminates either\r
- when *NumBytes of data have been written, or when a block boundary is\r
- reached. *NumBytes is updated to reflect the actual number of bytes\r
- written. The write opertion does not include erase. This routine will\r
- attempt to write only the specified bytes. If the writes do not stick,\r
- it will return an error.\r
-\r
- @param[in] This Calling context.\r
- @param[in] Lba Block in which to begin write.\r
- @param[in] Offset Offset in the block at which to begin write.\r
- @param[in,out] NumBytes On input, indicates the requested write size. On\r
- output, indicates the actual number of bytes written\r
- @param[in] Buffer Buffer containing source data for the write.\r
-\r
- @retval EFI_SUCCESS The firmware volume was written successfully.\r
- @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output,\r
- NumBytes contains the total number of bytes\r
- actually written.\r
- @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.\r
- @retval EFI_DEVICE_ERROR The block device is not functioning correctly and\r
- could not be written.\r
- @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FvbProtocolWrite (\r
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
- IN EFI_LBA Lba,\r
- IN UINTN Offset,\r
- IN OUT UINTN *NumBytes,\r
- IN UINT8 *Buffer\r
- )\r
-{\r
-\r
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
-\r
- FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
-\r
- DEBUG((EFI_D_INFO,\r
- "FvbProtocolWrite: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x\n",\r
- Lba,\r
- Offset,\r
- *NumBytes,\r
- Buffer)\r
- );\r
-\r
- return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer);\r
-}\r
-\r
-\r
-/**\r
- Reads data beginning at Lba:Offset from FV. The Read terminates either\r
- when *NumBytes of data have been read, or when a block boundary is\r
- reached. *NumBytes is updated to reflect the actual number of bytes\r
- written. The write opertion does not include erase. This routine will\r
- attempt to write only the specified bytes. If the writes do not stick,\r
- it will return an error.\r
-\r
- @param[in] This Calling context.\r
- @param[in] Lba Block in which to begin write.\r
- @param[in] Offset Offset in the block at which to begin write\r
- @param[in,out] NumBytes On input, indicates the requested write size. On\r
- output, indicates the actual number of bytes written.\r
- @param[in] Buffer Buffer containing source data for the write.\r
-\r
-\r
-Returns:\r
- @retval EFI_SUCCESS The firmware volume was read successfully and\r
- contents are in Buffer.\r
- @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output,\r
- NumBytes contains the total number of bytes returned\r
- in Buffer.\r
- @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state\r
- @retval EFI_DEVICE_ERROR The block device is not functioning correctly and\r
- could not be read.\r
- @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FvbProtocolRead (\r
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
- IN EFI_LBA Lba,\r
- IN UINTN Offset,\r
- IN OUT UINTN *NumBytes,\r
- OUT UINT8 *Buffer\r
- )\r
-{\r
-\r
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
- EFI_STATUS Status;\r
-\r
- FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
- Status = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer);\r
- DEBUG((EFI_D_INFO,\r
- "FvbProtocolRead: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x\n",\r
- Lba,\r
- Offset,\r
- *NumBytes,\r
- Buffer)\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Check the integrity of firmware volume header.\r
-\r
- @param[in] FwVolHeader A pointer to a firmware volume header.\r
-\r
- @retval TRUE The firmware volume is consistent.\r
- @retval FALSE The firmware volume has corrupted.\r
-\r
-**/\r
-BOOLEAN\r
-IsFvHeaderValid (\r
- IN EFI_PHYSICAL_ADDRESS FvBase,\r
- IN CONST EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader\r
- )\r
-{\r
- if (FvBase == PcdGet32(PcdFlashNvStorageVariableBase)) {\r
- if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid, sizeof(EFI_GUID)) != 0 ) {\r
- return FALSE;\r
- }\r
- } else {\r
- if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) {\r
- return FALSE;\r
- }\r
- }\r
- if ( (FwVolHeader->Revision != EFI_FVH_REVISION) ||\r
- (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||\r
- (FwVolHeader->FvLength == ((UINTN) -1)) ||\r
- ((FwVolHeader->HeaderLength & 0x01 ) !=0) ) {\r
- return FALSE;\r
- }\r
-\r
- if (CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength) != 0) {\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/**\r
- The function does the necessary initialization work for\r
- Firmware Volume Block Driver.\r
-\r
- @retval EFI_SUCCESS This funtion always return EFI_SUCCESS.\r
- It will ASSERT on errors.\r
-\r
-**/\r
-EFI_STATUS\r
-FvbInitialize (\r
- VOID\r
- )\r
-{\r
- EFI_FW_VOL_INSTANCE *FwhInstance;\r
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
- EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;\r
- EFI_PHYSICAL_ADDRESS BaseAddress;\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
- UINTN TmpHeaderLength;\r
- UINTN Idx;\r
- UINT32 MaxLbaSize;\r
-\r
- //\r
- // Calculate the total size for all firmware volume block instances.\r
- //\r
- BufferSize = 0;\r
- for (Idx = 0; Idx < 1; Idx++) {\r
- FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) mPlatformFvBaseAddress[Idx];\r
- BufferSize += (FvHeader->HeaderLength +\r
- sizeof (EFI_FW_VOL_INSTANCE) -\r
- sizeof (EFI_FIRMWARE_VOLUME_HEADER)\r
- );\r
- }\r
-\r
- mFvbModuleGlobal.FvInstance = (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize);\r
- ASSERT (NULL != mFvbModuleGlobal.FvInstance);\r
-\r
-\r
- MaxLbaSize = 0;\r
- FwhInstance = mFvbModuleGlobal.FvInstance;\r
- mFvbModuleGlobal.NumFv = 0;\r
-\r
- for (Idx = 0; Idx < 1; Idx++) {\r
- BaseAddress = mPlatformFvBaseAddress[Idx];\r
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;\r
-\r
- if (!IsFvHeaderValid (BaseAddress, FwVolHeader)) {\r
- //\r
- // If not valid, get FvbInfo from the information carried in\r
- // FVB driver.\r
- //\r
- DEBUG ((EFI_D_ERROR, "Fvb: FV header @ 0x%lx invalid\n", BaseAddress));\r
- Status = GetFvbInfo (BaseAddress, &FwVolHeader);\r
- ASSERT_EFI_ERROR(Status);\r
- //\r
- // Write back a healthy FV header.\r
- //\r
- DEBUG ((EFI_D_ERROR, "FwBlockService.c: Writing back healthy FV header\n"));\r
- LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length, FALSE);\r
-\r
- Status = LibFvbFlashDeviceBlockErase ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length);\r
-\r
- TmpHeaderLength = (UINTN) FwVolHeader->HeaderLength;\r
- Status = LibFvbFlashDeviceWrite (\r
- (UINTN)BaseAddress,\r
- &TmpHeaderLength,\r
- (UINT8 *) FwVolHeader\r
- );\r
-\r
- LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length, TRUE);\r
-\r
- WriteBackInvalidateDataCacheRange (\r
- (VOID *) (UINTN) BaseAddress,\r
- FwVolHeader->BlockMap->Length\r
- );\r
-\r
- }\r
-\r
- CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength);\r
-\r
- FwVolHeader = &(FwhInstance->VolumeHeader);\r
- FwhInstance->FvBase = (UINTN)BaseAddress;\r
-\r
- //\r
- // Process the block map for each FV.\r
- //\r
- FwhInstance->NumOfBlocks = 0;\r
- for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {\r
- //\r
- // Get the maximum size of a block.\r
- //\r
- if (MaxLbaSize < PtrBlockMapEntry->Length) {\r
- MaxLbaSize = PtrBlockMapEntry->Length;\r
- }\r
- FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks;\r
- }\r
-\r
- //\r
- // Add a FVB Protocol Instance.\r
- //\r
- mFvbModuleGlobal.NumFv++;\r
- InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1);\r
-\r
- //\r
- // Move on to the next FwhInstance.\r
- //\r
- FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) +\r
- FwVolHeader->HeaderLength +\r
- (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));\r
-\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r