Beispiel #1
0
/**
  Create entire FFS file.

  @param FileHeader      Starting Address of a Buffer that hold the FFS File image.
  @param FfsFileBuffer   The source buffer that contains the File Data.
  @param BufferSize      The length of FfsFileBuffer.
  @param ActualFileSize  Size of FFS file.
  @param FileName        The Guid of Ffs File.
  @param FileType        The type of the written Ffs File.
  @param FileAttributes  The attributes of the written Ffs File.

  @retval EFI_INVALID_PARAMETER  File type is not valid.
  @retval EFI_SUCCESS            FFS file is successfully created.

**/
EFI_STATUS
FvFillFfsFile (
  OUT EFI_FFS_FILE_HEADER   *FileHeader,
  IN UINT8                  *FfsFileBuffer,
  IN UINTN                  BufferSize,
  IN UINTN                  ActualFileSize,
  IN EFI_GUID               *FileName,
  IN EFI_FV_FILETYPE        FileType,
  IN EFI_FV_FILE_ATTRIBUTES FileAttributes
  )
{
  EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute;
  EFI_FFS_FILE_HEADER     *TmpFileHeader;

  //
  // File Type value 0x0E~0xE0 are reserved
  //
  if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) {
    return EFI_INVALID_PARAMETER;
  }

  TmpFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;
  //
  // First fill all fields ready in FfsFileBuffer
  //
  CopyGuid (&TmpFileHeader->Name, FileName);
  TmpFileHeader->Type = FileType;

  //
  // Convert the FileAttributes to FFSFileAttributes
  //
  FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute);

  TmpFileHeader->Attributes = TmpFileAttribute;

  if (ActualFileSize > 0x00FFFFFF) {
    ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;
    *(UINT32 *) FileHeader->Size &= 0xFF000000;
    FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
  } else {
    *(UINT32 *) FileHeader->Size &= 0xFF000000;
    *(UINT32 *) FileHeader->Size |= ActualFileSize;
  }

  SetHeaderChecksum (TmpFileHeader);
  SetFileChecksum (TmpFileHeader, ActualFileSize);

  SetFileState (EFI_FILE_HEADER_CONSTRUCTION, TmpFileHeader);
  SetFileState (EFI_FILE_HEADER_VALID, TmpFileHeader);
  SetFileState (EFI_FILE_DATA_VALID, TmpFileHeader);

  //
  // Copy data from FfsFileBuffer to FileHeader(cache)
  //
  CopyMem (FileHeader, FfsFileBuffer, BufferSize);

  return EFI_SUCCESS;
}
Beispiel #2
0
//-------------------------------------------------------------------------
// Function to add the variable object to the open netCDF file object nc
// No longer assumes the file is in define mode - will change it everytime
// This may cause slow down but allows the option of adding data to the 
// variable at the same time to make function calls 'nicer'
//-------------------------------------------------------------------------
void NCVariable::AddToFile(NcFile* nc)
{
   SetFileState(nc,DEFINE);
   //Add the dimensions if not already in file
   for(unsigned int i=0;i<dimensions.size();i++)
   {
      //If the dimension already exists don't try and re-add it
      if(nc->getDim(dimension_names[i]).isNull())
      {
         std::cout<<"Dimension does not exist: "<<dimension_names[i]<<" Will add it."<<std::endl;
         nc->addDim(dimension_names[i],dimensions[i]);
      }
      else
      {
         std::cout<<"Dimension already exists: "<<dimension_names[i]<<std::endl;
      }
      ncdimensions.push_back(nc->getDim(dimension_names[i]));
   }

   //Add the variable if not in the file - else silently fail
   if(nc->getVar(name).isNull())
   {
      NcVar var=nc->addVar(name,(*type),ncdimensions);
      var.setChunking(NcVar::nc_CHUNKED,chunksizes);
      //Add the associated attributes
      for(std::vector<NCAttribute*>::iterator it=attributes.begin();it!=attributes.end();it++)
      {
         if((*it)->Type()==NULL)
         {
            //Use the string adding function
            var.putAtt((*it)->Name(),std::string((*it)->Data(),(*it)->Length()));
         }
         else
         {
            var.putAtt((*it)->Name(),*((*it)->Type()),(*it)->Length(),(*it)->Data());
         }
      }
      //Set the fill value
      if(fillvalue!=NULL)
         var.setFill(true,(void*)fillvalue);
      //Set the compression - currently hard coded
      var.setCompression(false,true,6);
      //Add data to the file if associated with variable
      if(Data!=NULL)
      {
         SetFileState(nc,DATA);
         WriteVariableDataToFile(nc,*this);
      }
   }
   else
   {
      std::cout<<"Variable already exists"<<std::endl;
   }
   
}
Beispiel #3
0
/**
  Fill pad file header within firmware cache.

  @param PadFileHeader    The start of the Pad File Buffer.
  @param PadFileLength    The length of the pad file including the header.

**/
VOID
FvFillPadFile (
  IN EFI_FFS_FILE_HEADER  *PadFileHeader,
  IN UINTN                PadFileLength
  )
{
  //
  // Fill File Name Guid, here we assign a NULL-GUID to Pad files
  //
  ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));

  //
  // Fill File Type, checksum(0), Attributes(0), Size
  //
  PadFileHeader->Type       = EFI_FV_FILETYPE_FFS_PAD;
  PadFileHeader->Attributes = 0;
  if (PadFileLength > 0x00FFFFFF) {
    ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) PadFileLength;
    *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
    PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
  } else {
    *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
    *(UINT32 *) PadFileHeader->Size |= PadFileLength;
  }

  SetHeaderChecksum (PadFileHeader);
  SetPadFileChecksum (PadFileHeader);

  //
  // Set File State to 0x00000111
  //
  SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
  SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
  SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);

  return ;
}
Beispiel #4
0
/**
  Create a PAD File in the Free Space.

  @param FvDevice        Firmware Volume Device.
  @param FreeSpaceEntry  Indicating in which Free Space(Cache) the Pad file will be inserted.
  @param Size            Pad file Size, not include the header.
  @param PadFileEntry    The Ffs File Entry that points to this Pad File.

  @retval EFI_SUCCESS            Successfully create a PAD file.
  @retval EFI_OUT_OF_RESOURCES   No enough free space to create a PAD file.
  @retval EFI_INVALID_PARAMETER  Size is not 8 byte alignment.
  @retval EFI_DEVICE_ERROR       Free space is not erased.
**/
EFI_STATUS
FvCreatePadFileInFreeSpace (
  IN  FV_DEVICE           *FvDevice,
  IN  FREE_SPACE_ENTRY    *FreeSpaceEntry,
  IN  UINTN               Size,
  OUT FFS_FILE_LIST_ENTRY **PadFileEntry
  )
{
  EFI_STATUS                          Status;
  EFI_FFS_FILE_HEADER                 *PadFileHeader;
  UINTN                               Offset;
  UINTN                               NumBytesWritten;
  UINTN                               StateOffset;
  UINT8                               *StartPos;
  FFS_FILE_LIST_ENTRY                 *FfsFileEntry;
  UINTN                               HeaderSize;
  UINTN                               FileSize;

  HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
  FileSize = Size + HeaderSize;
  if (FileSize > 0x00FFFFFF) {
    HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
    FileSize = Size + HeaderSize;
  }

  if (FreeSpaceEntry->Length < FileSize) {
    return EFI_OUT_OF_RESOURCES;
  }

  if ((Size & 0x07) != 0) {
    return EFI_INVALID_PARAMETER;
  }

  StartPos = FreeSpaceEntry->StartingAddress;

  //
  // First double check the space
  //
  if (!IsBufferErased (
        FvDevice->ErasePolarity,
        StartPos,
        FileSize
        )) {
    return EFI_DEVICE_ERROR;
  }

  PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;

  //
  // Create File Step 1
  //
  SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);

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

  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
  Status = FvcWrite (
            FvDevice,
            StateOffset,
            &NumBytesWritten,
            &PadFileHeader->State
            );
  if (EFI_ERROR (Status)) {
    SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
    return Status;
  }
  //
  // Update Free Space Entry, since header is allocated
  //
  FreeSpaceEntry->Length -= HeaderSize;
  FreeSpaceEntry->StartingAddress += HeaderSize;

  //
  // Fill File Name Guid, here we assign a NULL-GUID to Pad files
  //
  ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));

  //
  // Fill File Type, checksum(0), Attributes(0), Size
  //
  PadFileHeader->Type       = EFI_FV_FILETYPE_FFS_PAD;
  PadFileHeader->Attributes = 0;
  if ((FileSize) > 0x00FFFFFF) {
    ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) FileSize;
    *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
    PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
  } else {
    *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
    *(UINT32 *) PadFileHeader->Size |= FileSize;
  }

  SetHeaderChecksum (PadFileHeader);
  SetPadFileChecksum (PadFileHeader);

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

  NumBytesWritten = HeaderSize;
  Status = FvcWrite (
            FvDevice,
            Offset,
            &NumBytesWritten,
            (UINT8 *) PadFileHeader
            );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Step 2, then Mark header valid, since no data write,
  // mark the data valid at the same time.
  //
  SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
  SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);

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

  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
  Status = FvcWrite (
            FvDevice,
            StateOffset,
            &NumBytesWritten,
            &PadFileHeader->State
            );
  if (EFI_ERROR (Status)) {
    SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
    SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
    return Status;
  }
  //
  // Update Free Space Entry, since header is allocated
  //
  FreeSpaceEntry->Length -= Size;
  FreeSpaceEntry->StartingAddress += Size;

  //
  // If successfully, insert an FfsFileEntry at the end of ffs file list
  //
  FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
  ASSERT (FfsFileEntry != NULL);

  FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) StartPos;
  InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);

  *PadFileEntry             = FfsFileEntry;
  FvDevice->CurrentFfsFile  = FfsFileEntry;

  return EFI_SUCCESS;
}
Beispiel #5
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;
}