Exemple #1
0
/**
  Fill some other extra space using 0xFF(Erase Value).

  @param  ErasePolarity  Fv erase value.
  @param  FileHeader     Point to the start of FFS File.
  @param  ExtraLength    The pading length.

**/
VOID
FvAdjustFfsFile (
  IN  UINT8                 ErasePolarity,
  IN  EFI_FFS_FILE_HEADER   *FileHeader,
  IN  UINTN                 ExtraLength
  )
{
  UINT8 *Ptr;
  UINT8 PadingByte;

  if (IS_FFS_FILE2 (FileHeader)) {
    Ptr         = (UINT8 *) FileHeader + FFS_FILE2_SIZE (FileHeader);
  } else {
    Ptr         = (UINT8 *) FileHeader + FFS_FILE_SIZE (FileHeader);
  }

  if (ErasePolarity == 0) {
    PadingByte = 0;
  } else {
    PadingByte = 0xFF;
  }
  //
  // Fill the non-used space with Padding Byte
  //
  SetMem (Ptr, ExtraLength, PadingByte);

  return ;
}
static size_t file_section_offset(const EFI_FFS_FILE_HEADER *ffsfh)
{
	if (IS_FFS_FILE2(ffsfh))
		return sizeof(EFI_FFS_FILE_HEADER2);
	else
		return sizeof(EFI_FFS_FILE_HEADER);
}
Exemple #3
0
/**
  Extract the System Firmware image from an authenticated image.

  @param[in]  AuthenticatedImage      The authenticated capsule image.
  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
  @param[out] SystemFirmwareImage     The System Firmware image.
  @param[out] SystemFirmwareImageSize The size of the System Firmware image in bytes.

  @retval TRUE  The System Firmware image is extracted.
  @retval FALSE The System Firmware image is not extracted.
**/
BOOLEAN
EFIAPI
ExtractSystemFirmwareImage (
  IN VOID                         *AuthenticatedImage,
  IN UINTN                        AuthenticatedImageSize,
  OUT VOID                        **SystemFirmwareImage,
  OUT UINTN                       *SystemFirmwareImageSize
  )
{
  BOOLEAN     Result;
  UINT32      FileHeaderSize;

  *SystemFirmwareImage = NULL;
  *SystemFirmwareImageSize = 0;

  Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &mEdkiiSystemFirmwareFileGuid, EFI_FV_FILETYPE_RAW, SystemFirmwareImage, SystemFirmwareImageSize);
  if (!Result) {
    // no nested FV, just return all data.
    *SystemFirmwareImage = AuthenticatedImage;
    *SystemFirmwareImageSize = AuthenticatedImageSize;

    return TRUE;
  }
  if (IS_FFS_FILE2 (*SystemFirmwareImage)) {
    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
  } else {
    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
  }
  *SystemFirmwareImage = (UINT8 *)*SystemFirmwareImage + FileHeaderSize;
  *SystemFirmwareImageSize = *SystemFirmwareImageSize - FileHeaderSize;

  return Result;
}
Exemple #4
0
/**
  Calculate the checksum for a PAD file.

  @param PadFileHeader   The Pad File to be caculeted the checksum.

**/
VOID
SetPadFileChecksum (
  IN EFI_FFS_FILE_HEADER *PadFileHeader
  )
{
  if ((PadFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {

    if (IS_FFS_FILE2 (PadFileHeader)) {
      //
      // Calculate checksum of Pad File Data
      //
      PadFileHeader->IntegrityCheck.Checksum.File =
        CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2));

      } else {
      //
      // Calculate checksum of Pad File Data
      //
      PadFileHeader->IntegrityCheck.Checksum.File =
        CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER));
    }

  } else {

    PadFileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;

  }

  return ;
}
Exemple #5
0
/**
  Extract the config image from an authenticated image.

  @param[in]  AuthenticatedImage      The authenticated capsule image.
  @param[in]  AuthenticatedImageSize  The size of the authenticated capsule image in bytes.
  @param[out] ConfigImage             The config image.
  @param[out] ConfigImageSize         The size of the config image in bytes.

  @retval TRUE  The config image is extracted.
  @retval FALSE The config image is not extracted.
**/
BOOLEAN
EFIAPI
ExtractConfigImage (
  IN VOID                         *AuthenticatedImage,
  IN UINTN                        AuthenticatedImageSize,
  OUT VOID                        **ConfigImage,
  OUT UINTN                       *ConfigImageSize
  )
{
  BOOLEAN     Result;
  UINT32      FileHeaderSize;

  *ConfigImage = NULL;
  *ConfigImageSize = 0;

  Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleConfigFileGuid, EFI_FV_FILETYPE_RAW, ConfigImage, ConfigImageSize);
  if (!Result) {
    return FALSE;
  }

  if (IS_FFS_FILE2(*ConfigImage)) {
    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
  } else {
    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
  }
  *ConfigImage = (UINT8 *)*ConfigImage + FileHeaderSize;
  *ConfigImageSize = *ConfigImageSize - FileHeaderSize;

  return Result;
}
Exemple #6
0
/**
  Check if it's a valid FFS file.
  Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.

  @param  ErasePolarity  Erase polarity attribute of the firmware volume
  @param  FfsHeader      Points to the FFS file to be checked

  @retval TRUE           Valid FFS file
  @retval FALSE          Invalid FFS file

**/
BOOLEAN
IsValidFfsFile (
  IN UINT8                ErasePolarity,
  IN EFI_FFS_FILE_HEADER  *FfsHeader
  )
{
  EFI_FFS_FILE_STATE  FileState;
  UINT8               DataCheckSum;

  FileState = GetFileState (ErasePolarity, FfsHeader);
  switch (FileState) {

  case EFI_FILE_DELETED:
  case EFI_FILE_DATA_VALID:
  case EFI_FILE_MARKED_FOR_UPDATE:
    DataCheckSum = FFS_FIXED_CHECKSUM;
    if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) {
      if (IS_FFS_FILE2 (FfsHeader)) {
        DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (FfsHeader) - sizeof(EFI_FFS_FILE_HEADER2));
      } else {
        DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (FfsHeader) - sizeof(EFI_FFS_FILE_HEADER));
      }
    }
    if (FfsHeader->IntegrityCheck.Checksum.File == DataCheckSum) {
      return TRUE;
    }

  default:
    return FALSE;
  }
}
static size_t ffs_file_size(const EFI_FFS_FILE_HEADER *ffsfh)
{
	size_t size;

	if (IS_FFS_FILE2(ffsfh))
		size = read_le32(&FFS_FILE2_SIZE(ffsfh));
	else {
		size = read_le8(&ffsfh->Size[0]) << 0;
		size |= read_le8(&ffsfh->Size[1]) << 8;
		size |= read_le8(&ffsfh->Size[2]) << 16;
	}
	return size;
}
Exemple #8
0
static size_t ffs_file_size(const EFI_FFS_FILE_HEADER *ffsfh)
{
	size_t size;

	if (IS_FFS_FILE2(ffsfh))
		size = FFS_FILE2_SIZE(ffsfh);
	else {
		size = ffsfh->Size[0] << 0;
		size |= ffsfh->Size[1] << 8;
		size |= ffsfh->Size[2] << 16;
	}
	return size;
}
Exemple #9
0
/**
  Extract ImageFmpInfo from system firmware.

  @param[in]  SystemFirmwareImage     The System Firmware image.
  @param[in]  SystemFirmwareImageSize The size of the System Firmware image in bytes.
  @param[out] ImageFmpInfo            The ImageFmpInfo.
  @param[out] ImageFmpInfoSize        The size of the ImageFmpInfo in bytes.

  @retval TRUE  The ImageFmpInfo is extracted.
  @retval FALSE The ImageFmpInfo is not extracted.
**/
BOOLEAN
EFIAPI
ExtractSystemFirmwareImageFmpInfo (
  IN VOID                                      *SystemFirmwareImage,
  IN UINTN                                     SystemFirmwareImageSize,
  OUT EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   **ImageFmpInfo,
  OUT UINTN                                    *ImageFmpInfoSize
  )
{
  BOOLEAN     Result;
  UINT32      SectionHeaderSize;
  UINT32      FileHeaderSize;

  *ImageFmpInfo = NULL;
  *ImageFmpInfoSize = 0;

  Result = GetFfsByName(SystemFirmwareImage, SystemFirmwareImageSize, &gEdkiiSystemFirmwareImageDescriptorFileGuid, EFI_FV_FILETYPE_ALL, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
  if (!Result) {
    return FALSE;
  }
  if (IS_FFS_FILE2 (*ImageFmpInfo)) {
    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
  } else {
    FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
  }
  *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + FileHeaderSize);
  *ImageFmpInfoSize = *ImageFmpInfoSize - FileHeaderSize;

  Result = GetSectionByType(*ImageFmpInfo, (UINT32)*ImageFmpInfoSize, EFI_SECTION_RAW, 0, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
  if (!Result) {
    return FALSE;
  }
  if (IS_SECTION2(*ImageFmpInfo)) {
    SectionHeaderSize = sizeof(EFI_RAW_SECTION2);
  } else {
    SectionHeaderSize = sizeof(EFI_RAW_SECTION);
  }
  *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + SectionHeaderSize);
  *ImageFmpInfoSize = *ImageFmpInfoSize - SectionHeaderSize;

  return TRUE;
}
Exemple #10
0
/**
  Verify checksum of the FFS file header.

  @param  FfsHeader      Points to the FFS file header to be checked

  @retval TRUE           Checksum verification passed
  @retval FALSE          Checksum verification failed

**/
BOOLEAN
VerifyHeaderChecksum (
  IN EFI_FFS_FILE_HEADER  *FfsHeader
  )
{
  UINT8 HeaderChecksum;

  if (IS_FFS_FILE2 (FfsHeader)) {
    HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER2));
  } else {
    HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
  }
  HeaderChecksum = (UINT8) (HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File);

  if (HeaderChecksum == 0) {
    return TRUE;
  } else {
    return FALSE;
  }
}
Exemple #11
0
/**
  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;
}
Exemple #12
0
/**
  Find core image base.

  @param[in]  BootFirmwareVolumePtr    Point to the boot firmware volume.
  @param[out] SecCoreImageBase         The base address of the SEC core image.
  @param[out] PeiCoreImageBase         The base address of the PEI core image.

**/
EFI_STATUS
EFIAPI
FindImageBase (
  IN  EFI_FIRMWARE_VOLUME_HEADER       *BootFirmwareVolumePtr,
  OUT EFI_PHYSICAL_ADDRESS             *SecCoreImageBase,
  OUT EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase
  )
{
  EFI_PHYSICAL_ADDRESS        CurrentAddress;
  EFI_PHYSICAL_ADDRESS        EndOfFirmwareVolume;
  EFI_FFS_FILE_HEADER         *File;
  UINT32                      Size;
  EFI_PHYSICAL_ADDRESS        EndOfFile;
  EFI_COMMON_SECTION_HEADER   *Section;
  EFI_PHYSICAL_ADDRESS        EndOfSection;

  *SecCoreImageBase = 0;
  *PeiCoreImageBase = 0;

  CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
  EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;

  //
  // Loop through the FFS files in the Boot Firmware Volume
  //
  for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {

    CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
    if (CurrentAddress > EndOfFirmwareVolume) {
      return EFI_NOT_FOUND;
    }

    File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
    if (IS_FFS_FILE2 (File)) {
      Size = FFS_FILE2_SIZE (File);
      if (Size <= 0x00FFFFFF) {
        return EFI_NOT_FOUND;
      }
    } else {
      Size = FFS_FILE_SIZE (File);
      if (Size < sizeof (EFI_FFS_FILE_HEADER)) {
        return EFI_NOT_FOUND;
      }
    }

    EndOfFile = CurrentAddress + Size;
    if (EndOfFile > EndOfFirmwareVolume) {
      return EFI_NOT_FOUND;
    }

    //
    // Look for SEC Core / PEI Core files
    //
    if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
        File->Type != EFI_FV_FILETYPE_PEI_CORE) {
      continue;
    }

    //
    // Loop through the FFS file sections within the FFS file
    //
    if (IS_FFS_FILE2 (File)) {
      EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER2));
    } else {
      EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER));
    }
    for (;;) {
      CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
      Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;

      if (IS_SECTION2 (Section)) {
        Size = SECTION2_SIZE (Section);
        if (Size <= 0x00FFFFFF) {
          return EFI_NOT_FOUND;
        }
      } else {
        Size = SECTION_SIZE (Section);
        if (Size < sizeof (EFI_COMMON_SECTION_HEADER)) {
          return EFI_NOT_FOUND;
        }
      }

      EndOfSection = CurrentAddress + Size;
      if (EndOfSection > EndOfFile) {
        return EFI_NOT_FOUND;
      }

      //
      // Look for executable sections
      //
      if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
        if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
          if (IS_SECTION2 (Section)) {
            *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
          } else {
            *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
          }
        } else {
          if (IS_SECTION2 (Section)) {
            *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
          } else {
            *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
          }
        }
        break;
      }
    }

    //
    // Both SEC Core and PEI Core images found
    //
    if (*SecCoreImageBase != 0 && *PeiCoreImageBase != 0) {
      return EFI_SUCCESS;
    }
  }
}
Exemple #13
0
/**
  Create multiple files within a PAD File area.

  @param FvDevice        Firmware Volume Device.
  @param PadFileEntry    The pad file entry to be written in.
  @param NumOfFiles      Total File number to be written.
  @param BufferSize      The array of buffer size of each FfsBuffer.
  @param ActualFileSize  The array of actual file size.
  @param PadSize         The array of leading pad file size for each FFS File
  @param FfsBuffer       The array of Ffs Buffer pointer.
  @param FileData        The array of EFI_FV_WRITE_FILE_DATA structure,
                         used to get name, attributes, type, etc.

  @retval EFI_SUCCESS           Add the input multiple files into PAD file area.
  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
  @retval other error           Files can't be added into PAD file area.

**/
EFI_STATUS
FvCreateMultipleFilesInsidePadFile (
  IN FV_DEVICE              *FvDevice,
  IN FFS_FILE_LIST_ENTRY    *PadFileEntry,
  IN UINTN                  NumOfFiles,
  IN UINTN                  *BufferSize,
  IN UINTN                  *ActualFileSize,
  IN UINTN                  *PadSize,
  IN UINT8                  **FfsBuffer,
  IN EFI_FV_WRITE_FILE_DATA *FileData
  )
{
  EFI_STATUS                          Status;
  EFI_FFS_FILE_HEADER                 *OldPadFileHeader;
  UINTN                               Index;
  EFI_FFS_FILE_HEADER                 *PadFileHeader;
  EFI_FFS_FILE_HEADER                 *FileHeader;
  EFI_FFS_FILE_HEADER                 *TailPadFileHeader;
  UINTN                               TotalSize;
  UINTN                               PadAreaLength;
  LIST_ENTRY                          NewFileList;
  FFS_FILE_LIST_ENTRY                 *NewFileListEntry;
  UINTN                               Offset;
  UINTN                               NumBytesWritten;
  UINT8                               *StartPos;
  FFS_FILE_LIST_ENTRY                 *FfsEntry;
  FFS_FILE_LIST_ENTRY                 *NextFfsEntry;

  InitializeListHead (&NewFileList);

  NewFileListEntry  = NULL;

  OldPadFileHeader  = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
  if (IS_FFS_FILE2 (OldPadFileHeader)) {
    PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
  } else {
    PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
  }

  Status = UpdateHeaderBit (
            FvDevice,
            OldPadFileHeader,
            EFI_FILE_MARKED_FOR_UPDATE
            );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Update PAD area
  //
  TotalSize     = 0;
  if (IS_FFS_FILE2 (OldPadFileHeader)) {
    PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
  } else {
    PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
  }
  FileHeader    = PadFileHeader;

  for (Index = 0; Index < NumOfFiles; Index++) {
    if (PadSize[Index] != 0) {
      FvFillPadFile (PadFileHeader, PadSize[Index]);
      NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
      if (NewFileListEntry == NULL) {
        FreeFileList (&NewFileList);
        return EFI_OUT_OF_RESOURCES;
      }

      NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
      InsertTailList (&NewFileList, &NewFileListEntry->Link);
    }

    FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
    Status = FvFillFfsFile (
              FileHeader,
              FfsBuffer[Index],
              BufferSize[Index],
              ActualFileSize[Index],
              FileData[Index].NameGuid,
              FileData[Index].Type,
              FileData[Index].FileAttributes
              );
    if (EFI_ERROR (Status)) {
      FreeFileList (&NewFileList);
      return Status;
    }

    NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    if (NewFileListEntry == NULL) {
      FreeFileList (&NewFileList);
      return EFI_OUT_OF_RESOURCES;
    }

    NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
    InsertTailList (&NewFileList, &NewFileListEntry->Link);

    PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
    TotalSize += PadSize[Index];
    TotalSize += BufferSize[Index];
  }

  FvDevice->CurrentFfsFile = NewFileListEntry;
  //
  // Maybe we need a tail pad file
  //
  if (PadAreaLength > TotalSize) {
    if ((PadAreaLength - TotalSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
      //
      // we can insert another PAD file
      //
      TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[NumOfFiles - 1]);
      FvFillPadFile (TailPadFileHeader, PadAreaLength - TotalSize);

      NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
      if (NewFileListEntry == NULL) {
        FreeFileList (&NewFileList);
        FvDevice->CurrentFfsFile = NULL;
        return EFI_OUT_OF_RESOURCES;
      }

      NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
      InsertTailList (&NewFileList, &NewFileListEntry->Link);
    } else {
      //
      // because left size cannot hold another PAD file header,
      // adjust the writing file size (just in cache)
      //
      FvAdjustFfsFile (
        FvDevice->ErasePolarity,
        FileHeader,
        PadAreaLength - TotalSize
        );
    }
  }
  //
  // Start writing to FV
  //
  if (IS_FFS_FILE2 (OldPadFileHeader)) {
    StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
  } else {
    StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
  }

  Offset          = (UINTN) (StartPos - FvDevice->CachedFv);

  NumBytesWritten = PadAreaLength;
  Status = FvcWrite (
            FvDevice,
            Offset,
            &NumBytesWritten,
            StartPos
            );
  if (EFI_ERROR (Status)) {
    FreeFileList (&NewFileList);
    FvDevice->CurrentFfsFile = NULL;
    return Status;
  }

  Status = UpdateHeaderBit (
            FvDevice,
            OldPadFileHeader,
            EFI_FILE_HEADER_INVALID
            );
  if (EFI_ERROR (Status)) {
    FreeFileList (&NewFileList);
    FvDevice->CurrentFfsFile = NULL;
    return Status;
  }

  //
  // Update File List Link
  //

  //
  // First delete old pad file entry
  //
  FfsEntry      = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
  NextFfsEntry  = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;

  FreePool (PadFileEntry);

  FfsEntry->Link.ForwardLink          = NewFileList.ForwardLink;
  (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
  NextFfsEntry->Link.BackLink         = NewFileList.BackLink;
  (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;

  return EFI_SUCCESS;
}
Exemple #14
0
/**
  Create a new file within a PAD file area.

  @param FvDevice        Firmware Volume Device.
  @param FfsFileBuffer   A buffer that holds an FFS file,(it contains a File Header which is in init state).
  @param BufferSize      The size of FfsFileBuffer.
  @param ActualFileSize  The actual file length, it may not be multiples of 8.
  @param FileName        The FFS File Name.
  @param FileType        The FFS File Type.
  @param FileAttributes  The Attributes of the FFS File to be created.

  @retval EFI_SUCCESS           Successfully create a new file within the found PAD file area.
  @retval EFI_OUT_OF_RESOURCES  No suitable PAD file is found.
  @retval other errors          New file is created failed.

**/
EFI_STATUS
FvCreateNewFileInsidePadFile (
  IN  FV_DEVICE               *FvDevice,
  IN  UINT8                   *FfsFileBuffer,
  IN  UINTN                   BufferSize,
  IN  UINTN                   ActualFileSize,
  IN  EFI_GUID                *FileName,
  IN  EFI_FV_FILETYPE         FileType,
  IN  EFI_FV_FILE_ATTRIBUTES  FileAttributes
  )
{
  UINTN                               RequiredAlignment;
  FFS_FILE_LIST_ENTRY                 *PadFileEntry;
  EFI_STATUS                          Status;
  UINTN                               PadAreaLength;
  UINTN                               PadSize;
  EFI_FFS_FILE_HEADER                 *FileHeader;
  EFI_FFS_FILE_HEADER                 *OldPadFileHeader;
  EFI_FFS_FILE_HEADER                 *PadFileHeader;
  EFI_FFS_FILE_HEADER                 *TailPadFileHeader;
  UINTN                               StateOffset;
  UINTN                               Offset;
  UINTN                               NumBytesWritten;
  UINT8                               *StartPos;
  LIST_ENTRY                          NewFileList;
  FFS_FILE_LIST_ENTRY                 *NewFileListEntry;
  FFS_FILE_LIST_ENTRY                 *FfsEntry;
  FFS_FILE_LIST_ENTRY                 *NextFfsEntry;

  //
  // First get the required alignment from the File Attributes
  //
  RequiredAlignment = GetRequiredAlignment (FileAttributes);

  //
  // Find a suitable PAD File
  //
  Status = FvLocatePadFile (
            FvDevice,
            BufferSize,
            RequiredAlignment,
            &PadSize,
            &PadFileEntry
            );

  if (EFI_ERROR (Status)) {
    return EFI_OUT_OF_RESOURCES;
  }

  OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;

  //
  // Step 1: Update Pad File Header
  //
  SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldPadFileHeader);

  StartPos = PadFileEntry->FfsHeader;

  Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
  StateOffset     = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;

  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
  Status = FvcWrite (
            FvDevice,
            StateOffset,
            &NumBytesWritten,
            &OldPadFileHeader->State
            );
  if (EFI_ERROR (Status)) {
    SetFileState (EFI_FILE_HEADER_CONSTRUCTION, OldPadFileHeader);
    return Status;
  }

  //
  // Step 2: Update Pad area
  //
  InitializeListHead (&NewFileList);

  if (IS_FFS_FILE2 (OldPadFileHeader)) {
    PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
    PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
  } else {
    PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
    PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
  }

  if (PadSize != 0) {
    //
    // Insert a PAD file before to achieve required alignment
    //
    FvFillPadFile (PadFileHeader, PadSize);
    NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    ASSERT (NewFileListEntry   != NULL);
    NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
    InsertTailList (&NewFileList, &NewFileListEntry->Link);
  }

  FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize);

  Status = FvFillFfsFile (
            FileHeader,
            FfsFileBuffer,
            BufferSize,
            ActualFileSize,
            FileName,
            FileType,
            FileAttributes
            );
  if (EFI_ERROR (Status)) {
    FreeFileList (&NewFileList);
    return Status;
  }

  NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
  ASSERT (NewFileListEntry   != NULL);

  NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
  InsertTailList (&NewFileList, &NewFileListEntry->Link);

  FvDevice->CurrentFfsFile = NewFileListEntry;

  if (PadAreaLength > (BufferSize + PadSize)) {
    if ((PadAreaLength - BufferSize - PadSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
      //
      // we can insert another PAD file
      //
      TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize);
      FvFillPadFile (TailPadFileHeader, PadAreaLength - BufferSize - PadSize);

      NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
      ASSERT (NewFileListEntry   != NULL);

      NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
      InsertTailList (&NewFileList, &NewFileListEntry->Link);
    } else {
      //
      // because left size cannot hold another PAD file header,
      // adjust the writing file size (just in cache)
      //
      FvAdjustFfsFile (
        FvDevice->ErasePolarity,
        FileHeader,
        PadAreaLength - BufferSize - PadSize
        );
    }
  }
  //
  // Start writing to FV
  //
  if (IS_FFS_FILE2 (OldPadFileHeader)) {
    StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
  } else {
    StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
  }

  Offset          = (UINTN) (StartPos - FvDevice->CachedFv);

  NumBytesWritten = PadAreaLength;
  Status = FvcWrite (
            FvDevice,
            Offset,
            &NumBytesWritten,
            StartPos
            );
  if (EFI_ERROR (Status)) {
    FreeFileList (&NewFileList);
    FvDevice->CurrentFfsFile = NULL;
    return Status;
  }

  //
  // Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID
  //
  SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);

  StartPos = PadFileEntry->FfsHeader;

  Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
  StateOffset     = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;

  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
  Status = FvcWrite (
            FvDevice,
            StateOffset,
            &NumBytesWritten,
            &OldPadFileHeader->State
            );
  if (EFI_ERROR (Status)) {
    SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
    FreeFileList (&NewFileList);
    FvDevice->CurrentFfsFile = NULL;
    return Status;
  }

  //
  // If all successfully, update FFS_FILE_LIST
  //

  //
  // Delete old pad file entry
  //
  FfsEntry      = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
  NextFfsEntry  = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;

  FreePool (PadFileEntry);

  FfsEntry->Link.ForwardLink          = NewFileList.ForwardLink;
  (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
  NextFfsEntry->Link.BackLink         = NewFileList.BackLink;
  (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;

  return EFI_SUCCESS;
}
Exemple #15
0
/**
  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;
}
Exemple #16
0
/**
  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;
}