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