/** Check if an FV is consistent and allocate cache for it. @param FvDevice A pointer to the FvDevice to be checked. @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. @retval EFI_SUCCESS FV is consistent and cache is allocated. @retval EFI_VOLUME_CORRUPTED File system is corrupted. **/ EFI_STATUS FvCheck ( IN OUT FV_DEVICE *FvDevice ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; EFI_FVB_ATTRIBUTES_2 FvbAttributes; EFI_FV_BLOCK_MAP_ENTRY *BlockMap; FFS_FILE_LIST_ENTRY *FfsFileEntry; EFI_FFS_FILE_HEADER *FfsHeader; UINT8 *CacheLocation; UINTN LbaOffset; UINTN HeaderSize; UINTN Index; EFI_LBA LbaIndex; UINTN Size; EFI_FFS_FILE_STATE FileState; UINT8 *TopFvAddress; UINTN TestLength; EFI_PHYSICAL_ADDRESS PhysicalAddress; BOOLEAN FileCached; UINTN WholeFileSize; EFI_FFS_FILE_HEADER *CacheFfsHeader; FileCached = FALSE; CacheFfsHeader = NULL; Fvb = FvDevice->Fvb; FwVolHeader = FvDevice->FwVolHeader; Status = Fvb->GetAttributes (Fvb, &FvbAttributes); if (EFI_ERROR (Status)) { return Status; } // // Size is the size of the FV minus the head. We have already allocated // the header to check to make sure the volume is valid // Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength); if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { FvDevice->IsMemoryMapped = TRUE; Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress); if (EFI_ERROR (Status)) { return Status; } // // Don't cache memory mapped FV really. // FvDevice->CachedFv = (UINT8 *) (UINTN) (PhysicalAddress + FwVolHeader->HeaderLength); } else { FvDevice->IsMemoryMapped = FALSE; FvDevice->CachedFv = AllocatePool (Size); if (FvDevice->CachedFv == NULL) { return EFI_OUT_OF_RESOURCES; } } // // Remember a pointer to the end fo the CachedFv // FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size; if (!FvDevice->IsMemoryMapped) { // // Copy FV minus header into memory using the block map we have all ready // read into memory. // BlockMap = FwVolHeader->BlockMap; CacheLocation = FvDevice->CachedFv; LbaIndex = 0; LbaOffset = 0; HeaderSize = FwVolHeader->HeaderLength; while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { Index = 0; Size = BlockMap->Length; if (HeaderSize > 0) { // // Skip header size // for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) { HeaderSize -= BlockMap->Length; LbaIndex ++; } // // Check whether FvHeader is crossing the multi block range. // if (Index >= BlockMap->NumBlocks) { BlockMap++; continue; } else if (HeaderSize > 0) { LbaOffset = HeaderSize; Size = BlockMap->Length - HeaderSize; HeaderSize = 0; } } // // read the FV data // for (; Index < BlockMap->NumBlocks; Index ++) { Status = Fvb->Read (Fvb, LbaIndex, LbaOffset, &Size, CacheLocation ); // // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length // if (EFI_ERROR (Status)) { goto Done; } LbaIndex++; CacheLocation += Size; // // After we skip Fv Header always read from start of block // LbaOffset = 0; Size = BlockMap->Length; } BlockMap++; } } // // Scan to check the free space & File list // if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) { FvDevice->ErasePolarity = 1; } else { FvDevice->ErasePolarity = 0; } // // go through the whole FV cache, check the consistence of the FV. // Make a linked list of all the Ffs file headers // Status = EFI_SUCCESS; InitializeListHead (&FvDevice->FfsFileListHeader); // // Build FFS list // if (FwVolHeader->ExtHeaderOffset != 0) { // // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. // FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + (FwVolHeader->ExtHeaderOffset - FwVolHeader->HeaderLength)); FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize); FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv); } TopFvAddress = FvDevice->EndOfCachedFv; while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) { if (FileCached) { CoreFreePool (CacheFfsHeader); FileCached = FALSE; } TestLength = TopFvAddress - ((UINT8 *) FfsHeader); if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { TestLength = sizeof (EFI_FFS_FILE_HEADER); } if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) { // // We have found the free space so we are done! // goto Done; } if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) { if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { if (IS_FFS_FILE2 (FfsHeader)) { if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsHeader->Name)); } FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2)); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER)); } continue; } else { // // File system is corrputed // Status = EFI_VOLUME_CORRUPTED; goto Done; } } CacheFfsHeader = FfsHeader; if ((CacheFfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) { if (FvDevice->IsMemoryMapped) { // // Memory mapped FV has not been cached. // Here is to cache FFS file to memory buffer for following checksum calculating. // And then, the cached file buffer can be also used for FvReadFile. // WholeFileSize = IS_FFS_FILE2 (CacheFfsHeader) ? FFS_FILE2_SIZE (CacheFfsHeader): FFS_FILE_SIZE (CacheFfsHeader); CacheFfsHeader = AllocateCopyPool (WholeFileSize, CacheFfsHeader); if (CacheFfsHeader == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } FileCached = TRUE; } } if (!IsValidFfsFile (FvDevice->ErasePolarity, CacheFfsHeader)) { // // File system is corrupted // Status = EFI_VOLUME_CORRUPTED; goto Done; } if (IS_FFS_FILE2 (CacheFfsHeader)) { ASSERT (FFS_FILE2_SIZE (CacheFfsHeader) > 0x00FFFFFF); if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &CacheFfsHeader->Name)); FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader)); // // Adjust pointer to the next 8-byte aligned boundry. // FfsHeader = (EFI_FFS_FILE_HEADER *) (((UINTN) FfsHeader + 7) & ~0x07); continue; } } FileState = GetFileState (FvDevice->ErasePolarity, CacheFfsHeader); // // check for non-deleted file // if (FileState != EFI_FILE_DELETED) { // // Create a FFS list entry for each non-deleted file // FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); if (FfsFileEntry == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } FfsFileEntry->FfsHeader = CacheFfsHeader; FfsFileEntry->FileCached = FileCached; FileCached = FALSE; InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); } if (IS_FFS_FILE2 (CacheFfsHeader)) { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader)); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE_SIZE (CacheFfsHeader)); } // // Adjust pointer to the next 8-byte aligned boundry. // FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07); } Done: if (EFI_ERROR (Status)) { if (FileCached) { CoreFreePool (CacheFfsHeader); FileCached = FALSE; } FreeFvDeviceResource (FvDevice); } return Status; }
/** Check if an FV is consistent and allocate cache for it. @param FvDevice A pointer to the FvDevice to be checked. @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. @retval EFI_VOLUME_CORRUPTED File system is corrupted. @retval EFI_SUCCESS FV is consistent and cache is allocated. **/ EFI_STATUS FvCheck ( IN FV_DEVICE *FvDevice ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FVB_ATTRIBUTES_2 FvbAttributes; EFI_FV_BLOCK_MAP_ENTRY *BlockMap; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; UINT8 *FwCache; LBA_ENTRY *LbaEntry; FREE_SPACE_ENTRY *FreeSpaceEntry; FFS_FILE_LIST_ENTRY *FfsFileEntry; UINT8 *LbaStart; UINTN Index; EFI_LBA LbaIndex; UINT8 *Ptr; UINTN Size; UINT8 *FreeStart; UINTN FreeSize; UINT8 ErasePolarity; EFI_FFS_FILE_STATE FileState; UINT8 *TopFvAddress; UINTN TestLength; EFI_PHYSICAL_ADDRESS BaseAddress; Fvb = FvDevice->Fvb; Status = Fvb->GetAttributes (Fvb, &FvbAttributes); if (EFI_ERROR (Status)) { return Status; } InitializeListHead (&FvDevice->LbaHeader); InitializeListHead (&FvDevice->FreeSpaceHeader); InitializeListHead (&FvDevice->FfsFileListHeader); FwVolHeader = NULL; Status = GetFwVolHeader (Fvb, &FwVolHeader); if (EFI_ERROR (Status)) { return Status; } ASSERT (FwVolHeader != NULL); FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); // // Double Check firmware volume header here // if (!VerifyFvHeaderChecksum (FwVolHeader)) { FreePool (FwVolHeader); return EFI_VOLUME_CORRUPTED; } BlockMap = FwVolHeader->BlockMap; // // FwVolHeader->FvLength is the whole FV length including FV header // FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength); if (FwCache == NULL) { FreePool (FwVolHeader); return EFI_OUT_OF_RESOURCES; } FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache; // // Copy to memory // LbaStart = FwCache; LbaIndex = 0; Ptr = NULL; if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { // // Get volume base address // Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress); if (EFI_ERROR (Status)) { FreePool (FwVolHeader); return Status; } Ptr = (UINT8 *) ((UINTN) BaseAddress); DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress)); } // // Copy whole FV into the memory // while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { for (Index = 0; Index < BlockMap->NumBlocks; Index++) { LbaEntry = AllocatePool (sizeof (LBA_ENTRY)); if (LbaEntry == NULL) { FreePool (FwVolHeader); FreeFvDeviceResource (FvDevice); return EFI_OUT_OF_RESOURCES; } LbaEntry->LbaIndex = LbaIndex; LbaEntry->StartingAddress = LbaStart; LbaEntry->BlockLength = BlockMap->Length; // // Copy each LBA into memory // if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { CopyMem (LbaStart, Ptr, BlockMap->Length); Ptr += BlockMap->Length; } else { Size = BlockMap->Length; Status = Fvb->Read ( Fvb, LbaIndex, 0, &Size, LbaStart ); // // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length // if (EFI_ERROR (Status)) { FreePool (FwVolHeader); FreeFvDeviceResource (FvDevice); return Status; } } LbaIndex++; LbaStart += BlockMap->Length; InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link); } BlockMap++; } FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache; // // it is not used any more, so free FwVolHeader // FreePool (FwVolHeader); // // Scan to check the free space & File list // if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) { ErasePolarity = 1; } else { ErasePolarity = 0; } FvDevice->ErasePolarity = ErasePolarity; // // go through the whole FV cache, check the consistence of the FV // if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) { // // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. // FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset); Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize; Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8); } else { Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength); } TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength); // // Build FFS list & Free Space List here // while (Ptr < TopFvAddress) { TestLength = TopFvAddress - Ptr; if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { TestLength = sizeof (EFI_FFS_FILE_HEADER); } if (IsBufferErased (ErasePolarity, Ptr, TestLength)) { // // We found free space // FreeStart = Ptr; FreeSize = 0; do { TestLength = TopFvAddress - Ptr; if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { TestLength = sizeof (EFI_FFS_FILE_HEADER); } if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) { break; } FreeSize += TestLength; Ptr += TestLength; } while (Ptr < TopFvAddress); FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY)); if (FreeSpaceEntry == NULL) { FreeFvDeviceResource (FvDevice); return EFI_OUT_OF_RESOURCES; } // // Create a Free space entry // FreeSpaceEntry->StartingAddress = FreeStart; FreeSpaceEntry->Length = FreeSize; InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link); continue; } // // double check boundry // if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) { break; } if (!IsValidFFSHeader ( FvDevice->ErasePolarity, (EFI_FFS_FILE_HEADER *) Ptr )) { FileState = GetFileState ( FvDevice->ErasePolarity, (EFI_FFS_FILE_HEADER *) Ptr ); if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { if (IS_FFS_FILE2 (Ptr)) { if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name)); } Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2); } else { Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER); } continue; } else { // // File system is corrputed, return // FreeFvDeviceResource (FvDevice); return EFI_VOLUME_CORRUPTED; } } if (IS_FFS_FILE2 (Ptr)) { ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF); if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name)); Ptr = Ptr + FFS_FILE2_SIZE (Ptr); // // Adjust Ptr to the next 8-byte aligned boundry. // while (((UINTN) Ptr & 0x07) != 0) { Ptr++; } continue; } } if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) { FileState = GetFileState ( FvDevice->ErasePolarity, (EFI_FFS_FILE_HEADER *) Ptr ); // // check for non-deleted file // if (FileState != EFI_FILE_DELETED) { // // Create a FFS list entry for each non-deleted file // FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); if (FfsFileEntry == NULL) { FreeFvDeviceResource (FvDevice); return EFI_OUT_OF_RESOURCES; } FfsFileEntry->FfsHeader = Ptr; InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); } if (IS_FFS_FILE2 (Ptr)) { Ptr = Ptr + FFS_FILE2_SIZE (Ptr); } else { Ptr = Ptr + FFS_FILE_SIZE (Ptr); } // // Adjust Ptr to the next 8-byte aligned boundry. // while (((UINTN) Ptr & 0x07) != 0) { Ptr++; } } else { // // File system is corrupted, return // FreeFvDeviceResource (FvDevice); return EFI_VOLUME_CORRUPTED; } } FvDevice->CurrentFfsFile = NULL; return EFI_SUCCESS; }
/** Create a PAD File in the Free Space. @param FvDevice Firmware Volume Device. @param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted. @param Size Pad file Size, not include the header. @param PadFileEntry The Ffs File Entry that points to this Pad File. @retval EFI_SUCCESS Successfully create a PAD file. @retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file. @retval EFI_INVALID_PARAMETER Size is not 8 byte alignment. @retval EFI_DEVICE_ERROR Free space is not erased. **/ EFI_STATUS FvCreatePadFileInFreeSpace ( IN FV_DEVICE *FvDevice, IN FREE_SPACE_ENTRY *FreeSpaceEntry, IN UINTN Size, OUT FFS_FILE_LIST_ENTRY **PadFileEntry ) { EFI_STATUS Status; EFI_FFS_FILE_HEADER *PadFileHeader; UINTN Offset; UINTN NumBytesWritten; UINTN StateOffset; UINT8 *StartPos; FFS_FILE_LIST_ENTRY *FfsFileEntry; UINTN HeaderSize; UINTN FileSize; HeaderSize = sizeof (EFI_FFS_FILE_HEADER); FileSize = Size + HeaderSize; if (FileSize > 0x00FFFFFF) { HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); FileSize = Size + HeaderSize; } if (FreeSpaceEntry->Length < FileSize) { return EFI_OUT_OF_RESOURCES; } if ((Size & 0x07) != 0) { return EFI_INVALID_PARAMETER; } StartPos = FreeSpaceEntry->StartingAddress; // // First double check the space // if (!IsBufferErased ( FvDevice->ErasePolarity, StartPos, FileSize )) { return EFI_DEVICE_ERROR; } PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos; // // Create File Step 1 // SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader); Offset = (UINTN) (StartPos - FvDevice->CachedFv); StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader; NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); Status = FvcWrite ( FvDevice, StateOffset, &NumBytesWritten, &PadFileHeader->State ); if (EFI_ERROR (Status)) { SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader); return Status; } // // Update Free Space Entry, since header is allocated // FreeSpaceEntry->Length -= HeaderSize; FreeSpaceEntry->StartingAddress += HeaderSize; // // Fill File Name Guid, here we assign a NULL-GUID to Pad files // ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID)); // // Fill File Type, checksum(0), Attributes(0), Size // PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD; PadFileHeader->Attributes = 0; if ((FileSize) > 0x00FFFFFF) { ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) FileSize; *(UINT32 *) PadFileHeader->Size &= 0xFF000000; PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE; } else { *(UINT32 *) PadFileHeader->Size &= 0xFF000000; *(UINT32 *) PadFileHeader->Size |= FileSize; } SetHeaderChecksum (PadFileHeader); SetPadFileChecksum (PadFileHeader); Offset = (UINTN) (StartPos - FvDevice->CachedFv); NumBytesWritten = HeaderSize; Status = FvcWrite ( FvDevice, Offset, &NumBytesWritten, (UINT8 *) PadFileHeader ); if (EFI_ERROR (Status)) { return Status; } // // Step 2, then Mark header valid, since no data write, // mark the data valid at the same time. // SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader); SetFileState (EFI_FILE_DATA_VALID, PadFileHeader); Offset = (UINTN) (StartPos - FvDevice->CachedFv); StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader; NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); Status = FvcWrite ( FvDevice, StateOffset, &NumBytesWritten, &PadFileHeader->State ); if (EFI_ERROR (Status)) { SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader); SetFileState (EFI_FILE_DATA_VALID, PadFileHeader); return Status; } // // Update Free Space Entry, since header is allocated // FreeSpaceEntry->Length -= Size; FreeSpaceEntry->StartingAddress += Size; // // If successfully, insert an FfsFileEntry at the end of ffs file list // FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); ASSERT (FfsFileEntry != NULL); FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) StartPos; InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); *PadFileEntry = FfsFileEntry; FvDevice->CurrentFfsFile = FfsFileEntry; return EFI_SUCCESS; }
/** Get FFS buffer pointer by FileName GUID and FileType. @param[in] FdStart The System Firmware FD image @param[in] FdSize The size of System Firmware FD image @param[in] FileName The FileName GUID of FFS to be found @param[in] Type The FileType of FFS to be found @param[out] OutFfsBuffer The FFS buffer found, including FFS_FILE_HEADER @param[out] OutFfsBufferSize The size of FFS buffer found, including FFS_FILE_HEADER @retval TRUE The FFS buffer is found. @retval FALSE The FFS buffer is not found. **/ BOOLEAN GetFfsByName ( IN VOID *FdStart, IN UINTN FdSize, IN EFI_GUID *FileName, IN EFI_FV_FILETYPE Type, OUT VOID **OutFfsBuffer, OUT UINTN *OutFfsBufferSize ) { UINTN FvSize; EFI_FIRMWARE_VOLUME_HEADER *FvHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; EFI_FFS_FILE_HEADER *FfsHeader; UINT32 FfsSize; UINTN TestLength; BOOLEAN FvFound; DEBUG ((DEBUG_INFO, "GetFfsByName - FV: 0x%08x - 0x%08x\n", (UINTN)FdStart, (UINTN)FdSize)); FvFound = FALSE; FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FdStart; while ((UINTN)FvHeader < (UINTN)FdStart + FdSize - 1) { FvSize = (UINTN)FdStart + FdSize - (UINTN)FvHeader; if (FvHeader->Signature != EFI_FVH_SIGNATURE) { FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvHeader + SIZE_4KB); continue; } DEBUG((DEBUG_ERROR, "checking FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength)); FvFound = TRUE; if (FvHeader->FvLength > FvSize) { DEBUG((DEBUG_ERROR, "GetFfsByName - FvSize: 0x%08x, MaxSize - 0x%08x\n", (UINTN)FvHeader->FvLength, (UINTN)FvSize)); return FALSE; } FvSize = (UINTN)FvHeader->FvLength; // // Find FFS // if (FvHeader->ExtHeaderOffset != 0) { FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + FvHeader->ExtHeaderOffset); FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvExtHeader + FvExtHeader->ExtHeaderSize); } else { FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvHeader + FvHeader->HeaderLength); } FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FvHeader + ALIGN_VALUE((UINTN)FfsHeader - (UINTN)FvHeader, 8)); while ((UINTN)FfsHeader < (UINTN)FvHeader + FvSize - 1) { DEBUG((DEBUG_INFO, "GetFfsByName - FFS: 0x%08x\n", FfsHeader)); TestLength = (UINTN)((UINTN)FvHeader + FvSize - (UINTN)FfsHeader); if (TestLength > sizeof(EFI_FFS_FILE_HEADER)) { TestLength = sizeof(EFI_FFS_FILE_HEADER); } if (IsBufferErased(1, FfsHeader, TestLength)) { break; } if (IS_FFS_FILE2(FfsHeader)) { FfsSize = FFS_FILE2_SIZE(FfsHeader); } else { FfsSize = FFS_FILE_SIZE(FfsHeader); } if (CompareGuid(FileName, &FfsHeader->Name) && ((Type == EFI_FV_FILETYPE_ALL) || (FfsHeader->Type == Type))) { // // Check section // *OutFfsBuffer = FfsHeader; *OutFfsBufferSize = FfsSize; return TRUE; } else { // // Any other type is not allowed // DEBUG((DEBUG_INFO, "GetFfsByName - other FFS type 0x%x, name %g\n", FfsHeader->Type, &FfsHeader->Name)); } // // Next File // FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FfsHeader + ALIGN_VALUE(FfsSize, 8)); } // // Next FV // FvHeader = (VOID *)(UINTN)((UINTN)FvHeader + FvHeader->FvLength); DEBUG((DEBUG_ERROR, "Next FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength)); } if (!FvFound) { DEBUG((DEBUG_ERROR, "GetFfsByName - NO FV Found\n")); } return FALSE; }