/** Get firmware block by address. @param Address Address specified the block @param FvBlock The block caller wanted @retval EFI_SUCCESS The protocol instance if found. @retval EFI_NOT_FOUND Block not found **/ EFI_HANDLE GetFvbByAddress ( IN EFI_PHYSICAL_ADDRESS Address, OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock ) { 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; EFI_HANDLE FvbHandle; *FvBlock = NULL; FvbHandle = NULL; HandleBuffer = NULL; // // Locate all handles of Fvb protocol // Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer); if (EFI_ERROR (Status)) { return NULL; } // // Get the FVB to access variable store // for (Index = 0; Index < HandleCount; Index += 1) { Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb); if (EFI_ERROR (Status)) { 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; FvbHandle = HandleBuffer[Index]; break; } } FreePool (HandleBuffer); return FvbHandle; }
/** Find the proper Firmware Volume Block protocol for FTW operation. @param[in, out] FtwDevice Pointer to the FTW device structure @retval EFI_SUCCESS Find the FVB protocol successfully. @retval EFI_NOT_FOUND No proper FVB protocol was found. @retval EFI_ABORTED Some data can not be got or be invalid. **/ EFI_STATUS FindFvbForFtw ( IN OUT EFI_FTW_DEVICE *FtwDevice ) { 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; EFI_FVB_ATTRIBUTES_2 Attributes; EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry; UINT32 LbaIndex; // // Get all FVB handle. // Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } // // Get the FVB to access variable store // Fvb = NULL; for (Index = 0; Index < HandleCount; Index += 1) { Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb); if (EFI_ERROR (Status)) { Status = EFI_NOT_FOUND; break; } // // Ensure this FVB protocol support Write operation. // Status = Fvb->GetAttributes (Fvb, &Attributes); if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) { continue; } // // 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 ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) && ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + FwVolHeader->FvLength)) ) { FtwDevice->FtwFvBlock = Fvb; // // To get the LBA of work space // if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { // // Now, one FV has one type of BlockLength // FvbMapEntry = &FwVolHeader->BlockMap[0]; for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { if ((FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1))) && (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) { FtwDevice->FtwWorkSpaceLba = LbaIndex - 1; // // Get the Work space size and Base(Offset) // FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength; FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1))); break; } } } } if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) && ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + FwVolHeader->FvLength)) ) { FtwDevice->FtwBackupFvb = Fvb; // // To get the LBA of spare // if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { // // Now, one FV has one type of BlockLength // FvbMapEntry = &FwVolHeader->BlockMap[0]; for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { if ((FtwDevice->SpareAreaAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1))) && (FtwDevice->SpareAreaAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) { // // Get the NumberOfSpareBlock and BlockSize // FtwDevice->FtwSpareLba = LbaIndex - 1; FtwDevice->BlockSize = FvbMapEntry->Length; FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->BlockSize; // // Check the range of spare area to make sure that it's in FV range // if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > FvbMapEntry->NumBlocks) { DEBUG ((EFI_D_ERROR, "Ftw: Spare area is out of FV range\n")); FreePool (HandleBuffer); ASSERT (FALSE); return EFI_ABORTED; } break; } } } } } FreePool (HandleBuffer); if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) || (FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) { return EFI_ABORTED; } return EFI_SUCCESS; }
/** Get the handle of the SMM FVB protocol by the FVB base address and attributes. @param[in] Address The base address of SMM FVB protocol. @param[in] Attributes The attributes of the SMM FVB protocol. @param[out] SmmFvbHandle The handle of the SMM FVB protocol. @retval EFI_SUCCESS The FVB handle is found. @retval EFI_ABORTED The FVB protocol is not found. **/ EFI_STATUS GetFvbByAddressAndAttribute ( IN EFI_PHYSICAL_ADDRESS Address, IN EFI_FVB_ATTRIBUTES_2 Attributes, OUT EFI_HANDLE *SmmFvbHandle ) { EFI_STATUS Status; EFI_HANDLE *HandleBuffer; UINTN HandleCount; UINTN Index; EFI_PHYSICAL_ADDRESS FvbBaseAddress; EFI_FVB_ATTRIBUTES_2 FvbAttributes; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; // // Locate all handles of SMM Fvb protocol. // Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Find the proper SMM Fvb handle by the address and attributes. // for (Index = 0; Index < HandleCount; Index++) { Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb); if (EFI_ERROR (Status)) { break; } // // Compare the address. // Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress); if (EFI_ERROR (Status)) { continue; } if (Address != FvbBaseAddress) { continue; } // // Compare the attribute. // Status = Fvb->GetAttributes (Fvb, &FvbAttributes); if (EFI_ERROR (Status)) { continue; } if (Attributes != FvbAttributes) { continue; } // // Found the proper FVB handle. // *SmmFvbHandle = HandleBuffer[Index]; FreePool (HandleBuffer); return EFI_SUCCESS; } FreePool (HandleBuffer); return EFI_ABORTED; }