X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FDispatcher%2FDispatcher.c;h=088cd81063137a269e0d9f2957713bd9cc239fc0;hp=5686d94e6a727372003ba6ba177d2103eb310ee1;hb=a82e52b3b82b66a377618e3fcf3604e8bc1e7f21;hpb=ac72474d001c1c084a45e34e330e34ef11e15173 diff --git a/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c index 5686d94e6a..088cd81063 100644 --- a/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c +++ b/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c @@ -773,7 +773,7 @@ FvIsBeingProcesssed ( for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) { KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE); if (CompareGuid (&FvNameGuid, &KnownHandle->FvNameGuid)) { - DEBUG ((EFI_D_ERROR, "FvImage on FvHandle %p and %p has the same FvNameGuid %g.\n", FvHandle, KnownHandle->Handle, FvNameGuid)); + DEBUG ((EFI_D_ERROR, "FvImage on FvHandle %p and %p has the same FvNameGuid %g.\n", FvHandle, KnownHandle->Handle, &FvNameGuid)); return NULL; } } @@ -938,7 +938,67 @@ FvFoundInHobFv2 ( return FALSE; } +/** + Find USED_SIZE FV_EXT_TYPE entry in FV extension header and get the FV used size. + + @param[in] FvHeader Pointer to FV header. + @param[out] FvUsedSize Pointer to FV used size returned, + only valid if USED_SIZE FV_EXT_TYPE entry is found. + @param[out] EraseByte Pointer to erase byte returned, + only valid if USED_SIZE FV_EXT_TYPE entry is found. + @retval TRUE USED_SIZE FV_EXT_TYPE entry is found, + FV used size and erase byte are returned. + @retval FALSE No USED_SIZE FV_EXT_TYPE entry found. + +**/ +BOOLEAN +GetFvUsedSize ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader, + OUT UINT32 *FvUsedSize, + OUT UINT8 *EraseByte + ) +{ + UINT16 ExtHeaderOffset; + EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader; + EFI_FIRMWARE_VOLUME_EXT_ENTRY *ExtEntryList; + EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *ExtEntryUsedSize; + + ExtHeaderOffset = ReadUnaligned16 (&FvHeader->ExtHeaderOffset); + if (ExtHeaderOffset != 0) { + ExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINT8 *) FvHeader + ExtHeaderOffset); + ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *) (ExtHeader + 1); + while ((UINTN) ExtEntryList < ((UINTN) ExtHeader + ReadUnaligned32 (&ExtHeader->ExtHeaderSize))) { + if (ReadUnaligned16 (&ExtEntryList->ExtEntryType) == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) { + // + // USED_SIZE FV_EXT_TYPE entry is found. + // + ExtEntryUsedSize = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *) ExtEntryList; + *FvUsedSize = ReadUnaligned32 (&ExtEntryUsedSize->UsedSize); + if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ERASE_POLARITY) != 0) { + *EraseByte = 0xFF; + } else { + *EraseByte = 0; + } + DEBUG (( + DEBUG_INFO, + "FV at 0x%x has 0x%x used size, and erase byte is 0x%02x\n", + FvHeader, + *FvUsedSize, + *EraseByte + )); + return TRUE; + } + ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *) + ((UINT8 *) ExtEntryList + ReadUnaligned16 (&ExtEntryList->ExtEntrySize)); + } + } + + // + // No USED_SIZE FV_EXT_TYPE entry found. + // + return FALSE; +} /** Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle. @@ -968,6 +1028,8 @@ CoreProcessFvImageFile ( EFI_FIRMWARE_VOLUME_HEADER *FvHeader; UINT32 FvAlignment; EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath; + UINT32 FvUsedSize; + UINT8 EraseByte; // // Read the first (and only the first) firmware volume section @@ -1023,32 +1085,58 @@ CoreProcessFvImageFile ( // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from // its initial linked location and maintain its alignment. // - if ((FvHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) { + if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) { // // Get FvHeader alignment // - FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); + FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16); // // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value. // if (FvAlignment < 8) { FvAlignment = 8; } + + DEBUG (( + DEBUG_INFO, + "%a() FV at 0x%x, FvAlignment required is 0x%x\n", + __FUNCTION__, + FvHeader, + FvAlignment + )); + // - // Allocate the aligned buffer for the FvImage. + // Check FvImage alignment. // - AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment); - if (AlignedBuffer == NULL) { - FreePool (Buffer); - return EFI_OUT_OF_RESOURCES; - } else { + if ((UINTN) FvHeader % FvAlignment != 0) { // - // Move FvImage into the aligned buffer and release the original buffer. + // Allocate the aligned buffer for the FvImage. // - CopyMem (AlignedBuffer, Buffer, BufferSize); - FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) AlignedBuffer; - CoreFreePool (Buffer); - Buffer = NULL; + AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment); + if (AlignedBuffer == NULL) { + FreePool (Buffer); + return EFI_OUT_OF_RESOURCES; + } else { + // + // Move FvImage into the aligned buffer and release the original buffer. + // + if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) { + // + // Copy the used bytes and fill the rest with the erase value. + // + CopyMem (AlignedBuffer, FvHeader, (UINTN) FvUsedSize); + SetMem ( + (UINT8 *) AlignedBuffer + FvUsedSize, + (UINTN) (BufferSize - FvUsedSize), + EraseByte + ); + } else { + CopyMem (AlignedBuffer, Buffer, BufferSize); + } + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) AlignedBuffer; + CoreFreePool (Buffer); + Buffer = NULL; + } } } //