From 28305207ea586d0b5ceb530b0e2a436cad9fdd8f Mon Sep 17 00:00:00 2001 From: lhauch Date: Thu, 5 Oct 2006 23:16:50 +0000 Subject: More renames for Tool Packages git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1675 6f19259b-4bc3-4df7-8a09-765794883524 --- Tools/CodeTools/Source/GenCapsuleHdr/CreateGuid.c | 50 + .../CodeTools/Source/GenCapsuleHdr/GenCapsuleHdr.c | 2674 ++++++++++++++++++++ Tools/CodeTools/Source/GenCapsuleHdr/build.xml | 72 + 3 files changed, 2796 insertions(+) create mode 100644 Tools/CodeTools/Source/GenCapsuleHdr/CreateGuid.c create mode 100644 Tools/CodeTools/Source/GenCapsuleHdr/GenCapsuleHdr.c create mode 100644 Tools/CodeTools/Source/GenCapsuleHdr/build.xml (limited to 'Tools/CodeTools/Source/GenCapsuleHdr') diff --git a/Tools/CodeTools/Source/GenCapsuleHdr/CreateGuid.c b/Tools/CodeTools/Source/GenCapsuleHdr/CreateGuid.c new file mode 100644 index 0000000000..2a984fa70e --- /dev/null +++ b/Tools/CodeTools/Source/GenCapsuleHdr/CreateGuid.c @@ -0,0 +1,50 @@ +/*++ + +Copyright (c) 2004-2006 Intel Corporation. All rights reserved +This program and the accompanying materials are licensed and made available +under the terms and conditions of the BSD License which accompanies this +distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + CreateGuid.c + +Abstract: + + Library routine to create a GUID + +--*/ + +#include +#include +#include +#include +#include + +void +CreateGuid ( + GUID *Guid + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Guid - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + CoCreateGuid (Guid); +} diff --git a/Tools/CodeTools/Source/GenCapsuleHdr/GenCapsuleHdr.c b/Tools/CodeTools/Source/GenCapsuleHdr/GenCapsuleHdr.c new file mode 100644 index 0000000000..d1f55b9abd --- /dev/null +++ b/Tools/CodeTools/Source/GenCapsuleHdr/GenCapsuleHdr.c @@ -0,0 +1,2674 @@ +/*++ + +Copyright (c) 2002-2006 Intel Corporation. All rights reserved +This program and the accompanying materials are licensed and made available +under the terms and conditions of the BSD License which accompanies this +distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + GenCapsuleHdr.c + +Abstract: + + Generate a capsule header for a file, and optionally prepend the + header to a file or list of files. + +--*/ + +#define _UNICODE + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include // for FV header GUID +#include +#include // for FV header GUID + +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +#define MAX_PATH 256 +#define PROGRAM_NAME "GenCapsuleHdr" + +#define UNICODE_BACKSLASH L'\\' +#define UNICODE_FILE_START 0xFEFF +#define UNICODE_CR 0x000D +#define UNICODE_LF 0x000A +#define UNICODE_NULL 0x0000 +#define UNICODE_SPACE L' ' +#define UNICODE_SLASH L'/' +#define UNICODE_DOUBLE_QUOTE L'"' +#define UNICODE_A L'A' +#define UNICODE_F L'F' +#define UNICODE_Z L'Z' +#define UNICODE_a L'a' +#define UNICODE_f L'f' +#define UNICODE_z L'z' +#define UNICODE_0 L'0' +#define UNICODE_9 L'9' +#define UNICODE_TAB L'\t' + +#define OEM_HEADER_STRING L"OemHeader" +#define AUTHOR_INFO_STRING L"AuthorInfo" +#define REVISION_INFO_STRING L"RevisionInfo" +#define SHORT_DESCRIPTION_STRING L"ShortDescription" +#define LONG_DESCRIPTION_STRING L"LongDescription" +#define EQUAL_STRING L"=" +#define OPEN_BRACE_STRING L"{" +#define CLOSE_BRACE_STRING L"}" +#define GUID_STRING L"GUID" +#define DATA_STRING L"DATA" + +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) +#define UEFI_CAPSULE_HEADER_NO_FALAGS 0 +#define UEFI_CAPSULE_HEADER_RESET_FALAGS CAPSULE_FLAGS_PERSIST_ACROSS_RESET +#define UEFI_CAPSULE_HEADER_ALL_FALAGS (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) +#endif + +typedef wchar_t WCHAR; + +typedef struct _FILE_LIST { + struct _FILE_LIST *Next; + INT8 FileName[MAX_PATH]; +} FILE_LIST; + +typedef struct _SIZE_LIST { + struct _SIZE_LIST *Next; + UINT32 Size; +} SIZE_LIST; + +typedef struct { + INT8 FileName[MAX_PATH]; + WCHAR *FileBuffer; + WCHAR *FileBufferPtr; + UINT32 FileSize; + FILE *FilePtr; + BOOLEAN EndOfFile; + UINT32 LineNum; +} SOURCE_FILE; + +// +// Here's all our globals. +// +static struct { + BOOLEAN Dump; + BOOLEAN Verbose; + BOOLEAN JoinMode; + INT8 ScriptFileName[MAX_PATH]; + INT8 OutputFileName[MAX_PATH]; + FILE_LIST *FileList; + FILE *OutFptr; + SIZE_LIST *SizeList; + SIZE_LIST *LastSize; + SIZE_LIST *CurrentSize; +} mOptions; + +static EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID; + +void +CreateGuid ( + EFI_GUID *Guid + ); + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +void +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +STATUS +GetHexValue ( + SOURCE_FILE *SourceFile, + UINT32 *Value, + UINT32 NumDigits + ); + +static +BOOLEAN +GetSplitFileName ( + INT8 *BaseFileName, + INT8 *NewFileName, + UINT32 SequenceNumber + ); + +static +STATUS +SplitCapsule ( + INT8 *CapsuleFileName + ); + +static +void +Usage ( + VOID + ); + +static +void +DumpCapsule ( + VOID + ); + +static +STATUS +JoinCapsule ( + VOID + ); + +static +STATUS +DumpCapsuleHeaderStrings ( + UINT8 *SectionName, + WCHAR *Buffer + ); + +static +STATUS +CheckFirmwareVolumeHeader ( + INT8 *FileName, + INT8 *Buffer, + UINT32 BufferSize + ); + +static +BOOLEAN +IsToken ( + SOURCE_FILE *File, + WCHAR *Token + ); + +static +BOOLEAN +GetNumber ( + INT8 *Str, + UINT32 *Value + ); + +static +STATUS +ProcessScriptFile ( + INT8 *ScriptFileName, + FILE *OutFptr, + EFI_CAPSULE_HEADER *CapsuleHeader + ); + +static +STATUS +ParseCapsuleInfo ( + SOURCE_FILE *SourceFile, + FILE *OutFptr, + WCHAR *SectionName + ); + +static +STATUS +CreateCapsule ( + VOID + ); + +static +STATUS +ParseOemInfo ( + SOURCE_FILE *SourceFile, + FILE *OutFptr + ); + +static +BOOLEAN +IsWhiteSpace ( + WCHAR Char + ); + +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *File + ); + +int +main ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + Call the routine to process the command-line arguments, then + dispatch to the appropriate function. + +Arguments: + Standard C main() argc and argv. + +Returns: + 0 if successful + nonzero otherwise + +--*/ +// GC_TODO: Argc - add argument and description to function comment +// GC_TODO: ] - add argument and description to function comment +{ + STATUS Status; + FILE_LIST *NextFile; + // + // Specify our program name to the error printing routines. + // + SetUtilityName (PROGRAM_NAME); + // + // Process the command-line arguments + // + Status = ProcessArgs (Argc, Argv); + if (Status == STATUS_SUCCESS) { + if (mOptions.Dump) { + DumpCapsule (); + } else if (mOptions.JoinMode) { + JoinCapsule (); + } else { + CreateCapsule (); + } + } + // + // Cleanup + // + while (mOptions.FileList != NULL) { + NextFile = mOptions.FileList->Next; + free (mOptions.FileList); + mOptions.FileList = NextFile; + } + + while (mOptions.SizeList != NULL) { + mOptions.CurrentSize = mOptions.SizeList->Next; + free (mOptions.SizeList); + mOptions.SizeList = mOptions.CurrentSize; + } + + return GetUtilityStatus (); +} + +static +STATUS +CreateCapsule ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +{ + FILE *InFptr; + FILE_LIST *FileList; + INT8 *Buffer; + UINT32 Size; + EFI_CAPSULE_HEADER CapsuleHeader; + UINT8 Zero; + UINT8 FirstFile; + UINT32 CapsuleHeaderSize; + long InsertedBlockMapEntryOffset; + EFI_FV_BLOCK_MAP_ENTRY InsertedBlockMapEntry; + UINT64 FirmwareVolumeSize; + long FileSize; + EFI_FIRMWARE_VOLUME_HEADER FVHeader; + + Buffer = NULL; + InFptr = NULL; + FirmwareVolumeSize = 0; + CapsuleHeaderSize = 0; + InsertedBlockMapEntryOffset = 0; + memset (&InsertedBlockMapEntry, 0, sizeof (EFI_FV_BLOCK_MAP_ENTRY)); + memset (&FVHeader, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + + if ((mOptions.OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + + memset ((char *) &CapsuleHeader, 0, sizeof (CapsuleHeader)); + memcpy ((void *) &CapsuleHeader.CapsuleGuid, (void *) &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)); + CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER); + CapsuleHeader.CapsuleImageSize = sizeof (EFI_CAPSULE_HEADER); + if (mOptions.ScriptFileName[0] != 0) { + if (ProcessScriptFile (mOptions.ScriptFileName, mOptions.OutFptr, &CapsuleHeader) != STATUS_SUCCESS) { + goto Done; + } + } else { + // + // Insert a default capsule header +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER); + CapsuleHeader.Flags = UEFI_CAPSULE_HEADER_ALL_FALAGS; +#endif + CapsuleHeader.OffsetToCapsuleBody = sizeof (EFI_CAPSULE_HEADER); + + if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + goto Done; + } + } + + CapsuleHeaderSize = CapsuleHeader.OffsetToCapsuleBody; + // + // Now copy the contents of any other files specified on the command + // line to the output file. Files must be FFS files, which are aligned + // on 8-byte boundaries. Don't align the first file, since it's the start + // of the image once the capsule header has been removed. + // + FileList = mOptions.FileList; + FirstFile = 1; + Zero = 0; + while (FileList != NULL) { + if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) { + Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading"); + goto Done; + } + // + // Allocate a buffer into which we can read the file. + // + fseek (InFptr, 0, SEEK_END); + Size = ftell (InFptr); + rewind (InFptr); + Buffer = (char *) malloc (Size); + if (Buffer == NULL) { + Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into"); + goto Done; + } + + if (fread ((void *) Buffer, Size, 1, InFptr) != 1) { + Error (NULL, 0, 0, FileList->FileName, "failed to read file contents"); + goto Done; + } + + if (Size > 0) { + // + // Align the write of the first bytes from the file if not the first file + // + if (FirstFile) { + // + // First file must be a firmware volume. Double-check, and then insert + // an additional block map entry so we can add more files from the command line + // + if (CheckFirmwareVolumeHeader (FileList->FileName, Buffer, Size) != STATUS_SUCCESS) { + goto Done; + } + // + // Save a copy of the firmware volume header for later + // + memcpy (&FVHeader, Buffer, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + FirmwareVolumeSize = FVHeader.FvLength; + if (FileList->Next != NULL) { + // + // Copy the firmware volume header + // + InsertedBlockMapEntryOffset = CapsuleHeaderSize + FVHeader.HeaderLength; + if (fwrite (Buffer, FVHeader.HeaderLength, 1, mOptions.OutFptr) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + goto Done; + } + + if (fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + goto Done; + } + + if (fwrite ( + Buffer + FVHeader.HeaderLength, + Size - FVHeader.HeaderLength, + 1, + mOptions.OutFptr + ) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + goto Done; + } + } else { + // + // Copy the file contents as-is + // + if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + goto Done; + } + } + } else { + while ((ftell (mOptions.OutFptr) - CapsuleHeaderSize) & 0x07) { + if (fwrite ((void *) &Zero, 1, 1, mOptions.OutFptr) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + goto Done; + } + } + + if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + goto Done; + } + } + + FirstFile = 0; + } + + free (Buffer); + Buffer = NULL; + fclose (InFptr); + InFptr = NULL; + FileList = FileList->Next; + } + +Done: + if (Buffer != NULL) { + free (Buffer); + } + + if (InFptr != NULL) { + fclose (InFptr); + } + // + // If we inserted an additional block map entry, then fix it up. Fix up the + // FV header as well to reflect our new size. + // + if (InsertedBlockMapEntryOffset != 0) { + FileSize = ftell (mOptions.OutFptr); + InsertedBlockMapEntry.NumBlocks = 1; + InsertedBlockMapEntry.BlockLength = (UINT32) ((UINT64) FileSize - (UINT64) CapsuleHeaderSize - FirmwareVolumeSize - sizeof (EFI_FV_BLOCK_MAP_ENTRY)); + fseek (mOptions.OutFptr, InsertedBlockMapEntryOffset, SEEK_SET); + fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr); + // + // Fix up the firmware volume header and write it out + // + fseek (mOptions.OutFptr, CapsuleHeaderSize, SEEK_SET); + FVHeader.FvLength = FileSize - CapsuleHeaderSize; + FVHeader.HeaderLength += sizeof (EFI_FV_BLOCK_MAP_ENTRY); + fwrite (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr); + // + // Reposition to the end of the file + // + } + // + // Close files and free the global string lists we allocated memory for + // + if (mOptions.OutFptr != NULL) { + // + // We should now know the full capsule image size. Update the header and write it again. + // + fseek (mOptions.OutFptr, 0, SEEK_END); + Size = ftell (mOptions.OutFptr); + CapsuleHeader.CapsuleImageSize = Size; + fseek (mOptions.OutFptr, 0, SEEK_SET); + if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + } + + fseek (mOptions.OutFptr, 0, SEEK_END); + fclose (mOptions.OutFptr); + mOptions.OutFptr = NULL; + } + // + // If they are doing split capsule output, then split it up now. + // + if ((mOptions.Dump == 0) && (GetUtilityStatus () == STATUS_SUCCESS) && (mOptions.SizeList != NULL)) { + SplitCapsule (mOptions.OutputFileName); + } + + return STATUS_SUCCESS; +} + +static +STATUS +ProcessScriptFile ( + INT8 *ScriptFileName, + FILE *OutFptr, + EFI_CAPSULE_HEADER *CapsuleHeader + ) +/*++ + +Routine Description: + Parse a capsule header script file. + +Arguments: + ScriptFileName - name of script file to parse + OutFptr - output to dump binary data + CapsuleHeader - capsule header to update with size info + of parsed fields in the script file + +Returns: + STATUS_SUCCESS - if all went well + +--*/ +{ +#if 0 + STATUS Status; + SOURCE_FILE SourceFile; + WCHAR *WScriptFileName; + BOOLEAN InComment; + + if (fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr) != 1) { + Error (NULL, 0, 0, "failed to write capsule header to output file", NULL); + return STATUS_ERROR; + } + + memset (&SourceFile, 0, sizeof (SOURCE_FILE)); + strcpy (SourceFile.FileName, ScriptFileName); + + Status = STATUS_ERROR; + // + // Open the input unicode script file and read it into a buffer + // + WScriptFileName = (WCHAR *) malloc ((strlen (ScriptFileName) + 1) * sizeof (WCHAR)); + if (WScriptFileName == NULL) { + Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL); + return STATUS_ERROR; + } + + swprintf (WScriptFileName, L"%S", ScriptFileName); + if ((SourceFile.FilePtr = _wfopen (WScriptFileName, L"r")) == NULL) { + free (WScriptFileName); + Error (NULL, 0, 0, ScriptFileName, "failed to open script file for reading"); + goto Done; + } + + free (WScriptFileName); + fseek (SourceFile.FilePtr, 0, SEEK_END); + SourceFile.FileSize = ftell (SourceFile.FilePtr); + rewind (SourceFile.FilePtr); + SourceFile.FileBuffer = (WCHAR *) malloc (SourceFile.FileSize + sizeof (WCHAR)); + if (SourceFile.FileBuffer == NULL) { + Error (__FILE__, __LINE__, 0, ScriptFileName, "failed to allocate memory to read in file contents"); + goto Done; + } + + if (fread (SourceFile.FileBuffer, SourceFile.FileSize, 1, SourceFile.FilePtr) != 1) { + Error (NULL, 0, 0, ScriptFileName, "failed to read file contents"); + goto Done; + } + + SourceFile.FileBufferPtr = SourceFile.FileBuffer; + SourceFile.LineNum = 1; + if (SourceFile.FileBuffer[0] != UNICODE_FILE_START) { + Error (ScriptFileName, 1, 0, "file does not appear to be a unicode file", NULL); + goto Done; + } + + SourceFile.FileBufferPtr++; + SourceFile.FileBuffer[SourceFile.FileSize / sizeof (WCHAR)] = 0; + // + // Walk the source file buffer and replace all carriage returns with 0 so + // we can print from the file contents on parse errors. + // + InComment = 0; + while (!EndOfFile (&SourceFile)) { + if (SourceFile.FileBufferPtr[0] == UNICODE_CR) { + SourceFile.FileBufferPtr[0] = 0; + InComment = 0; + } else if (SourceFile.FileBufferPtr[0] == UNICODE_LF) { + InComment = 0; + } else if (InComment) { + SourceFile.FileBufferPtr[0] = UNICODE_SPACE; + } else if ((SourceFile.FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile.FileBufferPtr[1] == UNICODE_SLASH)) { + InComment = 1; + SourceFile.FileBufferPtr[0] = UNICODE_SPACE; + } + + SourceFile.FileBufferPtr++; + } + // + // Reposition to the start of the file, but skip over the unicode file start + // + SourceFile.FileBufferPtr = SourceFile.FileBuffer; + SourceFile.FileBufferPtr++; + SourceFile.EndOfFile = 0; + CapsuleHeader->OffsetToOemDefinedHeader = ftell (OutFptr); + // + // Parse the OEM bytes + // + if (ParseOemInfo (&SourceFile, OutFptr) != STATUS_SUCCESS) { + goto Done; + } + // + // Parse the author information + // + CapsuleHeader->OffsetToAuthorInformation = ftell (OutFptr); + if (ParseCapsuleInfo (&SourceFile, OutFptr, AUTHOR_INFO_STRING) != STATUS_SUCCESS) { + goto Done; + } + // + // Parse the revision information + // + CapsuleHeader->OffsetToRevisionInformation = ftell (OutFptr); + if (ParseCapsuleInfo (&SourceFile, OutFptr, REVISION_INFO_STRING) != STATUS_SUCCESS) { + goto Done; + } + // + // Parse the short description + // + CapsuleHeader->OffsetToShortDescription = ftell (OutFptr); + if (ParseCapsuleInfo (&SourceFile, OutFptr, SHORT_DESCRIPTION_STRING) != STATUS_SUCCESS) { + goto Done; + } + // + // Parse the long description + // + CapsuleHeader->OffsetToLongDescription = ftell (OutFptr); + if (ParseCapsuleInfo (&SourceFile, OutFptr, LONG_DESCRIPTION_STRING) != STATUS_SUCCESS) { + goto Done; + } + // + // Better be end of contents + // + SkipWhiteSpace (&SourceFile); + if (!EndOfFile (&SourceFile)) { + Error (ScriptFileName, SourceFile.LineNum, 0, NULL, "expected end-of-file, not %.20S", SourceFile.FileBufferPtr); + goto Done; + } + + CapsuleHeader->OffsetToCapsuleBody = ftell (OutFptr); + rewind (OutFptr); + fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr); + fseek (OutFptr, 0, SEEK_END); + Status = STATUS_SUCCESS; +Done: + if (SourceFile.FilePtr != NULL) { + fclose (SourceFile.FilePtr); + } + + if (SourceFile.FileBuffer != NULL) { + free (SourceFile.FileBuffer); + } + + return Status; + +#endif + return STATUS_SUCCESS; +} +// +// Parse the OEM data of format: +// OemInfo { +// GUID = 12345676-1234-1234-123456789ABC +// DATA = 0x01, 0x02, 0x03... +// } +// +static +STATUS +ParseOemInfo ( + SOURCE_FILE *SourceFile, + FILE *OutFptr + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + SourceFile - GC_TODO: add argument description + OutFptr - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + long OemHeaderOffset; + UINT32 Data; + EFI_CAPSULE_OEM_HEADER OemHeader; + STATUS Status; + UINT32 DigitCount; + WCHAR *SaveFilePos; + UINT8 ByteData; + + Status = STATUS_ERROR; + memset (&OemHeader, 0, sizeof (EFI_CAPSULE_OEM_HEADER)); + OemHeaderOffset = ftell (OutFptr); + OemHeader.HeaderSize = sizeof (EFI_CAPSULE_OEM_HEADER); + if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) { + Error (NULL, 0, 0, "failed to write OEM header to output file", NULL); + goto Done; + } + + if (!IsToken (SourceFile, OEM_HEADER_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + OEM_HEADER_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + + if (!IsToken (SourceFile, EQUAL_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + EQUAL_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + + if (!IsToken (SourceFile, OPEN_BRACE_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + OPEN_BRACE_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + // + // Look for: GUID = xxxxxxx-xxxx-xxxx-xxxxxxxxxxxxx + // + if (!IsToken (SourceFile, GUID_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + GUID_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + + if (!IsToken (SourceFile, EQUAL_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + EQUAL_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + // + // Parse the xxxxxxxx-xxxx-xxxx-xxxx portion of the GUID + // + SkipWhiteSpace (SourceFile); + if (GetHexValue (SourceFile, &Data, 8) != STATUS_SUCCESS) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL); + goto Done; + } + + OemHeader.OemGuid.Data1 = Data; + if (!IsToken (SourceFile, L"-")) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected dash in GUID, not %S", + SourceFile->FileBufferPtr + ); + goto Done; + } + // + // Get 3 word values + // + for (DigitCount = 0; DigitCount < 3; DigitCount++) { + if (GetHexValue (SourceFile, &Data, 4) != STATUS_SUCCESS) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL); + goto Done; + } + + switch (DigitCount) { + case 0: + OemHeader.OemGuid.Data2 = (UINT16) Data; + break; + + case 1: + OemHeader.OemGuid.Data3 = (UINT16) Data; + break; + + case 2: + OemHeader.OemGuid.Data4[1] = (UINT8) Data; + OemHeader.OemGuid.Data4[0] = (UINT8) (Data >> 8); + break; + } + + if (!IsToken (SourceFile, L"-")) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected dash in GUID, not %S", + SourceFile->FileBufferPtr + ); + goto Done; + } + } + // + // Pick up the last 6 bytes of the GUID + // + SaveFilePos = SourceFile->FileBufferPtr; + for (DigitCount = 0; DigitCount < 6; DigitCount++) { + if (GetHexValue (SourceFile, &Data, 2) != STATUS_SUCCESS) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL); + goto Done; + } + + OemHeader.OemGuid.Data4[DigitCount + 2] = (UINT8) Data; + } + // + // Now read raw OEM data bytes. May or may not be present. + // DATA = 0x01, 0x02, 0x02... + // + if (IsToken (SourceFile, CLOSE_BRACE_STRING)) { + Status = STATUS_SUCCESS; + goto Done; + } + + if (!IsToken (SourceFile, DATA_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + DATA_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + + if (!IsToken (SourceFile, EQUAL_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + EQUAL_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + + while (!EndOfFile (SourceFile)) { + if (IsToken (SourceFile, CLOSE_BRACE_STRING)) { + Status = STATUS_SUCCESS; + goto Done; + } + + if (IsToken (SourceFile, L"0x")) { + if (swscanf (SourceFile->FileBufferPtr, L"%x", &Data) != 1) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected hex byte value, not %.20S", + SourceFile->FileBufferPtr + ); + goto Done; + } + + if (Data &~0xFF) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected byte hex byte value at %.20S", + SourceFile->FileBufferPtr + ); + goto Done; + } + // + // Skip over the hex digits, then write the data + // + while (iswxdigit (SourceFile->FileBufferPtr[0])) { + SourceFile->FileBufferPtr++; + } + + ByteData = (UINT8) Data; + if (fwrite (&ByteData, 1, 1, OutFptr) != 1) { + Error (NULL, 0, 0, "failed to write OEM data to output file", NULL); + goto Done; + } + + OemHeader.HeaderSize++; + // + // Optional comma + // + IsToken (SourceFile, L","); + } else { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected hex OEM data, not %.20S", + SourceFile->FileBufferPtr + ); + goto Done; + } + } + + if (EndOfFile (SourceFile)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S close to OEM header data", + CLOSE_BRACE_STRING + ); + goto Done; + } + + Status = STATUS_SUCCESS; +Done: + // + // re-write the oem header if no errors + // + if (Status == STATUS_SUCCESS) { + fseek (OutFptr, OemHeaderOffset, SEEK_SET); + if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) { + Error (NULL, 0, 0, "failed to write OEM header to output file", NULL); + goto Done; + } + + fseek (OutFptr, 0, SEEK_END); + } + + return Status; +} + +static +STATUS +ParseCapsuleInfo ( + SOURCE_FILE *SourceFile, + FILE *OutFptr, + WCHAR *SectionName + ) +// GC_TODO: function comment should start with '/*++' +// +// GC_TODO: function comment is missing 'Routine Description:' +// GC_TODO: function comment is missing 'Arguments:' +// GC_TODO: function comment is missing 'Returns:' +// GC_TODO: SourceFile - add argument and description to function comment +// GC_TODO: OutFptr - add argument and description to function comment +// GC_TODO: SectionName - add argument and description to function comment +// Parse: eng "string " "parts" +// spa "string " "parts" +// Write out: "eng string parts\0spa string parts\0\0 +// +{ + STATUS Status; + int StringCount; + WCHAR Zero; + WCHAR Spacebar; + + Status = STATUS_ERROR; + Zero = 0; + Spacebar = UNICODE_SPACE; + + if (!IsToken (SourceFile, SectionName)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + SectionName, + SourceFile->FileBufferPtr + ); + goto Done; + } + + if (!IsToken (SourceFile, EQUAL_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + EQUAL_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + + if (!IsToken (SourceFile, OPEN_BRACE_STRING)) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %S, not %.20S", + OPEN_BRACE_STRING, + SourceFile->FileBufferPtr + ); + goto Done; + } + + while (!EndOfFile (SourceFile)) { + if (IsToken (SourceFile, CLOSE_BRACE_STRING)) { + break; + } + // + // Look for language identifier (3 lowercase chars) + // + if ((SourceFile->FileBufferPtr[0] >= UNICODE_a) && + (SourceFile->FileBufferPtr[0] <= UNICODE_z) && + (SourceFile->FileBufferPtr[1] >= UNICODE_a) && + (SourceFile->FileBufferPtr[1] <= UNICODE_z) && + (SourceFile->FileBufferPtr[2] >= UNICODE_a) && + (SourceFile->FileBufferPtr[2] <= UNICODE_z) && + IsWhiteSpace (SourceFile->FileBufferPtr[3]) + ) { + // + // Write the 3 chars followed by a spacebar, and then look for opening quote + // + fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr); + SourceFile->FileBufferPtr++; + fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr); + SourceFile->FileBufferPtr++; + fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr); + SourceFile->FileBufferPtr++; + fwrite (&Spacebar, sizeof (WCHAR), 1, OutFptr); + StringCount = 0; + while (IsToken (SourceFile, L"\"")) { + StringCount++; + while (!EndOfFile (SourceFile)) { + if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) { + SourceFile->FileBufferPtr++; + break; + } else if ((SourceFile->FileBufferPtr[0] == UNICODE_LF) || (SourceFile->FileBufferPtr[0] == 0)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", NULL); + goto Done; + } else { + fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr); + SourceFile->FileBufferPtr++; + } + } + } + + if (StringCount == 0) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected quoted string, not %.20S", + SourceFile->FileBufferPtr + ); + goto Done; + } + // + // This string's null terminator + // + fwrite (&Zero, sizeof (WCHAR), 1, OutFptr); + } else { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected valid language identifer, not %.20S", + SourceFile->FileBufferPtr + ); + goto Done; + } + } + // + // Double null terminator + // + fwrite (&Zero, sizeof (WCHAR), 1, OutFptr); + Status = STATUS_SUCCESS; +Done: + return Status; +} + +static +STATUS +SplitCapsule ( + INT8 *CapsuleFileName + ) +/*++ + +Routine Description: + We've created an entire capsule image. Now split it up into the + size pieces they requested. + +Arguments: + CapsuleFileName - name of an existing capsule file on disk + +Returns: + STATUS_SUCCESS - if no problems + +Notes: + This implementation reads in the entire capsule image from + disk, then overwrites the original file with the first + in the series. + +--*/ +{ +#if 0 + EFI_CAPSULE_HEADER *CapHdr; + + EFI_CAPSULE_HEADER Hdr; + FILE *CapFptr; + FILE *OutFptr; + UINT32 SizeLeft; + UINT32 CurrentSize; + UINT32 DataSize; + UINT32 SequenceNumber; + INT8 *Buffer; + INT8 FileName[MAX_PATH]; + STATUS Status; + UINT32 FileSize; + // + // Figure out the total size, then rewind the input file and + // read the entire thing in + // + if ((CapFptr = fopen (CapsuleFileName, "rb")) == NULL) { + Error (NULL, 0, 0, CapsuleFileName, "failed to open capsule image for reading"); + return STATUS_ERROR; + } + + OutFptr = NULL; + Status = STATUS_SUCCESS; + fseek (CapFptr, 0, SEEK_END); + SizeLeft = ftell (CapFptr); + fseek (CapFptr, 0, SEEK_SET); + CapHdr = (EFI_CAPSULE_HEADER *) malloc (SizeLeft); + if (CapHdr == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + goto FailDone; + } + + if (fread (CapHdr, SizeLeft, 1, CapFptr) != 1) { + Error (NULL, 0, 0, "failed to read capsule contents", "split failed"); + goto FailDone; + } + + fclose (CapFptr); + CapFptr = NULL; + // + // Get a GUID to fill in the InstanceId GUID in the header + // + CreateGuid (&CapHdr->InstanceId); + SequenceNumber = 0; + // + // If the split size is larger than the original capsule image, then + // we're done. + // + if (mOptions.SizeList->Size >= SizeLeft) { + mOptions.SizeList->Size = SizeLeft; + goto Done; + } + // + // First size has to be big enough for the original header + // + if (mOptions.SizeList->Size < CapHdr->OffsetToCapsuleBody) { + Error (NULL, 0, 0, "first split size is insufficient for the original capsule header", NULL); + goto FailDone; + } + // + // Initialize the header we'll use on all but the first part + // + memset (&Hdr, 0, sizeof (Hdr)); + Hdr.CapsuleGuid = CapHdr->CapsuleGuid; + Hdr.HeaderSize = sizeof (Hdr); + Hdr.Flags = CapHdr->Flags; + Hdr.InstanceId = CapHdr->InstanceId; + Hdr.CapsuleImageSize = CapHdr->CapsuleImageSize; + Hdr.OffsetToCapsuleBody = Hdr.HeaderSize; + Hdr.SequenceNumber = 1; + // + // printf ("Created %s - 0x%X bytes\n", CapsuleFileName, mOptions.SizeList->Size); + // + Buffer = (UINT8 *) CapHdr; + // + // Walk the list of sizes and write out a capsule header, and + // then the raw capsule data. + // + // SizeLeft -= mOptions.SizeList->Size; + // + mOptions.CurrentSize = mOptions.SizeList; + while (SizeLeft) { + CurrentSize = mOptions.CurrentSize->Size; + GetSplitFileName (mOptions.OutputFileName, FileName, SequenceNumber); + if ((OutFptr = fopen (FileName, "wb")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open split file for writing"); + goto FailDone; + } + + if (Buffer == (UINT8 *) CapHdr) { + // + // First part -- write out original header and data + // + if (fwrite (Buffer, CurrentSize, 1, OutFptr) != 1) { + Error (NULL, 0, 0, FileName, "failed to write to split image file"); + goto FailDone; + } + + SizeLeft -= CurrentSize; + Buffer += CurrentSize; + DataSize = CurrentSize; + FileSize = CurrentSize; + } else { + // + // Not the first part. Write the default header, and then the raw bytes from the + // original image. + // + if (CurrentSize <= sizeof (Hdr)) { + Error (NULL, 0, 0, "split size too small for capsule header + data", "0x%X", CurrentSize); + goto FailDone; + } + + DataSize = CurrentSize - sizeof (Hdr); + if (DataSize > SizeLeft) { + DataSize = SizeLeft; + } + + if (fwrite (&Hdr, sizeof (Hdr), 1, OutFptr) != 1) { + Error (NULL, 0, 0, FileName, "failed to write capsule header to output file"); + fclose (OutFptr); + goto FailDone; + } + + if (fwrite (Buffer, DataSize, 1, OutFptr) != 1) { + Error (NULL, 0, 0, FileName, "failed to write capsule data to output file"); + fclose (OutFptr); + goto FailDone; + } + + Hdr.SequenceNumber++; + Buffer += DataSize; + SizeLeft -= DataSize; + FileSize = DataSize + sizeof (Hdr); + } + // + // Next size in list if there is one + // + if (mOptions.CurrentSize->Next != NULL) { + mOptions.CurrentSize = mOptions.CurrentSize->Next; + } + + SequenceNumber++; + fclose (OutFptr); + OutFptr = NULL; + printf ("Created %s - 0x%X bytes (0x%X bytes of data)\n", FileName, FileSize, DataSize); + } + + goto Done; +FailDone: + Status = STATUS_ERROR; +Done: + if (CapHdr != NULL) { + free (CapHdr); + } + + if (CapFptr != NULL) { + fclose (CapFptr); + } + + if (OutFptr != NULL) { + fclose (OutFptr); + } + + return Status; + +#endif + return STATUS_SUCCESS; +} + +static +BOOLEAN +GetSplitFileName ( + INT8 *BaseFileName, + INT8 *NewFileName, + UINT32 SequenceNumber + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + BaseFileName - GC_TODO: add argument description + NewFileName - GC_TODO: add argument description + SequenceNumber - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + /*++ + +Routine Description: + Given an initial split capsule file name and a sequence number, + create an appropriate file name for this split of a capsule image. + +Arguments: + BaseFileName - name of of the first split file in the series + NewFileName - output name of the split file + SequenceNumber - 0-based sequence number of split images + +Returns: + TRUE - name created successfully + FALSE - otherwise + +--*/ + INT8 *Ptr; + INT8 *Part2Start; + UINT32 Digits; + UINT32 Len; + UINT32 BaseOffset; + // + // Work back from the end of the file name and see if there is a number somewhere + // + for (Ptr = BaseFileName + strlen (BaseFileName) - 1; (Ptr > BaseFileName) && !isdigit (*Ptr); Ptr--) + ; + if ((Ptr == BaseFileName) && (!isdigit (*Ptr))) { + // + // Found no number, so just add it to the end + // + sprintf (NewFileName, "%s%d", BaseFileName, SequenceNumber); + return TRUE; + } else { + // + // Found a number. Look back to find the first digit. + // + Part2Start = Ptr + 1; + for (Digits = 1; isdigit (*Ptr) && (Ptr > BaseFileName); Ptr--, Digits++) + ; + if (!isdigit (*Ptr)) { + Ptr++; + Digits--; + } + + BaseOffset = atoi (Ptr); + SequenceNumber = SequenceNumber + BaseOffset; + if (Digits > 1) { + // + // Copy the first part of the original file name to the new filename + // This is the path for filenames with format path\name001.cap + // + Len = (UINT32) Ptr - (UINT32) BaseFileName; + strncpy (NewFileName, BaseFileName, Len); + sprintf (NewFileName + Len, "%0*d", Digits, SequenceNumber); + strcat (NewFileName, Part2Start); + return TRUE; + } else { + // + // Only one digit found. This is the path for filenames with + // format path\name1.cap + // + Len = (UINT32) Ptr - (UINT32) BaseFileName + 1; + strncpy (NewFileName, BaseFileName, Len); + sprintf (NewFileName + Len - 1, "%d", SequenceNumber); + strcat (NewFileName, Part2Start); + return TRUE; + } + } +} + +static +BOOLEAN +IsWhiteSpace ( + WCHAR Char + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Char - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + switch (Char) { + case UNICODE_SPACE: + case UNICODE_TAB: + case UNICODE_NULL: + case UNICODE_CR: + case UNICODE_LF: + return TRUE; + + default: + return FALSE; + } +} + +static +BOOLEAN +IsToken ( + SOURCE_FILE *File, + WCHAR *Token + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + File - GC_TODO: add argument description + Token - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + SkipWhiteSpace (File); + if (EndOfFile (File)) { + return FALSE; + } + + if (wcsncmp (Token, File->FileBufferPtr, wcslen (Token)) == 0) { + File->FileBufferPtr += wcslen (Token); + return TRUE; + } + + return FALSE; +} + +static +STATUS +CheckFirmwareVolumeHeader ( + INT8 *FileName, + INT8 *Buffer, + UINT32 BufferSize + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FileName - GC_TODO: add argument description + Buffer - GC_TODO: add argument description + BufferSize - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *Hdr; + EFI_GUID FVHeaderGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID; + + Hdr = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer; + if (Hdr->Signature != EFI_FVH_SIGNATURE) { + Error (NULL, 0, 0, FileName, "file does not appear to be a firmware volume (bad signature)"); + return STATUS_ERROR; + } + + if (Hdr->Revision != EFI_FVH_REVISION) { + Error (NULL, 0, 0, FileName, "unsupported firmware volume header version"); + return STATUS_ERROR; + } + + if (Hdr->FvLength > BufferSize) { + Error (NULL, 0, 0, FileName, "malformed firmware volume -- FvLength > file size"); + return STATUS_ERROR; + } + + if (memcmp (&Hdr->FileSystemGuid, &FVHeaderGuid, sizeof (EFI_GUID)) != 0) { + Error (NULL, 0, 0, FileName, "invalid FFS GUID in firmware volume header"); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +void +DumpCapsule ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +{ +#if 0 + FILE *InFptr; + FILE_LIST *FileList; + EFI_CAPSULE_HEADER CapsuleHeader; + EFI_FIRMWARE_VOLUME_HEADER FVHeader; + EFI_CAPSULE_OEM_HEADER *OemHeader; + UINT8 *BPtr; + UINT32 FileSize; + UINT32 CapsuleHeaderDataSize; + UINT8 ByteCount; + UINT8 *CapsuleHeaderData; + BOOLEAN SplitImage; + + InFptr = NULL; + CapsuleHeaderData = NULL; + FileList = mOptions.FileList; + while (FileList != NULL) { + if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) { + Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading"); + goto Done; + } + + if (fread (&CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, InFptr) != 1) { + Error (NULL, 0, 0, FileList->FileName, "failed to read capsule header"); + goto Done; + } + + fseek (InFptr, 0, SEEK_END); + FileSize = ftell (InFptr); + if (CapsuleHeader.CapsuleImageSize > FileSize) { + SplitImage = TRUE; + } else { + SplitImage = FALSE; + } + + printf ( + "Capsule %s Size=0x%X CargoSize=0x%X\n", + FileList->FileName, + FileSize, + FileSize - CapsuleHeader.OffsetToCapsuleBody + ); + printf ( + " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + CapsuleHeader.CapsuleGuid.Data1, + (UINT32) CapsuleHeader.CapsuleGuid.Data2, + (UINT32) CapsuleHeader.CapsuleGuid.Data3, + (UINT32) CapsuleHeader.CapsuleGuid.Data4[0], + (UINT32) CapsuleHeader.CapsuleGuid.Data4[1], + (UINT32) CapsuleHeader.CapsuleGuid.Data4[2], + (UINT32) CapsuleHeader.CapsuleGuid.Data4[3], + (UINT32) CapsuleHeader.CapsuleGuid.Data4[4], + (UINT32) CapsuleHeader.CapsuleGuid.Data4[5], + (UINT32) CapsuleHeader.CapsuleGuid.Data4[6], + (UINT32) CapsuleHeader.CapsuleGuid.Data4[7] + ); + if (memcmp (&CapsuleHeader.CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) { + printf (" INVALID GUID"); + } + + printf ("\n"); + printf (" Header size 0x%08X\n", CapsuleHeader.HeaderSize); + printf (" Flags 0x%08X\n", CapsuleHeader.Flags); + if (!SplitImage) { + printf (" Capsule image size 0x%08X\n", CapsuleHeader.CapsuleImageSize); + } else { + printf (" Capsule image size 0x%08X (split)\n", CapsuleHeader.CapsuleImageSize); + } + + printf (" Sequence number %d\n", CapsuleHeader.SequenceNumber); + printf ( + " InstanceId %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", + CapsuleHeader.InstanceId.Data1, + (UINT32) CapsuleHeader.InstanceId.Data2, + (UINT32) CapsuleHeader.InstanceId.Data3, + (UINT32) CapsuleHeader.InstanceId.Data4[0], + (UINT32) CapsuleHeader.InstanceId.Data4[1], + (UINT32) CapsuleHeader.InstanceId.Data4[2], + (UINT32) CapsuleHeader.InstanceId.Data4[3], + (UINT32) CapsuleHeader.InstanceId.Data4[4], + (UINT32) CapsuleHeader.InstanceId.Data4[5], + (UINT32) CapsuleHeader.InstanceId.Data4[6], + (UINT32) CapsuleHeader.InstanceId.Data4[7] + ); + printf (" Offset to capsule 0x%X\n", CapsuleHeader.OffsetToCapsuleBody); + // + // Dump header data if there + // + CapsuleHeaderDataSize = CapsuleHeader.OffsetToCapsuleBody - CapsuleHeader.HeaderSize; + if (CapsuleHeaderDataSize != 0) { + CapsuleHeaderData = (UINT8 *) malloc (CapsuleHeaderDataSize); + if (CapsuleHeaderData == NULL) { + Error ( + NULL, + 0, + 0, + "failed to allocate memory to read in capsule header data", + "0x%X bytes", + CapsuleHeaderDataSize + ); + goto Done; + } + + fseek (InFptr, CapsuleHeader.HeaderSize, SEEK_SET); + if (fread (CapsuleHeaderData, CapsuleHeaderDataSize, 1, InFptr) != 1) { + Error ( + NULL, + 0, + 0, + "failed to read capsule header data contents from file", + "0x%X bytes", + CapsuleHeaderDataSize + ); + goto Done; + } + // + // ************************************************************************ + // + // OEM HEADER + // + // ************************************************************************ + // + if (CapsuleHeader.OffsetToOemDefinedHeader != 0) { + OemHeader = (EFI_CAPSULE_OEM_HEADER *) (CapsuleHeaderData + CapsuleHeader.OffsetToOemDefinedHeader - CapsuleHeader.HeaderSize); + printf (" OEM Header\n"); + printf ( + " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", + OemHeader->OemGuid.Data1, + (UINT32) OemHeader->OemGuid.Data2, + (UINT32) OemHeader->OemGuid.Data3, + (UINT32) OemHeader->OemGuid.Data4[0], + (UINT32) OemHeader->OemGuid.Data4[1], + (UINT32) OemHeader->OemGuid.Data4[2], + (UINT32) OemHeader->OemGuid.Data4[3], + (UINT32) OemHeader->OemGuid.Data4[4], + (UINT32) OemHeader->OemGuid.Data4[5], + (UINT32) OemHeader->OemGuid.Data4[6], + (UINT32) OemHeader->OemGuid.Data4[7] + ); + printf (" Header size: 0x%X\n", OemHeader->HeaderSize); + printf (" OEM data"); + BPtr = (UINT8 *) (OemHeader + 1); + for (ByteCount = 0; ByteCount < OemHeader->HeaderSize - sizeof (EFI_CAPSULE_OEM_HEADER); ByteCount++) { + if ((ByteCount & 0x7) == 0) { + printf ("\n "); + } + + printf ("%02X ", (UINT32) *BPtr); + BPtr++; + } + + printf ("\n"); + } + // + // ************************************************************************ + // + // Author, revision, short description, and long description information + // + // ************************************************************************ + // + if (CapsuleHeader.OffsetToAuthorInformation != 0) { + if (DumpCapsuleHeaderStrings ( + "Author information", + (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToAuthorInformation - CapsuleHeader.HeaderSize) + ) != STATUS_SUCCESS) { + goto Done; + } + } + + if (CapsuleHeader.OffsetToRevisionInformation != 0) { + if (DumpCapsuleHeaderStrings ( + "Revision information", + (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToRevisionInformation - CapsuleHeader.HeaderSize) + ) != STATUS_SUCCESS) { + goto Done; + } + } + + if (CapsuleHeader.OffsetToShortDescription != 0) { + if (DumpCapsuleHeaderStrings ( + "Short description", + (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToShortDescription - CapsuleHeader.HeaderSize) + ) != STATUS_SUCCESS) { + goto Done; + } + } + + if (CapsuleHeader.OffsetToLongDescription != 0) { + if (DumpCapsuleHeaderStrings ( + "Long description", + (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToLongDescription - CapsuleHeader.HeaderSize) + ) != STATUS_SUCCESS) { + goto Done; + } + } + } + // + // If it's not a split image, or it is a split image and this is the first in the series, then + // dump the cargo volume. + // + if ((!SplitImage) || (CapsuleHeader.SequenceNumber == 0)) { + printf (" Cargo FV dump\n"); + fseek (InFptr, CapsuleHeader.OffsetToCapsuleBody, SEEK_SET); + if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) != 1) { + Error (NULL, 0, 0, FileList->FileName, "failed to read cargo FV header"); + goto Done; + } + + printf (" FV length 0x%X", FVHeader.FvLength); + if (FileSize - CapsuleHeader.OffsetToCapsuleBody != FVHeader.FvLength) { + if (!SplitImage) { + printf (" ERROR: expected 0x%X to jive with file size on disk", FileSize - CapsuleHeader.OffsetToCapsuleBody); + } + } + + printf ("\n"); + printf (" Signature 0x%X ", FVHeader.Signature); + if (FVHeader.Signature == EFI_FVH_SIGNATURE) { + printf ("_FVH\n"); + } else { + printf ("INVALID\n"); + } + + printf (" FV header length 0x%X\n", (UINT32) FVHeader.HeaderLength); + printf (" Revision 0x%X\n", (UINT32) FVHeader.Revision); + printf ("\n"); + } + + FileList = FileList->Next; + } + +Done: + if (InFptr != NULL) { + fclose (InFptr); + } + + if (CapsuleHeaderData != NULL) { + free (CapsuleHeaderData); + } +#endif +} + +static +STATUS +JoinCapsule ( + VOID + ) +/*++ + +Routine Description: + Join split capsule images into a single image. This is the + support function for the -j command-line option. + +Arguments: + None. + +Returns: + STATUS_SUCCESS - no problems encountered + +--*/ +{ +#if 0 + UINT32 Size; + FILE *InFptr; + FILE *OutFptr; + INT8 *Buffer; + FILE_LIST *FileList; + STATUS Status; + EFI_CAPSULE_HEADER CapHdr; + EFI_CAPSULE_HEADER *CapHdrPtr; + UINT32 SizeLeft; + UINT32 SequenceNumber; + // + // Must have at least two files for join mode + // + if ((mOptions.FileList == NULL) || (mOptions.FileList->Next == NULL)) { + Error (NULL, 0, 0, "must specify at least two file names to join", NULL); + return STATUS_ERROR; + } + // + // Open the output file + // + if ((OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + + FileList = mOptions.FileList; + Buffer = NULL; + SequenceNumber = 0; + InFptr = NULL; + SizeLeft = 0; + while (FileList != NULL) { + if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) { + Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading"); + goto FailDone; + } + // + // Allocate a buffer into which we can read the file. + // + fseek (InFptr, 0, SEEK_END); + Size = ftell (InFptr); + rewind (InFptr); + Buffer = (char *) malloc (Size); + if (Buffer == NULL) { + Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into"); + goto FailDone; + } + + CapHdrPtr = (EFI_CAPSULE_HEADER *) Buffer; + if (fread ((void *) Buffer, Size, 1, InFptr) != 1) { + Error (NULL, 0, 0, FileList->FileName, "failed to read file contents"); + goto FailDone; + } + // + // Check the header for validity. Check size first. + // + if (Size < sizeof (EFI_CAPSULE_HEADER)) { + Error (NULL, 0, 0, FileList->FileName, "file size is insufficient for a capsule header"); + goto FailDone; + } + // + // Check GUID + // + if (memcmp (&CapHdrPtr->CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) { + Error (NULL, 0, 0, FileList->FileName, "invalid capsule GUID"); + goto FailDone; + } + // + // Check sequence number + // + if (CapHdrPtr->SequenceNumber != SequenceNumber) { + Error ( + NULL, + 0, + 0, + FileList->FileName, + "invalid sequence number %d (expected %d)", + CapHdrPtr->SequenceNumber, + SequenceNumber + ); + goto FailDone; + } + // + // If the first file, read save the capsule header + // + if (SequenceNumber == 0) { + memcpy (&CapHdr, CapHdrPtr, sizeof (EFI_CAPSULE_HEADER)); + // + // Erase the InstanceId GUID + // + memset (&CapHdrPtr->InstanceId, 0, sizeof (EFI_GUID)); + if (fwrite (Buffer, Size, 1, OutFptr) != 1) { + Error (NULL, 0, 0, FileList->FileName, "failed to write contents to output file"); + goto FailDone; + } + + if (CapHdr.CapsuleImageSize < Size) { + Error (NULL, 0, 0, FileList->FileName, "capsule image size in capsule header < image size"); + goto FailDone; + } + + SizeLeft = CapHdr.CapsuleImageSize - Size; + } else { + // + // Check the GUID against the first file's GUID + // + if (memcmp (&CapHdr.CapsuleGuid, &CapHdrPtr->CapsuleGuid, sizeof (EFI_GUID)) != 0) { + Error (NULL, 0, 0, FileList->FileName, "GUID does not match first file's GUID"); + goto FailDone; + } + // + // Make sure we're not throwing out any header info + // + if (CapHdrPtr->OffsetToCapsuleBody > sizeof (EFI_CAPSULE_HEADER)) { + // + // Could be the split information, so just emit a warning + // + Warning ( + NULL, + 0, + 0, + FileList->FileName, + "image appears to have additional capsule header information -- ignoring" + ); + } else if (CapHdrPtr->OffsetToCapsuleBody < sizeof (EFI_CAPSULE_HEADER)) { + Error (NULL, 0, 0, FileList->FileName, "offset to capsule body in capsule header is insufficient"); + goto FailDone; + } + + if (fwrite (Buffer + CapHdrPtr->OffsetToCapsuleBody, Size - CapHdrPtr->OffsetToCapsuleBody, 1, OutFptr) != 1) { + Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file"); + goto FailDone; + } + + if (SizeLeft < (Size - CapHdrPtr->OffsetToCapsuleBody)) { + Error (NULL, 0, 0, "sum of image sizes exceeds size specified in initial capsule header", NULL); + goto FailDone; + } + // + // printf ("FILE: %s OffsetToCapsuleBody=0x%X\n", FileList->FileName, CapHdrPtr->OffsetToCapsuleBody); + // + SizeLeft = SizeLeft - (Size - CapHdrPtr->OffsetToCapsuleBody); + } + // + // printf ("FILE: %s sizeleft=0x%X\n", FileList->FileName, SizeLeft); + // + fclose (InFptr); + InFptr = NULL; + free (Buffer); + Buffer = NULL; + FileList = FileList->Next; + SequenceNumber++; + } + + if (SizeLeft) { + Error (NULL, 0, 0, "sum of capsule images is insufficient", "0x%X bytes missing", SizeLeft); + goto FailDone; + } + + Status = STATUS_SUCCESS; + goto Done; +FailDone: + Status = STATUS_ERROR; +Done: + if (InFptr != NULL) { + fclose (InFptr); + } + + if (OutFptr != NULL) { + fclose (OutFptr); + } + + if (Buffer != NULL) { + free (Buffer); + } + + return Status; + +#endif +return STATUS_SUCCESS; +} + +static +STATUS +DumpCapsuleHeaderStrings ( + UINT8 *SectionName, + WCHAR *Buffer + ) +/*++ + +Routine Description: + Given a pointer to string data from a capsule header, dump + the strings. + +Arguments: + SectionName - name of the capsule header section to which + the string data pertains + Buffer - pointer to string data from a capsule header + +Returns: + STATUS_SUCCESS - all went well + +--*/ +{ + printf (" %s\n", SectionName); + while (*Buffer) { + printf (" Language: %S\n", Buffer); + while (*Buffer) { + Buffer++; + } + + Buffer++; + while (*Buffer) { + if (wcslen (Buffer) > 60) { + printf (" %.60S\n", Buffer); + Buffer += 60; + } else { + printf (" %S\n", Buffer); + Buffer += wcslen (Buffer); + } + } + + Buffer++; + } + + return STATUS_SUCCESS; +} + +static +STATUS +GetHexValue ( + SOURCE_FILE *SourceFile, + UINT32 *Value, + UINT32 NumDigits + ) +/*++ + +Routine Description: + Scan a hex value from the input stream. + +Arguments: + SourceFile - input file contents + Value - returned value + NumDigits - number of digits to read + +Returns: + STATUS_SUCCESS - if NumDigits were read from the file + STATUS_ERROR - otherwise + + +--*/ +{ + WCHAR *SaveFilePos; + UINT32 Digits; + WCHAR Nibble; + + SaveFilePos = SourceFile->FileBufferPtr; + *Value = 0; + Digits = NumDigits; + while (Digits > 0) { + Nibble = SourceFile->FileBufferPtr[0]; + if ((Nibble >= UNICODE_0) && (Nibble <= UNICODE_9)) { + *Value = (*Value << 4) | (Nibble - UNICODE_0); + } else if ((Nibble >= UNICODE_A) && (Nibble <= UNICODE_F)) { + *Value = (*Value << 4) | (Nibble - UNICODE_A + 0x10); + } else if ((Nibble >= UNICODE_a) && (Nibble <= UNICODE_f)) { + *Value = (*Value << 4) | (Nibble - UNICODE_a + 0x10); + } else { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + NULL, + "expected %d valid hex nibbles at %.20S", + NumDigits, + SaveFilePos + ); + return STATUS_ERROR; + } + + SourceFile->FileBufferPtr++; + Digits--; + } + + return STATUS_SUCCESS; +} + +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *File + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + File - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + if ((UINT32) File->FileBufferPtr - (UINT32) File->FileBuffer >= File->FileSize) { + File->EndOfFile = TRUE; + } + // + // Reposition to the end of the file if we went beyond + // + if (File->EndOfFile) { + File->FileBufferPtr = File->FileBuffer + File->FileSize / sizeof (WCHAR); + } + + return File->EndOfFile; +} + +static +void +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + SourceFile - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + while (!EndOfFile (SourceFile)) { + switch (*SourceFile->FileBufferPtr) { + case UNICODE_NULL: + case UNICODE_CR: + case UNICODE_SPACE: + case UNICODE_TAB: + SourceFile->FileBufferPtr++; + break; + + case UNICODE_LF: + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + break; + + default: + return ; + } + } +} +// +// Parse a number. Possible format: +// 1234 +// 1234k +// 1234K +// 1M +// 1m +// 0x100 +// +static +BOOLEAN +GetNumber ( + INT8 *Str, + UINT32 *Value + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Str - GC_TODO: add argument description + Value - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + UINT32 LValue; + + *Value = 0; + LValue = 0; + if (!isdigit (Str[0])) { + return FALSE; + } + // + // Look for hex number + // + if ((Str[0] == '0') && (tolower (Str[1]) == 'x')) { + Str += 2; + if (Str[0] == 0) { + return FALSE; + } + + while (Str[0]) { + if ((Str[0] >= '0') && (Str[0] <= '9')) { + LValue = (LValue << 4) | (Str[0] - '0'); + } else if ((Str[0] >= 'A') && (Str[0] <= 'F')) { + LValue = (LValue << 4) | (Str[0] - 'A' + 0x10); + } else if ((Str[0] >= 'a') && (Str[0] <= 'f')) { + LValue = (LValue << 4) | (Str[0] - 'a' + 0x10); + } else { + break; + } + + Str++; + } + } else { + LValue = atoi (Str); + while (isdigit (*Str)) { + Str++; + } + } + // + // If string left over, better be one character we recognize + // + if (Str[0]) { + if (Str[1]) { + return FALSE; + } + + switch (Str[0]) { + case 'k': + case 'K': + LValue *= 1024; + break; + + case 'm': + case 'M': + LValue *= 1024 * 1024; + break; + + default: + return FALSE; + } + } + + *Value = LValue; + return TRUE; +} +// +// Process the command-line arguments +// +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + + Processes command line arguments. + +Arguments: + + Argc - Number of command line arguments + Argv[] - Array of files input on command line + +Returns: + + STATUS_ERROR - Function exited with an error + STATUS_SUCCESS - Function executed successfully + +--*/ +{ + FILE_LIST *NewFile; + + FILE_LIST *LastFile; + SIZE_LIST *NewSize; + + NewFile = NULL; + NewSize = NULL; + + // + // Clear our globals + // + memset ((char *) &mOptions, 0, sizeof (mOptions)); + + // + // Skip program name + // + Argc--; + Argv++; + + if (Argc == 0) { + Usage (); + return STATUS_ERROR; + } + // + // Process until no more options + // + while ((Argc > 0) && (Argv[0][0] == '-')) { + if (stricmp (Argv[0], "-script") == 0) { + // + // Check for one more arg + // + if (Argc > 1) { + // + // Save the file name + // + if (strlen (Argv[1]) >= sizeof (mOptions.ScriptFileName)) { + Error (NULL, 0, 0, NULL, "input script file name length exceeds internal buffer size"); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + strcpy (mOptions.ScriptFileName, Argv[1]); + } else { + Error (NULL, 0, 0, Argv[0], "missing script file name with option"); + Usage (); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + Argc--; + Argv++; + // + // -o outfilename -- specify output file name (required) + // + } else if (stricmp (Argv[0], "-o") == 0) { + // + // check for one more arg + // + if (Argc > 1) { + // + // Try to open the file + // + // if ((mOptions.OutFptr = fopen (Argv[1], "wb")) == NULL) { + // Error (NULL, 0, 0, Argv[1], "failed to open output file for writing"); + // return STATUS_ERROR; + // } + // + strcpy (mOptions.OutputFileName, Argv[1]); + } else { + Error (NULL, 0, 0, Argv[0], "missing output filename with option"); + Usage (); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-j") == 0) { + mOptions.JoinMode = TRUE; + // + // -split option (multiple allowed) + // + } else if (stricmp (Argv[0], "-split") == 0) { + if (Argc > 1) { + NewSize = (SIZE_LIST *) malloc (sizeof (SIZE_LIST)); + if (NewSize == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + memset (NewSize, 0, sizeof (SIZE_LIST)); + // + // Get the size from the next arg, and then add this size + // to our size list + // + if (!GetNumber (Argv[1], &NewSize->Size)) { + Error (NULL, 0, 0, Argv[1], "invalid split size argument"); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + if (mOptions.SizeList == NULL) { + mOptions.SizeList = NewSize; + mOptions.CurrentSize = NewSize; + } else { + mOptions.LastSize->Next = NewSize; + } + + mOptions.LastSize = NewSize; + free (NewSize); + } else { + Error (NULL, 0, 0, Argv[0], "missing size parameter with option"); + Usage (); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) { + Usage (); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + // + // Default minimum header + // + } else if (stricmp (Argv[0], "-dump") == 0) { + mOptions.Dump = TRUE; + } else if (stricmp (Argv[0], "-v") == 0) { + mOptions.Verbose = TRUE; + } else { + Error (NULL, 0, 0, Argv[0], "unrecognized option"); + Usage (); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + Argc--; + Argv++; + } + // + // Can't -j join files and -s split output capsule + // + if ((mOptions.SizeList != NULL) && (mOptions.JoinMode)) { + Error (NULL, 0, 0, "cannot specify both -j and -size", NULL); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + // + // Must have specified an output file name if not -dump + // + if ((mOptions.Dump == 0) && (mOptions.OutputFileName[0] == 0)) { + Error (NULL, 0, 0, NULL, "-o OutputFileName must be specified"); + Usage (); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + // + // Rest of arguments are input files. The first one is a firmware + // volume image, and the rest are FFS files that are to be inserted + // into the firmware volume. + // + LastFile = NULL; + while (Argc > 0) { + NewFile = (FILE_LIST *) malloc (sizeof (FILE_LIST)); + if (NewFile == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + memset ((char *) NewFile, 0, sizeof (FILE_LIST)); + strcpy (NewFile->FileName, Argv[0]); + if (mOptions.FileList == NULL) { + mOptions.FileList = NewFile; + } else { + if (LastFile == NULL) { + LastFile = NewFile; + } else { + LastFile->Next = NewFile; + } + } + + LastFile = NewFile; + Argc--; + Argv++; + } + + // + // Must have provided at least one file name + // + if (mOptions.FileList == NULL) { + Error (NULL, 0, 0, "must specify at least one file name", NULL); + Usage (); + + if (NewFile != NULL) { + free (NewFile); + } + if (NewSize != NULL) { + free (NewSize); + } + + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print usage information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. + +--*/ +{ + int Index; + static const char *Str[] = { + PROGRAM_NAME " -- create a capsule header", + " Usage: "PROGRAM_NAME " {options} [CapsuleFV]", + // + // {FfsFileNames}", + // + " Options include:", + " -h or -? for this help information", + " -script fname to take capsule header info from unicode script", + " file fname", + " -o fname write output to file fname (required)", + " -split size split capsule image into multiple output files", + " -dump to dump a capsule header", + " -v for verbose output\n", + " -j to join split capsule images into a single image", + "", + " CapsuleFV is the name of an existing well-formed Tiano firmware", + " volume file.", + // + // FfsFileNames are the names of one or more Tiano FFS files to", + // " insert into the output capsule image.", + // + NULL + }; + for (Index = 0; Str[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Str[Index]); + } +} diff --git a/Tools/CodeTools/Source/GenCapsuleHdr/build.xml b/Tools/CodeTools/Source/GenCapsuleHdr/build.xml new file mode 100644 index 0000000000..7c43d0a347 --- /dev/null +++ b/Tools/CodeTools/Source/GenCapsuleHdr/build.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3