4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Implements functions to pad firmware file.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync of the BSD License which accompanies this distribution. The
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "FwVolDriver.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Calculate the checksum for a PAD file.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PadFileHeader The Pad File to be caculeted the checksum.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSetPadFileChecksum (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FFS_FILE_HEADER *PadFileHeader
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PadFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IS_FFS_FILE2 (PadFileHeader)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Calculate checksum of Pad File Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->IntegrityCheck.Checksum.File =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Calculate checksum of Pad File Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->IntegrityCheck.Checksum.File =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create a PAD File in the Free Space.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FvDevice Firmware Volume Device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Size Pad file Size, not include the header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PadFileEntry The Ffs File Entry that points to this Pad File.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Successfully create a PAD file.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Size is not 8 byte alignment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR Free space is not erased.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFvCreatePadFileInFreeSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN FV_DEVICE *FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN FREE_SPACE_ENTRY *FreeSpaceEntry,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT FFS_FILE_LIST_ENTRY **PadFileEntry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN NumBytesWritten;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN StateOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *StartPos;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *FfsFileEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN FileSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileSize = Size + HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FileSize > 0x00FFFFFF) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileSize = Size + HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FreeSpaceEntry->Length < FileSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Size & 0x07) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos = FreeSpaceEntry->StartingAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First double check the space
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsBufferErased (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->ErasePolarity,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create File Step 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINTN) (StartPos - FvDevice->CachedFv);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvcWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StateOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NumBytesWritten,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PadFileHeader->State
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update Free Space Entry, since header is allocated
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeSpaceEntry->Length -= HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeSpaceEntry->StartingAddress += HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill File Name Guid, here we assign a NULL-GUID to Pad files
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill File Type, checksum(0), Attributes(0), Size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->Attributes = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((FileSize) > 0x00FFFFFF) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) FileSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) PadFileHeader->Size |= FileSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetHeaderChecksum (PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetPadFileChecksum (PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINTN) (StartPos - FvDevice->CachedFv);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumBytesWritten = HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvcWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NumBytesWritten,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8 *) PadFileHeader
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 2, then Mark header valid, since no data write,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // mark the data valid at the same time.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINTN) (StartPos - FvDevice->CachedFv);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvcWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StateOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NumBytesWritten,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PadFileHeader->State
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update Free Space Entry, since header is allocated
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeSpaceEntry->Length -= Size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeSpaceEntry->StartingAddress += Size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If successfully, insert an FfsFileEntry at the end of ffs file list
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (FfsFileEntry != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) StartPos;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *PadFileEntry = FfsFileEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = FfsFileEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fill pad file header within firmware cache.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PadFileHeader The start of the Pad File Buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PadFileLength The length of the pad file including the header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFvFillPadFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FFS_FILE_HEADER *PadFileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN PadFileLength
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill File Name Guid, here we assign a NULL-GUID to Pad files
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill File Type, checksum(0), Attributes(0), Size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->Attributes = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadFileLength > 0x00FFFFFF) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) PadFileLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) PadFileHeader->Size |= PadFileLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetHeaderChecksum (PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetPadFileChecksum (PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set File State to 0x00000111
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create entire FFS file.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileHeader Starting Address of a Buffer that hold the FFS File image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FfsFileBuffer The source buffer that contains the File Data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BufferSize The length of FfsFileBuffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ActualFileSize Size of FFS file.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileName The Guid of Ffs File.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileType The type of the written Ffs File.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileAttributes The attributes of the written Ffs File.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER File type is not valid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS FFS file is successfully created.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFvFillFfsFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT EFI_FFS_FILE_HEADER *FileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 *FfsFileBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN ActualFileSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_GUID *FileName,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FV_FILETYPE FileType,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FV_FILE_ATTRIBUTES FileAttributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *TmpFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // File Type value 0x0E~0xE0 are reserved
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TmpFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First fill all fields ready in FfsFileBuffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyGuid (&TmpFileHeader->Name, FileName);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TmpFileHeader->Type = FileType;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Convert the FileAttributes to FFSFileAttributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TmpFileHeader->Attributes = TmpFileAttribute;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ActualFileSize > 0x00FFFFFF) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) FileHeader->Size &= 0xFF000000;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) FileHeader->Size &= 0xFF000000;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *(UINT32 *) FileHeader->Size |= ActualFileSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetHeaderChecksum (TmpFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileChecksum (TmpFileHeader, ActualFileSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_CONSTRUCTION, TmpFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_VALID, TmpFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_DATA_VALID, TmpFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy data from FfsFileBuffer to FileHeader(cache)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (FileHeader, FfsFileBuffer, BufferSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fill some other extra space using 0xFF(Erase Value).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ErasePolarity Fv erase value.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileHeader Point to the start of FFS File.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ExtraLength The pading length.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFvAdjustFfsFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 ErasePolarity,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FFS_FILE_HEADER *FileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN ExtraLength
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Ptr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 PadingByte;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IS_FFS_FILE2 (FileHeader)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ptr = (UINT8 *) FileHeader + FFS_FILE2_SIZE (FileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ptr = (UINT8 *) FileHeader + FFS_FILE_SIZE (FileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ErasePolarity == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadingByte = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadingByte = 0xFF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill the non-used space with Padding Byte
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetMem (Ptr, ExtraLength, PadingByte);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Free File List entry pointed by FileListHead.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileListHeader FileListEntry Header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFreeFileList (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN LIST_ENTRY *FileListHead
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *FfsFileEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *NextEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsFileEntry = (FFS_FILE_LIST_ENTRY *) (FileListHead->ForwardLink);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Loop the whole list entry to free resources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (&FfsFileEntry->Link != FileListHead) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NextEntry = (&FfsFileEntry->Link)->ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (FfsFileEntry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create a new file within a PAD file area.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FvDevice Firmware Volume Device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BufferSize The size of FfsFileBuffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ActualFileSize The actual file length, it may not be multiples of 8.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileName The FFS File Name.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileType The FFS File Type.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileAttributes The Attributes of the FFS File to be created.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Successfully create a new file within the found PAD file area.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES No suitable PAD file is found.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval other errors New file is created failed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFvCreateNewFileInsidePadFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN FV_DEVICE *FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 *FfsFileBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN ActualFileSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_GUID *FileName,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FV_FILETYPE FileType,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FV_FILE_ATTRIBUTES FileAttributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN RequiredAlignment;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *PadFileEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN PadAreaLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN PadSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *FileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *OldPadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *TailPadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN StateOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN NumBytesWritten;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *StartPos;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY NewFileList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *NewFileListEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *FfsEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *NextFfsEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First get the required alignment from the File Attributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RequiredAlignment = GetRequiredAlignment (FileAttributes);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find a suitable PAD File
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvLocatePadFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RequiredAlignment,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PadSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PadFileEntry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 1: Update Pad File Header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldPadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos = PadFileEntry->FfsHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINTN) (StartPos - FvDevice->CachedFv);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StateOffset = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvcWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StateOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NumBytesWritten,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &OldPadFileHeader->State
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_CONSTRUCTION, OldPadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 2: Update Pad area
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IS_FFS_FILE2 (OldPadFileHeader)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadSize != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Insert a PAD file before to achieve required alignment
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvFillPadFile (PadFileHeader, PadSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (NewFileListEntry != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NewFileList, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvFillFfsFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsFileBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualFileSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileName,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileType,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileAttributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (NewFileListEntry != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NewFileList, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NewFileListEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadAreaLength > (BufferSize + PadSize)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PadAreaLength - BufferSize - PadSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // we can insert another PAD file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvFillPadFile (TailPadFileHeader, PadAreaLength - BufferSize - PadSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (NewFileListEntry != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NewFileList, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // because left size cannot hold another PAD file header,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // adjust the writing file size (just in cache)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvAdjustFfsFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->ErasePolarity,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadAreaLength - BufferSize - PadSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Start writing to FV
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IS_FFS_FILE2 (OldPadFileHeader)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINTN) (StartPos - FvDevice->CachedFv);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumBytesWritten = PadAreaLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvcWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NumBytesWritten,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos = PadFileEntry->FfsHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINTN) (StartPos - FvDevice->CachedFv);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StateOffset = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvcWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StateOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NumBytesWritten,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &OldPadFileHeader->State
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If all successfully, update FFS_FILE_LIST
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Delete old pad file entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NextFfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (PadFileEntry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsEntry->Link.ForwardLink = NewFileList.ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NextFfsEntry->Link.BackLink = NewFileList.BackLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Free all FfsBuffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param NumOfFiles Number of FfsBuffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FfsBuffer An array of pointer to an FFS File Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFreeFfsBuffer (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN NumOfFiles,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 **FfsBuffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < NumOfFiles; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FfsBuffer[Index] != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (FfsBuffer[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create multiple files within a PAD File area.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FvDevice Firmware Volume Device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PadFileEntry The pad file entry to be written in.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param NumOfFiles Total File number to be written.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BufferSize The array of buffer size of each FfsBuffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ActualFileSize The array of actual file size.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PadSize The array of leading pad file size for each FFS File
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FfsBuffer The array of Ffs Buffer pointer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync used to get name, attributes, type, etc.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Add the input multiple files into PAD file area.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval other error Files can't be added into PAD file area.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFvCreateMultipleFilesInsidePadFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN FV_DEVICE *FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN FFS_FILE_LIST_ENTRY *PadFileEntry,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN NumOfFiles,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN *BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN *ActualFileSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN *PadSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 **FfsBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FV_WRITE_FILE_DATA *FileData
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *OldPadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *FileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *TailPadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN PadAreaLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY NewFileList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *NewFileListEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN NumBytesWritten;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *StartPos;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *FfsEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *NextFfsEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IS_FFS_FILE2 (OldPadFileHeader)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = UpdateHeaderBit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldPadFileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FILE_MARKED_FOR_UPDATE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update PAD area
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TotalSize = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IS_FFS_FILE2 (OldPadFileHeader)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader = PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < NumOfFiles; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadSize[Index] != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvFillPadFile (PadFileHeader, PadSize[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewFileListEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NewFileList, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvFillFfsFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsBuffer[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualFileSize[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index].NameGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index].Type,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index].FileAttributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewFileListEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NewFileList, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TotalSize += PadSize[Index];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TotalSize += BufferSize[Index];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NewFileListEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Maybe we need a tail pad file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadAreaLength > TotalSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PadAreaLength - TotalSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // we can insert another PAD file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[NumOfFiles - 1]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvFillPadFile (TailPadFileHeader, PadAreaLength - TotalSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewFileListEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NewFileList, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // because left size cannot hold another PAD file header,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // adjust the writing file size (just in cache)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvAdjustFfsFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->ErasePolarity,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadAreaLength - TotalSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Start writing to FV
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IS_FFS_FILE2 (OldPadFileHeader)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINTN) (StartPos - FvDevice->CachedFv);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumBytesWritten = PadAreaLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvcWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NumBytesWritten,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = UpdateHeaderBit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldPadFileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FILE_HEADER_INVALID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update File List Link
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First delete old pad file entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NextFfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (PadFileEntry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsEntry->Link.ForwardLink = NewFileList.ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NextFfsEntry->Link.BackLink = NewFileList.BackLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create multiple files within the Free Space.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FvDevice Firmware Volume Device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FreeSpaceEntry Indicating in which Free Space(Cache) the multiple files will be inserted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param NumOfFiles Total File number to be written.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BufferSize The array of buffer size of each FfsBuffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ActualFileSize The array of actual file size.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PadSize The array of leading pad file size for each FFS File
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FfsBuffer The array of Ffs Buffer pointer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync used to get name, attributes, type, etc.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Add the input multiple files into PAD file area.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval other error Files can't be added into PAD file area.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFvCreateMultipleFilesInsideFreeSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN FV_DEVICE *FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN FREE_SPACE_ENTRY *FreeSpaceEntry,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN NumOfFiles,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN *BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN *ActualFileSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN *PadSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 **FfsBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FV_WRITE_FILE_DATA *FileData
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *FileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY NewFileList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *NewFileListEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN NumBytesWritten;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *StartPos;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TotalSize = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos = FreeSpaceEntry->StartingAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader = PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < NumOfFiles; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadSize[Index] != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvFillPadFile (PadFileHeader, PadSize[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewFileListEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NewFileList, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvFillFfsFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileHeader,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsBuffer[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualFileSize[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index].NameGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index].Type,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index].FileAttributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewFileListEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NewFileList, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TotalSize += PadSize[Index];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TotalSize += BufferSize[Index];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FreeSpaceEntry->Length < TotalSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NewFileListEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Start writing to FV
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINTN) (StartPos - FvDevice->CachedFv);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumBytesWritten = TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvcWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NumBytesWritten,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartPos
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFileList (&NewFileList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice->CurrentFfsFile = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeSpaceEntry->Length -= TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeSpaceEntry->StartingAddress += TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileList.ForwardLink);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (NewFileListEntry != (FFS_FILE_LIST_ENTRY *) &NewFileList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&FvDevice->FfsFileListHeader, &NewFileListEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileListEntry->Link.ForwardLink);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Write multiple files into FV in reliable method.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FvDevice Firmware Volume Device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param NumOfFiles Total File number to be written.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync used to get name, attributes, type, etc
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param FileOperation The array of operation for each file.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Files are added into FV.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER File number is less than or equal to 1.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFvCreateMultipleFiles (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN FV_DEVICE *FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN NumOfFiles,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_FV_WRITE_FILE_DATA *FileData,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN *FileOperation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *FfsBuffer[MAX_FILES];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN BufferSize[MAX_FILES];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN ActualFileSize[MAX_FILES];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN RequiredAlignment[MAX_FILES];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN PadSize[MAX_FILES];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *PadFileEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN TotalSizeNeeded;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FREE_SPACE_ENTRY *FreeSpaceEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Key;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_GUID FileNameGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FV_FILETYPE OldFileType;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FV_FILE_ATTRIBUTES OldFileAttributes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN OldFileSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FFS_FILE_LIST_ENTRY *OldFfsFileEntry[MAX_FILES];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FFS_FILE_HEADER *OldFileHeader[MAX_FILES];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IsCreateFile;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // To use this function, we must ensure that the NumOfFiles is great
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // than 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumOfFiles <= 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumOfFiles > MAX_FILES) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fv = &FvDevice->Fv;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetMem (FfsBuffer, NumOfFiles, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetMem (RequiredAlignment, NumOfFiles, 8);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetMem (PadSize, NumOfFiles, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (OldFfsFileEntry, sizeof (OldFfsFileEntry));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (OldFileHeader, sizeof (OldFileHeader));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Adjust file size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ActualFileSize[Index1] > 0x00FFFFFF) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize[Index1] = ActualFileSize[Index1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (BufferSize[Index1] == HeaderSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // clear file attributes, zero-length file does not have any attributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index1].FileAttributes = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ((BufferSize[Index1] & 0x07) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize[Index1]++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsBuffer[Index1] = AllocateZeroPool (BufferSize[Index1]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy File Data into FileBuffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsBuffer[Index1] + HeaderSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index1].Buffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData[Index1].BufferSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FvDevice->ErasePolarity == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index2 = 0; Index2 < HeaderSize; Index2++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsBuffer[Index1][Index2] = (UINT8)~FfsBuffer[Index1][Index2];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RequiredAlignment[Index1] = GetRequiredAlignment (FileData[Index1].FileAttributes);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If update file, mark the original file header to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // EFI_FILE_MARKED_FOR_UPDATE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsCreateFile = FileOperation[Index1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsCreateFile) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Key = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldFileType = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Fv->GetNextFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fv,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Key,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &OldFileType,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &FileNameGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &OldFileAttributes,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &OldFileSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFfsBuffer (NumOfFiles, FfsBuffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (!CompareGuid (&FileNameGuid, FileData[Index1].NameGuid));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get FfsFileEntry from the search key
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldFfsFileEntry[Index1] = (FFS_FILE_LIST_ENTRY *) Key;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldFileHeader[Index1] = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry[Index1]->FfsHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = UpdateHeaderBit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldFileHeader[Index1],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_FILE_MARKED_FOR_UPDATE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFfsBuffer (NumOfFiles, FfsBuffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First to search a suitable pad file that can hold so
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // many files
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvSearchSuitablePadFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumOfFiles,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RequiredAlignment,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &TotalSizeNeeded,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PadFileEntry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Status == EFI_NOT_FOUND) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Try to find a free space that can hold these files
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvSearchSuitableFreeSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumOfFiles,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RequiredAlignment,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &TotalSizeNeeded,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &FreeSpaceEntry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFfsBuffer (NumOfFiles, FfsBuffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvCreateMultipleFilesInsideFreeSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeSpaceEntry,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumOfFiles,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualFileSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create multiple files inside such a pad file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to achieve lock-step update
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FvCreateMultipleFilesInsidePadFile (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FvDevice,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadFileEntry,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumOfFiles,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualFileSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FfsBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FileData
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeFfsBuffer (NumOfFiles, FfsBuffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Delete those updated files
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsCreateFile = FileOperation[Index1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsCreateFile && OldFfsFileEntry[Index1] != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (OldFfsFileEntry[Index1]->Link.BackLink)->ForwardLink = OldFfsFileEntry[Index1]->Link.ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (OldFfsFileEntry[Index1]->Link.ForwardLink)->BackLink = OldFfsFileEntry[Index1]->Link.BackLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (OldFfsFileEntry[Index1]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set those files' state to EFI_FILE_DELETED
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsCreateFile = FileOperation[Index1];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsCreateFile && OldFileHeader[Index1] != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = UpdateHeaderBit (FvDevice, OldFileHeader[Index1], EFI_FILE_DELETED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}