--- /dev/null
+/** @file\r
+\r
+ FMMT main routine.\r
+\r
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "FirmwareModuleManagement.h"\r
+#include "Rebase.h"\r
+#include <stdlib.h>\r
+#include <wchar.h>\r
+\r
+CHAR8* mGuidToolDefinition = "FmmtConf.ini";\r
+extern EFI_FIRMWARE_VOLUME_HEADER *mFvHeader;\r
+extern UINT32 mFvLength;\r
+\r
+//\r
+// Store GUIDed Section guid->tool mapping\r
+//\r
+EFI_HANDLE mParsedGuidedSectionTools = NULL;\r
+#define EFI_FFS_VOLUME_TOP_FILE_GUID \\r
+{ \\r
+ 0x1BA0062E, 0xC779, 0x4582, { 0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x09 } \\r
+}\r
+#define FSP_FFS_INFORMATION_FILE_GUID \\r
+{ 0x912740be, 0x2284, 0x4734, { 0xb9, 0x71, 0x84, 0xb0, 0x27, 0x35, 0x3f, 0x0c }};\r
+\r
+static EFI_GUID mVTFGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
+static EFI_GUID mFSPGuid = FSP_FFS_INFORMATION_FILE_GUID;\r
+\r
+\r
+/**\r
+\r
+Routine Description:\r
+\r
+ The Usage of FMMT tool.\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+**/\r
+VOID\r
+Usage (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // Summary usage\r
+ //\r
+ fprintf (stdout, "Usage: %s [options] \n\n", UTILITY_SHORT_NAME);\r
+\r
+ //\r
+ // Copyright declaration\r
+ //\r
+ fprintf (stdout, "Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.\n\n");\r
+\r
+ //\r
+ // Details Option\r
+ //\r
+ fprintf (stdout, "Options:\n");\r
+\r
+ //\r
+ // Command Line for View\r
+ //\r
+ fprintf (stdout, " -v <input-binary-file>\n\\r
+ View each FV and the named files within each FV.\n");\r
+\r
+ //\r
+ // Command Line for Delete entire FV\r
+ //\r
+ fprintf (stdout, " -d <input-binary-file> <FV-id> <output-binary-file>\n\\r
+ Delete the entire FV in an FD binary\n");\r
+\r
+ //\r
+ // Command Line for Delete file from FV\r
+ //\r
+ fprintf (stdout, " -d <input-binary-file> <FV-id> <File-Name> [<FV-id> <File-Name> ...] <output-binary-file>\n\\r
+ Delete a file (or files) from the firmware volume in an FD binary\n");\r
+\r
+ //\r
+ // Command Line for Add\r
+ //\r
+ fprintf (stdout, " -a <input-binary-file> <FV-id> <NewFilePath> [<FV-id> <NewFilePath> ...] <output-binary-file>\n\\r
+ Add a file (or files) to the firmware volume in an FD binary\n");\r
+\r
+ //\r
+ // Command Line for Replace\r
+ //\r
+ fprintf (stdout, " -r <input-binary-file> <FV-id> <File-Name> <NewFilePath> [<FV-id> <File-Name> <NewFilePath> ...] <output-binary-file>\n\\r
+ The replace command combines the functionality of remove and add into a single operation.\n");\r
+\r
+ fprintf (stdout, "\nNote:\n");\r
+ fprintf (stdout, " <FV-id> is the sequence of the firmware volume included in the FD image, it both support the sequentially format like FV0, FV1 and the FV's file guid value format.\n");\r
+ return;\r
+}\r
+\r
+\r
+BOOLEAN\r
+IsVtf(EFI_FFS_FILE_HEADER2* ffs) {\r
+ if (!memcmp(&ffs->Name, &mVTFGuid, sizeof (EFI_GUID))) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+BOOLEAN\r
+IsFsp(EFI_FFS_FILE_HEADER2* ffs) {\r
+ if (!memcmp(&ffs->Name, &mFSPGuid, sizeof (EFI_GUID))) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+GetBaseAddrFromVtf(FIRMWARE_DEVICE *FdData, CHAR8 *FvId, UINT64 *BaseAddr) {\r
+ EFI_STATUS Status;\r
+ FV_INFORMATION *CurrentFv;\r
+ FV_INFORMATION *FvInFd;\r
+\r
+ Status = LibLocateFvViaFvId(FdData, FvId, &FvInFd);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get bottom FV\r
+ //\r
+ CurrentFv = FdData->Fv;\r
+ while (CurrentFv->FvNext) {\r
+ CurrentFv = CurrentFv->FvNext;\r
+ }\r
+ if (CurrentFv->FfsNumbers > 0 && IsVtf(&CurrentFv->FfsHeader[CurrentFv->FfsNumbers])) {\r
+ //\r
+ // Found VTF at the top of FV\r
+ // Assume 4G address\r
+ //\r
+ *BaseAddr = 0x100000000 - (FdData->Size - FvInFd->ImageAddress);\r
+ return EFI_SUCCESS;\r
+ }\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+GetBaseAddrFromFsp(FIRMWARE_DEVICE *FdData, CONST UINT8* FdBuffer, CHAR8 *FvId, UINT64 *BaseAddr)\r
+{\r
+ EFI_STATUS Status;\r
+ FV_INFORMATION *FvInFd;\r
+ FV_INFORMATION *CurrentFv;\r
+ FV_INFORMATION *FspFv;\r
+ UINT32 Offset;\r
+ UINT64 ImageSize;\r
+ UINT64 Size;\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile;\r
+ BOOLEAN FspFound;\r
+\r
+ Status = LibLocateFvViaFvId(FdData, FvId, &FvInFd);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ImageSize = 0;\r
+ Size = 0;\r
+ FspFound = FALSE;\r
+ FspFv = NULL;\r
+ CurrentFv = FdData->Fv;\r
+ while (CurrentFv) {\r
+ if (CurrentFv->FfsNumbers > 0 && IsFsp(&CurrentFv->FfsHeader[0])) {\r
+ Offset = CurrentFv->ImageAddress + CurrentFv->FfsAttuibutes[0].Offset;\r
+ CurrentFile = (EFI_FFS_FILE_HEADER2 *)(FdBuffer + Offset);\r
+ //\r
+ // Skip FFS header\r
+ //\r
+ Offset += GetFfsHeaderLength((EFI_FFS_FILE_HEADER *)CurrentFile);\r
+ //\r
+ // Stip section header\r
+ //\r
+ Offset += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)(FdBuffer + Offset));\r
+ //\r
+ // We have raw FSP here, and 24 is the image size\r
+ //\r
+ ImageSize = *((UINT32 *)(FdBuffer + Offset + 24));\r
+ //\r
+ // 28 is the base address\r
+ //\r
+ *BaseAddr = *((UINT32 *)(FdBuffer + Offset + 28));\r
+ FspFound = TRUE;\r
+ FspFv = CurrentFv;\r
+ }\r
+ if (CurrentFv == FvInFd){\r
+ break;\r
+ }\r
+ CurrentFv = CurrentFv->FvNext;\r
+ }\r
+ if (!FspFound) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // Check if FSP binary contains this FV\r
+ //\r
+ while (FspFv != NULL) {\r
+ Size += FspFv->FvHeader->FvLength;\r
+ if (FspFv == FvInFd) {\r
+ break;\r
+ }\r
+ FspFv = FspFv->FvNext;\r
+ }\r
+ if (Size <= ImageSize) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+static\r
+VOID\r
+AddPadFile(EFI_FIRMWARE_VOLUME_HEADER *Fv, EFI_FFS_FILE_HEADER2 *PadFile, UINT32 PadFileSize) {\r
+ UINT32 hdrSize;\r
+\r
+ if (Fv->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+ memset(PadFile, -1, PadFileSize);\r
+ }\r
+ else {\r
+ memset(PadFile, 0, PadFileSize);\r
+ }\r
+ PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
+ PadFile->Attributes = 0;\r
+\r
+ //\r
+ // Write pad file size (calculated size minus next file header size)\r
+ //\r
+ if (PadFileSize >= MAX_FFS_SIZE) {\r
+ memset(PadFile->Size, 0, sizeof(UINT8)* 3);\r
+ ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = PadFileSize;\r
+ PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
+ hdrSize = sizeof(EFI_FFS_FILE_HEADER2);\r
+ }\r
+ else {\r
+ PadFile->Size[0] = (UINT8)(PadFileSize & 0xFF);\r
+ PadFile->Size[1] = (UINT8)((PadFileSize >> 8) & 0xFF);\r
+ PadFile->Size[2] = (UINT8)((PadFileSize >> 16) & 0xFF);\r
+ hdrSize = sizeof(EFI_FFS_FILE_HEADER);\r
+ }\r
+\r
+ //\r
+ // Fill in checksums and state, they must be 0 for checksumming.\r
+ //\r
+ PadFile->IntegrityCheck.Checksum.Header = 0;\r
+ PadFile->IntegrityCheck.Checksum.File = 0;\r
+ PadFile->State = 0;\r
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8((UINT8 *)PadFile, hdrSize);\r
+ PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+\r
+ PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
+ if (Fv->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+ PadFile->State = (UINT8)~(PadFile->State);\r
+ }\r
+}\r
+\r
+static\r
+UINT8* ReadFileToBuffer(CONST CHAR8 *FdName, UINT32 *FdSize) {\r
+ FILE* file;\r
+\r
+ UINT8 *FdBuffer = NULL;\r
+\r
+ file = fopen(FdName, "rb");\r
+ if (file == NULL)\r
+ return NULL;\r
+\r
+ fseek(file, 0, SEEK_SET);\r
+ fseek(file, 0, SEEK_END);\r
+ *FdSize = ftell(file);\r
+ fseek(file, 0, SEEK_SET);\r
+\r
+ FdBuffer = malloc(*FdSize);\r
+ if (FdBuffer == NULL) {\r
+ goto FAIL;\r
+ }\r
+ if (fread(FdBuffer, 1, *FdSize, file) != *FdSize) {\r
+ goto FAIL;\r
+ }\r
+ fclose(file);\r
+ return FdBuffer;\r
+FAIL:\r
+ free(FdBuffer);\r
+ fclose(file);\r
+ return NULL;\r
+}\r
+\r
+static UINT32 CalcuFfsSize(EFI_FIRMWARE_VOLUME_HEADER* Fv, CONST EFI_FFS_FILE_HEADER2 *Ffs) {\r
+ EFI_FFS_FILE_HEADER2 *NextFile;\r
+ UINTN FfsSize;\r
+ UINTN FvSize;\r
+ UINTN Offset;\r
+\r
+ FfsSize = GetFfsFileLength((EFI_FFS_FILE_HEADER *)Ffs);\r
+ FfsSize += (UINT8 *)ALIGN_POINTER(((UINT8 *)Ffs + FfsSize), 8) - ((UINT8 *)Ffs + FfsSize);\r
+ FvBufGetSize(Fv, &FvSize);\r
+ Offset = (UINT8 *)Ffs - (UINT8 *)Fv;\r
+ if (Offset + FfsSize < FvSize) {\r
+ NextFile = (EFI_FFS_FILE_HEADER2 *)((UINT8 *)Ffs + FfsSize);\r
+ if (NextFile->Type == EFI_FV_FILETYPE_FFS_PAD) {\r
+ FfsSize += GetFfsFileLength((EFI_FFS_FILE_HEADER *)NextFile);\r
+ }\r
+ }\r
+ return FfsSize;\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+ReadFfsAlignment(\r
+IN EFI_FFS_FILE_HEADER *FfsFile,\r
+IN OUT UINT32 *Alignment\r
+)\r
+{\r
+ //\r
+ // Verify input parameters.\r
+ //\r
+ if (FfsFile == NULL || Alignment == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ switch ((FfsFile->Attributes >> 3) & 0x07) {\r
+\r
+ case 0:\r
+ //\r
+ // 1 byte alignment\r
+ //\r
+ *Alignment = 0;\r
+ break;\r
+\r
+ case 1:\r
+ //\r
+ // 16 byte alignment\r
+ //\r
+ *Alignment = 4;\r
+ break;\r
+\r
+ case 2:\r
+ //\r
+ // 128 byte alignment\r
+ //\r
+ *Alignment = 7;\r
+ break;\r
+\r
+ case 3:\r
+ //\r
+ // 512 byte alignment\r
+ //\r
+ *Alignment = 9;\r
+ break;\r
+\r
+ case 4:\r
+ //\r
+ // 1K byte alignment\r
+ //\r
+ *Alignment = 10;\r
+ break;\r
+\r
+ case 5:\r
+ //\r
+ // 4K byte alignment\r
+ //\r
+ *Alignment = 12;\r
+ break;\r
+\r
+ case 6:\r
+ //\r
+ // 32K byte alignment\r
+ //\r
+ *Alignment = 15;\r
+ break;\r
+\r
+ case 7:\r
+ //\r
+ // 64K byte alignment\r
+ //\r
+ *Alignment = 16;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+static\r
+BOOLEAN\r
+ReplaceFfs(EFI_FIRMWARE_VOLUME_HEADER* Fv, EFI_FFS_FILE_HEADER2 *InputFfs, EFI_FFS_FILE_HEADER2 *OldFfs) {\r
+ UINT32 FfsSize;\r
+ UINT32 NewFileSize;\r
+ UINT32 Offset;\r
+ UINT32 Align;\r
+ UINT32 HdrSize;\r
+ UINT32 PadSize;\r
+ EFI_FFS_FILE_HEADER2 *Pad;\r
+\r
+ Align = 0;\r
+ PadSize = 0;\r
+ Pad = NULL;\r
+ ReadFfsAlignment((EFI_FFS_FILE_HEADER *)InputFfs, &Align);\r
+ Align = 1 << Align;\r
+ HdrSize = GetFfsHeaderLength((EFI_FFS_FILE_HEADER *)InputFfs);\r
+\r
+ FfsSize = CalcuFfsSize(Fv, OldFfs);\r
+ //\r
+ // Align data\r
+ //\r
+ if ((((UINT8 *)OldFfs - (UINT8 *)Fv) + HdrSize) % Align != 0) {\r
+ PadSize = ((UINT8 *)OldFfs - (UINT8 *)Fv) + sizeof (EFI_FFS_FILE_HEADER)+HdrSize;\r
+ while (PadSize % Align != 0) {\r
+ PadSize++;\r
+ }\r
+ PadSize -= HdrSize;\r
+ PadSize -= ((UINT8 *)OldFfs - (UINT8 *)Fv);\r
+ if (FfsSize < PadSize) {\r
+ return FALSE;\r
+ }\r
+ FfsSize -= PadSize;\r
+ Pad = OldFfs;\r
+ OldFfs = (EFI_FFS_FILE_HEADER2 *)((UINT8 *)OldFfs + PadSize);\r
+ }\r
+\r
+ NewFileSize = GetFfsFileLength((EFI_FFS_FILE_HEADER *)InputFfs);\r
+ Offset = (UINT8 *)ALIGN_POINTER(((UINT8 *)OldFfs + NewFileSize), 8) - ((UINT8 *)OldFfs + NewFileSize);\r
+ if (FfsSize >= NewFileSize && FfsSize - NewFileSize <= 7) {\r
+ memcpy(OldFfs, (UINT8 *)InputFfs, NewFileSize);\r
+ if (Fv->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+ memset((UINT8 *)OldFfs + NewFileSize, -1, FfsSize - NewFileSize);\r
+ }\r
+ else {\r
+ memset((UINT8 *)OldFfs + NewFileSize, 0, FfsSize - NewFileSize);\r
+ }\r
+ }\r
+ else if (FfsSize >= NewFileSize + sizeof(EFI_FFS_FILE_HEADER) + Offset) {\r
+ memcpy(OldFfs, (UINT8 *)InputFfs, NewFileSize);\r
+ AddPadFile(\r
+ Fv,\r
+ (EFI_FFS_FILE_HEADER2 *)((UINT8 *)OldFfs + NewFileSize + Offset),\r
+ FfsSize - NewFileSize - Offset\r
+ );\r
+ }\r
+ else {\r
+ return FALSE;\r
+ }\r
+ if (Fv->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+ OldFfs->State = (UINT8)~(InputFfs->State);\r
+ }\r
+ if (PadSize != 0) {\r
+ AddPadFile(Fv, Pad, PadSize);\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+static\r
+\r
+EFI_STATUS\r
+AddFfs(UINT8 *FdBuffer, UINT32 ImageAddress, EFI_FIRMWARE_VOLUME_HEADER* Fv, EFI_FFS_FILE_HEADER2 *InputFfs, UINT32 *OffsetAdded) {\r
+ UINTN FreeOffset;\r
+ UINTN Offset;\r
+ UINTN FfsSize;\r
+ EFI_STATUS Status;\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile;\r
+ EFI_FFS_FILE_HEADER FreeHeader;\r
+\r
+ if (Fv->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+ memset(&FreeHeader, -1, sizeof(EFI_FFS_FILE_HEADER));\r
+ }\r
+ else {\r
+ memset(&FreeHeader, 0, sizeof(EFI_FFS_FILE_HEADER));\r
+ }\r
+\r
+ FfsSize = GetFfsFileLength((EFI_FFS_FILE_HEADER *)InputFfs);\r
+\r
+ Offset = 0;\r
+ CurrentFile = NULL;\r
+ FreeOffset = 0;\r
+ do {\r
+ if (FreeOffset == 0 && memcmp(FdBuffer + ImageAddress + (UINTN)ALIGN_POINTER(Offset, 8), &FreeHeader, sizeof(EFI_FFS_FILE_HEADER)) == 0) {\r
+ //\r
+ // Offset of free FV space found\r
+ //\r
+ FreeOffset = (UINTN)ALIGN_POINTER(Offset, 8);\r
+ }\r
+ Status = FvBufFindNextFile(FdBuffer + ImageAddress, &Offset, (VOID **)&CurrentFile);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ CurrentFile = NULL;\r
+ break;\r
+ }\r
+ else if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (CurrentFile != NULL && CurrentFile->Type == EFI_FV_FILETYPE_FFS_PAD &&\r
+ ReplaceFfs(Fv, InputFfs, CurrentFile)) {\r
+ *OffsetAdded = (UINT8 *)CurrentFile - (FdBuffer + ImageAddress);\r
+ return EFI_SUCCESS;\r
+ }\r
+ } while (CurrentFile != NULL);\r
+\r
+ if (FreeOffset != 0) {\r
+ if (Fv->FvLength - FreeOffset < FfsSize) {\r
+ return EFI_ABORTED;\r
+ }\r
+ if (Fv->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+ InputFfs->State = (UINT8)~(InputFfs->State);\r
+ }\r
+ memcpy(FdBuffer + ImageAddress + FreeOffset, InputFfs, FfsSize);\r
+ *OffsetAdded = FreeOffset;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+FindPreviousFile(VOID *Fv, VOID *CurrentFile, VOID **PreFile) {\r
+ EFI_STATUS Status;\r
+ VOID *File = NULL;\r
+ UINTN Offset = 0;\r
+\r
+ do {\r
+ *PreFile = File;\r
+ Status = FvBufFindNextFile(Fv, &Offset, &File);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ CurrentFile = NULL;\r
+ break;\r
+ }\r
+ else if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ if (File == CurrentFile) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ } while (CurrentFile != NULL);\r
+ *PreFile = NULL;\r
+ return Status;\r
+}\r
+\r
+static\r
+BOOLEAN\r
+NeedNewPath(FV_INFORMATION *FvInFd, CHAR8 *FvId, UINT32 FileIndex, BOOLEAN IsAdd) {\r
+ UINT32 Index;\r
+\r
+ Index = 0;\r
+\r
+ if (strcmp(FvId, FvInFd->FvName) != 0) {\r
+ return FALSE;\r
+ }\r
+ if (IsAdd) {\r
+ return TRUE;\r
+ }\r
+ if (FvInFd->FfsAttuibutes[FileIndex].FvLevel != 1) {\r
+ return FALSE;\r
+ }\r
+\r
+ for (Index = 0; Index <= FvInFd->FfsNumbers; Index++) {\r
+ if (FvInFd->FfsAttuibutes[Index].FvLevel != 1) {\r
+ continue;\r
+ }\r
+ switch (FvInFd->FfsHeader[Index].Type) {\r
+ case EFI_FV_FILETYPE_PEI_CORE:\r
+ case EFI_FV_FILETYPE_PEIM:\r
+ case EFI_FV_FILETYPE_SECURITY_CORE:\r
+ return TRUE;\r
+ }\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+static UINT32 FindFile(FV_INFORMATION *FvInFd, UINT8 FvLevel, CHAR8 *File, UINT32 *MatchIndex) {\r
+ UINT32 Index = 0;\r
+ CHAR16 *UIName;\r
+ CHAR16 *FfsUIName;\r
+ UINT32 FileNumber = 0;\r
+\r
+ UIName = (CHAR16 *)malloc(_MAX_PATH);\r
+ if (NULL == UIName) {\r
+ return 0;\r
+ }\r
+ FfsUIName = (CHAR16 *)malloc(_MAX_PATH);\r
+ if (NULL == FfsUIName) {\r
+ free(UIName);\r
+ return 0;\r
+ }\r
+ LibAscii2Unicode(File, UIName);\r
+ for (Index = 0; Index <= FvInFd->FfsNumbers; Index++) {\r
+ //\r
+ // Compare the New File Name with UI Name of FFS\r
+ // NOTE: The UI Name is Unicode, but the New File Name is Ascii.\r
+ //\r
+ memcpy(FfsUIName, (CHAR16 *)(FvInFd->FfsAttuibutes[Index].UiName), _MAX_PATH);\r
+\r
+ if (FvInFd->FfsAttuibutes[Index].UiNameSize > 0 && memcmp(UIName, FfsUIName, FvInFd->FfsAttuibutes[Index].UiNameSize) == 0) {\r
+ FileNumber += 1;\r
+ *MatchIndex = Index;\r
+ if (FileNumber > 1) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ }\r
+ free(UIName);\r
+ free(FfsUIName);\r
+\r
+ return FileNumber;\r
+}\r
+\r
+/**\r
+ Search the config file from the path list.\r
+\r
+ Split the path from env PATH, and then search the cofig\r
+ file from these paths. The priority is from left to\r
+ right of PATH string. When met the first Config file, it\r
+ will break and return the pointer to the full file name.\r
+\r
+ @param PathList the pointer to the path list.\r
+ @param FileName the pointer to the file name.\r
+\r
+ @retval The pointer to the file name.\r
+ @return NULL An error occurred.\r
+**/\r
+CHAR8 *\r
+SearchConfigFromPathList (\r
+ IN CHAR8 *PathList,\r
+ IN CHAR8 *FileName\r
+)\r
+{\r
+ CHAR8 *CurDir;\r
+ CHAR8 *FileNamePath;\r
+\r
+ CurDir = NULL;\r
+ FileNamePath = NULL;\r
+\r
+#ifndef __GNUC__\r
+ CurDir = strtok (PathList,";");\r
+#else\r
+ CurDir = strtok (PathList,":");\r
+#endif\r
+ while (CurDir != NULL) {\r
+ FileNamePath = (char *)calloc(\r
+ strlen (CurDir) + strlen (OS_SEP_STR) +strlen (FileName) + 1,\r
+ sizeof(char)\r
+ );\r
+ if (FileNamePath == NULL) {\r
+ return NULL;\r
+ }\r
+ sprintf(FileNamePath, "%s%c%s", CurDir, OS_SEP, FileName);\r
+ if (access (FileNamePath, 0) != -1) {\r
+ return FileNamePath;\r
+ }\r
+#ifndef __GNUC__\r
+ CurDir = strtok(NULL, ";");\r
+#else\r
+ CurDir = strtok(NULL, ":");\r
+#endif\r
+ free (FileNamePath);\r
+ FileNamePath = NULL;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+UINT32 lenList(FILENode* head){\r
+ FILENode *p = head;\r
+ UINT32 sum=0;\r
+ if(head==NULL) return 0;\r
+ while(p!=NULL){\r
+ sum+=1;\r
+ p=p->Next;\r
+ }\r
+ return sum;\r
+}\r
+\r
+void sortList(FILENode* head){\r
+ UINT32 len = lenList(head);\r
+ FILENode *p = head;\r
+ UINT32 i;\r
+ UINT32 j;\r
+ if(len==0) return;\r
+ for(i=1; i<len; ++i){\r
+ p = head;\r
+ for(j=0; j<len-i; j++){\r
+ if(p->SubLevel < p->Next->SubLevel){\r
+ CHAR8 *FileName = p->FileName;\r
+ UINT8 tmp = p->SubLevel;\r
+ p->SubLevel = p->Next->SubLevel;\r
+ p->Next->SubLevel = tmp;\r
+ p->FileName = p->Next->FileName;\r
+ p->Next->FileName = FileName;\r
+ }\r
+ p=p->Next;\r
+ }\r
+ }\r
+}\r
+\r
+BOOLEAN\r
+ParseSection (\r
+ IN EFI_FFS_FILE_HEADER2 *InputFfs\r
+)\r
+{\r
+ BOOLEAN UISectionFlag;\r
+ UINT32 SectionLength;\r
+ UINT32 ParsedLength;\r
+ UINT32 FfsFileSize;\r
+ UINT8 *Ptr;\r
+ EFI_SECTION_TYPE Type;\r
+\r
+ UISectionFlag = FALSE;\r
+ Ptr = NULL;\r
+ SectionLength = 0;\r
+ ParsedLength = GetFfsHeaderLength((EFI_FFS_FILE_HEADER *)InputFfs);\r
+ FfsFileSize = GetFfsFileLength((EFI_FFS_FILE_HEADER *)InputFfs);\r
+\r
+ while (ParsedLength < FfsFileSize) {\r
+ Ptr = (UINT8 *)InputFfs + ParsedLength;\r
+ SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size);\r
+ Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type;\r
+\r
+ //\r
+ // This is sort of an odd check, but is necessary because FFS files are\r
+ // padded to a QWORD boundary, meaning there is potentially a whole section\r
+ // header worth of 0xFF bytes.\r
+ //\r
+ if ((SectionLength == 0xffffff) && (Type == 0xff)) {\r
+ ParsedLength += 4;\r
+ continue;\r
+ }\r
+ if (Type == EFI_SECTION_USER_INTERFACE) {\r
+ UISectionFlag = TRUE;\r
+ break;\r
+ }\r
+ ParsedLength += SectionLength;\r
+ //\r
+ // We make then next section begin on a 4-byte boundary\r
+ //\r
+ ParsedLength = GetOccupiedSize (ParsedLength, 4);\r
+ }\r
+ return UISectionFlag;\r
+\r
+}\r
+\r
+\r
+/**\r
+\r
+ Show the FD image layout information. Only display the modules with UI name.\r
+\r
+ @param[in] FdInName Input FD binary/image file name;\r
+ @param[in] FvName The FV ID in the FD file;\r
+ @param[in] ViewFlag Is this call for view or other operate(add/del/replace)\r
+ @param[in] FdData The Fd data structure store the FD information.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval EFI_INVALID_PARAMETER\r
+ @retval EFI_ABORTED\r
+\r
+**/\r
+EFI_STATUS\r
+FmmtImageView (\r
+ IN CHAR8* FdInName,\r
+ IN CHAR8* FvName,\r
+ IN BOOLEAN ViewFlag,\r
+ IN FIRMWARE_DEVICE **FdData\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS ErrorStatus;\r
+ FIRMWARE_DEVICE *LocalFdData;\r
+ FV_INFORMATION *CurrentFv;\r
+ FILE *InputFile;\r
+ UINT32 FvSize;\r
+ UINTN BytesRead;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage;\r
+ UINT32 FfsCount;\r
+ UINT8 FvCount;\r
+ CHAR8 *TemDir;\r
+\r
+ LocalFdData = NULL;\r
+ CurrentFv = NULL;\r
+ FvImage = NULL;\r
+ TemDir = NULL;\r
+ FvSize = 0;\r
+ BytesRead = 0;\r
+ FfsCount = 0;\r
+ FvCount = 0;\r
+ ErrorStatus = EFI_SUCCESS;\r
+\r
+ //\r
+ // Check the FD file name/path.\r
+ //\r
+ if (FdInName == NULL) {\r
+ Error("FMMT", 0, 1001, "Invalid parameter! Please specify <input-binary-file>", FdInName);\r
+ Usage();\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Open the file containing the FV\r
+ //\r
+ InputFile = fopen (FdInName, "rb");\r
+ if (InputFile == NULL) {\r
+ Error (NULL, 0, 0001, "Error opening the input file", FdInName);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = LibFindFvInFd (InputFile, &LocalFdData);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 1001, "Error while search FV in FD", "");\r
+ fclose (InputFile);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ CurrentFv = LocalFdData->Fv;\r
+\r
+\r
+ do {\r
+\r
+ memset (CurrentFv->FvName, '\0', _MAX_PATH);\r
+\r
+ if (FvCount == 0) {\r
+ sprintf (CurrentFv->FvName, "FV%d", FvCount);\r
+ } else {\r
+ sprintf (CurrentFv->FvName, "FV%d", FvCount);\r
+ }\r
+\r
+ //\r
+ // Determine size of FV\r
+ //\r
+ if (fseek (InputFile, CurrentFv->ImageAddress, SEEK_SET) != 0) {\r
+ Error (NULL, 0, 0003, "error parsing FV image", "%s FD file is invalid", InputFile);\r
+ fclose (InputFile);\r
+ ErrorStatus = EFI_ABORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = LibGetFvSize(InputFile, &FvSize);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", InputFile);\r
+ fclose (InputFile);\r
+ ErrorStatus = EFI_ABORTED;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Seek to the start of the image, then read the entire FV to the buffer\r
+ //\r
+ fseek (InputFile, CurrentFv->ImageAddress, SEEK_SET);\r
+\r
+\r
+ FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (FvSize);\r
+\r
+ if (FvImage == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ fclose (InputFile);\r
+ ErrorStatus = EFI_ABORTED;\r
+ goto Done;\r
+ }\r
+\r
+ BytesRead = fread (FvImage, 1, FvSize, InputFile);\r
+ if ((unsigned int) BytesRead != FvSize) {\r
+ Error ("FMMT", 0, 0004, "error reading FvImage from", FdInName);\r
+ free (FvImage);\r
+ fclose (InputFile);\r
+ ErrorStatus = EFI_ABORTED;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Collect FV information each by each.\r
+ //\r
+ Status = LibGetFvInfo (FvImage, CurrentFv, FvName, 0, &CurrentFv->EncapData, &FfsCount, &FvCount, ViewFlag, FALSE);\r
+ if (FvImage != NULL) {\r
+ free (FvImage);\r
+ FvImage = NULL;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while get information from FV %s", FvName);\r
+ ErrorStatus = Status;\r
+ //\r
+ // If the FV to be parsed error is the same with the input FV in add, replace and delete\r
+ // operation, abort the program directly.\r
+ //\r
+ if ((FvName != NULL) && ((CurrentFv->FvName) != NULL) && !strcmp(CurrentFv->FvName, FvName)) {\r
+ fclose (InputFile);\r
+ ErrorStatus = EFI_ABORTED;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+\r
+ FfsCount = 0;\r
+\r
+ CurrentFv = CurrentFv->FvNext;\r
+\r
+ } while (CurrentFv != NULL);\r
+\r
+ fclose (InputFile);\r
+\r
+ if (ViewFlag) {\r
+\r
+ TemDir = getcwd (NULL, _MAX_PATH);\r
+ if (strlen (TemDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ ErrorStatus = EFI_ABORTED;\r
+ goto Done;\r
+ }\r
+ strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen(TemDir) - 1);\r
+ strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TemDir) - 1);\r
+\r
+ mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
+\r
+ Status = LibRmDir (TemDir);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "remove directory failed!");\r
+ ErrorStatus = Status;\r
+ }\r
+ }\r
+Done:\r
+ if (!ViewFlag) {\r
+ *FdData = LocalFdData;\r
+ } else {\r
+ LibFmmtFreeFd( LocalFdData);\r
+ }\r
+ return ErrorStatus;\r
+}\r
+\r
+/**\r
+ Add FFS file into a specify FV.\r
+\r
+ @param[in] FdInName Input FD binary/image file name;\r
+ @param[in] FileList The FV ID and FFS file Data;\r
+ @param[in] count The length of FileList;\r
+ @param[in] FdOutName Name of output FD binary/image file.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval EFI_INVALID_PARAMETER\r
+ @retval EFI_ABORTED\r
+\r
+**/\r
+EFI_STATUS\r
+FmmtImageAdd(\r
+ IN CHAR8* FdInName,\r
+ IN Data *FileList,\r
+ IN int count,\r
+ IN CHAR8* FdOutName\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ FIRMWARE_DEVICE *FdData;\r
+ FV_INFORMATION *FvInFd;\r
+ FILE* NewFdFile;\r
+ FILE* NewFvFile;\r
+ UINT64 NewFvLength;\r
+ VOID* Buffer;\r
+ CHAR8 *TemDir;\r
+ UINT8 FvNumInFd;\r
+ UINT8 FvNumInFdCounter;\r
+ UINT8 NewAddedFfsLevel;\r
+ FFS_INFORMATION *OutputFileName;\r
+ UINT32 Index;\r
+ UINT32 EndId;\r
+ UINT8 *FdBuffer;\r
+ EFI_FIRMWARE_VOLUME_HEADER *Fv;\r
+ UINT32 FdSize;\r
+ EFI_FFS_FILE_HEADER2 *InputFfs;\r
+ UINT32 NewFileSize;\r
+ UINT64 BaseAddr;\r
+ UINT32 OffsetAdded;\r
+ int i;\r
+ int j;\r
+ Data *tmp;\r
+ CHAR8* FvId;\r
+ CHAR8* NewFile;\r
+ FILENode *NewFileNode;\r
+ BOOLEAN HasUISection;\r
+ HasUISection = FALSE;\r
+ Index = 0;\r
+ EndId = 0;\r
+ NewFvLength = 0;\r
+ FvNumInFd = 0;\r
+ FvNumInFdCounter = 0;\r
+ NewAddedFfsLevel = 0;\r
+ FdData = NULL;\r
+ FvInFd = NULL;\r
+ NewFdFile = NULL;\r
+ NewFvFile = NULL;\r
+ Buffer = NULL;\r
+ TemDir = NULL;\r
+ OutputFileName = NULL;\r
+ FvId = NULL;\r
+ NewFile = NULL;\r
+\r
+ FdBuffer = NULL;\r
+ InputFfs = NULL;\r
+ BaseAddr = 0;\r
+ OffsetAdded = 0;\r
+ FdSize = 0;\r
+\r
+ for (i = 0; i < count; i ++){\r
+ tmp = FileList + i;\r
+ FvId = tmp->FvId;\r
+ FdData = tmp->FdData;\r
+ if (FdData == NULL) {\r
+ Status = FmmtImageView (FdInName, FvId, FALSE, &FdData);\r
+ if (EFI_ERROR (Status) && Status != EFI_UNSUPPORTED) {\r
+ Error ("FMMT", 0, 0004, "error while parsing FD Image", "Gathering FD information failed!");\r
+ return Status;\r
+ }\r
+ if (FdData == NULL) {\r
+ Error ("FMMT", 0, 0004, "error while parsing FD Image", "");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Status = LibLocateFvViaFvId (FdData, FvId, &FvInFd);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0005, "error while locate FV in FD", "");\r
+ return Status;\r
+ }\r
+ (FileList + i) -> FdData = FdData;\r
+ (FileList + i) -> FvInFd = FvInFd;\r
+ (FileList + i) -> FvLevel = FvInFd -> FvLevel;\r
+ }\r
+ }\r
+\r
+ for (i = 0; i < count; i++) {\r
+ for (j = i + 1; j < count; j++){\r
+ if (((FileList + i)->FvId == NULL) || ((FileList + j)->FvId == NULL)) {\r
+ continue;\r
+ }\r
+ if (strcmp((FileList + j)->FvId, (FileList + i)->FvInFd->FvName) == 0){\r
+ NewFileNode = (FileList + j)->NewFile;\r
+ while (NewFileNode ->Next != NULL) {\r
+ NewFileNode = NewFileNode->Next;\r
+ }\r
+ NewFileNode->Next = (FileList + i)->NewFile;\r
+ (FileList + i)->FvId = NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ for (i = 0; i < count; i ++){\r
+ if ((FileList + i)->FvId == NULL) {\r
+ continue;\r
+ }\r
+ sortList ((FileList + i)-> NewFile);\r
+ }\r
+\r
+ TemDir = getcwd(NULL, _MAX_PATH);\r
+ if (strlen (TemDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen(TemDir) - 1);\r
+ strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TemDir) - 1);\r
+\r
+ if (FdBuffer == NULL) {\r
+ FdBuffer = ReadFileToBuffer(FdInName, &FdSize);\r
+ if (FdBuffer == NULL) {\r
+ Error("FMMT", 0, 0004, "error while adding file", "cannot read input file.");\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+\r
+ for (i = 0; i < count; i ++){\r
+ tmp = FileList + i;\r
+ FvId = tmp->FvId;\r
+ if (FvId == NULL) {\r
+ continue;\r
+ }\r
+ FdData = tmp->FdData;\r
+ FvInFd = tmp->FvInFd;\r
+ NewFileNode =tmp->NewFile;\r
+\r
+ NewFile = NewFileNode->FileName;\r
+ InputFfs = (EFI_FFS_FILE_HEADER2 *)ReadFileToBuffer(NewFile, &NewFileSize);\r
+ if (InputFfs == NULL) {\r
+ Error("FMMT", 0, 0004, "error while adding file", "cannot read input file.");\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+ HasUISection = FALSE;\r
+ HasUISection = ParseSection(InputFfs);\r
+ if (!HasUISection) {\r
+ printf ("WARNING: The newly add file must have a user interface (UI) section, otherwise it cannot be deleted or replaced. \n");\r
+ }\r
+ if (NeedNewPath(FvInFd, FvId, 0, TRUE)) {\r
+ do {\r
+ NewFile = NewFileNode->FileName;\r
+ //\r
+ // TODO: currently only root FV is handled\r
+ //\r
+ InputFfs = (EFI_FFS_FILE_HEADER2 *)ReadFileToBuffer(NewFile, &NewFileSize);\r
+ if (InputFfs == NULL) {\r
+ Error("FMMT", 0, 0004, "error while adding file", "cannot read input file.");\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+\r
+ Fv = (EFI_FIRMWARE_VOLUME_HEADER *)(FdBuffer + FvInFd->ImageAddress);\r
+\r
+ Status = AddFfs(FdBuffer, FvInFd->ImageAddress, Fv, InputFfs, &OffsetAdded);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0003, "error while adding file", "Not enough space to add FFS");\r
+ goto FAILED;\r
+ }\r
+ //\r
+ // Calculate base address of Current FV\r
+ //\r
+ if (InputFfs->Type == EFI_FV_FILETYPE_PEIM || InputFfs->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+ Status = GetBaseAddrFromFsp(FdData, FdBuffer, FvId, &BaseAddr);\r
+ if (!EFI_ERROR(Status)) {\r
+ mFvHeader = FvInFd->FvHeader;\r
+ mFvLength = (UINT32)FvInFd->FvHeader->FvLength;\r
+ RebaseFfs(BaseAddr, NewFile, (EFI_FFS_FILE_HEADER *)(FdBuffer + FvInFd->ImageAddress + OffsetAdded), OffsetAdded);\r
+ }\r
+ else {\r
+ Status = GetBaseAddrFromVtf(FdData, FvId, &BaseAddr);\r
+ if (!EFI_ERROR(Status)) {\r
+ mFvHeader = FvInFd->FvHeader;\r
+ mFvLength = (UINT32)FvInFd->FvHeader->FvLength;\r
+ RebaseFfs(BaseAddr, NewFile, (EFI_FFS_FILE_HEADER *)(FdBuffer + FvInFd->ImageAddress + OffsetAdded), OffsetAdded);\r
+ }\r
+ }\r
+ }\r
+ NewFileNode = NewFileNode->Next;\r
+ free (InputFfs);\r
+ InputFfs = NULL;\r
+ } while (NewFileNode != NULL);\r
+ } else {\r
+ do {\r
+ NewFile = NewFileNode->FileName;\r
+ if (strlen (NewFile) > _MAX_PATH - 1) {\r
+ Error ("FMMT", 0, 2000, "error while adding file", "New file name is too long!");\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+ FvNumInFd = ((UINT8)atoi(FvId + 2) - (UINT8)atoi(FvInFd->FvName + 2));\r
+ if (FvInFd->FfsNumbers == 0) {\r
+ NewAddedFfsLevel = FvInFd->FfsAttuibutes[0].Level;\r
+ }\r
+ for (Index = 0; Index <= FvInFd->FfsNumbers; Index++) {\r
+ if (FvInFd->FfsAttuibutes[Index].IsFvStart == 1) {\r
+ FvNumInFdCounter++;\r
+ }\r
+ if ( FvNumInFdCounter == FvNumInFd && FvInFd->FfsAttuibutes[Index].IsFvEnd == 1) {\r
+ NewAddedFfsLevel = FvInFd->FfsAttuibutes[Index].Level;\r
+ EndId = Index+1;\r
+ break;\r
+ }\r
+ if (FvInFd->FfsAttuibutes[Index].IsFvEnd == 1) {\r
+ FvNumInFdCounter--;\r
+ if (FvNumInFdCounter == 0) {\r
+ FvNumInFd--;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add the new file into FV.\r
+ //\r
+ FvInFd->FfsNumbers += 1;\r
+ for (Index = FvInFd->FfsNumbers; Index > EndId; Index--) {\r
+ FvInFd->FfsAttuibutes[Index] = FvInFd->FfsAttuibutes[Index - 1];\r
+ }\r
+ strncpy(FvInFd->FfsAttuibutes[EndId].FfsName, NewFile, _MAX_PATH - 1);\r
+ FvInFd->FfsAttuibutes[EndId].FfsName[_MAX_PATH - 1] = 0;\r
+ FvInFd->FfsAttuibutes[EndId].Level = NewAddedFfsLevel;\r
+ memset (&FvInFd->FfsAttuibutes[EndId].GuidName, '\0', sizeof(EFI_GUID));\r
+ if (EndId > 0) {\r
+ FvInFd->FfsAttuibutes[EndId].FvLevel = FvInFd->FfsAttuibutes[EndId - 1].FvLevel;\r
+ FvInFd->FfsAttuibutes[EndId - 1].IsFvEnd = 0;\r
+ }\r
+ FvInFd->FfsAttuibutes[EndId].IsFvEnd = 1;\r
+ FvInFd->FfsAttuibutes[EndId].IsFvStart = 0;\r
+ NewFileNode = NewFileNode->Next;\r
+ } while (NewFileNode != NULL);\r
+\r
+ mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
+\r
+ Status = LibEncapNewFvFile (FvInFd, TemDir, NULL, 0, &OutputFileName);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Make new FV file failed!");\r
+ goto FAILED;\r
+ }\r
+\r
+ NewFvFile = fopen (OutputFileName->FFSName, "rb+");\r
+ if (NewFvFile == NULL) {\r
+ Error ("FMMT", 0, 0003, "error Open FV file", "cannot Create a new FD file.");\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+\r
+ fseek(NewFvFile,0,SEEK_SET);\r
+ fseek(NewFvFile,0,SEEK_END);\r
+\r
+ NewFvLength = ftell(NewFvFile);\r
+ fseek(NewFvFile,0,SEEK_SET);\r
+ Buffer = malloc ((size_t)NewFvLength);\r
+ if (Buffer == NULL) {\r
+ Status = EFI_ABORTED;\r
+ fclose(NewFvFile);\r
+ goto FAILED;\r
+ }\r
+\r
+ if (fread (Buffer, 1, (size_t) NewFvLength, NewFvFile) != (size_t) NewFvLength) {\r
+ Error ("FMMT", 0, 0003, "error reading FV file %s", OutputFileName->FFSName);\r
+ free (Buffer);\r
+ Status = EFI_ABORTED;\r
+ fclose(NewFvFile);\r
+ goto FAILED;\r
+ }\r
+\r
+ if (NewFvLength <= FvInFd->FvHeader->FvLength) {\r
+ memcpy(FdBuffer+FvInFd->ImageAddress,Buffer,(size_t) NewFvLength);\r
+ } else {\r
+ Error ("FMMT", 0, 0004, "error writing FD file", "The add ffs file is too large.");\r
+ }\r
+ fclose(NewFvFile);\r
+ free(Buffer);\r
+ }\r
+ }\r
+\r
+ Status = LibRmDir(TemDir);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0004, "error while encapsulate FD Image", "remove directory failed!");\r
+ goto FAILED;\r
+ }\r
+\r
+ NewFdFile = fopen(FdOutName, "wb");\r
+ if (NewFdFile == NULL) {\r
+ Error("FMMT", 0, 0004, "error while encapsulate FD Image", "Cannot open target FD file!");\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+\r
+ fwrite(FdBuffer, 1, FdSize, NewFdFile);\r
+ fclose(NewFdFile);\r
+ free(FdBuffer);\r
+ free(InputFfs);\r
+ printf ("Create New FD file successfully. \n\nDone! \n");\r
+ return EFI_SUCCESS;\r
+\r
+ FAILED:\r
+ if (FdBuffer != NULL) {\r
+ free(FdBuffer);\r
+ }\r
+ if (InputFfs != NULL) {\r
+ free(InputFfs);\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+Delete a root FV from FD.\r
+\r
+@param[in] FdInName Input FD binary/image file name;\r
+@param[in] FvName FV name;\r
+@param[in] FdOutName Name of output fd file.\r
+\r
+@retval EFI_SUCCESS\r
+@retval EFI_INVALID_PARAMETER\r
+@retval EFI_ABORTED\r
+\r
+**/\r
+EFI_STATUS\r
+FmmtImageDeleteFv(\r
+ IN CHAR8* FdInName,\r
+ IN CHAR8* FvName,\r
+ IN CHAR8* FdOutName\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ FV_INFORMATION *FvInFd;\r
+ FILE *NewFdFile;\r
+ CHAR8 *TemDir;\r
+\r
+ UINT8 *FdBuffer = NULL;\r
+ UINT8 *FdBak = NULL;\r
+ UINT32 FdSize = 0;\r
+\r
+ FIRMWARE_DEVICE *FdData = NULL;\r
+\r
+ TemDir = getcwd(NULL, _MAX_PATH);\r
+ if (strlen (TemDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen(TemDir) - 1);\r
+ strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TemDir) - 1);\r
+\r
+ Status = FmmtImageView(FdInName, NULL, FALSE, &FdData);\r
+ if (EFI_ERROR(Status) && Status != EFI_UNSUPPORTED) {\r
+ Error("FMMT", 0, 0004, "error while parsing FD Image", "Gathering FD information failed!");\r
+ goto END;\r
+ }\r
+ if (FdData == NULL) {\r
+ Error("FMMT", 0, 0004, "error while parsing FD Image", "");\r
+ Status = EFI_ABORTED;\r
+ goto END;\r
+ }\r
+\r
+ FvInFd = FdData->Fv;\r
+ while (FvInFd) {\r
+ if (FvInFd->FvUiName && strcmp(FvInFd->FvUiName, FvName) == 0) {\r
+ break;\r
+ }\r
+ FvInFd = FvInFd->FvNext;\r
+ }\r
+ if (!FvInFd) {\r
+ Error("FMMT", 0, 0004, "error while deleting root FV", "Cannot find this FV!");\r
+ Status = EFI_ABORTED;\r
+ goto END;\r
+ }\r
+ FdBuffer = ReadFileToBuffer(FdInName, &FdSize);\r
+ FdBak = FdBuffer;\r
+ if (FdBuffer == NULL) {\r
+ Error("FMMT", 0, 0004, "error while deleting root FV", "Cannot read FD file!");\r
+ Status = EFI_ABORTED;\r
+ goto END;\r
+ }\r
+\r
+ if (FvInFd->ImageAddress == 0) {\r
+ FdBuffer = FdBuffer + FvInFd->FvHeader->FvLength;\r
+ FdSize -= (UINT32)FvInFd->FvHeader->FvLength;\r
+ } else {\r
+ if (FvInFd->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+ memset(FdBuffer + FvInFd->ImageAddress, -1, (size_t)FvInFd->FvHeader->FvLength);\r
+ }\r
+ else {\r
+ memset(FdBuffer + FvInFd->ImageAddress, 0, (size_t)FvInFd->FvHeader->FvLength);\r
+ }\r
+ }\r
+\r
+ NewFdFile = fopen(FdOutName, "wb");\r
+ if (NewFdFile == NULL) {\r
+ Error("FMMT", 0, 0004, "error while deleting root FV", "Cannot open target FD file!");\r
+ Status = EFI_ABORTED;\r
+ goto END;\r
+ }\r
+ fwrite(FdBuffer, 1, FdSize, NewFdFile);\r
+ fclose(NewFdFile);\r
+\r
+ Status = LibRmDir(TemDir);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0004, "error while deleting root FV", "remove directory failed!");\r
+ goto END;\r
+ }\r
+\r
+ printf("Create New FD file successfully. \n\nDone! \n");\r
+END:\r
+ LibFmmtFreeFd(FdData);\r
+ free(FdBak);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Delete an FFS file from a specify FV.\r
+\r
+ @param[in] FdInName Input FD binary/image file name;\r
+ @param[in] FileList The FV ID and FFS file Data;\r
+ @param[in] count The length of FileList;\r
+ @param[in] FdOutName Name of output fd file.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval EFI_INVALID_PARAMETER\r
+ @retval EFI_ABORTED\r
+\r
+**/\r
+EFI_STATUS\r
+FmmtImageDelete (\r
+ IN CHAR8* FdInName,\r
+ IN Data *FileList,\r
+ IN int count,\r
+ IN CHAR8* FdOutName\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ FIRMWARE_DEVICE *FdData;\r
+ FV_INFORMATION *FvInFd;\r
+ UINT32 Index;\r
+ UINT32 FfsFoundFlag;\r
+ FFS_INFORMATION *OutputFileName;\r
+ FILE* NewFdFile;\r
+ FILE* NewFvFile;\r
+ UINT64 NewFvLength;\r
+ VOID* Buffer;\r
+ CHAR8 *TemDir;\r
+ UINT8 FvNumInFd;\r
+ UINT32 Offset;\r
+ UINT8 *FdBuffer;\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile;\r
+ EFI_FFS_FILE_HEADER2 *PreFile;\r
+ Data *tmp;\r
+ CHAR8* FvId;\r
+ CHAR8* DelFile;\r
+ FILENode *OldFileNode;\r
+ int i;\r
+ UINT32 FfsSize;\r
+ UINT32 FdSize;\r
+ int j;\r
+\r
+ FdSize = 0;\r
+ Index = 0;\r
+ NewFvLength = 0;\r
+ FfsFoundFlag = 0;\r
+ FdData = NULL;\r
+ FvInFd = NULL;\r
+ OutputFileName = NULL;\r
+ NewFdFile = NULL;\r
+ NewFvFile = NULL;\r
+ Buffer = NULL;\r
+ TemDir = NULL;\r
+ FvNumInFd = 0;\r
+ Offset = 0;\r
+ FdBuffer = NULL;\r
+\r
+ for (i = 0; i < count; i ++){\r
+ tmp = FileList + i;\r
+ FvId = tmp->FvId;\r
+ FdData = tmp->FdData;\r
+ if (FdData == NULL) {\r
+ Status = FmmtImageView (FdInName, FvId, FALSE, &FdData);\r
+ if (EFI_ERROR (Status) && Status != EFI_UNSUPPORTED) {\r
+ Error ("FMMT", 0, 0004, "error while parsing FD Image", "Gathering FD information failed!");\r
+ return Status;\r
+ }\r
+ if (FdData == NULL) {\r
+ Error ("FMMT", 0, 0004, "error while parsing FD Image", "");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Status = LibLocateFvViaFvId (FdData, FvId, &FvInFd);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0005, "error while locate FV in FD", "");\r
+ return Status;\r
+ }\r
+ (FileList + i) -> FdData = FdData;\r
+ (FileList + i) -> FvInFd = FvInFd;\r
+ (FileList + i) -> FvLevel = FvInFd -> FvLevel;\r
+ }\r
+ FvNumInFd = ((UINT8)atoi(FvId + 2) - (UINT8)atoi(FvInFd->FvName + 2)) + 1;\r
+ OldFileNode = tmp-> OldFile;\r
+ do {\r
+ DelFile = OldFileNode->FileName;\r
+ if (FvInFd == NULL) {\r
+ break;\r
+ }\r
+ FfsFoundFlag = FindFile(FvInFd, FvNumInFd, DelFile, &Index);\r
+ if (FfsFoundFlag) {\r
+ if (FfsFoundFlag > 1) {\r
+ printf("Duplicated file found in this FV, file name: %s\n", DelFile);\r
+ return EFI_ABORTED;\r
+ }\r
+ } else {\r
+ printf ("Could not found the FFS file from FD!, file name: %s\n", DelFile);\r
+ return EFI_ABORTED;\r
+ }\r
+ OldFileNode -> SubLevel = FvInFd -> FfsAttuibutes[Index].Level;\r
+ OldFileNode = OldFileNode->Next;\r
+ } while (OldFileNode != NULL);\r
+ }\r
+\r
+ for (i = 0; i < count; i++) {\r
+ for (j = i + 1; j < count; j++)\r
+ {\r
+ if (((FileList + i)->FvId == NULL) || ((FileList + j)->FvId == NULL)) {\r
+ continue;\r
+ }\r
+ if (strcmp((FileList + j)->FvId, (FileList + i)->FvInFd->FvName) == 0){\r
+ OldFileNode = (FileList + j)->OldFile;\r
+ while (OldFileNode ->Next != NULL) {\r
+ OldFileNode = OldFileNode->Next;\r
+ }\r
+ OldFileNode->Next = (FileList + i)->OldFile;\r
+ (FileList + i)->FvId = NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ for (i = 0; i < count; i ++){\r
+ if ((FileList + i)->FvId == NULL) {\r
+ continue;\r
+ }\r
+ sortList ((FileList + i)-> OldFile);\r
+ }\r
+\r
+ TemDir = getcwd(NULL, _MAX_PATH);\r
+ if (strlen (TemDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen(TemDir) - 1);\r
+ strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TemDir) - 1);\r
+\r
+ if (FdBuffer == NULL) {\r
+ FdBuffer = ReadFileToBuffer(FdInName, &FdSize);\r
+ if (FdBuffer == NULL) {\r
+ Error("FMMT", 0, 0004, "error while deleting file", "cannot read input file.");\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+\r
+ for (i = 0; i < count; i ++){\r
+ tmp = FileList + i;\r
+ FvId = tmp->FvId;\r
+ if (FvId == NULL) {\r
+ continue;\r
+ }\r
+ FdData = tmp->FdData;\r
+ FvInFd = tmp->FvInFd;\r
+ FvNumInFd = ((UINT8)atoi(FvId + 2) - (UINT8)atoi(FvInFd->FvName + 2)) + 1;\r
+ OldFileNode = tmp->OldFile;\r
+ DelFile = OldFileNode -> FileName;\r
+ FfsFoundFlag = FindFile(FvInFd, FvNumInFd, DelFile, &Index);\r
+ if (FfsFoundFlag && NeedNewPath(FvInFd, FvId, Index, FALSE)) {\r
+ do {\r
+ DelFile = OldFileNode -> FileName;\r
+ FfsFoundFlag = FindFile(FvInFd, FvNumInFd, DelFile, &Index);\r
+ //\r
+ // TODO: currently only root FV is handled\r
+ //\r
+ Offset = FvInFd->ImageAddress + FvInFd->FfsAttuibutes[Index].Offset;\r
+ if (FdBuffer != NULL) {\r
+ CurrentFile = (EFI_FFS_FILE_HEADER2 *)(FdBuffer + Offset);\r
+\r
+ FfsSize = CalcuFfsSize((EFI_FIRMWARE_VOLUME_HEADER *)(FdBuffer + FvInFd->ImageAddress), CurrentFile);\r
+\r
+ FindPreviousFile((EFI_FIRMWARE_VOLUME_HEADER *)(FdBuffer + FvInFd->ImageAddress), CurrentFile, (VOID **) &PreFile);\r
+ if (PreFile != NULL && PreFile->Type == EFI_FV_FILETYPE_FFS_PAD) {\r
+ FfsSize += (UINT8 *)CurrentFile - (UINT8 *)PreFile;\r
+ CurrentFile = PreFile;\r
+ }\r
+ AddPadFile((EFI_FIRMWARE_VOLUME_HEADER *)(FdBuffer + FvInFd->ImageAddress), CurrentFile, FfsSize);\r
+ }\r
+ OldFileNode = OldFileNode -> Next;\r
+ } while (OldFileNode != NULL);\r
+ } else {\r
+ do {\r
+ DelFile = OldFileNode -> FileName;\r
+ FfsFoundFlag = FindFile(FvInFd, FvNumInFd, DelFile, &Index);\r
+\r
+ if (FfsFoundFlag) {\r
+ //\r
+ // Delete this FFS file from Current FV structure.\r
+ //\r
+ Status = LibFmmtDeleteFile (FvInFd->FfsAttuibutes[Index].FfsName);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Delete the specified file failed!");\r
+ Error ("FMMT", 0, 0004, "Cannot find the file need to delete", "Please check the name of the file you want to delete!");\r
+ goto FAILED;\r
+ }\r
+\r
+ memset(FvInFd->FfsAttuibutes[Index].FfsName, '\0', _MAX_PATH);\r
+ FvInFd->FfsAttuibutes[Index].Level = 0xFF;\r
+\r
+ //\r
+ // Since we can avoid to add NULL ffs file, at this time we don't need to decrease the FFS number.\r
+ // If decrease operation executed, we should adjust the ffs list. It will bring in more complex.\r
+ //\r
+ //FvInFd->FfsNumbers -= 1;\r
+ memset(FvInFd->FfsAttuibutes[Index].UiName, '\0', _MAX_PATH);\r
+ if (FvInFd->FfsAttuibutes[Index].FvLevel > 1) {\r
+ for (j = Index - 1; j >= 0; j--) {\r
+ if (FvInFd->FfsAttuibutes[j].FvLevel == FvInFd->FfsAttuibutes[Index].FvLevel - 1) {\r
+ break;\r
+ }\r
+ }\r
+ if (Index+1 <= FvInFd->FfsNumbers) {\r
+ if (FvInFd->FfsAttuibutes[Index+1].FvLevel == FvInFd->FfsAttuibutes[Index].FvLevel + 1) {\r
+ for (j = Index+1; j <= (signed)FvInFd->FfsNumbers; j++) {\r
+ if (FvInFd->FfsAttuibutes[j].FvLevel > FvInFd->FfsAttuibutes[Index].FvLevel) {\r
+ Status = LibFmmtDeleteFile(FvInFd->FfsAttuibutes[j].FfsName);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0004, "error while encapsulate FD Image", "Delete the specified file failed!");\r
+ return Status;\r
+ }\r
+ memset(FvInFd->FfsAttuibutes[j].FfsName, '\0', _MAX_PATH);\r
+ FvInFd->FfsAttuibutes[j].Level = 0xFF;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ printf ("Could not found the FFS file from FD!, file name: %s\n", DelFile);\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+ OldFileNode = OldFileNode -> Next;\r
+\r
+ }while (OldFileNode != NULL);\r
+\r
+ mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
+\r
+ Status = LibEncapNewFvFile (FvInFd, TemDir, NULL, 0, &OutputFileName);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Make new FV file failed!");\r
+ goto FAILED;\r
+ }\r
+\r
+ NewFvFile = fopen (OutputFileName->FFSName, "rb+");\r
+ if (NewFvFile == NULL) {\r
+ Error ("FMMT", 0, 0003, "error Open FV file", "cannot Create a new FD file.");\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+\r
+ fseek(NewFvFile,0,SEEK_SET);\r
+ fseek(NewFvFile,0,SEEK_END);\r
+\r
+ NewFvLength = ftell(NewFvFile);\r
+ fseek(NewFvFile,0,SEEK_SET);\r
+ Buffer = malloc ((size_t)NewFvLength);\r
+ if (Buffer == NULL) {\r
+ fclose(NewFvFile);\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+\r
+ if (fread (Buffer, 1, (size_t) NewFvLength, NewFvFile) != (size_t) NewFvLength) {\r
+ Error ("FMMT", 0, 0003, "error reading FV file %s", OutputFileName->FFSName);\r
+ fclose(NewFvFile);\r
+ free(Buffer);\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+ memcpy(FdBuffer+FvInFd->ImageAddress,Buffer,(size_t) NewFvLength);\r
+ free(Buffer);\r
+ fclose(NewFvFile);\r
+ }\r
+ }\r
+\r
+ Status = LibRmDir(TemDir);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0004, "error while encapsulate FD Image", "remove directory failed!");\r
+ goto FAILED;\r
+ }\r
+\r
+ NewFdFile = fopen(FdOutName, "wb");\r
+ if (NewFdFile == NULL) {\r
+ Error("FMMT", 0, 0004, "error while encapsulate FD Image", "Cannot open target FD file!");\r
+ Status = EFI_ABORTED;\r
+ goto FAILED;\r
+ }\r
+\r
+ fwrite(FdBuffer, 1, FdSize, NewFdFile);\r
+ fclose(NewFdFile);\r
+ free(FdBuffer);\r
+ printf("Create New FD file successfully. \n\nDone! \n");\r
+ return EFI_SUCCESS;\r
+\r
+ FAILED:\r
+ free(FdBuffer);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Replace the exist FFS file with new one from a specify FV.\r
+\r
+ @param[in] FdInName Input FD binary/image file name;\r
+ @param[in] FileList The FV ID and FFS file Data;\r
+ @param[in] count The length of FileList;\r
+ @param[in] FdOutName Name of output fd file.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval EFI_INVALID_PARAMETER\r
+ @retval EFI_ABORTED\r
+\r
+**/\r
+EFI_STATUS\r
+FmmtImageReplace (\r
+ IN CHAR8* FdInName,\r
+ IN Data *FileList,\r
+ IN int count,\r
+ IN CHAR8* FdOutName\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ FIRMWARE_DEVICE *FdData;\r
+ FV_INFORMATION *FvInFd;\r
+ UINT32 Index;\r
+ UINT32 FfsFoundFlag;\r
+ FFS_INFORMATION *OutputFileName;\r
+ FILE* NewFdFile;\r
+ FILE* NewFvFile;\r
+ UINT64 NewFvLength;\r
+ VOID* Buffer;\r
+ CHAR8 *TemDir;\r
+ UINT32 Offset;\r
+ UINT8 *FdBuffer;\r
+ UINT8 FvNumInFd;\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile;\r
+ EFI_FIRMWARE_VOLUME_HEADER *Fv;\r
+ UINT32 FdSize;\r
+ EFI_FFS_FILE_HEADER2 *InputFfs;\r
+ UINT32 NewFileSize;\r
+ UINT32 PadFileSize;\r
+ UINT64 BaseAddr;\r
+ UINT32 OffsetAdded;\r
+ Data *tmp;\r
+ CHAR8* FvId;\r
+ CHAR8* OldFile;\r
+ CHAR8* NewFile;\r
+ int i;\r
+ int j;\r
+ FILENode *OldFileNode;\r
+ FILENode *NewFileNode;\r
+ BOOLEAN HasUISection;\r
+ HasUISection = FALSE;\r
+ Index = 0;\r
+ NewFvLength = 0;\r
+ FfsFoundFlag = 0;\r
+ FdData = NULL;\r
+ FvInFd = NULL;\r
+ OutputFileName = NULL;\r
+ NewFdFile = NULL;\r
+ NewFvFile = NULL;\r
+ Buffer = NULL;\r
+ TemDir = NULL;\r
+ Offset = 0;\r
+ FdBuffer = NULL;\r
+ InputFfs = NULL;\r
+ BaseAddr = 0;\r
+ OffsetAdded = 0;\r
+ FdSize = 0;\r
+\r
+ for (i = 0; i < count; i ++){\r
+ tmp = FileList + i;\r
+ FvId = tmp->FvId;\r
+ FdData = tmp->FdData;\r
+ if (FdData == NULL){\r
+ Status = FmmtImageView(FdInName, FvId, FALSE, &FdData);\r
+ if (EFI_ERROR(Status) && Status != EFI_UNSUPPORTED) {\r
+ Error("FMMT", 0, 0004, "error while parsing FD Image", "Gathering information failed!");\r
+ return Status;\r
+ }\r
+\r
+ if (FdData == NULL) {\r
+ Error("FMMT", 0, 0004, "error while parsing FD Image", "");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Status = LibLocateFvViaFvId(FdData, FvId, &FvInFd);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0005, "error while locate FV in FD", "");\r
+ return Status;\r
+ }\r
+ (FileList + i) -> FdData = FdData;\r
+ (FileList + i) -> FvInFd = FvInFd;\r
+ (FileList + i) -> FvLevel = FvInFd -> FvLevel;\r
+ }\r
+ FvNumInFd = ((UINT8)atoi(FvId + 2) - (UINT8)atoi(FvInFd->FvName + 2)) + 1;\r
+ OldFileNode = tmp-> OldFile;\r
+ NewFileNode = tmp-> NewFile;\r
+ do {\r
+ OldFile = OldFileNode -> FileName;\r
+ NewFile = NewFileNode -> FileName;\r
+ if (FvInFd == NULL) {\r
+ break;\r
+ }\r
+ FfsFoundFlag = FindFile(FvInFd, FvNumInFd, OldFile, &Index);\r
+\r
+ if (FfsFoundFlag) {\r
+ if (FfsFoundFlag > 1) {\r
+ printf("Duplicated file found in this FV, file name: %s\n", OldFile);\r
+ return EFI_ABORTED;\r
+ }\r
+ //\r
+ // Replace this FFS file with the new one.\r
+ // strcpy (FvInFd->FfsAttuibutes[Index].FfsName, NewFile);\r
+ } else {\r
+ printf ("Could not found the FFS file need to be replaced from FD! file name: %s\n", OldFile);\r
+ return EFI_ABORTED;\r
+ }\r
+ OldFileNode -> SubLevel = FvInFd -> FfsAttuibutes[Index].Level;\r
+ NewFileNode -> SubLevel = FvInFd -> FfsAttuibutes[Index].Level;\r
+ OldFileNode = OldFileNode->Next;\r
+ NewFileNode = NewFileNode->Next;\r
+ } while (OldFileNode != NULL && NewFileNode != NULL);\r
+ }\r
+\r
+ for (i = 0; i < count; i++) {\r
+ for (j = i + 1; j < count; j++)\r
+ {\r
+ if (((FileList + i)->FvId == NULL) || ((FileList + j)->FvId == NULL)) {\r
+ continue;\r
+ }\r
+ if (strcmp((FileList + j)->FvId, (FileList + i)->FvInFd->FvName) == 0){\r
+ OldFileNode = (FileList + j)->OldFile;\r
+ NewFileNode = (FileList + j)->NewFile;\r
+ while (OldFileNode->Next != NULL && NewFileNode->Next != NULL) {\r
+ OldFileNode = OldFileNode->Next;\r
+ NewFileNode = NewFileNode->Next;\r
+ }\r
+ OldFileNode->Next = (FileList + i)->OldFile;\r
+ NewFileNode->Next = (FileList + i)->NewFile;\r
+ (FileList + i)->FvId = NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ for (i = 0; i < count; i ++){\r
+ if ((FileList + i)->FvId == NULL) {\r
+ continue;\r
+ }\r
+ sortList ((FileList + i)-> OldFile);\r
+ sortList ((FileList + i)-> NewFile);\r
+ }\r
+ TemDir = getcwd (NULL, _MAX_PATH);\r
+ if (strlen (TemDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen(TemDir) - 1);\r
+ strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TemDir) - 1);\r
+ mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
+ if (FdBuffer == NULL) {\r
+ FdBuffer = ReadFileToBuffer(FdInName, &FdSize);\r
+ if (FdBuffer == NULL) {\r
+ Error("FMMT", 0, 0004, "error while replacing file", "cannot read input file.");\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+\r
+ for (i = 0; i < count; i ++){\r
+ tmp = FileList + i;\r
+ FvId = tmp->FvId;\r
+ if (FvId == NULL) {\r
+ continue;\r
+ }\r
+ FdData = tmp->FdData;\r
+ FvInFd = tmp->FvInFd;\r
+ FvNumInFd = ((UINT8)atoi(FvId + 2) - (UINT8)atoi(FvInFd->FvName + 2)) + 1;\r
+ OldFileNode = tmp-> OldFile;\r
+ OldFile = OldFileNode -> FileName;\r
+ NewFileNode = tmp-> NewFile;\r
+ FfsFoundFlag = FindFile(FvInFd, FvNumInFd, OldFile, &Index);\r
+\r
+ NewFile = NewFileNode->FileName;\r
+ InputFfs = (EFI_FFS_FILE_HEADER2 *)ReadFileToBuffer(NewFile, &NewFileSize);\r
+ if (InputFfs == NULL) {\r
+ Error("FMMT", 0, 0004, "error while replacing file", "cannot read input file.");\r
+ free (FdBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+ HasUISection = FALSE;\r
+ HasUISection = ParseSection(InputFfs);\r
+ if (!HasUISection) {\r
+ printf ("WARNING: The newly replace file must have a user interface (UI) section, otherwise it cannot be deleted or replaced. \n");\r
+ }\r
+ if (FfsFoundFlag && NeedNewPath(FvInFd, FvId, Index, FALSE)) {\r
+ do {\r
+ OldFile = OldFileNode -> FileName;\r
+ NewFile = NewFileNode -> FileName;\r
+ FfsFoundFlag = FindFile(FvInFd, FvNumInFd, OldFile, &Index);\r
+ //\r
+ // TODO: currently only root FV is handled\r
+ //\r
+ InputFfs = (EFI_FFS_FILE_HEADER2 *)ReadFileToBuffer(NewFile, &NewFileSize);\r
+ if (InputFfs == NULL) {\r
+ Error("FMMT", 0, 0004, "error while replacing file", "cannot read input file.");\r
+ free (FdBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Offset = FvInFd->ImageAddress + FvInFd->FfsAttuibutes[Index].Offset;\r
+ Fv = (EFI_FIRMWARE_VOLUME_HEADER *)(FdBuffer + FvInFd->ImageAddress);\r
+ OffsetAdded = FvInFd->FfsAttuibutes[Index].Offset;\r
+\r
+ if (!ReplaceFfs(Fv, InputFfs, (EFI_FFS_FILE_HEADER2 *)(FdBuffer + Offset))) {\r
+ Status = AddFfs(FdBuffer, FvInFd->ImageAddress, Fv, InputFfs, &OffsetAdded);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0003, "error while replacing file", "cannot add ffs");\r
+ goto END;\r
+ }\r
+ //\r
+ // Set original FFS to PAD file\r
+ //\r
+ CurrentFile = (EFI_FFS_FILE_HEADER2 *)(FdBuffer + FvInFd->ImageAddress + FvInFd->FfsAttuibutes[Index].Offset);\r
+ PadFileSize = CalcuFfsSize(Fv, CurrentFile);\r
+ AddPadFile(Fv, CurrentFile, PadFileSize);\r
+ }\r
+\r
+ //\r
+ // Calculate base address of Current FV\r
+ //\r
+ if (InputFfs->Type == EFI_FV_FILETYPE_PEIM || InputFfs->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+ Status = GetBaseAddrFromFsp(FdData, FdBuffer, FvId, &BaseAddr);\r
+ if (!EFI_ERROR(Status)) {\r
+ mFvHeader = FvInFd->FvHeader;\r
+ mFvLength = (UINT32)FvInFd->FvHeader->FvLength;\r
+ RebaseFfs(BaseAddr, NewFile, (EFI_FFS_FILE_HEADER *)(FdBuffer + FvInFd->ImageAddress + OffsetAdded), OffsetAdded);\r
+ }\r
+ else {\r
+ Status = GetBaseAddrFromVtf(FdData, FvId, &BaseAddr);\r
+ if (!EFI_ERROR(Status)) {\r
+ mFvHeader = FvInFd->FvHeader;\r
+ mFvLength = (UINT32)FvInFd->FvHeader->FvLength;\r
+ RebaseFfs(BaseAddr, NewFile, (EFI_FFS_FILE_HEADER *)(FdBuffer + FvInFd->ImageAddress + OffsetAdded), OffsetAdded);\r
+ }\r
+ }\r
+ }\r
+ OldFileNode = OldFileNode -> Next;\r
+ NewFileNode = NewFileNode -> Next;\r
+ free (InputFfs);\r
+ InputFfs = NULL;\r
+ } while (OldFileNode != NULL && NewFileNode!= NULL);\r
+ } else {\r
+ do {\r
+ OldFile = OldFileNode->FileName;\r
+ NewFile = NewFileNode->FileName;\r
+ FfsFoundFlag = FindFile(FvInFd, FvNumInFd, OldFile, &Index);\r
+ //\r
+ // Replace this FFS file with the new one.\r
+ //\r
+ if (strlen (NewFile) > _MAX_PATH - 1) {\r
+ Error ("FMMT", 0, 2000, "error while replacing file", "New file name is too long!");\r
+ free (FdBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+ strncpy(FvInFd->FfsAttuibutes[Index].FfsName, NewFile, _MAX_PATH - 1);\r
+ FvInFd->FfsAttuibutes[Index].FfsName[_MAX_PATH - 1] = 0;\r
+ OldFileNode = OldFileNode->Next;\r
+ NewFileNode = NewFileNode->Next;\r
+ } while (OldFileNode != NULL && NewFileNode != NULL);\r
+ Status = LibEncapNewFvFile (FvInFd, TemDir, NULL, 0, &OutputFileName);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Make new FV file failed!");\r
+ free (FdBuffer);\r
+ return Status;\r
+ }\r
+\r
+ NewFvFile = fopen (OutputFileName->FFSName, "rb+");\r
+ if (NewFvFile == NULL) {\r
+ Error ("FMMT", 0, 0003, "error Open FV file", "cannot Create a new FD file.");\r
+ free (FdBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ fseek(NewFvFile,0,SEEK_SET);\r
+ fseek(NewFvFile,0,SEEK_END);\r
+\r
+ NewFvLength = ftell(NewFvFile);\r
+ fseek(NewFvFile,0,SEEK_SET);\r
+ Buffer = malloc ((size_t)NewFvLength);\r
+ if (Buffer == NULL) {\r
+ fclose(NewFvFile);\r
+ free (FdBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (fread (Buffer, 1, (size_t) NewFvLength, NewFvFile) != (size_t) NewFvLength) {\r
+ Error ("FMMT", 0, 0003, "error reading FV file %s", OutputFileName->FFSName);\r
+ free(Buffer);\r
+ free (FdBuffer);\r
+ fclose(NewFvFile);\r
+ return EFI_ABORTED;\r
+ }\r
+ if (NewFvLength <= FvInFd->FvHeader->FvLength) {\r
+ memcpy(FdBuffer+FvInFd->ImageAddress,Buffer,(size_t) NewFvLength);\r
+ }else {\r
+ Error ("FMMT", 0, 0004, "error writing FD file", "The replace ffs file is too large.");\r
+ }\r
+ free(Buffer);\r
+ fclose(NewFvFile);\r
+ }\r
+ }\r
+\r
+ Status = LibRmDir(TemDir);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0004, "error while encapsulate FD Image", "remove directory failed!");\r
+ }\r
+\r
+ NewFdFile = fopen(FdOutName, "wb");\r
+ if (NewFdFile == NULL) {\r
+ Error("FMMT", 0, 0004, "error while replacing file", "Cannot open target FD file!");\r
+ Status = EFI_ABORTED;\r
+ goto END;\r
+ }\r
+ fwrite(FdBuffer, 1, FdSize, NewFdFile);\r
+ fclose(NewFdFile);\r
+ free(FdBuffer);\r
+ printf("Create New FD file successfully. \n\nDone! \n");\r
+ return EFI_SUCCESS;\r
+\r
+ END:\r
+ if (FdBuffer != NULL) {\r
+ free(FdBuffer);\r
+ }\r
+ if (InputFfs != NULL) {\r
+ free(InputFfs);\r
+ }\r
+ return EFI_ABORTED;\r
+}\r
+\r
+/**\r
+\r
+The main entry of FMMT.\r
+\r
+@param argc The number of input parameters.\r
+@param *argv[] The array pointer to the parameters.\r
+\r
+@retval 0 The application exited normally.\r
+@retval 1 An error occurred.\r
+\r
+**/\r
+int main(\r
+ int Argc,\r
+ char *Argv[]\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR8 *TemDir;\r
+ FILE *CheckFileExist;\r
+ CHAR8 *InFilePath;\r
+ CHAR8 FullGuidToolDefinition[_MAX_PATH];\r
+ CHAR8 *FileName;\r
+ UINTN FileNameIndex;\r
+ CHAR8 *PathList;\r
+ UINTN EnvLen;\r
+ CHAR8 *NewPathList;\r
+ Data *FileData;\r
+ int index;\r
+ int count;\r
+ int exist;\r
+ int j;\r
+ FILENode *p;\r
+ FILENode *q;\r
+\r
+ p = NULL;\r
+ q = NULL;\r
+ TemDir = NULL;\r
+ CheckFileExist = NULL;\r
+ PathList = NULL;\r
+ NewPathList = NULL;\r
+ EnvLen = 0;\r
+ count = 0;\r
+ exist = -1;\r
+\r
+ TemDir = getcwd (NULL, _MAX_PATH);\r
+ if (strlen (TemDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return 1;\r
+ }\r
+ strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen(TemDir) - 1);\r
+ strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TemDir) - 1);\r
+\r
+ //\r
+ // Print utility header\r
+ //\r
+ printf ("Intel(R) %s. Version %d.%d, %s. %s.\n",\r
+ UTILITY_NAME,\r
+ UTILITY_MAJOR_VERSION,\r
+ UTILITY_MINOR_VERSION,\r
+ __DATE__,\r
+ __BUILD_VERSION\r
+ );\r
+\r
+ //\r
+ // Should have more than 1 arguments.\r
+ //\r
+ if (Argc <= 1) {\r
+ Usage();\r
+ return 1;\r
+ }\r
+\r
+ //\r
+ // Workaroud: the first call to this function\r
+ // returns a file name ends with dot\r
+ //\r
+#ifndef __GNUC__\r
+ tmpnam (NULL);\r
+#else\r
+ CHAR8 tmp[] = "/tmp/fileXXXXXX";\r
+ UINTN Fdtmp;\r
+ Fdtmp = mkstemp(tmp);\r
+ close(Fdtmp);\r
+#endif\r
+\r
+ //\r
+ // Save, skip filename arg\r
+ //\r
+ FileName = Argv[0];\r
+ Argc--;\r
+ Argv++;\r
+\r
+ //\r
+ // Get the same path with the application itself\r
+ //\r
+ if (strlen (FileName) > _MAX_PATH - 1) {\r
+ Error ("FMMT", 0, 2000, "Parameter: The input filename is too long", NULL);\r
+ return 1;\r
+ }\r
+ strncpy (FullGuidToolDefinition, FileName, _MAX_PATH - 1);\r
+ FullGuidToolDefinition[_MAX_PATH - 1] = 0;\r
+ FileNameIndex = strlen (FullGuidToolDefinition);\r
+ while (FileNameIndex != 0) {\r
+ FileNameIndex --;\r
+ if (FullGuidToolDefinition[FileNameIndex] == OS_SEP) {\r
+ FullGuidToolDefinition[FileNameIndex] = 0;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Build the path list for Config file scan. The priority is below.\r
+ // 1. Scan the current path\r
+ // 2. Scan the same path with the application itself\r
+ // 3. Scan the current %PATH% of OS environment\r
+ // 4. Use the build-in default configuration\r
+ //\r
+ PathList = getenv("PATH");\r
+ if (PathList == NULL) {\r
+ Error (NULL, 0, 1001, "Option: Environment variable 'PATH' does not exist", NULL);\r
+ return 1;\r
+ }\r
+ EnvLen = strlen(PathList);\r
+ NewPathList = (char *)calloc(\r
+ strlen (".")\r
+ + strlen (";")\r
+ + strlen (FullGuidToolDefinition)\r
+ + strlen (";")\r
+ + EnvLen\r
+ + 1,\r
+ sizeof(char)\r
+ );\r
+ if (NewPathList == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ PathList = NULL;\r
+ free (PathList);\r
+ return 1;\r
+ }\r
+#ifndef __GNUC__\r
+ sprintf (NewPathList, "%s;%s;%s", ".", FullGuidToolDefinition, PathList);\r
+#else\r
+ sprintf (NewPathList, "%s:%s:%s", ".", FullGuidToolDefinition, PathList);\r
+#endif\r
+ PathList = NULL;\r
+ free (PathList);\r
+\r
+ //\r
+ // Load Guid Tools definition\r
+ //\r
+ InFilePath = SearchConfigFromPathList(NewPathList, mGuidToolDefinition);\r
+ free (NewPathList);\r
+ if (InFilePath != NULL) {\r
+ printf ("\nThe Guid Tool Definition comes from the '%s'. \n", InFilePath);\r
+ mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (InFilePath);\r
+ free (InFilePath);\r
+ } else {\r
+ //\r
+ // Use the pre-defined standard guided tools.\r
+ //\r
+ printf ("\nThe Guid Tool Definition comes from the build-in default configuration. \n");\r
+ mParsedGuidedSectionTools = LibPreDefinedGuidedTools ();\r
+ }\r
+\r
+ if ((strcmp(Argv[0], "-v") == 0) || (strcmp(Argv[0], "-V") == 0)) {\r
+ //\r
+ // View the FD binary image information.\r
+ //\r
+ if (Argc <= 1) {\r
+ Error("FMMT", 0, 1001, "Invalid parameter, Please make sure the parameter is correct.", "");\r
+ Usage ();\r
+ return 1;\r
+ }\r
+\r
+ //\r
+ // Open the file containing the FV to check whether it exist or not\r
+ //\r
+ CheckFileExist = fopen (Argv[1], "rb");\r
+ if (CheckFileExist == NULL) {\r
+ Error ("FMMT", 0, 0001, "Error opening the input binary file, Please make sure the <input-binary-file> exist!", Argv[1]);\r
+ return 1;\r
+ }\r
+ fclose(CheckFileExist);\r
+\r
+ Status = FmmtImageView(Argv[1], NULL, TRUE, NULL);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error("FMMT", 0, 1001, "Error while view the FD image file.", "");\r
+ LibRmDir (TemDir);\r
+ return 1;\r
+ }\r
+\r
+ } else if ((strcmp(Argv[0], "-d") == 0) || (strcmp(Argv[0], "-D") == 0)) {\r
+ //\r
+ // Delete some named FFS file from FD binary image.\r
+ //\r
+ if (!((Argc == 4) || ((Argc - 3) % 2 == 0))) {\r
+ Error("FMMT", 0, 1001, "Invalid parameter, Please make sure the parameter is correct.", "");\r
+ Usage ();\r
+ return 1;\r
+ }\r
+\r
+ //\r
+ // Open the file containing the FV to check whether it exist or not\r
+ //\r
+ CheckFileExist = fopen (Argv[1], "rb");\r
+ if (CheckFileExist == NULL) {\r
+ Error ("FMMT", 0, 0001, "Error opening the input binary file, Please make sure the <input-binary-file> exist!", Argv[1]);\r
+ return 1;\r
+ }\r
+ fclose(CheckFileExist);\r
+\r
+ if ((Argc - 3) % 2 == 0) {\r
+ FileData = malloc(sizeof (Data) * (Argc - 3)/2);\r
+ if (FileData == NULL) {\r
+ Error ("FMMT", 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return 1;\r
+ }\r
+ for(index = 0; index < (Argc - 3)/2; index ++) {\r
+ p = malloc(sizeof (FILENode));\r
+ if (p == NULL) {\r
+ Error ("FMMT", 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ free (FileData);\r
+ return 1;\r
+ }\r
+ p -> FileName = Argv[3 + index * 2];\r
+ p -> SubLevel = 0;\r
+ exist = -1;\r
+ for (j = 0; j < count; j ++) {\r
+ if ((strcmp(Argv[2 + index * 2], (FileData + j) -> FvId) == 0)) {\r
+ exist = j;\r
+ break;\r
+ }\r
+ }\r
+ if (exist >= 0) {\r
+ p -> Next = (FileData + j) -> OldFile;\r
+ (FileData + j) -> OldFile = p;\r
+ } else {\r
+ (FileData + count) -> NewFile = NULL;\r
+ (FileData + count) -> FdData = NULL;\r
+ (FileData + count) -> FvLevel = 0;\r
+ (FileData + count) -> FvInFd = NULL;\r
+ (FileData + count) -> FvId = Argv[2 + index * 2];;\r
+ (FileData + count) -> OldFile = p;\r
+ p -> Next = NULL;\r
+ count ++;\r
+ }\r
+ }\r
+\r
+ if (count <= 0) {\r
+ Error("FMMT", 0, 0004, "error while parsing FD Image", "Gathering information failed!");\r
+ }\r
+ for (index = 0; index < count; index ++) {\r
+ for (j = index + 1; j < count; j ++) {\r
+ if ((strcmp((FileData + index)->FvId, (FileData + j)->FvId) < 0)) {\r
+ CHAR8 *tmp = (FileData + index)->FvId;\r
+ FILENode *t = (FileData + index)->OldFile;\r
+ (FileData + index)->FvId = (FileData + j)->FvId;\r
+ (FileData + index)-> OldFile = (FileData + j)->OldFile;\r
+ (FileData + j)-> OldFile = t;\r
+ (FileData + j)-> FvId = tmp;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Delete some FFS file\r
+ //\r
+ Status = FmmtImageDelete(Argv[1], FileData, count, Argv[Argc-1]);\r
+ for (index = 0; index < count; index ++) {\r
+ if ((FileData + index) ->NewFile != NULL) {\r
+ free ((FileData + index)->NewFile);\r
+ (FileData + index)->NewFile = NULL;\r
+ }\r
+ if ((FileData + index)->OldFile != NULL) {\r
+ free ((FileData + index)->OldFile);\r
+ (FileData + index)->OldFile = NULL;\r
+ }\r
+ }\r
+ for (index = 0; index < count; index ++) {\r
+ if ((FileData + index)->FdData != NULL) {\r
+ LibFmmtFreeFd ((FileData + index)->FdData);\r
+ }\r
+ }\r
+ free (FileData);\r
+ if (EFI_ERROR (Status)) {\r
+ Error("FMMT", 0, 1001, "Error while delete some named ffs file from the FD image file.", "");\r
+ LibRmDir (TemDir);\r
+ return 1;\r
+ }\r
+ } else {\r
+ //\r
+ // Delete FV\r
+ //\r
+ Status = FmmtImageDeleteFv(Argv[1], Argv[2], Argv[3]);\r
+ if (EFI_ERROR (Status)) {\r
+ Error("FMMT", 0, 1001, "Error while delete the entire FV from the FD image file.", "");\r
+ LibRmDir (TemDir);\r
+ return 1;\r
+ }\r
+ }\r
+\r
+ } else if ((strcmp(Argv[0], "-a") == 0) || (strcmp(Argv[0], "-A") == 0)) {\r
+ //\r
+ // Add some named FFS file into FD binary image.\r
+ //\r
+ if ((Argc - 3 ) % 2 != 0) {\r
+ Error("FMMT", 0, 1001, "Invalid parameter, Please make sure the parameter is correct.", "");\r
+ Usage ();\r
+ return 1;\r
+ }\r
+\r
+ //\r
+ // Open the file containing the FV to check whether it exist or not\r
+ //\r
+ CheckFileExist = fopen (Argv[1], "rb");\r
+ if (CheckFileExist == NULL) {\r
+ Error ("FMMT", 0, 0001, "Error opening the input binary file, Please make sure the <input-binary-file> exist!", Argv[1]);\r
+ return 1;\r
+ }\r
+ fclose(CheckFileExist);\r
+\r
+ //\r
+ // Check whether the new added file exist or not.\r
+ //\r
+ for (index = 1; index < (Argc - 1) / 2; index ++) {\r
+ CheckFileExist = fopen(Argv[2 * index + 1], "rb");\r
+ if (CheckFileExist == NULL) {\r
+ Error("FMMT", 0, 0001, "Could not open the new FFS file, Please make sure the new FFS file exist.", Argv[2 * index + 1]);\r
+ return 1;\r
+ }\r
+ fclose(CheckFileExist);\r
+ }\r
+\r
+ FileData = malloc(sizeof (Data) * (Argc - 3)/2);\r
+ if (FileData == NULL) {\r
+ Error ("FMMT", 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return 1;\r
+ }\r
+ for(index = 0; index < (Argc - 3)/2; index ++) {\r
+ p = malloc(sizeof (FILENode));\r
+ if (p == NULL) {\r
+ Error ("FMMT", 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ free (FileData);\r
+ return 1;\r
+ }\r
+ p -> FileName = Argv[3 + index * 2];\r
+ p -> SubLevel = 0;\r
+ exist = -1;\r
+ for (j = 0; j < count; j ++) {\r
+ if ((strcmp(Argv[2 + index * 2], (FileData + j) -> FvId) == 0)) {\r
+ exist = j;\r
+ break;\r
+ }\r
+ }\r
+ if (exist >= 0) {\r
+ p -> Next = (FileData + j) -> NewFile;\r
+ (FileData + j) -> NewFile = p;\r
+ } else {\r
+ (FileData + count) -> OldFile = NULL;\r
+ (FileData + count) -> FdData = NULL;\r
+ (FileData + count) -> FvLevel = 0;\r
+ (FileData + count) -> FvInFd = NULL;\r
+ (FileData + count) -> FvId = Argv[2 + index * 2];\r
+ (FileData + count) -> NewFile = p;\r
+ p -> Next = NULL;\r
+ count ++;\r
+ }\r
+ }\r
+\r
+ if (count <= 0) {\r
+ Error("FMMT", 0, 0004, "error while parsing FD Image", "Gathering information failed!");\r
+ }\r
+\r
+ for (index = 0; index < count; index ++) {\r
+ for (j = index + 1; j < count; j ++) {\r
+ if ((strcmp((FileData + index)->FvId, (FileData + j)->FvId) < 0)) {\r
+ CHAR8 *tmp = (FileData + index)->FvId;\r
+ FILENode *temp = (FileData + index)->NewFile;\r
+ (FileData + index)->FvId = (FileData + j)->FvId;\r
+ (FileData + index)-> NewFile = (FileData + j)->NewFile;\r
+ (FileData + j)-> NewFile = temp;\r
+ (FileData + j)-> FvId = tmp;\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = FmmtImageAdd(Argv[1], FileData, count, Argv[Argc-1]);\r
+ for (index = 0; index < count; index ++) {\r
+ if ((FileData + index)->NewFile != NULL) {\r
+ free ((FileData + index)->NewFile);\r
+ (FileData + index)->NewFile = NULL;\r
+ }\r
+ if ((FileData + index)->OldFile != NULL) {\r
+ free ((FileData + index)->OldFile);\r
+ (FileData + index)->OldFile = NULL;\r
+ }\r
+ }\r
+ for (index = 0; index < count; index ++) {\r
+ if ((FileData + index)->FdData != NULL) {\r
+ LibFmmtFreeFd ((FileData + index)->FdData);\r
+ }\r
+ }\r
+ free (FileData);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error("FMMT", 0, 1001, "Error while add some named ffs file into the FD image file.", "");\r
+ LibRmDir (TemDir);\r
+ return 1;\r
+ }\r
+\r
+ } else if ((strcmp(Argv[0], "-r") == 0) || (strcmp(Argv[0], "-R") == 0)) {\r
+ //\r
+ // Replace some named FFS file in the FD binary.\r
+ //\r
+ if ((Argc - 3) % 3 != 0) {\r
+ Error("FMMT", 0, 1001, "Invalid parameter, Please make sure the parameter is correct.", "");\r
+ Usage();\r
+ return 1;\r
+ }\r
+\r
+ //\r
+ // Open the file containing the FV to check whether it exist or not\r
+ //\r
+ CheckFileExist = fopen (Argv[1], "rb");\r
+ if (CheckFileExist == NULL) {\r
+ Error ("FMMT", 0, 0001, "Error opening the input binary file, Please make sure the <input-binary-file> exist!", Argv[1]);\r
+ return 1;\r
+ }\r
+ fclose(CheckFileExist);\r
+\r
+ //\r
+ // Check whether the new FFS file exist or not.\r
+ //\r
+ for (index = 1; index < Argc/3; index ++) {\r
+ CheckFileExist = fopen(Argv[3 * index + 1], "rb");\r
+ if (CheckFileExist == NULL) {\r
+ Error ("FMMT", 0, 0001, "Could not open the new FFS file, Please make sure the new FFS file exist.", Argv[3 * index + 1]);\r
+ return 1;\r
+ }\r
+ fclose(CheckFileExist);\r
+ }\r
+\r
+ FileData = malloc(sizeof (Data) * (Argc - 3)/3);\r
+ if (FileData == NULL) {\r
+ Error ("FMMT", 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return 1;\r
+ }\r
+ for(index = 0; index < (Argc - 3)/3; index ++) {\r
+ p = malloc(sizeof (FILENode)); //p for old file\r
+ if (p == NULL) {\r
+ Error ("FMMT", 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ free (FileData);\r
+ return 1;\r
+ }\r
+ q = malloc(sizeof (FILENode)); //q for new file\r
+ if (q == NULL) {\r
+ Error ("FMMT", 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ free (FileData);\r
+ free (p);\r
+ return 1;\r
+ }\r
+ p -> FileName = Argv[3 + index * 3];\r
+ q -> FileName = Argv[4 + index * 3];\r
+ p -> SubLevel = 0;\r
+ q -> SubLevel = 0;\r
+ exist = -1;\r
+ for (j = 0; j < count; j ++) {\r
+ if ((strcmp(Argv[2 + index * 3], (FileData + j) -> FvId) == 0)) {\r
+ exist = j;\r
+ break;\r
+ }\r
+ }\r
+ if (exist >= 0) {\r
+ p -> Next = (FileData + j) -> OldFile;\r
+ (FileData + j) -> OldFile = p;\r
+ q -> Next = (FileData + j) -> NewFile;\r
+ (FileData + j) -> NewFile = q;\r
+ } else {\r
+ (FileData + count) -> FdData = NULL;\r
+ (FileData + count) -> FvLevel = 0;\r
+ (FileData + count) -> FvInFd = NULL;\r
+ (FileData + count) -> FvId = Argv[2 + index * 3];;\r
+ (FileData + count) -> OldFile = p;\r
+ (FileData + count) -> NewFile = q;\r
+ p -> Next = NULL;\r
+ q -> Next = NULL;\r
+ count ++;\r
+ }\r
+ }\r
+\r
+ if (count <= 0) {\r
+ Error("FMMT", 0, 0004, "error while parsing FD Image", "Gathering information failed!");\r
+ }\r
+ for (index = 0; index < count; index ++) {\r
+ for (j = index + 1; j < count; j ++) {\r
+ if ((strcmp((FileData + index)->FvId, (FileData + j)->FvId) < 0)) {\r
+ CHAR8 *tmp = (FileData + index)->FvId;\r
+ FILENode *Old = (FileData + index)->OldFile;\r
+ FILENode *New = (FileData + index)->NewFile;\r
+ (FileData + index)->FvId = (FileData + j)->FvId;\r
+ (FileData + index)->OldFile = (FileData + j)->OldFile;\r
+ (FileData + index)->NewFile = (FileData + j)->NewFile;\r
+ (FileData + j)->OldFile = Old;\r
+ (FileData + j)->NewFile = New;\r
+ (FileData + j)->FvId = tmp;\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = FmmtImageReplace(Argv[1], FileData, count, Argv[Argc-1]);\r
+ for (index = 0; index < count; index ++) {\r
+ if ((FileData + index)->NewFile != NULL) {\r
+ free ((FileData + index)->NewFile);\r
+ (FileData + index)->NewFile = NULL;\r
+ }\r
+ if ((FileData + index)->OldFile != NULL) {\r
+ free ((FileData + index)->OldFile);\r
+ (FileData + index)->OldFile = NULL;\r
+ }\r
+ }\r
+ for (index = 0; index < count; index ++) {\r
+ if ((FileData + index)->FdData != NULL) {\r
+ LibFmmtFreeFd ((FileData + index)->FdData);\r
+ }\r
+ }\r
+ free (FileData);\r
+ if (EFI_ERROR (Status)) {\r
+ Error("FMMT", 0, 1001, "Error while replace the named ffs file in the FD image file with the new ffs file.", "");\r
+ LibRmDir (TemDir);\r
+ return 1;\r
+ }\r
+\r
+ } else if ((strcmp(Argv[0], "-h") == 0) || (strcmp(Argv[0], "--help") == 0) ||\r
+ (strcmp(Argv[0], "-?") == 0) || (strcmp(Argv[0], "/?") == 0)) {\r
+ //\r
+ // print help information to user.\r
+ //\r
+ Usage();\r
+\r
+ } else {\r
+ //\r
+ // Invalid parameter.\r
+ //\r
+ printf("\n");\r
+ Error("FMMT", 0, 1001, "Invalid parameter", Argv[0]);\r
+ Usage();\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+\r
+ Library to parse and generate FV image.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "FirmwareModuleManagement.h"\r
+\r
+#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \\r
+ ( \\r
+ (BOOLEAN) ( \\r
+ (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \\r
+ ) \\r
+ )\r
+\r
+CHAR8 mFirmwareFileSystem2Guid[16] = {0x78, 0xE5, 0x8C, 0x8C, 0x3D, 0x8A, 0x1C, 0x4F, 0x99, 0x35, 0x89, 0x61, 0x85, 0xC3, 0x2D, 0xD3};\r
+\r
+CHAR8 mFirmwareFileSystem3Guid[16] = {0x7A, 0xC0, 0x73, 0x54, 0xCB, 0x3D, 0xCA, 0x4D, 0xBD, 0x6F, 0x1E, 0x96, 0x89, 0xE7, 0x34, 0x9A };\r
+\r
+EFI_GUID mEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
+extern CHAR8* mGuidToolDefinition;\r
+\r
+static CHAR8 *mSectionTypeName[] = {\r
+ NULL, // 0x00 - reserved\r
+ "EFI_SECTION_COMPRESSION", // 0x01\r
+ "EFI_SECTION_GUID_DEFINED", // 0x02\r
+ NULL, // 0x03 - reserved\r
+ NULL, // 0x04 - reserved\r
+ NULL, // 0x05 - reserved\r
+ NULL, // 0x06 - reserved\r
+ NULL, // 0x07 - reserved\r
+ NULL, // 0x08 - reserved\r
+ NULL, // 0x09 - reserved\r
+ NULL, // 0x0A - reserved\r
+ NULL, // 0x0B - reserved\r
+ NULL, // 0x0C - reserved\r
+ NULL, // 0x0D - reserved\r
+ NULL, // 0x0E - reserved\r
+ NULL, // 0x0F - reserved\r
+ "EFI_SECTION_PE32", // 0x10\r
+ "EFI_SECTION_PIC", // 0x11\r
+ "EFI_SECTION_TE", // 0x12\r
+ "EFI_SECTION_DXE_DEPEX", // 0x13\r
+ "EFI_SECTION_VERSION", // 0x14\r
+ "EFI_SECTION_USER_INTERFACE", // 0x15\r
+ "EFI_SECTION_COMPATIBILITY16", // 0x16\r
+ "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17\r
+ "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18\r
+ "EFI_SECTION_RAW", // 0x19\r
+ NULL, // 0x1A\r
+ "EFI_SECTION_PEI_DEPEX", // 0x1B\r
+ "EFI_SECTION_SMM_DEPEX" // 0x1C\r
+};\r
+\r
+\r
+static CHAR8 *mFfsFileType[] = {\r
+ NULL, // 0x00\r
+ "EFI_FV_FILETYPE_RAW", // 0x01\r
+ "EFI_FV_FILETYPE_FREEFORM", // 0x02\r
+ "EFI_FV_FILETYPE_SECURITY_CORE", // 0x03\r
+ "EFI_FV_FILETYPE_PEI_CORE", // 0x04\r
+ "EFI_FV_FILETYPE_DXE_CORE", // 0x05\r
+ "EFI_FV_FILETYPE_PEIM", // 0x06\r
+ "EFI_FV_FILETYPE_DRIVER", // 0x07\r
+ "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER", // 0x08\r
+ "EFI_FV_FILETYPE_APPLICATION", // 0x09\r
+ "EFI_FV_FILETYPE_SMM", // 0x0A\r
+ "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B\r
+ "EFI_FV_FILETYPE_COMBINED_SMM_DXE", // 0x0C\r
+ "EFI_FV_FILETYPE_SMM_CORE" // 0x0D\r
+ };\r
+\r
+static CHAR8 *mGuidSectionAttr[] = {\r
+ "NONE", // 0x00\r
+ "PROCESSING_REQUIRED", // 0x01\r
+ "AUTH_STATUS_VALID" // 0x02\r
+};\r
+\r
+static EFI_GUID mFvUiGuid = {\r
+ 0xA67DF1FA, 0x8DE8, 0x4E98, {\r
+ 0xAF, 0x09, 0x4B, 0xDF, 0x2E, 0xFF, 0xBC, 0x7C\r
+ }\r
+};\r
+\r
+\r
+/**\r
+ Generate the unique template filename.\r
+**/\r
+CHAR8 *\r
+GenTempFile (\r
+ VOID\r
+ )\r
+{\r
+ CHAR8 *TemString;\r
+ TemString = NULL;\r
+#ifndef __GNUC__\r
+ TemString = CloneString (tmpnam (NULL));\r
+#else\r
+ CHAR8 tmp[] = "/tmp/fileXXXXXX";\r
+ UINTN Fdtmp;\r
+ Fdtmp = mkstemp(tmp);\r
+ TemString = CloneString(tmp);\r
+ close(Fdtmp);\r
+#endif\r
+ return TemString;\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+LibExtractFvUiName(CONST EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader, CHAR8 **FvUiName)\r
+{\r
+ UINT8 *ExtEnd;\r
+ UINT32 ExtDataSize;\r
+ EFI_FIRMWARE_VOLUME_EXT_ENTRY *ExtEntry;\r
+ EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE *GuidEntry;\r
+\r
+\r
+ ExtEnd = (UINT8 *)FvExtHeader + FvExtHeader->ExtHeaderSize;\r
+ ExtEntry = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)(FvExtHeader + 1);\r
+ while ((UINT8 *)ExtEntry < ExtEnd) {\r
+ //\r
+ // GUID type EXT\r
+ //\r
+ if (ExtEntry->ExtEntryType == 0x0002) {\r
+ GuidEntry = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE *)ExtEntry;\r
+ if (memcmp(&GuidEntry->FormatType, &mFvUiGuid, sizeof(EFI_GUID)) == 0) {\r
+ ExtDataSize = ExtEntry->ExtEntrySize - (sizeof(EFI_GUID)+sizeof(*ExtEntry));\r
+ *FvUiName = malloc(ExtDataSize + 1);\r
+ if (*FvUiName != NULL) {\r
+ memcpy(*FvUiName, (UINT8 *)GuidEntry + sizeof(EFI_GUID)+sizeof(*ExtEntry), ExtDataSize);\r
+ (*FvUiName)[ExtDataSize] = '\0';\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ ExtEntry = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtEntry + ExtEntry->ExtEntrySize);\r
+ }\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+FV_INFORMATION *\r
+LibInitializeFvStruct (\r
+ FV_INFORMATION *Fv\r
+)\r
+{\r
+ UINT32 Index;\r
+\r
+ if (Fv == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index ++) {\r
+ memset (Fv->FfsAttuibutes[Index].FfsName, '\0', _MAX_PATH);\r
+ memset (Fv->FfsAttuibutes[Index].UiName, '\0', _MAX_PATH);\r
+ memset (&Fv->FfsAttuibutes[Index].GuidName, '\0', sizeof(EFI_GUID));\r
+ Fv->FfsAttuibutes[Index].UiNameSize = 0;\r
+ Fv->FfsAttuibutes[Index].IsLeaf = TRUE;\r
+ Fv->FfsAttuibutes[Index].Level = 0xFF;\r
+ Fv->FfsAttuibutes[Index].TotalSectionNum = 0;\r
+ Fv->FfsAttuibutes[Index].Depex = NULL;\r
+ Fv->FfsAttuibutes[Index].DepexLen = 0;\r
+ Fv->FfsAttuibutes[Index].IsHandle = FALSE;\r
+ Fv->FfsAttuibutes[Index].IsFvStart = FALSE;\r
+ Fv->FfsAttuibutes[Index].IsFvEnd = FALSE;\r
+ }\r
+\r
+ Fv->EncapData = NULL;\r
+ Fv->FvNext = NULL;\r
+ Fv->ChildFvFFS = NULL;\r
+ Fv->FvLevel = 0;\r
+ Fv->MulFvLevel = 1;\r
+ strcpy(Fv->AlignmentStr,"8");\r
+ return Fv;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+LibFindFvInFd (\r
+ IN FILE *InputFile,\r
+ IN OUT FIRMWARE_DEVICE **FdData\r
+)\r
+{\r
+ FIRMWARE_DEVICE *LocalFdData;\r
+ UINT16 Index;\r
+ CHAR8 Ffs2Guid[16];\r
+ CHAR8 SignatureCheck[5] = "";\r
+ CHAR8 Signature[5] = "_FVH";\r
+ FV_INFORMATION *CurrentFv;\r
+ FV_INFORMATION *NewFoundFv;\r
+ BOOLEAN FirstMatch;\r
+ UINT32 FdSize;\r
+ UINT16 FvCount;\r
+ UINT8 *FdBuffer;\r
+ UINT8 *FdBufferEnd;\r
+ UINT8 *FdBufferOri;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
+\r
+ CurrentFv = NULL;\r
+ NewFoundFv = NULL;\r
+ FdBuffer = NULL;\r
+ FdBufferOri = NULL;\r
+ FirstMatch = TRUE;\r
+ Index = 0;\r
+ FdSize = 0;\r
+ FvCount = 0;\r
+ LocalFdData = NULL;\r
+\r
+ if (InputFile == NULL) {\r
+ Error ("FMMT", 0, 0001, "Error opening the input file", "");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Find each FVs in the FD\r
+ //\r
+\r
+ fseek(InputFile,0,SEEK_SET);\r
+ fseek(InputFile,0,SEEK_END);\r
+\r
+ FdSize = ftell(InputFile);\r
+\r
+ fseek(InputFile,0,SEEK_SET);\r
+ //\r
+ // Create an FD structure to store useful information.\r
+ //\r
+ LocalFdData = (FIRMWARE_DEVICE *) malloc (sizeof (FIRMWARE_DEVICE));\r
+ if (LocalFdData == NULL) {\r
+ Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Allocate memory error");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ LocalFdData->Fv = (FV_INFORMATION *) malloc (sizeof (FV_INFORMATION));\r
+ if (LocalFdData->Fv == NULL) {\r
+ Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Allocate memory error");\r
+ free (LocalFdData);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ LibInitializeFvStruct (LocalFdData->Fv);\r
+\r
+ //\r
+ // Readout the FD file data to buffer.\r
+ //\r
+ FdBuffer = malloc (FdSize);\r
+\r
+ if (FdBuffer == NULL) {\r
+ Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Allocate memory error");\r
+ free (LocalFdData->Fv);\r
+ free (LocalFdData);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (fread (FdBuffer, 1, FdSize, InputFile) != FdSize) {\r
+ Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Read FD file error!");\r
+ free (LocalFdData->Fv);\r
+ free (LocalFdData);\r
+ free (FdBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ FdBufferOri = FdBuffer;\r
+ FdBufferEnd = FdBuffer + FdSize;\r
+\r
+ while (FdBuffer <= FdBufferEnd - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FdBuffer;\r
+ //\r
+ // Copy 4 bytes of fd data to check the _FVH signature\r
+ //\r
+ memcpy (SignatureCheck, &FvHeader->Signature, 4);\r
+\r
+ if (strncmp(SignatureCheck, Signature, 4) == 0){\r
+ //\r
+ // Still need to determine the FileSystemGuid in EFI_FIRMWARE_VOLUME_HEADER equal to\r
+ // EFI_FIRMWARE_FILE_SYSTEM2_GUID or EFI_FIRMWARE_FILE_SYSTEM3_GUID.\r
+ // Turn back 28 bytes to find the GUID.\r
+ //\r
+ memcpy (Ffs2Guid, &FvHeader->FileSystemGuid, 16);\r
+\r
+ //\r
+ // Compare GUID.\r
+ //\r
+ for (Index = 0; Index < 16; Index ++) {\r
+ if (Ffs2Guid[Index] != mFirmwareFileSystem2Guid[Index]) {\r
+ break;\r
+ }\r
+ }\r
+ if (Index != 16) {\r
+ for (Index = 0; Index < 16; Index ++) {\r
+ if (Ffs2Guid[Index] != mFirmwareFileSystem3Guid[Index]) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Here we found an FV.\r
+ //\r
+ if ((Index == 16) && ((FdBuffer + FvHeader->FvLength) <= FdBufferEnd)) {\r
+ if (FirstMatch) {\r
+ LocalFdData->Fv->ImageAddress = (UINTN)((UINT8 *)FdBuffer - (UINT8 *)FdBufferOri);\r
+ CurrentFv = LocalFdData->Fv;\r
+ CurrentFv->FvNext = NULL;\r
+ //\r
+ // Store the FV name by found sequence\r
+ //\r
+ sprintf(CurrentFv->FvName, "FV%d", FvCount);\r
+\r
+ FirstMatch = FALSE;\r
+ } else {\r
+ NewFoundFv = (FV_INFORMATION *) malloc (sizeof (FV_INFORMATION));\r
+ if (NewFoundFv == NULL) {\r
+ Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Allocate memory error");\r
+ free (LocalFdData->Fv);\r
+ free (LocalFdData);\r
+ free (FdBuffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ LibInitializeFvStruct (NewFoundFv);\r
+\r
+ //\r
+ // Need to turn back 0x2c bytes\r
+ //\r
+ NewFoundFv->ImageAddress = (UINTN)((UINT8 *)FdBuffer - (UINT8 *)FdBufferOri);\r
+\r
+ //\r
+ // Store the FV name by found sequence\r
+ //\r
+ sprintf(NewFoundFv->FvName, "FV%d", FvCount);\r
+\r
+ //\r
+ // Value it to NULL for found FV usage.\r
+ //\r
+ NewFoundFv->FvNext = NULL;\r
+ CurrentFv->FvNext = NewFoundFv;\r
+\r
+ //\r
+ // Make the CurrentFv point to next FV.\r
+ //\r
+ CurrentFv = CurrentFv->FvNext;\r
+ }\r
+\r
+ FvCount ++;\r
+ FdBuffer = FdBuffer + FvHeader->FvLength;\r
+ } else {\r
+ FdBuffer ++;\r
+ }\r
+\r
+ } else {\r
+ FdBuffer ++;\r
+ }\r
+ }\r
+\r
+ LocalFdData->Size = FdSize;\r
+\r
+ *FdData = LocalFdData;\r
+\r
+ free (FdBufferOri);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+UINTN\r
+GetFreeOffset (\r
+ IN VOID *InputFv\r
+)\r
+{\r
+ UINTN FreeOffset;\r
+ UINTN Offset;\r
+ EFI_STATUS Status;\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile;\r
+\r
+ Offset = 0;\r
+ CurrentFile = NULL;\r
+ FreeOffset = 0;\r
+ do {\r
+ FreeOffset = (UINTN)ALIGN_POINTER(Offset, 8);\r
+ Status = FvBufFindNextFile(InputFv, &Offset, (VOID **)&CurrentFile);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ CurrentFile = NULL;\r
+ break;\r
+ }\r
+ else if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ } while (CurrentFile != NULL);\r
+\r
+ return FreeOffset;\r
+}\r
+\r
+/*\r
+ Construct a set of blank chars based on the number.\r
+\r
+ @param[in] Count The number of blank chars.\r
+\r
+ @return A string contained the blank chars.\r
+\r
+*/\r
+CHAR8 *\r
+LibConstructBlankChar (\r
+ IN UINT8 Count\r
+)\r
+{\r
+ CHAR8 *RetStr;\r
+ UINT8 Index;\r
+\r
+ Index = 0;\r
+ RetStr = NULL;\r
+\r
+ RetStr = (CHAR8 *) malloc (Count +1);\r
+\r
+ if (RetStr == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return NULL;\r
+ }\r
+\r
+ memset (RetStr , '\0', Count + 1);\r
+\r
+ for (Index=0; Index <= Count -1; Index ++) {\r
+ RetStr[Index] = ' ';\r
+ }\r
+\r
+ return RetStr;\r
+\r
+}\r
+\r
+/**\r
+\r
+ This function determines the size of the FV and the erase polarity. The\r
+ erase polarity is the FALSE value for file state.\r
+\r
+\r
+ @param[in ] InputFile The file that contains the FV image.\r
+ @param[out] FvSize The size of the FV.\r
+ @param[out] ErasePolarity The FV erase polarity.\r
+\r
+ @return EFI_SUCCESS Function completed successfully.\r
+ @return EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.\r
+ @return EFI_ABORTED The function encountered an error.\r
+\r
+**/\r
+EFI_STATUS\r
+LibReadFvHeader (\r
+ IN VOID *InputFv,\r
+ IN BOOLEAN ViewFlag,\r
+ IN UINT8 FvLevel,\r
+ IN UINT8 FvCount,\r
+ IN CHAR8 *FvName\r
+ )\r
+{\r
+ EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader;\r
+ CHAR8 *BlankSpace;\r
+ CHAR8 *FvUiName;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;\r
+\r
+ BlankSpace = NULL;\r
+ FvUiName = NULL;\r
+\r
+ //\r
+ // Check input parameters\r
+ //\r
+ if (InputFv == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "FMMT application error", "invalid parameter to function");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Read the header\r
+ //\r
+ VolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *) InputFv;\r
+\r
+\r
+ BlankSpace = LibConstructBlankChar((FvLevel)*2);\r
+\r
+ if (BlankSpace == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+\r
+ if (ViewFlag) {\r
+ if ((FvLevel -1) == 0) {\r
+ printf ("\n%s :\n", FvName);\r
+ } else {\r
+ printf ("%sChild FV named FV%d of %s\n", BlankSpace, FvCount, FvName);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Print FV header information\r
+ //\r
+ if (ViewFlag) {\r
+ printf ("\n%sAttributes: %X\n", BlankSpace, (unsigned) VolumeHeader->Attributes);\r
+ printf ("%sTotal Volume Size: 0x%08X\n", BlankSpace, (unsigned) VolumeHeader->FvLength);\r
+ printf ("%sFree Volume Size: 0x%08X\n", BlankSpace, (unsigned) (VolumeHeader->FvLength - GetFreeOffset(InputFv)));\r
+ }\r
+\r
+ if (ViewFlag && VolumeHeader->ExtHeaderOffset != 0) {\r
+ FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)VolumeHeader + VolumeHeader->ExtHeaderOffset);\r
+ printf("%sFvNameGuid: %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",\r
+ BlankSpace,\r
+ FvExtHeader->FvName.Data1,\r
+ FvExtHeader->FvName.Data2,\r
+ FvExtHeader->FvName.Data3,\r
+ FvExtHeader->FvName.Data4[0],\r
+ FvExtHeader->FvName.Data4[1],\r
+ FvExtHeader->FvName.Data4[2],\r
+ FvExtHeader->FvName.Data4[3],\r
+ FvExtHeader->FvName.Data4[4],\r
+ FvExtHeader->FvName.Data4[5],\r
+ FvExtHeader->FvName.Data4[6],\r
+ FvExtHeader->FvName.Data4[7]);\r
+ LibExtractFvUiName(FvExtHeader, &FvUiName);\r
+ if (FvUiName != NULL && FvLevel == 1) {\r
+ printf("%sFV UI Name: %s\n\n", BlankSpace, FvUiName);\r
+ }\r
+ free(FvUiName);\r
+ }\r
+ free (BlankSpace);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/*\r
+ Get size info from FV file.\r
+\r
+ @param[in]\r
+ @param[out]\r
+\r
+ @retval\r
+\r
+*/\r
+EFI_STATUS\r
+LibGetFvSize (\r
+ IN FILE *InputFile,\r
+ OUT UINT32 *FvSize\r
+ )\r
+{\r
+\r
+ UINTN BytesRead;\r
+ UINT32 Size;\r
+ EFI_FV_BLOCK_MAP_ENTRY BlockMap;\r
+\r
+ BytesRead = 0;\r
+ Size = 0;\r
+\r
+ if (InputFile == NULL || FvSize == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "FMMT application error", "invalid parameter to function");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ fseek (InputFile, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), SEEK_CUR);\r
+ do {\r
+ fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+ BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
+\r
+ if (BlockMap.NumBlocks != 0) {\r
+ Size += BlockMap.NumBlocks * BlockMap.Length;\r
+ }\r
+ } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0));\r
+\r
+\r
+ *FvSize = Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Clears out all files from the Fv buffer in memory\r
+\r
+ @param[in] Fv - Address of the Fv in memory\r
+\r
+ @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+FvBufGetSize (\r
+ IN VOID *Fv,\r
+ OUT UINTN *Size\r
+ )\r
+{\r
+ EFI_FIRMWARE_VOLUME_HEADER *hdr;\r
+ EFI_FV_BLOCK_MAP_ENTRY *blk;\r
+\r
+ *Size = 0;\r
+ hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
+ blk = hdr->BlockMap;\r
+\r
+ while (blk->Length != 0 || blk->NumBlocks != 0) {\r
+ *Size = *Size + (blk->Length * blk->NumBlocks);\r
+ if (*Size >= 0x40000000) {\r
+ //\r
+ // If size is greater than 1GB, then assume it is corrupted\r
+ //\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
+ blk++;\r
+ }\r
+\r
+ if (*Size == 0) {\r
+ //\r
+ // If size is 0, then assume the volume is corrupted\r
+ //\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/*\r
+ Generate the leaf FFS files.\r
+\r
+*/\r
+EFI_STATUS\r
+LibGenFfsFile (\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile,\r
+ FV_INFORMATION *CurrentFv,\r
+ CHAR8 *FvName,\r
+ UINT8 Level,\r
+ UINT32 *FfsCount,\r
+ BOOLEAN ErasePolarity\r
+)\r
+{\r
+ UINT32 FfsFileSize;\r
+ CHAR8 *FfsFileName;\r
+ FILE *FfsFile;\r
+ CHAR8 *TempDir;\r
+\r
+\r
+ FfsFileSize = 0;\r
+ FfsFileName = NULL;\r
+ FfsFile = NULL;\r
+ TempDir = NULL;\r
+\r
+ TempDir = getcwd (NULL, _MAX_PATH);\r
+ if (strlen (TempDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (TempDir, OS_SEP_STR, _MAX_PATH - strlen(TempDir) - 1);\r
+ strncat (TempDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TempDir) - 1);\r
+\r
+ mkdir(TempDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
+\r
+ FfsFileName = (CHAR8 *) malloc (_MAX_PATH);\r
+ if (FfsFileName == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ memset (FfsFileName, '\0', _MAX_PATH);\r
+ FfsFileSize = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);\r
+ sprintf (\r
+ (CHAR8 *)FfsFileName,\r
+ "%s%cNum%d-%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X-Level%d",\r
+ TempDir,\r
+ OS_SEP,\r
+ *FfsCount,\r
+ (unsigned) CurrentFile->Name.Data1,\r
+ CurrentFile->Name.Data2,\r
+ CurrentFile->Name.Data3,\r
+ CurrentFile->Name.Data4[0],\r
+ CurrentFile->Name.Data4[1],\r
+ CurrentFile->Name.Data4[2],\r
+ CurrentFile->Name.Data4[3],\r
+ CurrentFile->Name.Data4[4],\r
+ CurrentFile->Name.Data4[5],\r
+ CurrentFile->Name.Data4[6],\r
+ CurrentFile->Name.Data4[7],\r
+ Level\r
+ );\r
+\r
+ memcpy (CurrentFv->FfsAttuibutes[*FfsCount].FfsName, FfsFileName, strlen(FfsFileName));\r
+ memcpy (&CurrentFv->FfsAttuibutes[*FfsCount].GuidName, &CurrentFile->Name, sizeof(EFI_GUID));\r
+ //\r
+ // Update current FFS files file state.\r
+ //\r
+ if (ErasePolarity) {\r
+ CurrentFile->State = (UINT8)~(CurrentFile->State);\r
+ }\r
+\r
+ FfsFile = fopen (FfsFileName, "wb+");\r
+ if (FfsFile == NULL) {\r
+ Error ("FMMT", 0, 0003, "error writing FFS file", "cannot Create a new ffs file.");\r
+ free(FfsFileName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (fwrite (CurrentFile, 1, FfsFileSize, FfsFile) != FfsFileSize) {\r
+ Error ("FMMT", 0, 0004, "error writing FFS file", "cannot Create a new ffs file.");\r
+ fclose(FfsFile);\r
+ free(FfsFileName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ fclose(FfsFile);\r
+ free(FfsFileName);\r
+ FfsFileName = NULL;\r
+\r
+ CurrentFv->FfsNumbers = *FfsCount;\r
+\r
+ *FfsCount += 1;\r
+\r
+ if (ErasePolarity) {\r
+ CurrentFile->State = (UINT8)~(CurrentFile->State);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+Unicode2AsciiString (\r
+ IN CHAR16 *Source,\r
+ OUT CHAR8 *Destination\r
+ )\r
+ /*++\r
+\r
+ Routine Description:\r
+\r
+ Convert a null-terminated unicode string to a null-terminated ascii string.\r
+\r
+ Arguments:\r
+\r
+ Source - The pointer to the null-terminated input unicode string.\r
+ Destination - The pointer to the null-terminated output ascii string.\r
+\r
+ Returns:\r
+\r
+ N/A\r
+\r
+ --*/\r
+{\r
+ while (*Source != '\0') {\r
+ *(Destination++) = (CHAR8) *(Source++);\r
+ }\r
+ //\r
+ // End the ascii with a NULL.\r
+ //\r
+ *Destination = '\0';\r
+}\r
+\r
+\r
+/**\r
+\r
+ Parses EFI Sections, if the view flag turn on, then will collect FFS section information\r
+ and extract FFS files.\r
+\r
+ @param[in] SectionBuffer - Buffer containing the section to parse.\r
+ @param[in] BufferLength - Length of SectionBuffer\r
+ @param[in, out] CurrentFv\r
+ @param[in] FvName\r
+ @param[in] CurrentFile\r
+ @param[in] Level\r
+ @param[in, out] FfsCount\r
+ @param[in] ViewFlag\r
+ @param[in] ErasePolarity\r
+\r
+ @retval EFI_SECTION_ERROR - Problem with section parsing.\r
+ (a) compression errors\r
+ (b) unrecognized section\r
+ @retval EFI_UNSUPPORTED - Do not know how to parse the section.\r
+ @retval EFI_SUCCESS - Section successfully parsed.\r
+ @retval EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
+\r
+--*/\r
+EFI_STATUS\r
+LibParseSection (\r
+ UINT8 *SectionBuffer,\r
+ UINT32 BufferLength,\r
+ FV_INFORMATION *CurrentFv,\r
+ CHAR8 *FvName,\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile,\r
+ UINT8 Level,\r
+ ENCAP_INFO_DATA **CurrentFvEncapData,\r
+ UINT8 FfsLevel,\r
+ UINT32 *FfsCount,\r
+ UINT8 *FvCount,\r
+ BOOLEAN ViewFlag,\r
+ BOOLEAN ErasePolarity,\r
+ BOOLEAN *IsFfsGenerated\r
+ )\r
+{\r
+ UINT32 ParsedLength;\r
+ UINT8 *Ptr;\r
+ UINT32 SectionLength;\r
+ UINT32 UiSectionLength;\r
+ EFI_SECTION_TYPE Type;\r
+ EFI_STATUS Status;\r
+ CHAR8 *ExtractionTool;\r
+ CHAR8 *ToolInputFile;\r
+ CHAR8 *ToolOutputFile;\r
+ CHAR8 *SystemCommandFormatString;\r
+ CHAR8 *SystemCommand;\r
+ UINT8 *ToolOutputBuffer;\r
+ UINT32 ToolOutputLength;\r
+ CHAR16 *UIName;\r
+ UINT32 UINameSize;\r
+ BOOLEAN HasDepexSection;\r
+ UINT32 NumberOfSections;\r
+ ENCAP_INFO_DATA *LocalEncapData;\r
+ ENCAP_INFO_DATA *LocalEncapDataTemp;\r
+ CHAR8 *BlankChar;\r
+ UINT8 *UncompressedBuffer;\r
+ UINT32 UncompressedLength;\r
+ UINT8 *CompressedBuffer;\r
+ UINT32 CompressedLength;\r
+ UINT8 CompressionType;\r
+ DECOMPRESS_FUNCTION DecompressFunction;\r
+ GETINFO_FUNCTION GetInfoFunction;\r
+ UINT32 DstSize;\r
+ UINT32 ScratchSize;\r
+ UINT8 *ScratchBuffer;\r
+ BOOLEAN EncapDataNeedUpdata;\r
+ CHAR8 *TempDir;\r
+ CHAR8 *ToolInputFileFullName;\r
+ CHAR8 *ToolOutputFileFullName;\r
+ UINT8 LargeHeaderOffset;\r
+ UINT16 GuidAttr;\r
+ UINT16 DataOffset;\r
+ CHAR8 *UIFileName;\r
+ CHAR8 *ToolInputFileName;\r
+ CHAR8 *ToolOutputFileName;\r
+\r
+ DataOffset = 0;\r
+ GuidAttr = 0;\r
+ ParsedLength = 0;\r
+ ToolOutputLength = 0;\r
+ UINameSize = 0;\r
+ NumberOfSections = 0;\r
+ UncompressedLength = 0;\r
+ CompressedLength = 0;\r
+ CompressionType = 0;\r
+ DstSize = 0;\r
+ ScratchSize = 0;\r
+ Ptr = NULL;\r
+ ExtractionTool = NULL;\r
+ ToolInputFile = NULL;\r
+ ToolOutputFile = NULL;\r
+ SystemCommand = NULL;\r
+ SystemCommandFormatString = NULL;\r
+ ToolOutputBuffer = NULL;\r
+ UIName = NULL;\r
+ LocalEncapData = NULL;\r
+ LocalEncapDataTemp = NULL;\r
+ BlankChar = NULL;\r
+ UncompressedBuffer = NULL;\r
+ CompressedBuffer = NULL;\r
+ ScratchBuffer = NULL;\r
+ TempDir = NULL;\r
+ ToolInputFileFullName = NULL;\r
+ ToolOutputFileFullName = NULL;\r
+ ToolInputFileName = NULL;\r
+ ToolOutputFileFullName = NULL;\r
+ HasDepexSection = FALSE;\r
+ EncapDataNeedUpdata = TRUE;\r
+ LargeHeaderOffset = 0;\r
+\r
+\r
+ while (ParsedLength < BufferLength) {\r
+ Ptr = SectionBuffer + ParsedLength;\r
+\r
+ SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size);\r
+ Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type;\r
+\r
+ //\r
+ // This is sort of an odd check, but is necessary because FFS files are\r
+ // padded to a QWORD boundary, meaning there is potentially a whole section\r
+ // header worth of 0xFF bytes.\r
+ //\r
+ if (SectionLength == 0xffffff && Type == 0xff) {\r
+ ParsedLength += 4;\r
+ continue;\r
+ }\r
+ //\r
+ //If Size is 0xFFFFFF then ExtendedSize contains the size of the section.\r
+ //\r
+ if (SectionLength == 0xffffff) {\r
+ SectionLength = ((EFI_COMMON_SECTION_HEADER2 *) Ptr)->ExtendedSize;\r
+ LargeHeaderOffset = sizeof (EFI_COMMON_SECTION_HEADER2) - sizeof (EFI_COMMON_SECTION_HEADER);\r
+ }\r
+\r
+ switch (Type) {\r
+\r
+ case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:\r
+\r
+ EncapDataNeedUpdata = TRUE;\r
+\r
+ Level ++;\r
+ NumberOfSections ++;\r
+\r
+ CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf = FALSE;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].IsFvStart = TRUE;\r
+ //\r
+ // Put in encapsulate data information.\r
+ //\r
+ LocalEncapData = *CurrentFvEncapData;\r
+ if (LocalEncapData->NextNode != NULL) {\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ while (LocalEncapData->RightNode != NULL) {\r
+ LocalEncapData = LocalEncapData->RightNode;\r
+ }\r
+ }\r
+\r
+ if (EncapDataNeedUpdata) {\r
+ //\r
+ // Put in this is an FFS with FV section\r
+ //\r
+\r
+ //\r
+ // Construct the new ENCAP_DATA\r
+ //\r
+ LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+\r
+ if (LocalEncapData->NextNode == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+\r
+ LocalEncapData->Level = Level;\r
+ LocalEncapData->Type = FMMT_ENCAP_TREE_FV_SECTION;\r
+\r
+ //\r
+ // We don't need additional data for encapsulate this FFS but type.\r
+ //\r
+ LocalEncapData->Data = NULL;\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ LocalEncapData->NextNode = NULL;\r
+ LocalEncapData->RightNode = NULL;\r
+ LocalEncapData->Depex = NULL;\r
+ LocalEncapData->DepexLen = 0;\r
+ LocalEncapData->UiNameSize = 0;\r
+ LocalEncapData->FvId = *FvCount;\r
+ }\r
+\r
+ //\r
+ //save parent level FFS file's GUID name\r
+ //\r
+ LocalEncapDataTemp = CurrentFv->EncapData;\r
+ while (LocalEncapDataTemp->NextNode != NULL) {\r
+ if (LocalEncapDataTemp->Level == FfsLevel) {\r
+ while (LocalEncapDataTemp->RightNode != NULL) {\r
+ LocalEncapDataTemp = LocalEncapDataTemp->RightNode;\r
+ }\r
+ if (LocalEncapDataTemp != NULL && LocalEncapDataTemp->FvExtHeader == NULL) {\r
+ LocalEncapDataTemp->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)malloc(sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER));\r
+ if (LocalEncapDataTemp->FvExtHeader == NULL) {\r
+ Error(NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (*FfsCount >= 1) {\r
+ if ((memcmp(&CurrentFv->FfsAttuibutes[*FfsCount - 1].GuidName, &(LocalEncapDataTemp->FvExtHeader->FvName), sizeof(EFI_GUID)) == 0)) {\r
+ memcpy(LocalEncapDataTemp->UiName, CurrentFv->FfsAttuibutes[*FfsCount - 1].UiName, _MAX_PATH);\r
+ LocalEncapDataTemp->UiNameSize = CurrentFv->FfsAttuibutes[*FfsCount - 1].UiNameSize;\r
+ LocalEncapDataTemp->DepexLen = CurrentFv->FfsAttuibutes[*FfsCount - 1].DepexLen;\r
+ LocalEncapDataTemp->Depex = malloc (LocalEncapDataTemp->DepexLen);\r
+ if (LocalEncapDataTemp->Depex == NULL) {\r
+ Error(NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ memcpy(LocalEncapDataTemp->Depex, CurrentFv->FfsAttuibutes[*FfsCount - 1].Depex, LocalEncapDataTemp->DepexLen);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ LocalEncapDataTemp = LocalEncapDataTemp->NextNode;\r
+ }\r
+\r
+ Status = LibGetFvInfo ((UINT8*)((EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)Ptr + 1) + LargeHeaderOffset, CurrentFv, FvName, Level, &LocalEncapData, FfsCount, FvCount, ViewFlag, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0003, "printing of FV section contents failed", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+ if (*FfsCount >= 1) {\r
+ CurrentFv->FfsAttuibutes[*FfsCount -1].IsFvEnd = TRUE;\r
+ }\r
+ break;\r
+\r
+ case EFI_SECTION_COMPRESSION:\r
+ Level ++;\r
+ NumberOfSections ++;\r
+\r
+ EncapDataNeedUpdata = TRUE;\r
+ //\r
+ // Put in encapsulate data information.\r
+ //\r
+ LocalEncapData = *CurrentFvEncapData;\r
+ if (LocalEncapData->NextNode != NULL) {\r
+ EncapDataNeedUpdata = FALSE;\r
+ while (LocalEncapData->RightNode != NULL) {\r
+ LocalEncapData = LocalEncapData->RightNode;\r
+ }\r
+ }\r
+\r
+ if (EncapDataNeedUpdata) {\r
+ //\r
+ // Put in this is an FFS with FV section\r
+ //\r
+\r
+ //\r
+ // Construct the new ENCAP_DATA\r
+ //\r
+ LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+\r
+ if (LocalEncapData->NextNode == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+\r
+ LocalEncapData->Level = Level;\r
+ LocalEncapData->Type = FMMT_ENCAP_TREE_COMPRESS_SECTION;\r
+\r
+ //\r
+ // Store the compress type\r
+ //\r
+ LocalEncapData->Data = malloc (sizeof (UINT8));\r
+\r
+ if (LocalEncapData->Data == NULL) {\r
+ Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ *(UINT8 *)LocalEncapData->Data = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->CompressionType;\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ LocalEncapData->NextNode = NULL;\r
+ LocalEncapData->RightNode = NULL;\r
+ } else {\r
+ LocalEncapData->RightNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+ if (LocalEncapData->RightNode == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ LocalEncapData = LocalEncapData->RightNode;\r
+\r
+ LocalEncapData->Level = Level;\r
+ LocalEncapData->Type = FMMT_ENCAP_TREE_COMPRESS_SECTION;\r
+\r
+ //\r
+ // Store the compress type\r
+ //\r
+ LocalEncapData->Data = malloc (sizeof (UINT8));\r
+\r
+ if (LocalEncapData->Data == NULL) {\r
+ Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ *(UINT8 *)LocalEncapData->Data = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->CompressionType;\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ LocalEncapData->NextNode = NULL;\r
+ LocalEncapData->RightNode = NULL;\r
+\r
+ }\r
+\r
+ //\r
+ // Process compressed section\r
+ //\r
+ CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf = FALSE;\r
+\r
+ UncompressedBuffer = NULL;\r
+ CompressedLength = SectionLength - sizeof (EFI_COMPRESSION_SECTION) - LargeHeaderOffset;\r
+ UncompressedLength = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->UncompressedLength;\r
+ CompressionType = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->CompressionType;\r
+\r
+ if (CompressionType == EFI_NOT_COMPRESSED) {\r
+ //printf (" Compression Type: EFI_NOT_COMPRESSED\n");\r
+ if (CompressedLength != UncompressedLength) {\r
+ Error ("FMMT", 0, 0, "file is not compressed, but the compressed length does not match the uncompressed length", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+\r
+ UncompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION) + LargeHeaderOffset;\r
+ } else if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
+ GetInfoFunction = EfiGetInfo;\r
+ DecompressFunction = EfiDecompress;\r
+\r
+ CompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION) + LargeHeaderOffset;\r
+\r
+ Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0003, "error getting compression info from compression section", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+\r
+ if (DstSize != UncompressedLength) {\r
+ Error ("FMMT", 0, 0003, "compression error in the compression section", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+\r
+ ScratchBuffer = malloc (ScratchSize);\r
+ if (ScratchBuffer == NULL) {\r
+ Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ UncompressedBuffer = malloc (UncompressedLength);\r
+ if (UncompressedBuffer == NULL) {\r
+ Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);\r
+ free (ScratchBuffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Decompress the section.\r
+ //\r
+ Status = DecompressFunction (\r
+ CompressedBuffer,\r
+ CompressedLength,\r
+ UncompressedBuffer,\r
+ UncompressedLength,\r
+ ScratchBuffer,\r
+ ScratchSize\r
+ );\r
+ free (ScratchBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0003, "decompress failed", NULL);\r
+ free (UncompressedBuffer);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+ } else {\r
+ Error ("FMMT", 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+\r
+ Status = LibParseSection ( UncompressedBuffer,\r
+ UncompressedLength,\r
+ CurrentFv,\r
+ FvName,\r
+ CurrentFile,\r
+ Level,\r
+ &LocalEncapData,\r
+ FfsLevel,\r
+ FfsCount,\r
+ FvCount,\r
+ ViewFlag,\r
+ ErasePolarity,\r
+ IsFfsGenerated);\r
+\r
+ if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
+ //\r
+ // We need to deallocate Buffer\r
+ //\r
+ free (UncompressedBuffer);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0003, "failed to parse section", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_SECTION_GUID_DEFINED:\r
+ //\r
+ // Process GUID defined\r
+ // looks up the appropriate tool to use for extracting\r
+ // a GUID defined FV section.\r
+ //\r
+ Level ++;\r
+ NumberOfSections++;\r
+ EncapDataNeedUpdata = TRUE;\r
+ //\r
+ // Put in encapsulate data information.\r
+ //\r
+ LocalEncapData = *CurrentFvEncapData;\r
+ if (LocalEncapData->NextNode != NULL) {\r
+ EncapDataNeedUpdata = FALSE;\r
+ while (LocalEncapData->RightNode != NULL) {\r
+ LocalEncapData = LocalEncapData->RightNode;\r
+ }\r
+ }\r
+ GuidAttr = ((EFI_GUID_DEFINED_SECTION *)(Ptr + LargeHeaderOffset))->Attributes;\r
+ DataOffset = ((EFI_GUID_DEFINED_SECTION *)(Ptr + LargeHeaderOffset))->DataOffset;\r
+\r
+ if ((ViewFlag) && ((GuidAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0)) {\r
+ ToolOutputBuffer = Ptr + DataOffset;\r
+ ToolOutputLength = SectionLength - DataOffset;\r
+ Status = LibParseSection(\r
+ ToolOutputBuffer,\r
+ ToolOutputLength,\r
+ CurrentFv,\r
+ FvName,\r
+ CurrentFile,\r
+ Level,\r
+ &LocalEncapData,\r
+ FfsLevel,\r
+ FfsCount,\r
+ FvCount,\r
+ ViewFlag,\r
+ ErasePolarity,\r
+ IsFfsGenerated\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (EncapDataNeedUpdata) {\r
+\r
+ //\r
+ // Put in this is an FFS with FV section\r
+ //\r
+\r
+ //\r
+ // Construct the new ENCAP_DATA\r
+ //\r
+ LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+\r
+ if (LocalEncapData->NextNode == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+\r
+ LocalEncapData->Level = Level;\r
+ LocalEncapData->Type = FMMT_ENCAP_TREE_GUIDED_SECTION;\r
+ LocalEncapData->Depex = NULL;\r
+ LocalEncapData->DepexLen = 0;\r
+ LocalEncapData->UiNameSize = 0;\r
+ //\r
+ // We don't need additional data for encapsulate this FFS but type.\r
+ // include DataOffset + Attributes\r
+ //\r
+\r
+ LocalEncapData->Data = (EFI_GUID *) malloc (sizeof (EFI_GUID) + 4);\r
+\r
+ if (LocalEncapData->Data == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // include guid attribute and dataoffset\r
+ //\r
+ memcpy (LocalEncapData->Data, Ptr + LargeHeaderOffset + OFFSET_OF (EFI_GUID_DEFINED_SECTION, SectionDefinitionGuid), sizeof (EFI_GUID) + 4);\r
+\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ LocalEncapData->NextNode = NULL;\r
+ LocalEncapData->RightNode = NULL;\r
+ } else {\r
+ LocalEncapData->RightNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+ if (LocalEncapData->RightNode == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ LocalEncapData = LocalEncapData->RightNode;\r
+ LocalEncapData->Level = Level;\r
+ LocalEncapData->Type = FMMT_ENCAP_TREE_GUIDED_SECTION;\r
+ LocalEncapData->Depex = NULL;\r
+ LocalEncapData->DepexLen = 0;\r
+ LocalEncapData->UiNameSize = 0;\r
+ //\r
+ // We don't need additional data for encapsulate this FFS but type.\r
+ // include DataOffset + Attributes\r
+ //\r
+\r
+ LocalEncapData->Data = (EFI_GUID *) malloc (sizeof (EFI_GUID) + 4);\r
+\r
+ if (LocalEncapData->Data == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // include guid attribute and dataoffset\r
+ //\r
+ memcpy (LocalEncapData->Data, Ptr + LargeHeaderOffset + OFFSET_OF (EFI_GUID_DEFINED_SECTION, SectionDefinitionGuid), sizeof (EFI_GUID) + 4);\r
+\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ LocalEncapData->NextNode = NULL;\r
+ LocalEncapData->RightNode = NULL;\r
+ }\r
+\r
+ CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf = FALSE;\r
+\r
+ ExtractionTool =\r
+ LookupGuidedSectionToolPath (\r
+ mParsedGuidedSectionTools,\r
+ &((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->SectionDefinitionGuid\r
+ );\r
+\r
+ if (ExtractionTool != NULL && ((GuidAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0)) {\r
+\r
+ TempDir = getcwd (NULL, _MAX_PATH);\r
+ if (strlen (TempDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ free (ExtractionTool);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+ strncat (TempDir, OS_SEP_STR, _MAX_PATH - strlen(TempDir) - 1);\r
+ strncat (TempDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TempDir) - 1);\r
+ mkdir(TempDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
+ ToolInputFile = GenTempFile ();\r
+ if (ToolInputFile == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ free (ExtractionTool);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ ToolOutputFile = GenTempFile ();\r
+ if (ToolOutputFile == NULL) {\r
+ free (ToolInputFile);\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ free (ExtractionTool);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ ToolInputFileName = strrchr(ToolInputFile, OS_SEP);\r
+ if (ToolInputFileName == NULL) {\r
+ free (ToolInputFile);\r
+ free (ToolOutputFile);\r
+ free (ExtractionTool);\r
+ return EFI_ABORTED;\r
+ }\r
+ ToolOutputFileName = strrchr(ToolOutputFile, OS_SEP);\r
+ if (ToolOutputFileName == NULL) {\r
+ free (ToolInputFile);\r
+ free (ToolOutputFile);\r
+ free (ExtractionTool);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ ToolInputFileFullName = malloc (strlen("%s%s") + strlen(TempDir) + strlen(ToolInputFileName) + 1);\r
+ if (ToolInputFileFullName == NULL) {\r
+ free (ToolInputFile);\r
+ free (ToolOutputFile);\r
+ free (ExtractionTool);\r
+ Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ ToolOutputFileFullName = malloc (strlen("%s%s") + strlen(TempDir) + strlen(ToolOutputFileName) + 1);\r
+\r
+ if (ToolOutputFileFullName == NULL) {\r
+ free (ToolInputFile);\r
+ free (ToolOutputFile);\r
+ free (ToolInputFileFullName);\r
+ free (ExtractionTool);\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ sprintf (ToolInputFileFullName, "%s%s", TempDir, ToolInputFileName);\r
+ sprintf (ToolOutputFileFullName, "%s%s", TempDir, ToolOutputFileName);\r
+\r
+ //\r
+ // Construction 'system' command string\r
+ //\r
+ SystemCommandFormatString = "%s -d -o \"%s\" \"%s\"";\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (ExtractionTool) +\r
+ strlen (ToolInputFileFullName) +\r
+ strlen (ToolOutputFileFullName) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ free (ToolInputFile);\r
+ free (ToolOutputFile);\r
+ free (ToolInputFileFullName);\r
+ free (ToolOutputFileFullName);\r
+ free (ExtractionTool);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "%s -d -o \"%s\" \"%s\"",\r
+ ExtractionTool,\r
+ ToolOutputFileFullName,\r
+ ToolInputFileFullName\r
+ );\r
+ free (ExtractionTool);\r
+ ExtractionTool = NULL;\r
+\r
+ Status = PutFileImage (\r
+ ToolInputFileFullName,\r
+ (CHAR8*) Ptr + ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset,\r
+ SectionLength - ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset\r
+ );\r
+\r
+ if (HasDepexSection) {\r
+ HasDepexSection = FALSE;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "unable to decoded GUIDED section", NULL);\r
+ free (SystemCommand);\r
+ free (ToolInputFile);\r
+ free (ToolOutputFile);\r
+ free (ToolOutputFileFullName);\r
+ remove (ToolInputFileFullName);\r
+ free (ToolInputFileFullName);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ printf("Command failed: %s\n", SystemCommand);\r
+ free (SystemCommand);\r
+ free (ToolInputFile);\r
+ free (ToolOutputFile);\r
+ free (ToolOutputFileFullName);\r
+ remove (ToolInputFileFullName);\r
+ free (ToolInputFileFullName);\r
+ return EFI_ABORTED;\r
+ }\r
+ free (SystemCommand);\r
+ remove (ToolInputFileFullName);\r
+ free (ToolInputFile);\r
+ free (ToolInputFileFullName);\r
+ ToolInputFile = NULL;\r
+ ToolInputFileFullName = NULL;\r
+\r
+\r
+ Status = GetFileImage (\r
+ ToolOutputFileFullName,\r
+ (CHAR8 **)&ToolOutputBuffer,\r
+ &ToolOutputLength\r
+ );\r
+ remove (ToolOutputFileFullName);\r
+ free (ToolOutputFile);\r
+ free (ToolOutputFileFullName);\r
+ ToolOutputFile = NULL;\r
+ ToolOutputFileFullName = NULL;\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "unable to read decoded GUIDED section", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+\r
+ Status = LibParseSection (\r
+ ToolOutputBuffer,\r
+ ToolOutputLength,\r
+ CurrentFv,\r
+ FvName,\r
+ CurrentFile,\r
+ Level,\r
+ &LocalEncapData,\r
+ FfsLevel,\r
+ FfsCount,\r
+ FvCount,\r
+ ViewFlag,\r
+ ErasePolarity,\r
+ IsFfsGenerated\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+ } else if ((GuidAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0){\r
+ Status = LibParseSection (\r
+ Ptr + ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset,\r
+ SectionLength - ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset,\r
+ CurrentFv,\r
+ FvName,\r
+ CurrentFile,\r
+ Level,\r
+ &LocalEncapData,\r
+ FfsLevel,\r
+ FfsCount,\r
+ FvCount,\r
+ ViewFlag,\r
+ ErasePolarity,\r
+ IsFfsGenerated\r
+ );\r
+ if (ExtractionTool != NULL) {\r
+ free (ExtractionTool);\r
+ ExtractionTool = NULL;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+ }else {\r
+ //\r
+ // We don't know how to parse it now.\r
+ //\r
+ if (ExtractionTool != NULL) {\r
+ free (ExtractionTool);\r
+ ExtractionTool = NULL;\r
+ }\r
+ Error ("FMMT", 0, 0003, "Error parsing section", \\r
+ "EFI_SECTION_GUID_DEFINED cannot be parsed at this time. Tool to decode this section should have been defined in %s file.", mGuidToolDefinition);\r
+ printf(" Its GUID is: ");\r
+ PrintGuid(&(((EFI_GUID_DEFINED_SECTION *)(Ptr + LargeHeaderOffset))->SectionDefinitionGuid));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ break;\r
+\r
+ //\r
+ //Leaf sections\r
+ //\r
+ case EFI_SECTION_RAW:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ if (!ViewFlag) {\r
+ if (!*IsFfsGenerated) {\r
+ LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);\r
+ *IsFfsGenerated = TRUE;\r
+ }\r
+ }\r
+\r
+ break;\r
+ case EFI_SECTION_PE32:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ if (!ViewFlag) {\r
+ if (!*IsFfsGenerated) {\r
+ LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);\r
+ *IsFfsGenerated = TRUE;\r
+ }\r
+ }\r
+\r
+ break;\r
+ case EFI_SECTION_PIC:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ if (!ViewFlag) {\r
+ if (!*IsFfsGenerated) {\r
+ LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);\r
+ *IsFfsGenerated = TRUE;\r
+ }\r
+ }\r
+\r
+ break;\r
+ case EFI_SECTION_TE:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ if (!ViewFlag) {\r
+ if (!*IsFfsGenerated) {\r
+ LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);\r
+ *IsFfsGenerated = TRUE;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_SECTION_COMPATIBILITY16:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ if (!ViewFlag) {\r
+ if (!*IsFfsGenerated) {\r
+ LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);\r
+ *IsFfsGenerated = TRUE;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_SECTION_FREEFORM_SUBTYPE_GUID:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ if (!ViewFlag) {\r
+ if (!*IsFfsGenerated) {\r
+ LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);\r
+ *IsFfsGenerated = TRUE;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_SECTION_VERSION:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ break;\r
+ case EFI_SECTION_PEI_DEPEX:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ HasDepexSection = TRUE;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Depex = malloc (SectionLength);\r
+ memcpy(CurrentFv->FfsAttuibutes[*FfsCount].Depex, Ptr, SectionLength);\r
+ CurrentFv->FfsAttuibutes[*FfsCount].DepexLen = SectionLength;\r
+ break;\r
+ case EFI_SECTION_DXE_DEPEX:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ HasDepexSection = TRUE;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Depex = malloc (SectionLength);\r
+ memcpy(CurrentFv->FfsAttuibutes[*FfsCount].Depex, Ptr, SectionLength);\r
+ CurrentFv->FfsAttuibutes[*FfsCount].DepexLen = SectionLength;\r
+ break;\r
+ case EFI_SECTION_SMM_DEPEX:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ HasDepexSection = TRUE;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Depex = malloc (SectionLength);\r
+ memcpy(CurrentFv->FfsAttuibutes[*FfsCount].Depex, Ptr, SectionLength);\r
+ CurrentFv->FfsAttuibutes[*FfsCount].DepexLen = SectionLength;\r
+ break;\r
+\r
+ case EFI_SECTION_USER_INTERFACE:\r
+ NumberOfSections ++;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+\r
+ UiSectionLength = GetLength (((EFI_USER_INTERFACE_SECTION *) Ptr)->CommonHeader.Size);\r
+ if (UiSectionLength == 0xffffff) {\r
+ UiSectionLength = ((EFI_USER_INTERFACE_SECTION2 *) Ptr)->CommonHeader.ExtendedSize;\r
+ UINameSize = UiSectionLength - sizeof(EFI_COMMON_SECTION_HEADER2);\r
+ } else {\r
+ UINameSize = UiSectionLength - sizeof(EFI_COMMON_SECTION_HEADER);\r
+ }\r
+\r
+ UIName = (CHAR16 *) malloc (UINameSize + 2);\r
+ if (UIName != NULL) {\r
+ memset (UIName, '\0', UINameSize + 2);\r
+ if (UiSectionLength >= 0xffffff) {\r
+ memcpy(UIName, ((EFI_USER_INTERFACE_SECTION2 *) Ptr)->FileNameString, UINameSize);\r
+ } else {\r
+ memcpy(UIName, ((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString, UINameSize);\r
+ }\r
+ } else {\r
+ Error ("FMMT", 0, 0001, "Memory allocate error!", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ BlankChar = LibConstructBlankChar( CurrentFv->FvLevel * 2);\r
+ if (BlankChar == NULL) {\r
+ free(UIName);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (ViewFlag) {\r
+ UIFileName = malloc (UINameSize + 2);\r
+ if (UIFileName == NULL) {\r
+ Error ("FMMT", 0, 4001, "Memory allocation fail!", NULL);\r
+ free (UIName);\r
+ free (BlankChar);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Unicode2AsciiString (UIName, UIFileName);\r
+ fprintf(stdout, "%sFile \"%s\"\n", BlankChar, UIFileName);\r
+ free(UIFileName);\r
+ }\r
+ free (BlankChar);\r
+\r
+ //\r
+ // If Ffs file has been generated, then the FfsCount should decrease 1.\r
+ //\r
+ if (*IsFfsGenerated) {\r
+ memcpy (CurrentFv->FfsAttuibutes[*FfsCount -1].UiName, UIName, UINameSize);\r
+ CurrentFv->FfsAttuibutes[*FfsCount -1].UiNameSize = UINameSize;\r
+ } else {\r
+ memcpy (CurrentFv->FfsAttuibutes[*FfsCount].UiName, UIName, UINameSize);\r
+ CurrentFv->FfsAttuibutes[*FfsCount].UiNameSize = UINameSize;\r
+ }\r
+\r
+ HasDepexSection = FALSE;\r
+ free(UIName);\r
+ UINameSize = 0;\r
+\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ ParsedLength += SectionLength;\r
+ //\r
+ // We make then next section begin on a 4-byte boundary\r
+ //\r
+ ParsedLength = GetOccupiedSize (ParsedLength, 4);\r
+ }\r
+\r
+ if (ParsedLength < BufferLength) {\r
+ Error ("FMMT", 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL);\r
+ return EFI_SECTION_ERROR;\r
+ }\r
+\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Iterates through the files contained within the firmware volume\r
+\r
+ @param[in] Fv - Address of the Fv in memory\r
+ @param[in] Key - Should be 0 to get the first file. After that, it should be\r
+ passed back in without modifying it's contents to retrieve\r
+ subsequent files.\r
+ @param[in] File- Output file pointer\r
+ File == NULL - invalid parameter\r
+ otherwise - *File will be update to the location of the file\r
+\r
+ @return EFI_STATUS\r
+ EFI_NOT_FOUND\r
+ EFI_VOLUME_CORRUPTED\r
+\r
+**/\r
+EFI_STATUS\r
+FvBufFindNextFile (\r
+ IN VOID *Fv,\r
+ IN OUT UINTN *Key,\r
+ OUT VOID **File\r
+ )\r
+{\r
+ EFI_FIRMWARE_VOLUME_HEADER *hdr;\r
+ EFI_FFS_FILE_HEADER *fhdr;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;\r
+ EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
+ UINTN fsize;\r
+ EFI_STATUS Status;\r
+ UINTN fvSize;\r
+\r
+ hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
+ fhdr = NULL;\r
+\r
+ if (Fv == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = FvBufGetSize (Fv, &fvSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (*Key == 0) {\r
+ if (hdr->ExtHeaderOffset != 0) {\r
+ //\r
+ // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.\r
+ //\r
+ FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)hdr + hdr->ExtHeaderOffset);\r
+ *Key = (UINTN)hdr->ExtHeaderOffset + FwVolExtHeader->ExtHeaderSize;\r
+ *Key = (UINTN)ALIGN_POINTER(*Key, 8);\r
+ } else {\r
+ *Key = hdr->HeaderLength;\r
+ }\r
+ }\r
+\r
+ FvbAttributes = hdr->Attributes;\r
+\r
+ for(\r
+ *Key = (UINTN)ALIGN_POINTER (*Key, 8);\r
+ (*Key + sizeof (*fhdr)) < fvSize;\r
+ *Key = (UINTN)ALIGN_POINTER (*Key, 8)\r
+ ) {\r
+ fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key);\r
+ fsize = GetFfsFileLength (fhdr);\r
+ if (!EFI_TEST_FFS_ATTRIBUTES_BIT(\r
+ FvbAttributes,\r
+ fhdr->State,\r
+ EFI_FILE_HEADER_VALID\r
+ ) ||\r
+ EFI_TEST_FFS_ATTRIBUTES_BIT(\r
+ FvbAttributes,\r
+ fhdr->State,\r
+ EFI_FILE_HEADER_INVALID\r
+ )\r
+ ) {\r
+ *Key = *Key + 1;\r
+ continue;\r
+ } else if(\r
+ EFI_TEST_FFS_ATTRIBUTES_BIT(\r
+ FvbAttributes,\r
+ fhdr->State,\r
+ EFI_FILE_MARKED_FOR_UPDATE\r
+ ) ||\r
+ EFI_TEST_FFS_ATTRIBUTES_BIT(\r
+ FvbAttributes,\r
+ fhdr->State,\r
+ EFI_FILE_DELETED\r
+ )\r
+ ) {\r
+ *Key = *Key + fsize;\r
+ continue;\r
+ } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(\r
+ FvbAttributes,\r
+ fhdr->State,\r
+ EFI_FILE_DATA_VALID\r
+ )\r
+ ) {\r
+ *File = (UINT8*)hdr + *Key;\r
+ *Key = *Key + fsize;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ *Key = *Key + 1;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+\r
+ TODO: Add function description\r
+\r
+ FvImage - TODO: add argument description\r
+ FileHeader - TODO: add argument description\r
+ ErasePolarity - TODO: add argument description\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+ EFI_ABORTED - TODO: Add description for return value\r
+\r
+**/\r
+EFI_STATUS\r
+LibGetFileInfo (\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage,\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile,\r
+ BOOLEAN ErasePolarity,\r
+ FV_INFORMATION *CurrentFv,\r
+ CHAR8 *FvName,\r
+ UINT8 Level,\r
+ ENCAP_INFO_DATA **CurrentFvEncapData,\r
+ UINT32 *FfsCount,\r
+ UINT8 *FvCount,\r
+ BOOLEAN ViewFlag\r
+ )\r
+{\r
+ UINT32 FileLength;\r
+ UINT8 FileState;\r
+ UINT8 Checksum;\r
+ EFI_FFS_FILE_HEADER2 BlankHeader;\r
+ EFI_STATUS Status;\r
+ UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];\r
+ ENCAP_INFO_DATA *LocalEncapData;\r
+ BOOLEAN EncapDataNeedUpdateFlag;\r
+ BOOLEAN IsGeneratedFfs;\r
+ UINT32 FfsFileHeaderSize;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ LocalEncapData = NULL;\r
+ EncapDataNeedUpdateFlag = TRUE;\r
+ IsGeneratedFfs = FALSE;\r
+\r
+ FfsFileHeaderSize = GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) CurrentFile);\r
+ FileLength = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);\r
+\r
+ //\r
+ // Check if we have free space\r
+ //\r
+ if (ErasePolarity) {\r
+ memset (&BlankHeader, -1, FfsFileHeaderSize);\r
+ } else {\r
+ memset (&BlankHeader, 0, FfsFileHeaderSize);\r
+ }\r
+\r
+ //\r
+ // Is this FV blank?\r
+ //\r
+ if (memcmp (&BlankHeader, CurrentFile, FfsFileHeaderSize) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Print file information.\r
+ //\r
+ FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER *)CurrentFile);\r
+ PrintGuidToBuffer (&(CurrentFile->Name), GuidBuffer, PRINTED_GUID_BUFFER_SIZE, FALSE);\r
+ if (FileState == EFI_FILE_DATA_VALID) {\r
+ //\r
+ // Calculate header checksum\r
+ //\r
+ Checksum = CalculateSum8 ((UINT8 *) CurrentFile, FfsFileHeaderSize);\r
+ Checksum = (UINT8) (Checksum - CurrentFile->IntegrityCheck.Checksum.File);\r
+ Checksum = (UINT8) (Checksum - CurrentFile->State);\r
+ if (Checksum != 0) {\r
+ Error ("FMMT", 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (CurrentFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+ //\r
+ // Calculate file checksum\r
+ //\r
+ Checksum = CalculateSum8 ((UINT8 *) ((UINTN)CurrentFile + FfsFileHeaderSize), FileLength - FfsFileHeaderSize);\r
+ Checksum = Checksum + CurrentFile->IntegrityCheck.Checksum.File;\r
+ if (Checksum != 0) {\r
+ Error ("FMMT", 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+ } else {\r
+ if (CurrentFile->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {\r
+ Error ("FMMT", 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0xAA", GuidBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+ } else {\r
+ Error ("FMMT", 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Level += 1;\r
+\r
+ if ((CurrentFile->Type != EFI_FV_FILETYPE_ALL) && (CurrentFile->Type != EFI_FV_FILETYPE_FFS_PAD)) {\r
+\r
+ //\r
+ // Put in encapsulate data information.\r
+ //\r
+ LocalEncapData = *CurrentFvEncapData;\r
+ if (LocalEncapData->NextNode != NULL) {\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ EncapDataNeedUpdateFlag = FALSE;\r
+ while (LocalEncapData->RightNode != NULL) {\r
+ LocalEncapData = LocalEncapData->RightNode;\r
+ }\r
+ }\r
+\r
+ if (EncapDataNeedUpdateFlag) {\r
+ //\r
+ // Construct the new ENCAP_DATA\r
+ //\r
+ LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+\r
+ if (LocalEncapData->NextNode == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+\r
+ LocalEncapData->Level = Level;\r
+ LocalEncapData->Type = FMMT_ENCAP_TREE_FFS;\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ LocalEncapData->Depex = NULL;\r
+ LocalEncapData->DepexLen = 0;\r
+ LocalEncapData->UiNameSize = 0;\r
+ //\r
+ // Store the header of FFS file.\r
+ //\r
+ LocalEncapData->Data = malloc (FfsFileHeaderSize);\r
+ if (LocalEncapData->Data == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ memcpy (LocalEncapData->Data, CurrentFile, FfsFileHeaderSize);\r
+ LocalEncapData->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)malloc(sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER));\r
+ if (LocalEncapData->FvExtHeader == NULL) {\r
+ Error(NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ LocalEncapData->FvExtHeader->FvName.Data1 = CurrentFile->Name.Data1;\r
+ LocalEncapData->FvExtHeader->FvName.Data2 = CurrentFile->Name.Data2;\r
+ LocalEncapData->FvExtHeader->FvName.Data3 = CurrentFile->Name.Data3;\r
+ LocalEncapData->FvExtHeader->FvName.Data4[0] = CurrentFile->Name.Data4[0];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[1] = CurrentFile->Name.Data4[1];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[2] = CurrentFile->Name.Data4[2];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[3] = CurrentFile->Name.Data4[3];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[4] = CurrentFile->Name.Data4[4];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[5] = CurrentFile->Name.Data4[5];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[6] = CurrentFile->Name.Data4[6];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[7] = CurrentFile->Name.Data4[7];\r
+ LocalEncapData->NextNode = NULL;\r
+ LocalEncapData->RightNode = NULL;\r
+ }else{\r
+ //\r
+ // Construct the new ENCAP_DATA\r
+ //\r
+ LocalEncapData->RightNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+\r
+ if (LocalEncapData->RightNode == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ LocalEncapData = LocalEncapData->RightNode;\r
+\r
+ LocalEncapData->Level = Level;\r
+ LocalEncapData->Type = FMMT_ENCAP_TREE_FFS;\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ LocalEncapData->Depex = NULL;\r
+ LocalEncapData->DepexLen = 0;\r
+ LocalEncapData->UiNameSize = 0;\r
+ //\r
+ // Store the header of FFS file.\r
+ //\r
+ LocalEncapData->Data = malloc (FfsFileHeaderSize);\r
+ if (LocalEncapData->Data == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ memcpy (LocalEncapData->Data, CurrentFile, FfsFileHeaderSize);\r
+ LocalEncapData->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)malloc(sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER));\r
+ if (LocalEncapData->FvExtHeader == NULL) {\r
+ Error(NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ LocalEncapData->FvExtHeader->FvName.Data1 = CurrentFile->Name.Data1;\r
+ LocalEncapData->FvExtHeader->FvName.Data2 = CurrentFile->Name.Data2;\r
+ LocalEncapData->FvExtHeader->FvName.Data3 = CurrentFile->Name.Data3;\r
+ LocalEncapData->FvExtHeader->FvName.Data4[0] = CurrentFile->Name.Data4[0];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[1] = CurrentFile->Name.Data4[1];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[2] = CurrentFile->Name.Data4[2];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[3] = CurrentFile->Name.Data4[3];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[4] = CurrentFile->Name.Data4[4];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[5] = CurrentFile->Name.Data4[5];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[6] = CurrentFile->Name.Data4[6];\r
+ LocalEncapData->FvExtHeader->FvName.Data4[7] = CurrentFile->Name.Data4[7];\r
+ LocalEncapData->RightNode = NULL;\r
+ LocalEncapData->NextNode = NULL;\r
+ }\r
+\r
+ if ( CurrentFile->Type == EFI_FV_FILETYPE_RAW){\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;\r
+ if (!ViewFlag){\r
+ LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);\r
+ }\r
+ } else if( CurrentFile->Type == EFI_FV_FILETYPE_FFS_PAD){\r
+ //EFI_FV_FILETYPE_FFS_PAD\r
+ } else {\r
+ //\r
+ // All other files have sections\r
+ //\r
+ Status = LibParseSection (\r
+ (UINT8 *) ((UINTN) CurrentFile + FfsFileHeaderSize),\r
+ FileLength - FfsFileHeaderSize,\r
+ CurrentFv,\r
+ FvName,\r
+ CurrentFile,\r
+ Level,\r
+ &LocalEncapData,\r
+ Level,\r
+ FfsCount,\r
+ FvCount,\r
+ ViewFlag,\r
+ ErasePolarity,\r
+ &IsGeneratedFfs\r
+ );\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ printf ("ERROR: Parsing the FFS file.\n");\r
+ return Status;\r
+ }\r
+ }\r
+\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Get firmware information. Including the FV headers,\r
+\r
+ @param[in] Fv - Firmware Volume to get information from\r
+\r
+ @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+LibGetFvInfo (\r
+ IN VOID *Fv,\r
+ IN OUT FV_INFORMATION *CurrentFv,\r
+ IN CHAR8 *FvName,\r
+ IN UINT8 Level,\r
+ IN ENCAP_INFO_DATA **CurrentFvEncapData,\r
+ IN UINT32 *FfsCount,\r
+ IN OUT UINT8 *FvCount,\r
+ IN BOOLEAN ViewFlag,\r
+ IN BOOLEAN IsChildFv\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN NumberOfFiles;\r
+ BOOLEAN ErasePolarity;\r
+ UINTN FvSize;\r
+ EFI_FFS_FILE_HEADER2 *CurrentFile;\r
+ UINTN Key;\r
+ ENCAP_INFO_DATA *LocalEncapData;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHdrPtr;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHdr;\r
+\r
+ NumberOfFiles = 0;\r
+ Key = 0;\r
+ LocalEncapData = NULL;\r
+ CurrentFile = NULL;\r
+ FvHdr = (EFI_FIRMWARE_VOLUME_HEADER *)Fv;\r
+\r
+\r
+ Level += 1;\r
+ *FvCount += 1;\r
+ CurrentFv->FvLevel += 1;\r
+\r
+ Status = FvBufGetSize (Fv, &FvSize);\r
+\r
+ ErasePolarity = (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ? TRUE : FALSE;\r
+\r
+ Status = LibReadFvHeader (Fv, ViewFlag, CurrentFv->FvLevel, *FvCount - 1, CurrentFv->FvName);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0003, "error parsing FV image", "Header is invalid");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (!IsChildFv) {\r
+ //\r
+ // Write FV header information into CurrentFv struct.\r
+ //\r
+ CurrentFv->FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (FvHdr->HeaderLength);\r
+\r
+ if (CurrentFv->FvHeader == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Get the FV Header information\r
+ //\r
+ memcpy(CurrentFv->FvHeader, Fv, FvHdr->HeaderLength);\r
+ CurrentFv->FvExtHeader = NULL;\r
+ CurrentFv->FvUiName = NULL;\r
+\r
+ //\r
+ // Exist Extend FV header.\r
+ //\r
+ if (CurrentFv->FvHeader->ExtHeaderOffset != 0){\r
+ ExtHdrPtr = (VOID *)((UINTN)Fv + CurrentFv->FvHeader->ExtHeaderOffset);\r
+ CurrentFv->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) malloc (ExtHdrPtr->ExtHeaderSize);\r
+\r
+ if (CurrentFv->FvExtHeader == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Get the FV extended Header information\r
+ //\r
+ memcpy (CurrentFv->FvExtHeader, (VOID *)((UINTN)Fv + CurrentFv->FvHeader->ExtHeaderOffset), ExtHdrPtr->ExtHeaderSize);\r
+ LibExtractFvUiName(CurrentFv->FvExtHeader, &CurrentFv->FvUiName);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Put encapsulate information into structure.\r
+ //\r
+ LocalEncapData = *CurrentFvEncapData;\r
+ if (LocalEncapData == NULL && !IsChildFv) {\r
+ //\r
+ // First time in, the root FV\r
+ //\r
+ LocalEncapData = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+ CurrentFv->EncapData = LocalEncapData;\r
+ if (CurrentFv->EncapData == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ CurrentFv->EncapData->FvExtHeader = NULL;\r
+ CurrentFv->EncapData->Depex = NULL;\r
+ CurrentFv->EncapData->DepexLen = 0;\r
+ CurrentFv->EncapData->UiNameSize = 0;\r
+ CurrentFv->EncapData->Level = Level;\r
+ CurrentFv->EncapData->Type = FMMT_ENCAP_TREE_FV;\r
+ CurrentFv->EncapData->Data = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+ CurrentFv->EncapData->FvId = *FvCount;\r
+\r
+ if (CurrentFv->EncapData->Data == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ memcpy (CurrentFv->EncapData->Data, Fv, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+\r
+ if (((EFI_FIRMWARE_VOLUME_HEADER *)(CurrentFv->EncapData->Data))->ExtHeaderOffset != 0) {\r
+ ExtHdrPtr = (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(CurrentFv->EncapData->Data))->ExtHeaderOffset);\r
+ CurrentFv->EncapData->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) malloc (ExtHdrPtr->ExtHeaderSize);\r
+\r
+ if (CurrentFv->EncapData->FvExtHeader == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Get the FV extended Header information\r
+ //\r
+ memcpy(CurrentFv->EncapData->FvExtHeader, (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(CurrentFv->EncapData->Data))->ExtHeaderOffset), ExtHdrPtr->ExtHeaderSize);\r
+ }\r
+\r
+ CurrentFv->EncapData->NextNode = NULL;\r
+ CurrentFv->EncapData->RightNode = NULL;\r
+ } else if (LocalEncapData == NULL) {\r
+ return EFI_ABORTED;\r
+ } else if (IsChildFv) {\r
+\r
+ LocalEncapData = *CurrentFvEncapData;\r
+ while (LocalEncapData->NextNode != NULL) {\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+\r
+ //\r
+ // Construct the new ENCAP_DATA\r
+ //\r
+ LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));\r
+\r
+ if (LocalEncapData->NextNode == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+\r
+ LocalEncapData->Level = Level;\r
+ LocalEncapData->Type = FMMT_ENCAP_TREE_FV;\r
+ LocalEncapData->Data = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ LocalEncapData->Depex = NULL;\r
+ LocalEncapData->DepexLen = 0;\r
+ LocalEncapData->UiNameSize = 0;\r
+ LocalEncapData->FvId = *FvCount;\r
+ if (LocalEncapData->Data == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ memcpy (LocalEncapData->Data, Fv, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+\r
+ if (((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset != 0) {\r
+ ExtHdrPtr = (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset);\r
+ LocalEncapData->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)malloc(ExtHdrPtr->ExtHeaderSize);\r
+\r
+ if (LocalEncapData->FvExtHeader == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Get the FV extended Header information\r
+ //\r
+ memcpy(LocalEncapData->FvExtHeader, (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset), ExtHdrPtr->ExtHeaderSize);\r
+ }\r
+\r
+ LocalEncapData->NextNode = NULL;\r
+ LocalEncapData->RightNode = NULL;\r
+\r
+ }\r
+\r
+\r
+ //\r
+ // Get the first file\r
+ //\r
+ Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ CurrentFile = NULL;\r
+ } else if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");\r
+ return Status;\r
+ }\r
+\r
+ while (CurrentFile != NULL) {\r
+\r
+ //\r
+ // Increment the number of files counter\r
+ //\r
+ NumberOfFiles++;\r
+\r
+ //\r
+ // Store FFS file Header information\r
+ //\r
+ CurrentFv->FfsHeader[*FfsCount].Attributes = CurrentFile->Attributes;\r
+ CurrentFv->FfsHeader[*FfsCount].IntegrityCheck = CurrentFile->IntegrityCheck;\r
+ CurrentFv->FfsHeader[*FfsCount].Name = CurrentFile->Name;\r
+ CurrentFv->FfsHeader[*FfsCount].Size[0] = CurrentFile->Size[0];\r
+ CurrentFv->FfsHeader[*FfsCount].Size[1] = CurrentFile->Size[1];\r
+ CurrentFv->FfsHeader[*FfsCount].Size[2] = CurrentFile->Size[2];\r
+ CurrentFv->FfsHeader[*FfsCount].State = CurrentFile->State;\r
+ CurrentFv->FfsHeader[*FfsCount].Type = CurrentFile->Type;\r
+ CurrentFv->FfsHeader[*FfsCount].ExtendedSize = CurrentFile->ExtendedSize;\r
+ CurrentFv->FfsAttuibutes[*FfsCount].Offset = Key - GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);\r
+\r
+ CurrentFv->FfsAttuibutes[*FfsCount].FvLevel = CurrentFv->FvLevel;\r
+ if (CurrentFv->FvLevel > CurrentFv->MulFvLevel) {\r
+ CurrentFv->MulFvLevel = CurrentFv->FvLevel;\r
+ }\r
+ //\r
+ // Display info about this file\r
+ //\r
+ Status = LibGetFileInfo (Fv, CurrentFile, ErasePolarity, CurrentFv, FvName, Level, &LocalEncapData, FfsCount, FvCount, ViewFlag);\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0003, "error parsing FV image", "failed to parse a file in the FV");\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the next file\r
+ //\r
+ Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ CurrentFile = NULL;\r
+ } else if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ if (IsChildFv) {\r
+ if (CurrentFv->FvLevel > 1) {\r
+ CurrentFv->FvLevel -= 1;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ This function returns the next larger size that meets the alignment\r
+ requirement specified.\r
+\r
+ @param[in] ActualSize The size.\r
+ @param[in] Alignment The desired alignment.\r
+\r
+ @retval EFI_SUCCESS Function completed successfully.\r
+ @retval EFI_ABORTED The function encountered an error.\r
+\r
+**/\r
+UINT32\r
+GetOccupiedSize (\r
+ IN UINT32 ActualSize,\r
+ IN UINT32 Alignment\r
+ )\r
+{\r
+ UINT32 OccupiedSize;\r
+\r
+ OccupiedSize = ActualSize;\r
+ while ((OccupiedSize & (Alignment - 1)) != 0) {\r
+ OccupiedSize++;\r
+ }\r
+\r
+ return OccupiedSize;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+LibDeleteAndRenameFfs(\r
+ IN CHAR8* DeleteFile,\r
+ IN CHAR8* NewFile\r
+)\r
+{\r
+ CHAR8* SystemCommand;\r
+ CHAR8* TemDir;\r
+ SystemCommand = NULL;\r
+\r
+ if (DeleteFile == NULL ||\r
+ NewFile == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Delete the file of the specified extract FFS file.\r
+ //\r
+ SystemCommand = malloc (\r
+ strlen (DEL_STR) +\r
+ strlen (DeleteFile) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ sprintf (\r
+ SystemCommand,\r
+ DEL_STR,\r
+ DeleteFile\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+\r
+ TemDir = getcwd (NULL, _MAX_PATH);\r
+ if (strlen (TemDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen(TemDir) - 1);\r
+ strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TemDir) - 1);\r
+\r
+ mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
+ //\r
+ // Create a copy the new file.\r
+ //\r
+\r
+ SystemCommand = malloc (\r
+ strlen (COPY_STR) +\r
+ strlen (NewFile) +\r
+ strlen (DeleteFile) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ sprintf (\r
+ SystemCommand,\r
+ COPY_STR,\r
+ NewFile,\r
+ DeleteFile\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Converts ASCII characters to Unicode.\r
+ Assumes that the Unicode characters are only these defined in the ASCII set.\r
+\r
+ String - Pointer to string that is written to FILE.\r
+ UniString - Pointer to unicode string\r
+\r
+ The address to the ASCII string - same as AsciiStr.\r
+\r
+**/\r
+VOID\r
+LibAscii2Unicode (\r
+ IN CHAR8 *String,\r
+ OUT CHAR16 *UniString\r
+ )\r
+{\r
+ while (*String != '\0') {\r
+ *(UniString++) = (CHAR16) *(String++);\r
+ }\r
+ //\r
+ // End the UniString with a NULL.\r
+ //\r
+ *UniString = '\0';\r
+}\r
+\r
+\r
+EFI_STATUS\r
+LibCreateGuidedSectionOriginalData(\r
+ IN CHAR8* FileIn,\r
+ IN CHAR8* ToolName,\r
+ IN CHAR8* FileOut\r
+)\r
+{\r
+ CHAR8* SystemCommandFormatString;\r
+ CHAR8* SystemCommand;\r
+\r
+ SystemCommandFormatString = NULL;\r
+ SystemCommand = NULL;\r
+\r
+ if (FileIn == NULL ||\r
+ ToolName == NULL ||\r
+ FileOut == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Delete the file of the specified extract FFS file.\r
+ //\r
+ SystemCommandFormatString = "%s -e \"%s\" -o \"%s\"";\r
+\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (FileIn) +\r
+ strlen (ToolName) +\r
+ strlen (FileOut) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ sprintf (\r
+ SystemCommand,\r
+ "%s -e \"%s\" -o \"%s\"",\r
+ ToolName,\r
+ FileIn,\r
+ FileOut\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ printf("Command failed: %s\n", SystemCommand);\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ This function convert the FV header's attribute to a string. The converted string\r
+ will be put into an INF file as the input of GenFV.\r
+\r
+ @param[in] Attr FV header's attribute.\r
+ @param[out] InfFile InfFile contain FV header attribute information.\r
+\r
+ @retval EFI_SUCCESS.\r
+ @retval EFI_INVLID_PARAMETER\r
+ @retval EFI_OUT_OF_RESOURCES\r
+\r
+**/\r
+EFI_STATUS\r
+LibFvHeaderAttributeToStr (\r
+ IN EFI_FVB_ATTRIBUTES_2 Attr,\r
+ IN FILE* InfFile\r
+)\r
+{\r
+ CHAR8 *LocalStr;\r
+\r
+ LocalStr = NULL;\r
+\r
+ LocalStr = (CHAR8 *) malloc (1024 * 4);\r
+\r
+ if (LocalStr == NULL) {\r
+ printf ("Memory allocate error!\n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ memset (LocalStr, '\0', 1024 * 4);\r
+\r
+ if (Attr == 0 || InfFile == NULL) {\r
+ free (LocalStr);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ strncat (LocalStr, "[attributes] \n", sizeof("[attributes] \n"));\r
+\r
+ if (Attr & EFI_FVB2_READ_DISABLED_CAP) {\r
+ strncat (LocalStr, "EFI_READ_DISABLED_CAP = TRUE \n", sizeof ("EFI_READ_DISABLED_CAP = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_READ_ENABLED_CAP) {\r
+ strncat (LocalStr, "EFI_READ_ENABLED_CAP = TRUE \n", sizeof ("EFI_READ_ENABLED_CAP = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_READ_STATUS) {\r
+ strncat (LocalStr, "EFI_READ_STATUS = TRUE \n", sizeof ("EFI_READ_STATUS = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_WRITE_DISABLED_CAP) {\r
+ strncat (LocalStr, "EFI_WRITE_DISABLED_CAP = TRUE \n", sizeof ("EFI_WRITE_DISABLED_CAP = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_WRITE_ENABLED_CAP) {\r
+ strncat (LocalStr, "EFI_WRITE_ENABLED_CAP = TRUE \n", sizeof ("EFI_WRITE_ENABLED_CAP = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_WRITE_STATUS) {\r
+ strncat (LocalStr, "EFI_WRITE_STATUS = TRUE \n", sizeof ("EFI_WRITE_STATUS = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_LOCK_CAP) {\r
+ strncat (LocalStr, "EFI_LOCK_CAP = TRUE \n", sizeof ("EFI_LOCK_CAP = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_LOCK_STATUS) {\r
+ strncat (LocalStr, "EFI_LOCK_STATUS = TRUE \n", sizeof ("EFI_LOCK_STATUS = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_STICKY_WRITE) {\r
+ strncat (LocalStr, "EFI_STICKY_WRITE = TRUE \n", sizeof ("EFI_STICKY_WRITE = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_MEMORY_MAPPED) {\r
+ strncat (LocalStr, "EFI_MEMORY_MAPPED = TRUE \n", sizeof ("EFI_MEMORY_MAPPED = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_ERASE_POLARITY) {\r
+ strncat (LocalStr, "EFI_ERASE_POLARITY = 1 \n", sizeof ("EFI_ERASE_POLARITY = 1 \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_READ_LOCK_CAP) {\r
+ strncat (LocalStr, "EFI_READ_LOCK_CAP = TRUE \n", sizeof ("EFI_READ_LOCK_CAP = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_READ_LOCK_STATUS) {\r
+ strncat (LocalStr, "EFI_READ_LOCK_STATUS = TRUE \n", sizeof ("EFI_READ_LOCK_STATUS = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_WRITE_LOCK_CAP) {\r
+ strncat (LocalStr, "EFI_WRITE_LOCK_CAP = TRUE \n", sizeof ("EFI_WRITE_LOCK_CAP = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_WRITE_LOCK_STATUS) {\r
+ strncat (LocalStr, "EFI_WRITE_LOCK_STATUS = TRUE \n", sizeof ("EFI_WRITE_LOCK_STATUS = TRUE \n"));\r
+ }\r
+\r
+ if (Attr & EFI_FVB2_LOCK_STATUS) {\r
+ strncat (LocalStr, "EFI_READ_LOCK_STATUS = TRUE \n", sizeof ("EFI_READ_LOCK_STATUS = TRUE \n"));\r
+ }\r
+\r
+ //\r
+ // Alignment\r
+ //\r
+ if (Attr & EFI_FVB2_ALIGNMENT_1) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_1 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_2) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_2 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_4) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_4 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_8) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_8 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_16) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_16 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_32) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_32 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_64) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_64 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_128) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_128 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_256) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_256 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_512) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_512 = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_1K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_1K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_2K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_2K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_4K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_4K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_8K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_8K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_16K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_16K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_32K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_32K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_64K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_64K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_128K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_128K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_256K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_256K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_512K) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_512K = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_1M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_1M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_2M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_2M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_4M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_4M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_8M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_8M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_16M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_16M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_32M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_32M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_64M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_64M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_128M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_128M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_256M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_256M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_512M) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_512M = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_1G) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1G = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_1G = TRUE \n"));\r
+ } else if (Attr & EFI_FVB2_ALIGNMENT_2G) {\r
+ strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2G = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_2G = TRUE \n"));\r
+ }\r
+\r
+ if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) != (size_t) strlen (LocalStr)) {\r
+ printf ("Error while writing data to %p file.", (void*)InfFile);\r
+ free (LocalStr);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ free (LocalStr);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function fill the FV inf files option field.\r
+\r
+ @param[in] BlockMap FV header's attribute.\r
+ @param[out] InfFile InfFile contain FV header attribute information.\r
+\r
+ @retval EFI_SUCCESS.\r
+ @retval EFI_INVLID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+LibFvHeaderOptionToStr (\r
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,\r
+ IN FILE* InfFile,\r
+ IN BOOLEAN IsRootFv\r
+)\r
+{\r
+ CHAR8 *LocalStr;\r
+ CHAR8 *TempStr;\r
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
+\r
+ LocalStr = NULL;\r
+ TempStr = NULL;\r
+\r
+ if (FvHeader == NULL || InfFile == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // This section will not over 1024 bytes and each line will never over 128 bytes.\r
+ //\r
+ LocalStr = (CHAR8 *) malloc (1024);\r
+ TempStr = (CHAR8 *) malloc (128);\r
+\r
+ if (LocalStr == NULL ||\r
+ TempStr == NULL ) {\r
+ if (LocalStr != NULL) {\r
+ free (LocalStr);\r
+ }\r
+ if (TempStr != NULL) {\r
+ free (TempStr);\r
+ }\r
+ printf ("Memory allocate error! \n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ BlockMap = FvHeader->BlockMap;\r
+ memset (LocalStr, '\0', 1024);\r
+ memset (TempStr, '\0', 128);\r
+\r
+ strncat (LocalStr, "[options] \n", sizeof("[Options] \n"));\r
+\r
+\r
+ snprintf (TempStr, 128, "EFI_BLOCK_SIZE = 0x%x \n", BlockMap->Length);\r
+ strncat (LocalStr, TempStr, strlen(TempStr));\r
+\r
+ if (IsRootFv) {\r
+ snprintf (TempStr, 128, "EFI_NUM_BLOCKS = 0x%x \n", BlockMap->NumBlocks);\r
+ strncat (LocalStr, TempStr, strlen(TempStr));\r
+ }\r
+\r
+ if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) != (size_t) strlen (LocalStr)) {\r
+ printf ("Error while writing data to %p file.", (void*)InfFile);\r
+ free (LocalStr);\r
+ free (TempStr);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ free (LocalStr);\r
+ free (TempStr);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function fill the FV inf files option field.\r
+\r
+ @param[in] FfsName Ffs file path/name.\r
+ @param[out] InfFile InfFile contain FV header attribute information\r
+ @param[in] FirstIn Is the first time call this function? If yes, should create [files] section.\r
+\r
+ @retval EFI_SUCCESS.\r
+ @retval EFI_INVLID_PARAMETER\r
+\r
+**/\r
+EFI_STATUS\r
+LibAddFfsFileToFvInf (\r
+ IN CHAR8 *FfsName,\r
+ IN FILE* InfFile,\r
+ IN BOOLEAN FirstIn\r
+)\r
+{\r
+\r
+ CHAR8 *LocalStr;\r
+\r
+ LocalStr = NULL;\r
+\r
+ if (FfsName == NULL || InfFile == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (strlen(FfsName) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ LocalStr = (CHAR8 *) malloc (_MAX_PATH);\r
+\r
+ if (LocalStr == NULL) {\r
+ printf ("Memory allocate error! \n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ memset (LocalStr, '\0', _MAX_PATH);\r
+\r
+ if (FirstIn) {\r
+ sprintf (LocalStr, "[files] \nEFI_FILE_NAME = %s \n", FfsName);\r
+ } else {\r
+ sprintf (LocalStr, "EFI_FILE_NAME = %s \n", FfsName);\r
+ }\r
+\r
+ if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) != (size_t) strlen (LocalStr)) {\r
+ printf ("Error while writing data to %p file.", (void*)InfFile);\r
+ free (LocalStr);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ free (LocalStr);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Convert EFI file to PE or TE section\r
+\r
+ @param[in] InputFilePath .efi file, it's optional unless process PE/TE section.\r
+ @param[in] Type PE or TE and UI/Version\r
+ @param[in] OutputFilePath .te or .pe file\r
+ @param[in] UiString String for generate UI section usage, this parameter is optional\r
+ unless Type is EFI_SECTION_USER_INTERFACE.\r
+ @param[in] VerString String for generate Version section usage, this parameter is optional\r
+ unless Type is EFI_SECTION_VERSION.\r
+\r
+ @retval EFI_SUCCESS\r
+\r
+**/\r
+EFI_STATUS\r
+LibCreateFfsSection (\r
+ IN FV_INFORMATION *FvInFd, OPTIONAL\r
+ IN CHAR8* InputFilePath, OPTIONAL\r
+ IN CHAR8* Sections, OPTIONAL\r
+ IN UINT8 Type,\r
+ IN CHAR8* OutputFilePath,\r
+ IN CHAR8* UiString, OPTIONAL\r
+ IN CHAR8* VerString, OPTIONAL\r
+ IN CHAR8* GuidToolGuid, OPTIONAL\r
+ IN UINT16 GuidHeaderLength,\r
+ IN UINT16 GuidAttr,\r
+ IN CHAR8* CompressType OPTIONAL\r
+ )\r
+{\r
+ //EFI_STATUS Status;\r
+ CHAR8* SystemCommandFormatString;\r
+ CHAR8* SystemCommand;\r
+ FILE *file;\r
+ UINT8 Buffer[4];\r
+ int BitNum;\r
+ int Position;\r
+ UINT32 AlignmentValue;\r
+ //\r
+ // Workaround for static code checkers.\r
+ // Ensures the size of 'AlignmentStr' can hold all the digits of an\r
+ // unsigned 32-bit integer plus the size unit character.\r
+ //\r
+ char AlignmentStr[16];\r
+\r
+ SystemCommandFormatString = NULL;\r
+ SystemCommand = NULL;\r
+ strcpy(AlignmentStr,"1");\r
+ //\r
+ // Call GenSec tool to generate FFS section.\r
+ //\r
+\r
+ //\r
+ // -s SectionType.\r
+ //\r
+ if (Type != 0) {\r
+ switch (Type) {\r
+ //\r
+ // Process compression section\r
+ //\r
+ case EFI_SECTION_COMPRESSION:\r
+ SystemCommandFormatString = "GenSec -s %s -c %s \"%s\" -o \"%s\"";\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (mSectionTypeName[Type]) +\r
+ strlen (CompressType) +\r
+ strlen (InputFilePath) +\r
+ strlen (OutputFilePath) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "GenSec -s %s -c %s \"%s\" -o \"%s\"",\r
+ mSectionTypeName[Type],\r
+ CompressType,\r
+ InputFilePath,\r
+ OutputFilePath\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+ break;\r
+\r
+ //\r
+ // Process GUID defined section\r
+ //\r
+ case EFI_SECTION_GUID_DEFINED:\r
+ SystemCommandFormatString = "GenSec -s %s -g %s \"%s\" -o \"%s\" -r %s -r %s -l %d";\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (mSectionTypeName[Type]) +\r
+ strlen (GuidToolGuid) +\r
+ strlen (InputFilePath) +\r
+ strlen (OutputFilePath) +\r
+ strlen (mGuidSectionAttr[GuidAttr&0x01]) +\r
+ strlen (mGuidSectionAttr[GuidAttr&0x02]) +\r
+ 4 +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "GenSec -s %s -g %s \"%s\" -o \"%s\" -r %s -r %s -l %d",\r
+ mSectionTypeName[Type],\r
+ GuidToolGuid,\r
+ InputFilePath,\r
+ OutputFilePath,\r
+ mGuidSectionAttr[GuidAttr&0x01],\r
+ mGuidSectionAttr[GuidAttr&0x02],\r
+ GuidHeaderLength\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+ break;\r
+\r
+ case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:\r
+\r
+ SystemCommandFormatString = "GenSec -s %s \"%s\" -o \"%s\"";\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (mSectionTypeName[Type]) +\r
+ strlen (InputFilePath) +\r
+ strlen (OutputFilePath) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "GenSec -s %s \"%s\" -o \"%s\"",\r
+ mSectionTypeName[Type],\r
+ InputFilePath,\r
+ OutputFilePath\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+ break;\r
+\r
+ default:\r
+ Error ("FMMT", 0, 0003, "Please specify the section type while call GenSec tool.", NULL);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ //\r
+ // Create Dummy section.\r
+ //\r
+ file = fopen(InputFilePath, "rb");\r
+ if (file == NULL) {\r
+ Error(NULL, 0, 0001, "Error opening the file", InputFilePath);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ // The Section Struct, 3 bits for Size, then 1 bit for Type\r
+ if (fread(Buffer, 1, (size_t)(4), file) != (size_t)(4)) {\r
+ fclose(file);\r
+ return EFI_ABORTED;\r
+ }\r
+ if (*(Buffer + 3) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
+ // The Section Struct, if size is not 0xFFFF, the length is 4\r
+ Position = 4;\r
+ // If Size is 0xFFFFFF then ExtendedSize contains the size of the section\r
+ if ((*Buffer == 0xFF) && (*(Buffer + 1) == 0xFF) && (*(Buffer + 2) == 0xFF)) {\r
+ Position = 8;\r
+ }\r
+ //Per EFI_FIRMWARE_VOLUME_HEADER struct, 0x2E bit is EFI_FVB_ATTRIBUTES_2 attr\r
+ fseek(file, 0x2E + Position, SEEK_SET);\r
+ BitNum = fgetc(file);\r
+ AlignmentValue = 1 << (BitNum & 0x1F);\r
+ if (AlignmentValue >= 0x400){\r
+ if (AlignmentValue >= 0x10000){\r
+ strcpy(AlignmentStr,"64K");\r
+ }\r
+ else{\r
+ sprintf(AlignmentStr, "%d", AlignmentValue/0x400);\r
+ strcat(AlignmentStr, "K");\r
+ }\r
+ }\r
+ else{\r
+ sprintf(AlignmentStr, "%d", AlignmentValue);\r
+ }\r
+ strcpy(FvInFd->AlignmentStr, AlignmentStr);\r
+ }\r
+ fclose(file);\r
+ SystemCommandFormatString = "GenSec \"%s\" -o \"%s\" --sectionalign %s";\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (InputFilePath) +\r
+ strlen (OutputFilePath) +\r
+ 4 + // Alignment maximum length\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "GenSec \"%s\" -o \"%s\" --sectionalign %s",\r
+ InputFilePath,\r
+ OutputFilePath,\r
+ AlignmentStr\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Encapsulate FFSs to FV\r
+\r
+ @param[in] InputFilePath Section file will be read into this FFS file. This option is required.\r
+ @param[in] OutputFilePath The created PI firmware file name. This option is required.\r
+ @param[in] BlockSize BlockSize is one HEX or DEC format value required by FV image.\r
+ @param[in] FileTakeSize\r
+\r
+ @retval EFI_SUCCESS\r
+\r
+**/\r
+EFI_STATUS\r
+LibEncapsulateFfsToFv (\r
+ IN CHAR8* InfFilePath,\r
+ IN CHAR8* InputFFSs,\r
+ IN CHAR8* OutputFilePath,\r
+ IN CHAR8* FvGuidName,\r
+ IN BOOLEAN IsLargeFile\r
+ )\r
+{\r
+\r
+ CHAR8* SystemCommandFormatString;\r
+ CHAR8* SystemCommand;\r
+ CHAR8* FfsGuid = "8c8ce578-8a3d-4f1c-9935-896185c32dd3";\r
+\r
+ if (IsLargeFile == TRUE) {\r
+ FfsGuid = "5473c07a-3dcb-4dca-bd6f-1e9689e7349a";\r
+ }\r
+\r
+ SystemCommandFormatString = NULL;\r
+ SystemCommand = NULL;\r
+\r
+ if (OutputFilePath == NULL ||\r
+ InfFilePath == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (InfFilePath != NULL) {\r
+ if (FvGuidName == NULL) {\r
+ SystemCommandFormatString = "GenFv -i \"%s\" -g %s -o \"%s\"";\r
+\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (InfFilePath) +\r
+ strlen (FfsGuid) +\r
+ strlen (OutputFilePath) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "GenFv -i \"%s\" -g %s -o \"%s\"",\r
+ InfFilePath, // -i\r
+ FfsGuid, // -g\r
+ OutputFilePath // -o\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ free(SystemCommand);\r
+ } else {\r
+ //\r
+ // Have FvGuidName in it.\r
+ //\r
+ SystemCommandFormatString = "GenFv -i \"%s\" -g %s -o \"%s\" --FvNameGuid %s";\r
+\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (InfFilePath) +\r
+ strlen (FfsGuid) +\r
+ strlen (OutputFilePath) +\r
+ strlen (FvGuidName) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "GenFv -i \"%s\" -g %s -o \"%s\" --FvNameGuid %s",\r
+ InfFilePath, // -i\r
+ FfsGuid, // -g\r
+ OutputFilePath, // -o\r
+ FvGuidName // FvNameGuid\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+\r
+ Convert a GUID to a string.\r
+\r
+\r
+ @param[in] Guid - Pointer to GUID to print.\r
+\r
+\r
+ @return The string after convert.\r
+\r
+**/\r
+CHAR8 *\r
+LibFmmtGuidToStr (\r
+ IN EFI_GUID *Guid\r
+)\r
+{\r
+ CHAR8 * Buffer;\r
+\r
+ Buffer = NULL;\r
+\r
+ if (Guid == NULL) {\r
+ printf ("The guid is NULL while convert guid to string! \n");\r
+ return NULL;\r
+ }\r
+\r
+ Buffer = (CHAR8 *) malloc (36 + 1);\r
+\r
+ if (Buffer == NULL) {\r
+ printf ("Error while allocate resource! \n");\r
+ return NULL;\r
+ }\r
+ memset (Buffer, '\0', 36 + 1);\r
+\r
+ sprintf (\r
+ Buffer,\r
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
+ Guid->Data1,\r
+ Guid->Data2,\r
+ Guid->Data3,\r
+ Guid->Data4[0],\r
+ Guid->Data4[1],\r
+ Guid->Data4[2],\r
+ Guid->Data4[3],\r
+ Guid->Data4[4],\r
+ Guid->Data4[5],\r
+ Guid->Data4[6],\r
+ Guid->Data4[7]\r
+ );\r
+\r
+ return Buffer;\r
+}\r
+\r
+\r
+/**\r
+ Encapsulate an FFS section file to an FFS file.\r
+\r
+ @param[in] Type Type is one FV file type defined in PI spec, which is one type of EFI_FV_FILETYPE_RAW, EFI_FV_FILETYPE_FREEFORM,\r
+ EFI_FV_FILETYPE_SECURITY_CORE, EFI_FV_FILETYPE_PEIM, EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,\r
+ EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION, EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\r
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE. This option is required.\r
+ @param[in] InputFilePath Section file will be read into this FFS file. This option is required.\r
+ @param[in] OutputFilePath The created PI firmware file name. This option is required.\r
+ @param[in] FileGuid FileGuid is the unique identifier for this FFS file. This option is required.\r
+ @param[in] Fixed Set fixed attribute in FFS file header to indicate that the file may not be moved from its present location.\r
+ @param[in] SectionAlign FileAlign specifies FFS file alignment, which only support the following alignment: 8,16,128,512,1K,4K,32K,64K.\r
+\r
+ @retval EFI_SUCCESS\r
+\r
+**/\r
+EFI_STATUS\r
+LibEncapSectionFileToFFS (\r
+ IN UINT8 Type,\r
+ IN CHAR8* InputFilePath,\r
+ IN CHAR8* OutputFilePath,\r
+ IN EFI_GUID FileGuid,\r
+ IN BOOLEAN Fixed,\r
+ IN CHAR8* SectionAlign\r
+ )\r
+{\r
+ CHAR8* SystemCommandFormatString;\r
+ CHAR8* SystemCommand;\r
+ CHAR8* GuidStr;\r
+\r
+\r
+ SystemCommandFormatString = NULL;\r
+ SystemCommand = NULL;\r
+ GuidStr = NULL;\r
+\r
+ GuidStr = LibFmmtGuidToStr(&FileGuid);\r
+\r
+ if (GuidStr == NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+\r
+ //\r
+ // -t Type\r
+ // -i InputFilePath\r
+ // -o OutPutFilePath\r
+ // -g FileGuid\r
+ // -x Fixed\r
+ // -n SectionAlign\r
+ //\r
+\r
+ if (Fixed) {\r
+ SystemCommandFormatString = "GenFfs -t %s -i \"%s\" -g %s -x -o \"%s\" -a %s";\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (mFfsFileType[Type]) +\r
+ strlen (InputFilePath) +\r
+ strlen (GuidStr) +\r
+ strlen (OutputFilePath) +\r
+ 4 +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ free (GuidStr);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "GenFfs -t %s -i \"%s\" -g %s -x -o \"%s\" -a %s",\r
+ mFfsFileType[Type], // -t\r
+ InputFilePath, // -i\r
+ GuidStr, // -g\r
+ OutputFilePath, // -o\r
+ SectionAlign\r
+ );\r
+\r
+ free (GuidStr);\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+ } else {\r
+ SystemCommandFormatString = "GenFfs -t %s -i \"%s\" -g %s -o \"%s\" -a %s";\r
+ SystemCommand = malloc (\r
+ strlen (SystemCommandFormatString) +\r
+ strlen (mFfsFileType[Type]) +\r
+ strlen (InputFilePath) +\r
+ strlen (GuidStr) +\r
+ strlen (OutputFilePath) +\r
+ 4 +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ free (GuidStr);\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ sprintf (\r
+ SystemCommand,\r
+ "GenFfs -t %s -i \"%s\" -g %s -o \"%s\" -a %s",\r
+ mFfsFileType[Type], // -t\r
+ InputFilePath, // -i\r
+ GuidStr, // -g\r
+ OutputFilePath, // -o\r
+ SectionAlign\r
+ );\r
+\r
+ free (GuidStr);\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+ }\r
+\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LibCreateNewFdCopy(\r
+ IN CHAR8* OldFd,\r
+ IN CHAR8* NewFd\r
+)\r
+{\r
+\r
+ FILE* NewFdFile;\r
+ FILE* OldFdFile;\r
+ CHAR8 *NewFdDir;\r
+ CHAR8 *OldFdDir;\r
+ UINT64 FdLength;\r
+ UINT32 Count;\r
+ BOOLEAN UseNewDirFlag;\r
+ CHAR8 *Buffer;\r
+\r
+ NewFdFile = NULL;\r
+ OldFdFile = NULL;\r
+ NewFdDir = NULL;\r
+ OldFdDir = NULL;\r
+ Count = 0;\r
+ UseNewDirFlag = FALSE;\r
+\r
+ if (OldFd == NULL ||\r
+ NewFd == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+\r
+ NewFdDir = getcwd (NULL, _MAX_PATH);\r
+\r
+ Count = strlen(NewFdDir);\r
+\r
+ if (strlen(NewFd) > Count) {\r
+\r
+ do {\r
+ if (NewFdDir[Count-1] == NewFd[Count-1]) {\r
+ Count--;\r
+ } else {\r
+ if (strlen(NewFdDir) + strlen (OS_SEP_STR) + strlen (NewFd) > _MAX_PATH -1) {\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (NewFdDir,OS_SEP_STR, _MAX_PATH - strlen (NewFdDir) -1);\r
+ strncat (NewFdDir,NewFd, _MAX_PATH - strlen (NewFdDir) -1);\r
+ UseNewDirFlag = TRUE;\r
+ break;\r
+ }\r
+\r
+ } while (Count != 1);\r
+\r
+ }else {\r
+ if (strlen(NewFdDir) + strlen (OS_SEP_STR) + strlen (NewFd) > _MAX_PATH -1) {\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (NewFdDir,OS_SEP_STR, _MAX_PATH - strlen (NewFdDir) -1);\r
+ strncat (NewFdDir,NewFd, _MAX_PATH - strlen (NewFdDir) -1);\r
+ UseNewDirFlag = TRUE;\r
+ }\r
+\r
+ if (UseNewDirFlag) {\r
+ NewFdFile = fopen (NewFdDir, "wb+");\r
+ if (NewFdFile == NULL) {\r
+ NewFdFile = fopen (NewFd, "wb+");\r
+ }\r
+ } else {\r
+ NewFdFile = fopen (NewFd, "wb+");\r
+ }\r
+ // support network path file\r
+ if (OldFd[0] == '\\' && OldFd[1] == '\\') {\r
+ OldFdFile = fopen (OldFd, "rb");\r
+ } else {\r
+ UseNewDirFlag = FALSE;\r
+\r
+ OldFdDir = getcwd (NULL, _MAX_PATH);\r
+\r
+ Count = strlen(OldFdDir);\r
+\r
+ if (strlen(OldFd) > Count) {\r
+\r
+ do {\r
+ if (OldFdDir[Count-1] == OldFd[Count-1]) {\r
+ Count--;\r
+ } else {\r
+ if (strlen(OldFdDir) + strlen (OS_SEP_STR) + strlen (OldFd) > _MAX_PATH -1) {\r
+ if (NewFdFile != NULL) {\r
+ fclose(NewFdFile);\r
+ }\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (OldFdDir,OS_SEP_STR, _MAX_PATH - strlen (OldFdDir) -1);\r
+ strncat (OldFdDir,OldFd, _MAX_PATH - strlen (OldFdDir) -1);\r
+ UseNewDirFlag = TRUE;\r
+ break;\r
+ }\r
+\r
+ } while (Count != 1);\r
+\r
+ }else {\r
+ if (strlen(OldFdDir) + strlen (OS_SEP_STR) + strlen (OldFd) > _MAX_PATH -1) {\r
+ if (NewFdFile != NULL) {\r
+ fclose(NewFdFile);\r
+ }\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (OldFdDir,OS_SEP_STR, _MAX_PATH - strlen (OldFdDir) -1);\r
+ strncat (OldFdDir,OldFd, _MAX_PATH - strlen (OldFdDir) -1);\r
+ UseNewDirFlag = TRUE;\r
+ }\r
+\r
+ if (UseNewDirFlag) {\r
+ OldFdFile = fopen (OldFdDir, "rb+");\r
+ if (OldFdFile == NULL) {\r
+ OldFdFile = fopen (OldFd, "rb+");\r
+ }\r
+ } else {\r
+ OldFdFile = fopen (OldFd, "rb+");\r
+ }\r
+ }\r
+\r
+ if (NewFdFile == NULL) {\r
+ Error ("FMMT", 0, 0003, "error Open FD file", "cannot Create a new FD file.");\r
+ if (OldFdFile != NULL) {\r
+ fclose (OldFdFile);\r
+ }\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (OldFdFile == NULL) {\r
+ Error ("FMMT", 0, 0003, "error Open FD file", "cannot Create a new FD file.");\r
+ if (NewFdFile != NULL) {\r
+ fclose (NewFdFile);\r
+ }\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+\r
+ fseek(OldFdFile,0,SEEK_SET);\r
+ fseek(OldFdFile,0,SEEK_END);\r
+\r
+ FdLength = ftell(OldFdFile);\r
+\r
+ fseek(OldFdFile,0,SEEK_SET);\r
+ fseek(NewFdFile,0,SEEK_SET);\r
+\r
+ Buffer = malloc ((size_t)FdLength);\r
+\r
+ if (Buffer == NULL) {\r
+ fclose(OldFdFile);\r
+ fclose(NewFdFile);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (fread (Buffer, 1, (size_t) FdLength, OldFdFile) != (size_t) FdLength) {\r
+ Error ("FMMT", 0, 0003, "error reading FD file %s", OldFd);\r
+ free (Buffer);\r
+ fclose(OldFdFile);\r
+ fclose(NewFdFile);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (fwrite (Buffer, 1, (size_t) FdLength, NewFdFile) != (size_t) FdLength) {\r
+ Error ("FMMT", 0, 0004, "error writing FD file", "cannot Create a new FD file.");\r
+ free (Buffer);\r
+ fclose(OldFdFile);\r
+ fclose(NewFdFile);\r
+ return EFI_ABORTED;\r
+ }\r
+ free (Buffer);\r
+ fclose(OldFdFile);\r
+ fclose (NewFdFile);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will assemble the filename, directory and extend and return the combined string.\r
+ Like FileName = file1, Dir = c:\temp extend = txt, the output string will be:\r
+ c:\temp\file1.txt.\r
+\r
+ @param[in]\r
+ @param[in]\r
+ @param[in]\r
+\r
+ @retrun A string contain all the input information.\r
+\r
+**/\r
+CHAR8 *\r
+LibFilenameStrExtended (\r
+ IN CHAR8 *FileName,\r
+ IN CHAR8 *Dir,\r
+ IN CHAR8 *Extend\r
+)\r
+{\r
+ CHAR8 *RetStr;\r
+\r
+ RetStr = NULL;\r
+\r
+ if (FileName == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ if (Dir == NULL || Extend == NULL) {\r
+ return FileName;\r
+ }\r
+\r
+ RetStr = (CHAR8 *) malloc (strlen (FileName) +\r
+ strlen (Dir) +\r
+ strlen (Extend) +\r
+ strlen ("%s%s.%s") +\r
+ 1);\r
+ if (RetStr == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return NULL;\r
+ }\r
+\r
+ memset (RetStr, '\0', (strlen (FileName) + strlen (Dir) + strlen (Extend) + strlen ("%s%s.%s") + 1));\r
+\r
+ sprintf (RetStr, "%s%s.%s", Dir, FileName, Extend);\r
+\r
+ return RetStr;\r
+}\r
+\r
+/**\r
+ Delete a directory and files in it.\r
+\r
+ @param[in] DirName Name of the directory need to be deleted.\r
+\r
+ @return EFI_INVALID_PARAMETER\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+LibRmDir (\r
+ IN CHAR8* DirName\r
+)\r
+{\r
+ CHAR8* SystemCommand;\r
+\r
+ SystemCommand = NULL;\r
+\r
+\r
+ if (DirName == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (access (DirName, 0) == -1){\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Delete a directory and files in it.\r
+ //\r
+\r
+ SystemCommand = malloc (\r
+ strlen (RMDIR_STR) +\r
+ strlen (DirName) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ sprintf (\r
+ SystemCommand,\r
+ RMDIR_STR,\r
+ DirName\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LibGenExtFile(\r
+CONST EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtPtr,\r
+FILE *InfFile\r
+)\r
+{\r
+ CHAR8 *TempDir;\r
+ FILE *ExtFile;\r
+ CHAR8 OutputExtFile[_MAX_PATH];\r
+ CHAR8 Line[512];\r
+ size_t Len;\r
+\r
+ TempDir = NULL;\r
+\r
+ TempDir = getcwd(NULL, _MAX_PATH);\r
+ if (strlen (TempDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (TempDir, OS_SEP_STR, _MAX_PATH - strlen (TempDir) -1);\r
+ strncat (TempDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TempDir) -1);\r
+\r
+ mkdir(TempDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
+\r
+ sprintf(\r
+ Line,\r
+ "%c%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X%d.ext",\r
+ OS_SEP,\r
+ (unsigned)ExtPtr->FvName.Data1,\r
+ ExtPtr->FvName.Data2,\r
+ ExtPtr->FvName.Data3,\r
+ ExtPtr->FvName.Data4[0],\r
+ ExtPtr->FvName.Data4[1],\r
+ ExtPtr->FvName.Data4[2],\r
+ ExtPtr->FvName.Data4[3],\r
+ ExtPtr->FvName.Data4[4],\r
+ ExtPtr->FvName.Data4[5],\r
+ ExtPtr->FvName.Data4[6],\r
+ ExtPtr->FvName.Data4[7],\r
+ ExtPtr->ExtHeaderSize\r
+ );\r
+ if (strlen (TempDir) + strlen (Line) > _MAX_PATH - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncpy (OutputExtFile, TempDir, _MAX_PATH - 1);\r
+ OutputExtFile[_MAX_PATH - 1] = 0;\r
+ strncat (OutputExtFile, Line, _MAX_PATH - strlen (OutputExtFile) - 1);\r
+\r
+\r
+ ExtFile = fopen(OutputExtFile, "wb+");\r
+ if (ExtFile == NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (fwrite(ExtPtr, 1, ExtPtr->ExtHeaderSize, ExtFile) != ExtPtr->ExtHeaderSize) {\r
+ fclose(ExtFile);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ fclose(ExtFile);\r
+\r
+ strcpy (Line, "EFI_FV_EXT_HEADER_FILE_NAME = ");\r
+ if (strlen (Line) + strlen (OutputExtFile) + 1 > sizeof(Line) / sizeof (CHAR8) - 1) {\r
+ Error("FMMT", 0, 1001, "The directory is too long.", "");\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (Line, OutputExtFile, sizeof(Line) / sizeof (CHAR8) - strlen (Line) - 1);\r
+ strncat (Line, "\n", sizeof(Line) / sizeof (CHAR8) - strlen (Line) - 1);\r
+ Len = strlen(Line);\r
+ if (fwrite(Line, 1, Len, InfFile) != Len) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Delete a file.\r
+\r
+ @param[in] FileName Name of the file need to be deleted.\r
+\r
+ @return EFI_INVALID_PARAMETER\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+LibFmmtDeleteFile(\r
+ IN CHAR8 *FileName\r
+)\r
+{\r
+ CHAR8* SystemCommand;\r
+ CHAR8 *TemDir;\r
+\r
+ SystemCommand = NULL;\r
+ TemDir = NULL;\r
+\r
+\r
+ if (FileName == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // if the FileName is not in TemDir, we don't need to delete.\r
+ TemDir = getcwd (NULL, _MAX_PATH);\r
+ if (*(TemDir + strlen(TemDir) - 1) == OS_SEP) {\r
+ *(TemDir + strlen(TemDir) - 1) = '\0';\r
+ }\r
+ if (strlen (TemDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
+ Error (NULL, 0, 2000, "Path: The current path is too long.", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1);\r
+ strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1);\r
+ if (strstr(FileName, TemDir) == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Delete a file\r
+ //\r
+\r
+ SystemCommand = malloc (\r
+ strlen (DEL_STR) +\r
+ strlen (FileName) +\r
+ 1\r
+ );\r
+ if (SystemCommand == NULL) {\r
+ Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ sprintf (\r
+ SystemCommand,\r
+ DEL_STR,\r
+ FileName\r
+ );\r
+\r
+ if (system (SystemCommand) != EFI_SUCCESS) {\r
+ free(SystemCommand);\r
+ return EFI_ABORTED;\r
+ }\r
+ free(SystemCommand);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+\r
+ Free the whole Fd data structure.\r
+\r
+ @param[in] Fd The pointer point to the Fd data structure.\r
+\r
+**/\r
+VOID\r
+LibFmmtFreeFd (\r
+ FIRMWARE_DEVICE *Fd\r
+ )\r
+{\r
+ FV_INFORMATION *CurrentFv;\r
+ FV_INFORMATION *TempFv;\r
+ ENCAP_INFO_DATA *EncapData1;\r
+ ENCAP_INFO_DATA *EncapData2;\r
+\r
+ CurrentFv = NULL;\r
+ TempFv = NULL;\r
+ EncapData1 = NULL;\r
+ EncapData2 = NULL;\r
+\r
+ if (Fd == NULL) {\r
+ return;\r
+ }\r
+\r
+ CurrentFv = Fd->Fv;\r
+\r
+ do {\r
+ TempFv = CurrentFv;\r
+ CurrentFv = CurrentFv->FvNext;\r
+\r
+ free (TempFv->FvHeader);\r
+\r
+ if (TempFv->FvExtHeader != NULL) {\r
+ free (TempFv->FvExtHeader);\r
+ }\r
+ if (TempFv->FvUiName) {\r
+ free(TempFv->FvUiName);\r
+ }\r
+\r
+ //\r
+ // Free encapsulate data;\r
+ //\r
+ EncapData1 = TempFv->EncapData;\r
+\r
+ while (EncapData1 != NULL) {\r
+\r
+ EncapData2 = EncapData1;\r
+ EncapData1 = EncapData1->NextNode;\r
+\r
+ if (EncapData2->Data != NULL) {\r
+ free (EncapData2->Data);\r
+ }\r
+ if (EncapData2->FvExtHeader != NULL) {\r
+ free(EncapData2->FvExtHeader);\r
+ }\r
+ free (EncapData2);\r
+ EncapData2 = NULL;\r
+ }\r
+\r
+ EncapData1 = NULL;\r
+\r
+ free (TempFv);\r
+ TempFv = NULL;\r
+\r
+ } while (CurrentFv != NULL);\r
+\r
+ CurrentFv = NULL;\r
+ free (Fd);\r
+ Fd = NULL;\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Generate the compressed section with specific type.\r
+ Type could be EFI_STANDARD_COMPRESSION or EFI_NOT_COMPRESSED\r
+\r
+ @param[in] InputFileName File name of the raw data.\r
+ @param[in] OutPutFileName File name of the sectioned data.\r
+ @param[in] CompressionType The compression type.\r
+\r
+ @return EFI_INVALID_PARAMETER\r
+ @return EFI_ABORTED\r
+ @return EFI_OUT_OF_RESOURCES\r
+ @return EFI_SUCCESS\r
+\r
+**/\r
+EFI_STATUS\r
+LibGenCompressedSection (\r
+ CHAR8 *InputFileName,\r
+ CHAR8 *OutPutFileName,\r
+ UINT8 CompressionType\r
+)\r
+{\r
+ //FILE *UnCompressFile;\r
+ //FILE *CompressedFile;\r
+ //VOID *UnCompressedBuffer;\r
+ //VOID *CompressedBuffer;\r
+ //UINT32 UnCompressedSize;\r
+ //UINT32 CompressedSize;\r
+ //CHAR8 *TempName;\r
+ //CHAR8 *TemDir;\r
+ //EFI_STATUS Status;\r
+\r
+ //UnCompressFile = NULL;\r
+ //CompressedFile = NULL;\r
+ //UnCompressedBuffer = NULL;\r
+ //CompressedBuffer = NULL;\r
+ //TempName = NULL;\r
+ //TemDir = NULL;\r
+ //UnCompressedSize = 0;\r
+ //CompressedSize = 0;\r
+\r
+ if ( InputFileName == NULL ||\r
+ OutPutFileName == NULL) {\r
+ printf ("Error while generate compressed section!\n");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
+ /*\r
+\r
+ UnCompressFile = fopen (InputFileName, "rb");\r
+ if (UnCompressFile == NULL) {\r
+ printf ("Error while open file %s \n", InputFileName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ TemDir = _getcwd (NULL, _MAX_PATH);\r
+ sprintf(TemDir, "%s\\%s", TemDir, TEMP_DIR_NAME);\r
+\r
+ TempName= LibFilenameStrExtended (strrchr(CloneString (tmpnam (NULL)),'\\'), TemDir, "comp");\r
+\r
+ CompressedFile = fopen (TempName, "wb+");\r
+ if (CompressedFile == NULL) {\r
+ printf ("Error while open file %s \n", TempName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Get the original file size;\r
+ //\r
+ fseek(UnCompressFile,0,SEEK_SET);\r
+ fseek(UnCompressFile,0,SEEK_END);\r
+\r
+ UnCompressedSize = ftell(UnCompressFile);\r
+\r
+ fseek(UnCompressFile,0,SEEK_SET);\r
+\r
+ UnCompressedBuffer = malloc (UnCompressedSize);\r
+\r
+ if (UnCompressedBuffer == NULL) {\r
+ printf("Error while allocate memory! \n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CompressedBuffer = malloc (UnCompressedSize);\r
+\r
+ if (CompressedBuffer == NULL) {\r
+ printf("Error while allocate memory! \n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (fread (UnCompressedBuffer, 1, (size_t) UnCompressedSize, UnCompressFile) == (size_t) UnCompressedSize) {\r
+ CompressedSize = UnCompressedSize;\r
+\r
+ Status = EfiCompress ( UnCompressedBuffer,\r
+ UnCompressedSize,\r
+ CompressedBuffer,\r
+ &CompressedSize);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ printf("Error while do compress operation! \n");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (CompressedSize > UnCompressedSize) {\r
+ printf("Error while do compress operation! \n");\r
+ return EFI_ABORTED;\r
+ }\r
+ } else {\r
+ printf("Error while reading file %s! \n", InputFileName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Write the compressed data into output file\r
+ //\r
+ if (fwrite (CompressedBuffer, 1, (size_t) CompressedSize, CompressedFile) != (size_t) CompressedSize) {\r
+ Error ("FMMT", 0, 0004, "error writing %s file", OutPutFileName);\r
+ fclose(UnCompressFile);\r
+ fclose (CompressedFile);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ fclose(UnCompressFile);\r
+ fclose (CompressedFile);\r
+ */\r
+\r
+ //\r
+ // Call GenSec tool to generate the compressed section.\r
+ //\r
+ LibCreateFfsSection(NULL, InputFileName, NULL, EFI_SECTION_COMPRESSION, OutPutFileName, NULL, NULL, NULL, 0, 0, "PI_STD");\r
+\r
+ } else if (CompressionType == EFI_NOT_COMPRESSED) {\r
+\r
+ LibCreateFfsSection(NULL, InputFileName, NULL, EFI_SECTION_COMPRESSION, OutPutFileName, NULL, NULL, NULL, 0, 0, "PI_NONE");\r
+\r
+ } else {\r
+ printf ("Error while generate compressed section, unknown compression type! \n");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LibEncapNewFvFile(\r
+ IN FV_INFORMATION *FvInFd,\r
+ IN CHAR8 *TemDir,\r
+ IN ENCAP_INFO_DATA *CurrentEncapData,\r
+ IN UINT32 Level_Break,\r
+ OUT FFS_INFORMATION **OutputFile\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 ParentType;\r
+ UINT8 ParentLevel;\r
+ UINT32 Type;\r
+ UINT8 Level;\r
+ CHAR8 *InfFileName;\r
+ FILE *InfFile;\r
+ ENCAP_INFO_DATA *LocalEncapData;\r
+ ENCAP_INFO_DATA *LocalEncapDataTemp;\r
+ ENCAP_INFO_DATA *LocalEncapDataNext;\r
+ BOOLEAN FfsFoundFlag;\r
+ UINT32 Index;\r
+ UINT32 OuterIndex;\r
+ CHAR8 *ExtractionTool;\r
+ BOOLEAN IsLastLevelFfs;\r
+ BOOLEAN IsLeafFlagIgnore;\r
+ BOOLEAN FirstInFlag;\r
+ BOOLEAN OutputFileNameListFlag;\r
+ CHAR8 *InputFileName;\r
+ CHAR8 *OutputFileName;\r
+ FFS_INFORMATION *OutputFileNameList;\r
+ FFS_INFORMATION *ChildFileNameList;\r
+ FFS_INFORMATION *NewFileNameList;\r
+ CHAR8 *FvGuidName;\r
+ UINT16 GuidAttributes;\r
+ UINT16 GuidDataOffset;\r
+ BOOLEAN IsRootFv;\r
+ BOOLEAN IsLargeFile;\r
+ UINT32 EncapFvStart;\r
+ UINT32 EncapFvIndex;\r
+ CHAR8 *TmpFileName;\r
+ FILE *TmpFile;\r
+ FILE *InputFile;\r
+ FILE *OutFile;\r
+ UINT32 InputFileSize;\r
+ UINT32 OutputFileSize;\r
+ UINT32 LargeFileSize;\r
+ UINT8 *Buffer = NULL;\r
+ UINT8 SectionHeader[4] = { 0x00, 0x00, 0x00, 0x00 };\r
+ UINT32 Id;\r
+ UINT32 SubFvId;\r
+ UINT32 header;\r
+ UINT8 AlignN;\r
+ UINT8 AlignV[1] = {0xFF};\r
+ AlignN = 0;\r
+ Id = 0;\r
+ InputFileSize = 0;\r
+ EncapFvIndex = 0;\r
+ Index = 0;\r
+ OuterIndex = 0;\r
+ ParentType = 0;\r
+ ParentLevel = 0;\r
+ Type = 0;\r
+ Level = 0;\r
+ SubFvId = 0;\r
+ FfsFoundFlag = FALSE;\r
+ LocalEncapDataTemp = NULL;\r
+ LocalEncapDataNext = NULL;\r
+ ExtractionTool = NULL;\r
+ InputFileName = NULL;\r
+ OutputFileName = NULL;\r
+ IsLastLevelFfs = TRUE;\r
+ IsLeafFlagIgnore = FALSE;\r
+ FirstInFlag = TRUE;\r
+ FvGuidName = NULL;\r
+ OutputFileNameListFlag = TRUE;\r
+ IsLargeFile = FALSE;\r
+ OutputFileSize = 0;\r
+ LargeFileSize = 0x1000000;\r
+\r
+\r
+ OutputFileNameList = (FFS_INFORMATION *)malloc(sizeof(FV_INFORMATION));\r
+ if (OutputFileNameList == NULL) {\r
+ Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ OutputFileNameList->FFSName = NULL;\r
+ OutputFileNameList->InFvId = 0;\r
+ OutputFileNameList->IsFFS = FALSE;\r
+ OutputFileNameList->ParentLevel = 0;\r
+ OutputFileNameList->Next = NULL;\r
+ OutputFileNameList->UiNameSize = 0;\r
+ OutputFileNameList->Depex = NULL;\r
+ OutputFileNameList->DepexLen = 0;\r
+ OutputFileNameList->FfsFoundFlag = FALSE;\r
+\r
+ ChildFileNameList = (FFS_INFORMATION *)malloc(sizeof(FV_INFORMATION));\r
+ if (ChildFileNameList == NULL) {\r
+ Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ ChildFileNameList->FFSName = NULL;\r
+ ChildFileNameList->InFvId = 0;\r
+ ChildFileNameList->ParentLevel = 0;\r
+ ChildFileNameList->Next = NULL;\r
+ ChildFileNameList->IsFFS = FALSE;\r
+ ChildFileNameList->UiNameSize = 0;\r
+ ChildFileNameList->Depex = NULL;\r
+ ChildFileNameList->DepexLen = 0;\r
+ ChildFileNameList->FfsFoundFlag = FALSE;\r
+ //\r
+ // Encapsulate from the lowest FFS file level.\r
+ //\r
+ LocalEncapData = CurrentEncapData;\r
+ if (LocalEncapData == NULL) {\r
+ LocalEncapData = FvInFd->EncapData;\r
+ }\r
+ Level = LocalEncapData->Level;\r
+ Type = LocalEncapData->Type;\r
+\r
+ if (CurrentEncapData == NULL) {\r
+ LocalEncapData = FvInFd->EncapData;\r
+ while (LocalEncapData != NULL) {\r
+ if (LocalEncapData->Type == FMMT_ENCAP_TREE_FFS) {\r
+ LocalEncapDataTemp = LocalEncapData->RightNode;\r
+ while (LocalEncapDataTemp != NULL) {\r
+ LocalEncapDataNext = LocalEncapDataTemp->NextNode;\r
+ if (LocalEncapDataNext != NULL && LocalEncapDataNext->NextNode != NULL) {\r
+\r
+ LibEncapNewFvFile(FvInFd, TemDir, LocalEncapDataTemp, 1, &ChildFileNameList);\r
+ ChildFileNameList->ParentLevel = LocalEncapDataTemp->Level -1;\r
+ if (FvInFd->ChildFvFFS == NULL) {\r
+ FvInFd->ChildFvFFS = ChildFileNameList;\r
+ } else {\r
+ NewFileNameList = FvInFd->ChildFvFFS;\r
+ while (NewFileNameList->Next != NULL) {\r
+ NewFileNameList = NewFileNameList->Next;\r
+ }\r
+ NewFileNameList->Next = ChildFileNameList;\r
+ }\r
+ }\r
+ LocalEncapDataTemp = LocalEncapDataTemp->RightNode;\r
+ }\r
+ }\r
+\r
+ if (LocalEncapData->Level > Level) {\r
+ if (LocalEncapData->Type == FMMT_ENCAP_TREE_FFS) {\r
+ ParentLevel = Level;\r
+ ParentType = Type;\r
+ }\r
+ Level = LocalEncapData->Level;\r
+ Type = LocalEncapData->Type;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+ } else {\r
+ LocalEncapData = CurrentEncapData;\r
+ while (LocalEncapData != NULL) {\r
+ if (LocalEncapData->Level > Level) {\r
+ if (LocalEncapData->Type == FMMT_ENCAP_TREE_FFS) {\r
+ ParentLevel = Level;\r
+ ParentType = Type;\r
+ }\r
+ Level = LocalEncapData->Level;\r
+ Type = LocalEncapData->Type;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+ }\r
+\r
+ do {\r
+ switch (ParentType) {\r
+ case FMMT_ENCAP_TREE_FV:\r
+ OutputFileNameListFlag = TRUE;\r
+ EncapFvStart = 0;\r
+ for(OuterIndex=0;OutputFileNameListFlag;OuterIndex++){\r
+ //\r
+ // Generate FV.inf attributes.\r
+ //\r
+ InfFileName = LibFilenameStrExtended (strrchr(GenTempFile (),OS_SEP), TemDir, "inf");\r
+ FirstInFlag = TRUE;\r
+\r
+ InfFile = fopen (InfFileName, "wt+");\r
+\r
+ if (InfFile == NULL) {\r
+ Error ("FMMT", 0, 0004, "Could not open inf file %s to store FV information! \n", "");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (CurrentEncapData == NULL) {\r
+ LocalEncapData = FvInFd->EncapData;\r
+ } else {\r
+ LocalEncapData = CurrentEncapData;\r
+ }\r
+\r
+ while (LocalEncapData->NextNode != NULL) {\r
+ if (LocalEncapData->Level == ParentLevel) {\r
+ break;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+\r
+ if (((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset != 0) {\r
+ //\r
+ // FV GUID Name memory allocation\r
+ //\r
+ FvGuidName = (CHAR8 *) malloc (255);\r
+\r
+ if (FvGuidName == NULL) {\r
+ Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");\r
+ fclose (InfFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ memset(FvGuidName, '\0', 255);\r
+\r
+ sprintf(\r
+ FvGuidName,\r
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",\r
+ LocalEncapData->FvExtHeader->FvName.Data1,\r
+ LocalEncapData->FvExtHeader->FvName.Data2,\r
+ LocalEncapData->FvExtHeader->FvName.Data3,\r
+ LocalEncapData->FvExtHeader->FvName.Data4[0],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[1],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[2],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[3],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[4],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[5],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[6],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[7]\r
+ );\r
+\r
+ } else {\r
+ FvGuidName = NULL;\r
+ }\r
+\r
+\r
+ if (ParentLevel == 1) {\r
+ Status = LibFvHeaderOptionToStr((EFI_FIRMWARE_VOLUME_HEADER *)LocalEncapData->Data, InfFile, TRUE);\r
+ } else {\r
+ Status = LibFvHeaderOptionToStr((EFI_FIRMWARE_VOLUME_HEADER *)LocalEncapData->Data, InfFile, FALSE);\r
+ }\r
+\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "generate FV INF file [Options] section failed.");\r
+ fclose (InfFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+\r
+ Status = LibFvHeaderAttributeToStr(((EFI_FIRMWARE_VOLUME_HEADER *)LocalEncapData->Data)->Attributes, InfFile);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV header attribute failed");\r
+ fclose (InfFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ if (LocalEncapData->FvExtHeader != NULL) {\r
+ Status = LibGenExtFile(LocalEncapData->FvExtHeader, InfFile);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV EXT header failed");\r
+ fclose (InfFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ FvGuidName = NULL;\r
+ }\r
+\r
+ if (CurrentEncapData != NULL) {\r
+ for (Index = 0; Index <= FvInFd->FfsNumbers; Index++) {\r
+ if ((memcmp(&FvInFd->FfsAttuibutes[Index].GuidName, &(CurrentEncapData->FvExtHeader->FvName), sizeof(EFI_GUID)) == 0)) {\r
+ SubFvId = Index;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Found FFSs from Fv structure.\r
+ //\r
+ FfsFoundFlag = FALSE;\r
+ IsRootFv = FALSE;\r
+ for (Index=0; Index <= FvInFd->FfsNumbers; Index++) {\r
+ if (OutputFileNameList != NULL && OutputFileNameList->FFSName != NULL && OutputFileNameList->IsFFS == FALSE){\r
+ break;\r
+ }\r
+ if (OutputFileNameList != NULL && OutputFileNameList->FFSName != NULL && OutputFileNameList->IsFFS == TRUE){\r
+ if (Index == EncapFvIndex) {\r
+ if (FirstInFlag) {\r
+ Status = LibAddFfsFileToFvInf (OutputFileNameList->FFSName, InfFile, TRUE);\r
+ FirstInFlag = FALSE;\r
+ } else {\r
+ Status = LibAddFfsFileToFvInf (OutputFileNameList->FFSName, InfFile, FALSE);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");\r
+ fclose (InfFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+\r
+ NewFileNameList = FvInFd->ChildFvFFS;\r
+ while (NewFileNameList != NULL && NewFileNameList -> FFSName != NULL) {\r
+ if (NewFileNameList -> ParentLevel == ParentLevel && Index == NewFileNameList->InFvId && NewFileNameList->FfsFoundFlag==TRUE) {\r
+ if (FirstInFlag) {\r
+ Status = LibAddFfsFileToFvInf (NewFileNameList->FFSName, InfFile, TRUE);\r
+ FirstInFlag = FALSE;\r
+ } else {\r
+ Status = LibAddFfsFileToFvInf (NewFileNameList->FFSName, InfFile, FALSE);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");\r
+ fclose (InfFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ }\r
+ NewFileNameList = NewFileNameList->Next;\r
+ }\r
+\r
+ if (FvInFd->FfsAttuibutes[Index].IsHandle==TRUE) {\r
+ continue;\r
+ }\r
+ if (SubFvId > 0 && Index < SubFvId) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // For the last level FFS, the level below FFSs we should not care the IsLeaf Flag.\r
+ //\r
+ if (IsLastLevelFfs) {\r
+ IsLeafFlagIgnore = TRUE;\r
+ } else {\r
+ IsLeafFlagIgnore = FvInFd->FfsAttuibutes[Index].IsLeaf;\r
+ }\r
+\r
+ if (FvInFd->FfsAttuibutes[Index].Level >= ParentLevel + 1 && IsLeafFlagIgnore) {\r
+ if (FirstInFlag) {\r
+ if (FvInFd->FfsAttuibutes[Index].Level < 0xFF) {\r
+ FfsFoundFlag = TRUE;\r
+ Status = LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Index].FfsName, InfFile, TRUE);\r
+ FirstInFlag = FALSE;\r
+ FvInFd->FfsAttuibutes[Index].IsHandle=TRUE;\r
+ EncapFvStart = Index;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");\r
+ fclose (InfFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ if (Index == 0) {\r
+ // Root FV need to include all FFS files.\r
+ IsRootFv = TRUE;\r
+ }\r
+ } else {\r
+ if (FvInFd->FfsAttuibutes[Index].Level < 0xFF) {\r
+ FfsFoundFlag = TRUE;\r
+ Status = LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Index].FfsName, InfFile, FALSE);\r
+ FvInFd->FfsAttuibutes[Index].IsHandle=TRUE;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");\r
+ fclose (InfFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ if (Index == 0) {\r
+ // Root FV need to include all FFS files.\r
+ IsRootFv = TRUE;\r
+ }\r
+ }\r
+\r
+\r
+ //avoid a FV contain too many ffs files\r
+ if ((!IsRootFv) && (FvInFd->FfsAttuibutes[Index].FvLevel <= FvInFd->MulFvLevel) && (FvInFd->FfsAttuibutes[Index+1].FvLevel <= FvInFd->MulFvLevel) &&\r
+ (FvInFd->FfsAttuibutes[Index].FvLevel != FvInFd->FfsAttuibutes[Index+1].FvLevel) && (ParentLevel != 1) && (FvInFd->FfsAttuibutes[Index].Level != FvInFd->FfsAttuibutes[Index+1].Level) &&\r
+ FvInFd->FfsAttuibutes[Index].Level != 0xFF && FvInFd->FfsAttuibutes[Index+1].Level != 0xFF && FvInFd->FfsAttuibutes[Index+1].Level != 0x0){\r
+ FvInFd->FfsAttuibutes[Index].Level = 0;\r
+ break;\r
+ }else{\r
+ if (FvInFd->FfsAttuibutes[Index].Level != 0xFF){\r
+ FvInFd->FfsAttuibutes[Index].Level = 0;\r
+ }\r
+ }\r
+\r
+ }\r
+ }\r
+ // The Fv may has multiple level (> 2), when it is in the FvLevel == 2, we set the IsLastLevelFfs Flag\r
+ if (Index <=FvInFd->FfsNumbers && FvInFd->FfsAttuibutes[Index].FvLevel <= FvInFd->MulFvLevel) {\r
+ if (FvInFd->FfsAttuibutes[Index].FvLevel == 2) {\r
+ IsLastLevelFfs = FALSE;\r
+ }\r
+ }\r
+ if (!FfsFoundFlag){\r
+ OutputFileNameListFlag = FALSE;\r
+ if (OuterIndex > 0){\r
+ fclose (InfFile);\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Create FV\r
+ //\r
+ fclose (InfFile);\r
+\r
+ EncapFvIndex = EncapFvStart;\r
+\r
+ OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "FV");\r
+\r
+ Status = LibEncapsulateFfsToFv (InfFileName, NULL, OutputFileName, FvGuidName, IsLargeFile);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+\r
+ OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);\r
+ if (OutputFileNameList->FFSName == NULL) {\r
+ Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);\r
+ if (CurrentEncapData != NULL) {\r
+ OutputFileNameList->InFvId = EncapFvIndex;\r
+ if (EncapFvIndex > 0) {\r
+ memcpy(OutputFileNameList->UiName,FvInFd->FfsAttuibutes[EncapFvIndex - 1].UiName, FvInFd->FfsAttuibutes[EncapFvIndex - 1].UiNameSize);\r
+ OutputFileNameList->UiNameSize = FvInFd->FfsAttuibutes[EncapFvIndex - 1].UiNameSize;\r
+ OutputFileNameList->Depex = FvInFd->FfsAttuibutes[EncapFvIndex - 1].Depex;\r
+ OutputFileNameList->DepexLen = FvInFd->FfsAttuibutes[EncapFvIndex - 1].DepexLen;\r
+ OutputFileNameList->FfsFoundFlag = FfsFoundFlag;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case FMMT_ENCAP_TREE_FFS:\r
+\r
+ while(OutputFileNameList!= NULL && OutputFileNameList->FFSName != NULL){\r
+ InputFileName = OutputFileNameList->FFSName;\r
+ OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "ffs");\r
+ LocalEncapData = CurrentEncapData;\r
+ if (LocalEncapData == NULL) {\r
+ LocalEncapData = FvInFd->EncapData;\r
+ }\r
+ while (LocalEncapData->NextNode != NULL) {\r
+ if (LocalEncapData->Level == ParentLevel) {\r
+ for(;LocalEncapData->NextNode != NULL;) {\r
+ if(LocalEncapData->FvExtHeader != NULL) {\r
+ break;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+ break;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+\r
+ if (LocalEncapData->FvExtHeader == NULL) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FFS file failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (OutputFileNameList->UiNameSize > 0) {\r
+ TmpFileName = LibFilenameStrExtended(strrchr(GenTempFile (), OS_SEP), TemDir, "tmp");\r
+ TmpFile = fopen(TmpFileName, "wb+");\r
+ if (TmpFile == NULL) {\r
+ Error("FMMT", 0, 0004, "Could not open tmp file %s to store UI section information! \n", "");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+ header = (OutputFileNameList->UiNameSize+4) | (EFI_SECTION_USER_INTERFACE << 24);\r
+ Index = 0;\r
+ while (header) {\r
+ SectionHeader[Index] = header % 0x100;\r
+ header /= 0x100;\r
+ Index ++;\r
+ }\r
+ InputFile = fopen(InputFileName, "rb+");\r
+ if (InputFile == NULL) {\r
+ Error("FMMT", 0, 0004, "Could not open input file %s! \n", "");\r
+ fclose(TmpFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+ fseek(InputFile, 0, SEEK_SET);\r
+ fseek(InputFile, 0, SEEK_END);\r
+ InputFileSize = ftell(InputFile);\r
+ fseek(InputFile, 0, SEEK_SET);\r
+\r
+ Buffer = malloc(InputFileSize+OutputFileNameList->UiNameSize+4);\r
+ memcpy(Buffer, (CHAR16 *)SectionHeader, 4);\r
+ memcpy(Buffer + 4, (CHAR16 *)(OutputFileNameList->UiName), OutputFileNameList->UiNameSize);\r
+ if (fread(Buffer+4+OutputFileNameList->UiNameSize, 1, InputFileSize, InputFile) != InputFileSize) {\r
+ Error("FMMT", 0, 0004, "Could not open sec file %s to add UI section information! \n", "");\r
+ fclose(TmpFile);\r
+ fclose(InputFile);\r
+ free(Buffer);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+ fwrite(Buffer, 1, InputFileSize + OutputFileNameList->UiNameSize + 4, TmpFile);\r
+ free(Buffer);\r
+ fclose(TmpFile);\r
+ fclose(InputFile);\r
+ InputFileName = TmpFileName;\r
+ }\r
+ if (OutputFileNameList->DepexLen > 0) {\r
+ TmpFileName = LibFilenameStrExtended(strrchr(GenTempFile (), OS_SEP), TemDir, "tmp");\r
+ TmpFile = fopen(TmpFileName, "wb+");\r
+ if (TmpFile == NULL) {\r
+ Error("FMMT", 0, 0004, "Could not open tmp file %s to store Depex section information! \n", "");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+ InputFile = fopen(InputFileName, "rb+");\r
+ if (InputFile == NULL) {\r
+ Error("FMMT", 0, 0004, "Could not open input file %s! \n", "");\r
+ fclose(TmpFile);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+ fseek(InputFile, 0, SEEK_SET);\r
+ fseek(InputFile, 0, SEEK_END);\r
+ InputFileSize = ftell(InputFile);\r
+ fseek(InputFile, 0, SEEK_SET);\r
+ // make sure the section is 4 byte align\r
+ if (OutputFileNameList->DepexLen % 4 != 0) {\r
+ AlignN = 4 - OutputFileNameList->DepexLen % 4;\r
+ }\r
+ Buffer = malloc(InputFileSize + OutputFileNameList->DepexLen + AlignN);\r
+ memcpy(Buffer, OutputFileNameList->Depex, OutputFileNameList->DepexLen);\r
+ if (AlignN != 0) {\r
+ for (Index = 0; Index < AlignN; Index ++) {\r
+ memcpy(Buffer + OutputFileNameList->DepexLen + Index, AlignV, 1);\r
+ }\r
+ }\r
+ if (fread(Buffer + OutputFileNameList->DepexLen + AlignN, 1, InputFileSize, InputFile) != InputFileSize) {\r
+ Error("FMMT", 0, 0004, "Could not open sec file %s to add Depex section information! \n", "");\r
+ fclose(TmpFile);\r
+ fclose(InputFile);\r
+ free(Buffer);\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+ fwrite(Buffer, 1, InputFileSize + OutputFileNameList->DepexLen + AlignN, TmpFile);\r
+ free(Buffer);\r
+ fclose(TmpFile);\r
+ fclose(InputFile);\r
+ InputFileName = TmpFileName;\r
+ }\r
+ for (Id = FvInFd->FfsNumbers; Id <= FvInFd->FfsNumbers; Id--) {\r
+ if ((memcmp(&FvInFd->FfsAttuibutes[Id].GuidName, &(LocalEncapData->FvExtHeader->FvName), sizeof(EFI_GUID)) == 0)){\r
+ if (access(FvInFd->FfsAttuibutes[Id].FfsName, 0) != -1) {\r
+ Status = LibFmmtDeleteFile(FvInFd->FfsAttuibutes[Id].FfsName);\r
+ if (EFI_ERROR(Status)) {\r
+ Error("FMMT", 0, 0004, "error while encapsulate FD Image", "Delete the specified file failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ memset(FvInFd->FfsAttuibutes[Id].FfsName, '\0', _MAX_PATH);\r
+ FvInFd->FfsAttuibutes[Id].Level = 0xFF;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (LocalEncapData->NextNode != NULL) {\r
+ LocalEncapDataTemp = LocalEncapData->NextNode;\r
+ if ((LocalEncapDataTemp->Type == FMMT_ENCAP_TREE_GUIDED_SECTION) || (LocalEncapDataTemp->Type == FMMT_ENCAP_TREE_COMPRESS_SECTION)) {\r
+ Status = LibEncapSectionFileToFFS(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, InputFileName, OutputFileName, LocalEncapData->FvExtHeader->FvName, FALSE, "1");\r
+ }\r
+ else{\r
+ Status = LibEncapSectionFileToFFS(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, InputFileName, OutputFileName, LocalEncapData->FvExtHeader->FvName, FALSE, FvInFd->AlignmentStr);\r
+ }\r
+ }\r
+ else{\r
+ Status = LibEncapSectionFileToFFS(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, InputFileName, OutputFileName, LocalEncapData->FvExtHeader->FvName, FALSE, FvInFd->AlignmentStr);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FFS file failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ free(LocalEncapData->FvExtHeader);\r
+ LocalEncapData->FvExtHeader = NULL;\r
+ OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);\r
+ if (OutputFileNameList->FFSName == NULL) {\r
+ Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);\r
+ OutputFileNameList->IsFFS = TRUE;\r
+ if (OutputFileNameList->Next == NULL){\r
+ break;\r
+ }\r
+ OutputFileNameList = OutputFileNameList->Next;\r
+ }\r
+ break;\r
+ case FMMT_ENCAP_TREE_GUIDED_SECTION:\r
+ while(OutputFileNameList!= NULL && OutputFileNameList->FFSName != NULL){\r
+ //\r
+ // Create the guided section original data, do compress operation.\r
+ //\r
+ InputFileName = OutputFileNameList->FFSName;\r
+ OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "compressed");\r
+\r
+ //\r
+ // Use the guided section header guid to find out compress application name.\r
+ //\r
+ LocalEncapData = CurrentEncapData;\r
+ if (LocalEncapData == NULL) {\r
+ LocalEncapData = FvInFd->EncapData;\r
+ }\r
+ while (LocalEncapData->NextNode != NULL) {\r
+ if (LocalEncapData->Level == ParentLevel) {\r
+ break;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+\r
+ ExtractionTool =\r
+ LookupGuidedSectionToolPath (\r
+ mParsedGuidedSectionTools,\r
+ (EFI_GUID *)LocalEncapData->Data\r
+ );\r
+ GuidDataOffset = *(UINT16 *) ((UINT8 *) LocalEncapData->Data + sizeof (EFI_GUID));\r
+ GuidAttributes = *(UINT16 *) ((UINT8 *) LocalEncapData->Data + sizeof (EFI_GUID) + sizeof (UINT16));\r
+\r
+ Status = LibCreateGuidedSectionOriginalData (InputFileName, ExtractionTool, OutputFileName);\r
+\r
+ if (EFI_ERROR (Status) || GuidDataOffset < sizeof (EFI_GUID_DEFINED_SECTION)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Compress guided data failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+\r
+ GuidDataOffset = GuidDataOffset - sizeof (EFI_GUID_DEFINED_SECTION);\r
+ InputFileName = OutputFileName;\r
+ OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "guided");\r
+\r
+ Status = LibCreateFfsSection(NULL, InputFileName, NULL, EFI_SECTION_GUID_DEFINED, OutputFileName, NULL, NULL, LibFmmtGuidToStr((EFI_GUID *)LocalEncapData->Data), GuidDataOffset, GuidAttributes, NULL);\r
+ OutFile = fopen(OutputFileName, "rb+");\r
+ if (OutFile == NULL) {\r
+ Error("FMMT", 0, 0004, "Could not open the file %s! \n", "");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+ fseek(OutFile, 0, SEEK_SET);\r
+ fseek(OutFile, 0, SEEK_END);\r
+ OutputFileSize = ftell(OutFile);\r
+ fclose(OutFile);\r
+ if (OutputFileSize > LargeFileSize) {\r
+ IsLargeFile = TRUE;\r
+ }\r
+ OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);\r
+ if (OutputFileNameList->FFSName == NULL) {\r
+ Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate guided section failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ if (OutputFileNameList->Next == NULL){\r
+ break;\r
+ }\r
+ OutputFileNameList = OutputFileNameList->Next;\r
+ }\r
+ break;\r
+ case FMMT_ENCAP_TREE_COMPRESS_SECTION:\r
+ while(OutputFileNameList!= NULL && OutputFileNameList->FFSName != NULL){\r
+ InputFileName = OutputFileNameList->FFSName;\r
+\r
+ OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "comsec");\r
+ LocalEncapData = CurrentEncapData;\r
+ if (LocalEncapData == NULL) {\r
+ LocalEncapData = FvInFd->EncapData;\r
+ }\r
+ while (LocalEncapData->NextNode != NULL) {\r
+ if (LocalEncapData->Level == ParentLevel) {\r
+ break;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+\r
+ Status = LibGenCompressedSection (InputFileName, OutputFileName, *(UINT8 *)(LocalEncapData->Data));\r
+ OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);\r
+ if (OutputFileNameList->FFSName == NULL) {\r
+ Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate compressed section failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ if (OutputFileNameList->Next == NULL){\r
+ break;\r
+ }\r
+ OutputFileNameList = OutputFileNameList->Next;\r
+ }\r
+ break;\r
+ case FMMT_ENCAP_TREE_FV_SECTION:\r
+ while(OutputFileNameList!= NULL && OutputFileNameList->FFSName != NULL){\r
+ InputFileName = OutputFileNameList->FFSName;\r
+ OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "sec");\r
+\r
+ Status = LibCreateFfsSection(NULL, InputFileName, NULL, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, OutputFileName, NULL, NULL, NULL, 0, 0, NULL);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV section failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+\r
+ InputFileName = OutputFileName;\r
+ OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "sec");\r
+\r
+ //\r
+ // Make it alignment.\r
+ //\r
+ Status = LibCreateFfsSection(FvInFd, InputFileName, NULL, 0, OutputFileName, NULL, NULL, NULL, 0, 0, NULL);\r
+ OutFile = fopen(OutputFileName, "rb+");\r
+ if (OutFile == NULL) {\r
+ Error("FMMT", 0, 0004, "Could not open the file %s! \n", "");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return EFI_ABORTED;\r
+ }\r
+ fseek(OutFile, 0, SEEK_SET);\r
+ fseek(OutFile, 0, SEEK_END);\r
+ OutputFileSize = ftell(OutFile);\r
+ fclose(OutFile);\r
+ if (OutputFileSize > LargeFileSize) {\r
+ IsLargeFile = TRUE;\r
+ }\r
+\r
+ OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);\r
+ if (OutputFileNameList->FFSName == NULL) {\r
+ Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV section failed!");\r
+ free (OutputFileNameList);\r
+ free (ChildFileNameList);\r
+ return Status;\r
+ }\r
+ if (OutputFileNameList->Next == NULL){\r
+ break;\r
+ }\r
+ OutputFileNameList = OutputFileNameList->Next;\r
+ }\r
+ break;\r
+ default:\r
+ for (Id = FvInFd->FfsNumbers; Id <= FvInFd->FfsNumbers; Id--) {\r
+ if ((memcmp(&FvInFd->FfsAttuibutes[Id].GuidName, &(CurrentEncapData->FvExtHeader->FvName), sizeof(EFI_GUID)) == 0)){\r
+ FvInFd->FfsAttuibutes[Id].IsHandle = TRUE;\r
+ memcpy(OutputFileNameList->UiName, FvInFd->FfsAttuibutes[Id].UiName, FvInFd->FfsAttuibutes[Id].UiNameSize);\r
+ OutputFileNameList->UiNameSize = FvInFd->FfsAttuibutes[Id].UiNameSize;\r
+ OutputFileNameList->FFSName = FvInFd->FfsAttuibutes[Id].FfsName;\r
+ OutputFileNameList->Depex = FvInFd->FfsAttuibutes[Id].Depex;\r
+ OutputFileNameList->DepexLen = FvInFd->FfsAttuibutes[Id].DepexLen;\r
+ OutputFileNameList->FfsFoundFlag = TRUE;\r
+ OutputFileNameList->IsFFS = TRUE;\r
+ OutputFileNameList->InFvId = Id;\r
+ *OutputFile = OutputFileNameList;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (CurrentEncapData == NULL) {\r
+ LocalEncapData = FvInFd->EncapData;\r
+ } else {\r
+ if (OutputFileNameList != NULL && OutputFileNameList->FFSName != NULL && OutputFileNameList->IsFFS == TRUE) {\r
+ *OutputFile = OutputFileNameList;\r
+ return EFI_SUCCESS;\r
+ }\r
+ LocalEncapData = CurrentEncapData;\r
+ }\r
+ ParentLevel -= 1;\r
+\r
+ while (LocalEncapData->NextNode != NULL) {\r
+ if (LocalEncapData->Level == ParentLevel) {\r
+ LocalEncapDataTemp = LocalEncapData->NextNode;\r
+ if ((LocalEncapDataTemp != NULL) && (LocalEncapDataTemp->Level == ParentLevel)) {\r
+ ParentType = LocalEncapDataTemp->Type;\r
+ break;\r
+ }\r
+ ParentType = LocalEncapData->Type;\r
+ break;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+ } while (ParentLevel != Level_Break);\r
+\r
+ *OutputFile = OutputFileNameList;\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+LibFindFvInEncapData (\r
+ ENCAP_INFO_DATA *EncapData,\r
+ UINT8 *Index\r
+)\r
+{\r
+ ENCAP_INFO_DATA *LocalEncapData;\r
+ LocalEncapData = EncapData;\r
+ if (LocalEncapData == NULL) {\r
+ Error("FMMT", 0, 0005, "error while find FV in Encapulate buffer", "Invalid parameters.");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ while (LocalEncapData != NULL) {\r
+ if (LocalEncapData->RightNode != NULL) {\r
+ LibFindFvInEncapData (LocalEncapData->RightNode, Index);\r
+ }\r
+ if (LocalEncapData->Type == FMMT_ENCAP_TREE_FV) {\r
+ (*Index)++;\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+LibLocateFvViaFvId (\r
+ IN FIRMWARE_DEVICE *FdData,\r
+ IN CHAR8 *FvId,\r
+ IN OUT FV_INFORMATION **FvInFd\r
+)\r
+{\r
+ UINT8 FvIndex1;\r
+ UINT8 FvIndex2;\r
+ BOOLEAN FvFoundFlag;\r
+ CHAR8* FvGuidName;\r
+ ENCAP_INFO_DATA *LocalEncapData;\r
+ ENCAP_INFO_DATA *LocalEncapDataRight;\r
+ ENCAP_INFO_DATA *LocalEncapDataNext;\r
+ FvIndex1 = 0;\r
+ FvIndex2 = 0;\r
+ FvFoundFlag = FALSE;\r
+ FvGuidName = NULL;\r
+ LocalEncapDataNext = NULL;\r
+ LocalEncapDataRight = NULL;\r
+\r
+ if (FdData == NULL || FvId == NULL || FvInFd == NULL || FdData->Fv == NULL) {\r
+ Error ("FMMT", 0, 0005, "error while find FV in FD", "Invalid parameters.");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *FvInFd = FdData->Fv;\r
+\r
+ if (strlen(FvId) < 3) {\r
+ Error ("FMMT", 0, 0005, "error while find FV in FD", "Invalid FvId, please double check the FvId. You can use view operate to get the FvId information!");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ FvGuidName = (CHAR8 *) malloc (255);\r
+ if (FvGuidName == NULL) {\r
+ Error ("FMMT", 0, 0005, "Resource: Memory can't be allocated", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+ memset(FvGuidName, '\0', 255);\r
+ LocalEncapData = NULL;\r
+\r
+ if (strlen(FvId) == 36) {\r
+ while (FvInFd != NULL) {\r
+ if (((*FvInFd)->FvExtHeader) != NULL) {\r
+ sprintf(\r
+ FvGuidName,\r
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
+ (*FvInFd)->FvExtHeader->FvName.Data1,\r
+ (*FvInFd)->FvExtHeader->FvName.Data2,\r
+ (*FvInFd)->FvExtHeader->FvName.Data3,\r
+ (*FvInFd)->FvExtHeader->FvName.Data4[0],\r
+ (*FvInFd)->FvExtHeader->FvName.Data4[1],\r
+ (*FvInFd)->FvExtHeader->FvName.Data4[2],\r
+ (*FvInFd)->FvExtHeader->FvName.Data4[3],\r
+ (*FvInFd)->FvExtHeader->FvName.Data4[4],\r
+ (*FvInFd)->FvExtHeader->FvName.Data4[5],\r
+ (*FvInFd)->FvExtHeader->FvName.Data4[6],\r
+ (*FvInFd)->FvExtHeader->FvName.Data4[7]);\r
+ if (strcmp(FvGuidName, FvId) == 0) {\r
+ FvId = (*FvInFd)->FvName;\r
+ break;\r
+ }\r
+ }\r
+ if ((*FvInFd)->MulFvLevel > 1) {\r
+ LocalEncapData = (*FvInFd) -> EncapData;\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ while (LocalEncapData != NULL) {\r
+ if (LocalEncapData->RightNode != NULL) {\r
+ LocalEncapDataRight = LocalEncapData->RightNode;\r
+ while (LocalEncapDataRight !=NULL) {\r
+ if (LocalEncapDataRight->NextNode != NULL) {\r
+ LocalEncapDataNext = LocalEncapDataRight->NextNode;\r
+ while (LocalEncapDataNext != NULL) {\r
+ if (LocalEncapDataNext->Type == FMMT_ENCAP_TREE_FV) {\r
+ if (LocalEncapDataNext->FvExtHeader != NULL) {\r
+ sprintf(\r
+ FvGuidName,\r
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data1,\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data2,\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data3,\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data4[0],\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data4[1],\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data4[2],\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data4[3],\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data4[4],\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data4[5],\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data4[6],\r
+ LocalEncapDataNext->FvExtHeader->FvName.Data4[7]);\r
+ if (strcmp(FvGuidName, FvId) == 0)\r
+ {\r
+ sprintf(FvId, "%s%d", "FV", LocalEncapDataNext->FvId - 1);\r
+ break;\r
+ }\r
+\r
+ }\r
+ }\r
+ LocalEncapDataNext = LocalEncapDataNext->NextNode;\r
+ }\r
+ }\r
+ LocalEncapDataRight = LocalEncapDataRight->RightNode;\r
+ }\r
+ }\r
+ if (LocalEncapData->Type == FMMT_ENCAP_TREE_FV) {\r
+ if (LocalEncapData->FvExtHeader != NULL) {\r
+ sprintf(\r
+ FvGuidName,\r
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
+ LocalEncapData->FvExtHeader->FvName.Data1,\r
+ LocalEncapData->FvExtHeader->FvName.Data2,\r
+ LocalEncapData->FvExtHeader->FvName.Data3,\r
+ LocalEncapData->FvExtHeader->FvName.Data4[0],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[1],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[2],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[3],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[4],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[5],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[6],\r
+ LocalEncapData->FvExtHeader->FvName.Data4[7]);\r
+\r
+ if (strcmp(FvGuidName, FvId) == 0) {\r
+ sprintf(FvId, "%s%d", "FV", LocalEncapData->FvId - 1);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ LocalEncapData = LocalEncapData->NextNode;\r
+ }\r
+ }\r
+ if ((*FvInFd)->FvNext == 0) {\r
+ break;\r
+ }\r
+ *FvInFd = (*FvInFd)->FvNext;\r
+ }\r
+ }\r
+ *FvInFd = FdData->Fv;\r
+ FvIndex1 = (UINT8) atoi (FvId + 2);\r
+\r
+ while (FvInFd != NULL) {\r
+ if (((*FvInFd)->FvName) != NULL) {\r
+ FvIndex2 = (UINT8) atoi ((*FvInFd)->FvName + 2);\r
+ LocalEncapData = (*FvInFd)->EncapData;\r
+ LibFindFvInEncapData (LocalEncapData, &FvIndex2);\r
+\r
+ if ((FvIndex2 - 1 >= FvIndex1)) {\r
+ FvFoundFlag = TRUE;\r
+ break;\r
+ }\r
+ if ((*FvInFd)->FvNext == 0) {\r
+ break;\r
+ }\r
+ }\r
+ *FvInFd = (*FvInFd)->FvNext;\r
+ }\r
+ if (FvGuidName != NULL) {\r
+ free (FvGuidName);\r
+ }\r
+ //\r
+ // The specified FV id has issue, can not find the FV in FD.\r
+ //\r
+ if (!FvFoundFlag) {\r
+ Error ("FMMT", 0, 0005, "error while find FV in FD", "Invalid FvId, please double check the FvId. You can use view operate to get the FvId information!");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+#define BUILD_IN_TOOL_COUNT 4\r
+\r
+EFI_HANDLE\r
+LibPreDefinedGuidedTools (\r
+ VOID\r
+)\r
+{\r
+ EFI_GUID Guid;\r
+ STRING_LIST *Tool;\r
+ GUID_SEC_TOOL_ENTRY *FirstGuidTool;\r
+ GUID_SEC_TOOL_ENTRY *LastGuidTool;\r
+ GUID_SEC_TOOL_ENTRY *NewGuidTool;\r
+ UINT8 Index;\r
+ EFI_STATUS Status;\r
+\r
+ CHAR8 PreDefinedGuidedTool[BUILD_IN_TOOL_COUNT][255] = {\r
+ "a31280ad-481e-41b6-95e8-127f4c984779 TIANO TianoCompress",\r
+ "ee4e5898-3914-4259-9d6e-dc7bd79403cf LZMA LzmaCompress",\r
+ "fc1bcdb0-7d31-49aa-936a-a4600d9dd083 CRC32 GenCrc32",\r
+ "3d532050-5cda-4fd0-879e-0f7f630d5afb BROTLI BrotliCompress"\r
+ };\r
+\r
+ Tool = NULL;\r
+ FirstGuidTool = NULL;\r
+ LastGuidTool = NULL;\r
+ NewGuidTool = NULL;\r
+ Index = 0;\r
+\r
+ for (Index = 0; Index < BUILD_IN_TOOL_COUNT; Index++) {\r
+ Tool = SplitStringByWhitespace (PreDefinedGuidedTool[Index]);\r
+ if ((Tool != NULL) &&\r
+ (Tool->Count == 3)\r
+ ) {\r
+ Status = StringToGuid (Tool->Strings[0], &Guid);\r
+ if (!EFI_ERROR (Status)) {\r
+ NewGuidTool = malloc (sizeof (GUID_SEC_TOOL_ENTRY));\r
+ if (NewGuidTool != NULL) {\r
+ memcpy (&(NewGuidTool->Guid), &Guid, sizeof (Guid));\r
+ NewGuidTool->Name = CloneString(Tool->Strings[1]);\r
+ NewGuidTool->Path = CloneString(Tool->Strings[2]);\r
+ NewGuidTool->Next = NULL;\r
+ } else {\r
+ printf ("Error while allocate resource! \n");\r
+ FreeStringList (Tool);\r
+ return NULL;\r
+ }\r
+ if (FirstGuidTool == NULL) {\r
+ FirstGuidTool = NewGuidTool;\r
+ } else {\r
+ LastGuidTool->Next = NewGuidTool;\r
+ }\r
+ LastGuidTool = NewGuidTool;\r
+ }\r
+ } else {\r
+ fprintf (stdout, "Error");\r
+ }\r
+ if (Tool != NULL) {\r
+ FreeStringList (Tool);\r
+ Tool = NULL;\r
+ }\r
+ }\r
+ return FirstGuidTool;\r
+}\r