Layers on top of Firmware Block protocol to produce a file abstraction\r
of FV based files.\r
\r
- Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
@retval EFI_SUCCESS Successfully read volume header to the allocated\r
buffer.\r
@retval EFI_ACCESS_DENIED Read status of FV is not enabled.\r
+ @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or\r
+ the file system could not be understood.\r
**/\r
EFI_STATUS\r
GetFwVolHeader (\r
);\r
}\r
\r
+ //\r
+ // Validate FV Header signature, if not as expected, continue.\r
+ //\r
+ if (TempFvh.Signature != EFI_FVH_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check to see that the file system is indeed formatted in a way we can\r
+ // understand it...\r
+ //\r
+ if ((!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&\r
+ (!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
*FwVolHeader = AllocatePool (TempFvh.HeaderLength);\r
if (*FwVolHeader == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
return ;\r
}\r
\r
+/**\r
+\r
+ Firmware volume inherits authentication status from the FV image file and section(in another firmware volume)\r
+ where it came from or propagated from PEI-phase.\r
+\r
+ @param FvDevice A pointer to the FvDevice.\r
+\r
+**/\r
+VOID\r
+FwVolInheritAuthenticationStatus (\r
+ IN FV_DEVICE *FvDevice\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_VOLUME_HEADER *CachedFvHeader;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *CachedFvExtHeader;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *ParentFvProtocol;\r
+ UINTN Key;\r
+ EFI_GUID FileNameGuid;\r
+ EFI_FV_FILETYPE FileType;\r
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
+ UINTN FileSize;\r
+ EFI_SECTION_TYPE SectionType;\r
+ UINT32 AuthenticationStatus;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;\r
+ UINTN BufferSize;\r
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
+ EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
+ EFI_PHYSICAL_ADDRESS BaseAddress;\r
+ EFI_PEI_HOB_POINTERS Fv3Hob;\r
+\r
+ if (FvDevice->Fv.ParentHandle != NULL) {\r
+ CachedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvDevice->CachedFv;\r
+\r
+ //\r
+ // By Parent Handle, find out the FV image file and section(in another firmware volume) where the firmware volume came from\r
+ //\r
+ Status = gBS->HandleProtocol (FvDevice->Fv.ParentHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &ParentFvProtocol);\r
+ if (!EFI_ERROR (Status) && (ParentFvProtocol != NULL)) {\r
+ Key = 0;\r
+ do {\r
+ FileType = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;\r
+ Status = ParentFvProtocol->GetNextFile (\r
+ ParentFvProtocol,\r
+ &Key,\r
+ &FileType,\r
+ &FileNameGuid,\r
+ &FileAttributes,\r
+ &FileSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
+ FvHeader = NULL;\r
+ BufferSize = 0;\r
+ Status = ParentFvProtocol->ReadSection (\r
+ ParentFvProtocol,\r
+ &FileNameGuid,\r
+ SectionType,\r
+ 0,\r
+ (VOID **) &FvHeader,\r
+ &BufferSize,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((FvHeader->FvLength == CachedFvHeader->FvLength) &&\r
+ (FvHeader->ExtHeaderOffset == CachedFvHeader->ExtHeaderOffset)) {\r
+ if (FvHeader->ExtHeaderOffset != 0) {\r
+ //\r
+ // Both FVs contain extension header, then compare their FV Name GUID\r
+ //\r
+ FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) FvHeader + FvHeader->ExtHeaderOffset);\r
+ CachedFvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) CachedFvHeader + CachedFvHeader->ExtHeaderOffset);\r
+ if (CompareGuid (&FvExtHeader->FvName, &CachedFvExtHeader->FvName)) {\r
+ //\r
+ // Found the FV image section where the firmware volume came from,\r
+ // and then inherit authentication status from it.\r
+ //\r
+ FvDevice->AuthenticationStatus = AuthenticationStatus;\r
+ FreePool ((VOID *) FvHeader);\r
+ return;\r
+ }\r
+ } else {\r
+ //\r
+ // Both FVs don't contain extension header, then compare their whole FV Image.\r
+ //\r
+ if (CompareMem ((VOID *) FvHeader, (VOID *) CachedFvHeader, (UINTN) FvHeader->FvLength) == 0) {\r
+ //\r
+ // Found the FV image section where the firmware volume came from\r
+ // and then inherit authentication status from it.\r
+ //\r
+ FvDevice->AuthenticationStatus = AuthenticationStatus;\r
+ FreePool ((VOID *) FvHeader);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ FreePool ((VOID *) FvHeader);\r
+ }\r
+ } while (TRUE);\r
+ }\r
+ } else {\r
+ Fvb = FvDevice->Fvb;\r
+\r
+ Status = Fvb->GetAttributes (Fvb, &FvbAttributes);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
+ //\r
+ // Get volume base address\r
+ //\r
+ Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Get the authentication status propagated from PEI-phase to DXE.\r
+ //\r
+ Fv3Hob.Raw = GetHobList ();\r
+ while ((Fv3Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV3, Fv3Hob.Raw)) != NULL) {\r
+ if (Fv3Hob.FirmwareVolume3->BaseAddress == BaseAddress) {\r
+ FvDevice->AuthenticationStatus = Fv3Hob.FirmwareVolume3->AuthenticationStatus;\r
+ return;\r
+ }\r
+ Fv3Hob.Raw = GET_NEXT_HOB (Fv3Hob);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Check if an FV is consistent and allocate cache for it.\r
\r
EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;\r
UINT8 *FwCache;\r
LBA_ENTRY *LbaEntry;\r
FREE_SPACE_ENTRY *FreeSpaceEntry;\r
UINT8 *FreeStart;\r
UINTN FreeSize;\r
UINT8 ErasePolarity;\r
- UINTN FileLength;\r
EFI_FFS_FILE_STATE FileState;\r
UINT8 *TopFvAddress;\r
UINTN TestLength;\r
}\r
ASSERT (FwVolHeader != NULL);\r
\r
+ FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);\r
+\r
//\r
// Double Check firmware volume header here\r
//\r
//\r
// go through the whole FV cache, check the consistence of the FV\r
//\r
- Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);\r
- TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength - 1);\r
+ if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) {\r
+ //\r
+ // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.\r
+ //\r
+ FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset);\r
+ Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize;\r
+ Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8);\r
+ } else {\r
+ Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);\r
+ }\r
+ TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength);\r
\r
//\r
// Build FFS list & Free Space List here\r
//\r
- while (Ptr <= TopFvAddress) {\r
- TestLength = TopFvAddress - Ptr + 1;\r
+ while (Ptr < TopFvAddress) {\r
+ TestLength = TopFvAddress - Ptr;\r
\r
if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
FreeSize = 0;\r
\r
do {\r
- TestLength = TopFvAddress - Ptr + 1;\r
+ TestLength = TopFvAddress - Ptr;\r
\r
if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
\r
FreeSize += TestLength;\r
Ptr += TestLength;\r
- } while (Ptr <= TopFvAddress);\r
+ } while (Ptr < TopFvAddress);\r
\r
FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY));\r
if (FreeSpaceEntry == NULL) {\r
continue;\r
}\r
//\r
- // double check boundry\r
+ // double check boundary\r
//\r
if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) {\r
break;\r
(EFI_FFS_FILE_HEADER *) Ptr\r
);\r
if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {\r
- Ptr += sizeof (EFI_FFS_FILE_HEADER);\r
+ if (IS_FFS_FILE2 (Ptr)) {\r
+ if (!FvDevice->IsFfs3Fv) {\r
+ DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));\r
+ }\r
+ Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2);\r
+ } else {\r
+ Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER);\r
+ }\r
\r
continue;\r
\r
}\r
}\r
\r
+ if (IS_FFS_FILE2 (Ptr)) {\r
+ ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF);\r
+ if (!FvDevice->IsFfs3Fv) {\r
+ DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));\r
+ Ptr = Ptr + FFS_FILE2_SIZE (Ptr);\r
+ //\r
+ // Adjust Ptr to the next 8-byte aligned boundary.\r
+ //\r
+ while (((UINTN) Ptr & 0x07) != 0) {\r
+ Ptr++;\r
+ }\r
+ continue;\r
+ }\r
+ }\r
+\r
if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) {\r
- FileLength = *(UINT32 *) ((EFI_FFS_FILE_HEADER *) Ptr)->Size & 0x00FFFFFF;\r
FileState = GetFileState (\r
FvDevice->ErasePolarity,\r
(EFI_FFS_FILE_HEADER *) Ptr\r
InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);\r
}\r
\r
- Ptr += FileLength;\r
+ if (IS_FFS_FILE2 (Ptr)) {\r
+ Ptr = Ptr + FFS_FILE2_SIZE (Ptr);\r
+ } else {\r
+ Ptr = Ptr + FFS_FILE_SIZE (Ptr);\r
+ }\r
\r
//\r
- // Adjust Ptr to the next 8-byte aligned boundry.\r
+ // Adjust Ptr to the next 8-byte aligned boundary.\r
//\r
while (((UINTN) Ptr & 0x07) != 0) {\r
Ptr++;\r
if (EFI_ERROR (Status)) {\r
return EFI_NOT_FOUND;\r
}\r
- //\r
- // Get FV with gEfiFirmwareFileSystemGuid\r
- //\r
+\r
for (Index = 0; Index < HandleCount; Index += 1) {\r
Status = gBS->HandleProtocol (\r
HandleBuffer[Index],\r
continue;\r
}\r
ASSERT (FwVolHeader != NULL);\r
- //\r
- // Check to see that the file system is indeed formatted in a way we can\r
- // understand it...\r
- //\r
- if (!CompareGuid (\r
- &FwVolHeader->FileSystemGuid,\r
- &gEfiFirmwareFileSystem2Guid\r
- )) {\r
- FreePool (FwVolHeader);\r
- continue;\r
- }\r
FreePool (FwVolHeader);\r
\r
Reinstall = FALSE;\r
FvDevice->Fv.KeySize = KEYSIZE;\r
FvDevice->Fv.GetInfo = FvGetVolumeInfo;\r
FvDevice->Fv.SetInfo = FvSetVolumeInfo;\r
+ FvDevice->Fv.ParentHandle = Fvb->ParentHandle;\r
\r
Status = FvCheck (FvDevice);\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
\r
+ FwVolInheritAuthenticationStatus (FvDevice);\r
+\r
if (Reinstall) {\r
//\r
// Reinstall an New FV protocol\r
} else {\r
FreePool (FvDevice);\r
}\r
- \r
+\r
DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status));\r
ASSERT_EFI_ERROR (Status);\r
} else {\r
} else {\r
FreePool (FvDevice);\r
}\r
- \r
+\r
DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status));\r
ASSERT_EFI_ERROR (Status);\r
}\r
if (InstallFlag) {\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
//\r
// No FV protocol install/reinstall successfully.\r
// EFI_NOT_FOUND should return to ensure this image will be unloaded.\r