/** 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; }
//------------------------------------------------------------------------- // 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; } }
/** 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 ; }
/** 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; }
/** 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; }