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