From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001
From: Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com>
Date: Tue, 10 Oct 2023 14:33:42 +0000
Subject: Add submodule dependency files

Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
---
 roms/edk2/BaseTools/Source/C/GenSec/GenSec.c | 1811 ++++++++++++++++++++++++++
 1 file changed, 1811 insertions(+)
 create mode 100644 roms/edk2/BaseTools/Source/C/GenSec/GenSec.c

(limited to 'roms/edk2/BaseTools/Source/C/GenSec/GenSec.c')

diff --git a/roms/edk2/BaseTools/Source/C/GenSec/GenSec.c b/roms/edk2/BaseTools/Source/C/GenSec/GenSec.c
new file mode 100644
index 000000000..d54a4f9e0
--- /dev/null
+++ b/roms/edk2/BaseTools/Source/C/GenSec/GenSec.c
@@ -0,0 +1,1811 @@
+/** @file
+Creates output file that is a properly formed section per the PI spec.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef __GNUC__
+#include <windows.h>
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/PiFirmwareFile.h>
+#include <Protocol/GuidedSectionExtraction.h>
+#include <IndustryStandard/PeImage.h>
+
+#include "CommonLib.h"
+#include "Compress.h"
+#include "Crc32.h"
+#include "EfiUtilityMsgs.h"
+#include "ParseInf.h"
+#include "FvLib.h"
+#include "PeCoffLib.h"
+
+//
+// GenSec Tool Information
+//
+#define UTILITY_NAME            "GenSec"
+#define UTILITY_MAJOR_VERSION   0
+#define UTILITY_MINOR_VERSION   1
+
+STATIC CHAR8      *mSectionTypeName[] = {
+  NULL,                                 // 0x00 - reserved
+  "EFI_SECTION_COMPRESSION",            // 0x01
+  "EFI_SECTION_GUID_DEFINED",           // 0x02
+  NULL,                                 // 0x03 - reserved
+  NULL,                                 // 0x04 - reserved
+  NULL,                                 // 0x05 - reserved
+  NULL,                                 // 0x06 - reserved
+  NULL,                                 // 0x07 - reserved
+  NULL,                                 // 0x08 - reserved
+  NULL,                                 // 0x09 - reserved
+  NULL,                                 // 0x0A - reserved
+  NULL,                                 // 0x0B - reserved
+  NULL,                                 // 0x0C - reserved
+  NULL,                                 // 0x0D - reserved
+  NULL,                                 // 0x0E - reserved
+  NULL,                                 // 0x0F - reserved
+  "EFI_SECTION_PE32",                   // 0x10
+  "EFI_SECTION_PIC",                    // 0x11
+  "EFI_SECTION_TE",                     // 0x12
+  "EFI_SECTION_DXE_DEPEX",              // 0x13
+  "EFI_SECTION_VERSION",                // 0x14
+  "EFI_SECTION_USER_INTERFACE",         // 0x15
+  "EFI_SECTION_COMPATIBILITY16",        // 0x16
+  "EFI_SECTION_FIRMWARE_VOLUME_IMAGE",  // 0x17
+  "EFI_SECTION_FREEFORM_SUBTYPE_GUID",  // 0x18
+  "EFI_SECTION_RAW",                    // 0x19
+  NULL,                                 // 0x1A
+  "EFI_SECTION_PEI_DEPEX",              // 0x1B
+  "EFI_SECTION_SMM_DEPEX"               // 0x1C
+};
+
+STATIC CHAR8      *mCompressionTypeName[]    = { "PI_NONE", "PI_STD" };
+
+#define EFI_GUIDED_SECTION_NONE 0x80
+STATIC CHAR8      *mGUIDedSectionAttribue[]  = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
+
+STATIC CHAR8 *mAlignName[] = {
+  "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
+  "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",
+  "512K", "1M", "2M", "4M", "8M", "16M"
+};
+
+//
+// Crc32 GUID section related definitions.
+//
+typedef struct {
+  EFI_GUID_DEFINED_SECTION  GuidSectionHeader;
+  UINT32                    CRC32Checksum;
+} CRC32_SECTION_HEADER;
+
+typedef struct {
+  EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;
+  UINT32                    CRC32Checksum;
+} CRC32_SECTION_HEADER2;
+
+STATIC EFI_GUID  mZeroGuid                 = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
+STATIC EFI_GUID  mEfiCrc32SectionGuid      = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
+
+STATIC
+VOID
+Version (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Print out version information for this utility.
+
+Arguments:
+
+  None
+
+Returns:
+
+  None
+
+--*/
+{
+  fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
+}
+
+STATIC
+VOID
+Usage (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Print Help message.
+
+Arguments:
+
+  VOID
+
+Returns:
+
+  None
+
+--*/
+{
+  //
+  // Summary usage
+  //
+  fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);
+
+  //
+  // Copyright declaration
+  //
+  fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
+
+  //
+  // Details Option
+  //
+  fprintf (stdout, "Options:\n");
+  fprintf (stdout, "  -o FileName, --outputfile FileName\n\
+                        File is the SectionFile to be created.\n");
+  fprintf (stdout, "  -s [SectionType], --sectiontype [SectionType]\n\
+                        SectionType defined in PI spec is one type of\n\
+                        EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
+                        EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
+                        EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
+                        EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
+                        EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
+                        EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
+                        EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
+                        if -s option is not given, \n\
+                        EFI_SECTION_ALL is default section type.\n");
+  fprintf (stdout, "  -c [Type], --compress [Type]\n\
+                        Compress method type can be PI_NONE or PI_STD.\n\
+                        if -c option is not given, PI_STD is default type.\n");
+  fprintf (stdout, "  -g GuidValue, --vendor GuidValue\n\
+                        GuidValue is one specific vendor guid value.\n\
+                        Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
+  fprintf (stdout, "  -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
+                        GuidHeaderLength is the size of header of guided data\n");
+  fprintf (stdout, "  -r GuidAttr, --attributes GuidAttr\n\
+                        GuidAttr is guid section attributes, which may be\n\
+                        PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
+                        if -r option is not given, default PROCESSING_REQUIRED\n");
+  fprintf (stdout, "  -n String, --name String\n\
+                        String is a NULL terminated string used in Ui section.\n");
+  fprintf (stdout, "  -j Number, --buildnumber Number\n\
+                        Number is an integer value between 0 and 65535\n\
+                        used in Ver section.\n");
+  fprintf (stdout, "  --sectionalign SectionAlign\n\
+                        SectionAlign points to section alignment, which support\n\
+                        the alignment scope 0~16M. If SectionAlign is specified\n\
+                        as 0, tool get alignment value from SectionFile. It is\n\
+                        specified in same order that the section file is input.\n");
+  fprintf (stdout, "  --dummy dummyfile\n\
+                        compare dummpyfile with input_file to decide whether\n\
+                        need to set PROCESSING_REQUIRED attribute.\n");
+  fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");
+  fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");
+  fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");
+  fprintf (stdout, "  --version             Show program's version number and exit.\n");
+  fprintf (stdout, "  -h, --help            Show this help message and exit.\n");
+}
+
+VOID
+Ascii2UnicodeString (
+  CHAR8    *String,
+  CHAR16   *UniString
+  )
+/*++
+
+Routine Description:
+
+  Write ascii string as unicode string format to FILE
+
+Arguments:
+
+  String      - Pointer to string that is written to FILE.
+  UniString   - Pointer to unicode string
+
+Returns:
+
+  NULL
+
+--*/
+{
+  while (*String != '\0') {
+    *(UniString++) = (CHAR16) *(String++);
+  }
+  //
+  // End the UniString with a NULL.
+  //
+  *UniString = '\0';
+}
+
+STATUS
+GenSectionCommonLeafSection (
+  CHAR8   **InputFileName,
+  UINT32  InputFileNum,
+  UINT8   SectionType,
+  UINT8   **OutFileBuffer
+  )
+/*++
+
+Routine Description:
+
+  Generate a leaf section of type other than EFI_SECTION_VERSION
+  and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
+  The function won't validate the input file's contents. For
+  common leaf sections, the input file may be a binary file.
+  The utility will add section header to the file.
+
+Arguments:
+
+  InputFileName  - Name of the input file.
+
+  InputFileNum   - Number of input files. Should be 1 for leaf section.
+
+  SectionType    - A valid section type string
+
+  OutFileBuffer  - Buffer pointer to Output file contents
+
+Returns:
+
+  STATUS_ERROR            - can't continue
+  STATUS_SUCCESS          - successful return
+
+--*/
+{
+  UINT32                    InputFileLength;
+  FILE                      *InFile;
+  UINT8                     *Buffer;
+  UINT32                    TotalLength;
+  UINT32                    HeaderLength;
+  EFI_COMMON_SECTION_HEADER *CommonSect;
+  STATUS                    Status;
+
+  if (InputFileNum > 1) {
+    Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");
+    return STATUS_ERROR;
+  } else if (InputFileNum < 1) {
+    Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");
+    return STATUS_ERROR;
+  }
+  //
+  // Open the input file
+  //
+  InFile = fopen (LongFilePath (InputFileName[0]), "rb");
+  if (InFile == NULL) {
+    Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);
+    return STATUS_ERROR;
+  }
+
+  Status  = STATUS_ERROR;
+  Buffer  = NULL;
+  //
+  // Seek to the end of the input file so we can determine its size
+  //
+  fseek (InFile, 0, SEEK_END);
+  InputFileLength = ftell (InFile);
+  fseek (InFile, 0, SEEK_SET);
+  DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength);
+  TotalLength     = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;
+  //
+  // Size must fit in 3 bytes
+  //
+  //if (TotalLength >= MAX_SECTION_SIZE) {
+  //  Error (NULL, 0, 2000, "Invalid parameter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);
+  //  goto Done;
+  //}
+  HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);
+  if (TotalLength >= MAX_SECTION_SIZE) {
+    TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;
+    HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);
+  }
+  VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
+  //
+  // Fill in the fields in the local section header structure
+  //
+  Buffer = (UINT8 *) malloc ((size_t) TotalLength);
+  if (Buffer == NULL) {
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+    goto Done;
+  }
+  CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;
+  CommonSect->Type     = SectionType;
+  if (TotalLength < MAX_SECTION_SIZE) {
+    CommonSect->Size[0]  = (UINT8) (TotalLength & 0xff);
+    CommonSect->Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
+    CommonSect->Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
+  } else {
+    memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3);
+    ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength;
+  }
+
+  //
+  // read data from the input file.
+  //
+  if (InputFileLength != 0) {
+    if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {
+      Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);
+      goto Done;
+    }
+  }
+
+  //
+  // Set OutFileBuffer
+  //
+  *OutFileBuffer = Buffer;
+  Status = STATUS_SUCCESS;
+
+Done:
+  fclose (InFile);
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+StringtoAlignment (
+  IN  CHAR8  *AlignBuffer,
+  OUT UINT32 *AlignNumber
+  )
+/*++
+
+Routine Description:
+
+  Converts Align String to align value (1~16M).
+
+Arguments:
+
+  AlignBuffer    - Pointer to Align string.
+  AlignNumber    - Pointer to Align value.
+
+Returns:
+
+  EFI_SUCCESS             Successfully convert align string to align value.
+  EFI_INVALID_PARAMETER   Align string is invalid or align value is not in scope.
+
+--*/
+{
+  UINT32 Index = 0;
+  //
+  // Check AlignBuffer
+  //
+  if (AlignBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {
+    if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {
+      *AlignNumber = 1 << Index;
+      return EFI_SUCCESS;
+    }
+  }
+  return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+GetSectionContents (
+  CHAR8   **InputFileName,
+  UINT32  *InputFileAlign,
+  UINT32  InputFileNum,
+  UINT8   *FileBuffer,
+  UINT32  *BufferLength
+  )
+/*++
+
+Routine Description:
+
+  Get the contents of all section files specified in InputFileName
+  into FileBuffer.
+
+Arguments:
+
+  InputFileName  - Name of the input file.
+
+  InputFileAlign - Alignment required by the input file data.
+
+  InputFileNum   - Number of input files. Should be at least 1.
+
+  FileBuffer     - Output buffer to contain data
+
+  BufferLength   - On input, this is size of the FileBuffer.
+                   On output, this is the actual length of the data.
+
+Returns:
+
+  EFI_SUCCESS on successful return
+  EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
+  EFI_ABORTED if unable to open input file.
+  EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
+--*/
+{
+  UINT32                     Size;
+  UINT32                     Offset;
+  UINT32                     FileSize;
+  UINT32                     Index;
+  FILE                       *InFile;
+  EFI_COMMON_SECTION_HEADER  *SectHeader;
+  EFI_COMMON_SECTION_HEADER2 TempSectHeader;
+  EFI_TE_IMAGE_HEADER        TeHeader;
+  UINT32                     TeOffset;
+  EFI_GUID_DEFINED_SECTION   GuidSectHeader;
+  EFI_GUID_DEFINED_SECTION2  GuidSectHeader2;
+  UINT32                     HeaderSize;
+
+  if (InputFileNum < 1) {
+    Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file");
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BufferLength == NULL) {
+    Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Size          = 0;
+  Offset        = 0;
+  TeOffset      = 0;
+  //
+  // Go through our array of file names and copy their contents
+  // to the output buffer.
+  //
+  for (Index = 0; Index < InputFileNum; Index++) {
+    //
+    // make sure section ends on a DWORD boundary
+    //
+    while ((Size & 0x03) != 0) {
+      if (FileBuffer != NULL && Size < *BufferLength) {
+        FileBuffer[Size] = 0;
+      }
+      Size++;
+    }
+
+    //
+    // Open file and read contents
+    //
+    InFile = fopen (LongFilePath (InputFileName[Index]), "rb");
+    if (InFile == NULL) {
+      Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);
+      return EFI_ABORTED;
+    }
+
+    fseek (InFile, 0, SEEK_END);
+    FileSize = ftell (InFile);
+    fseek (InFile, 0, SEEK_SET);
+    DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize);
+    //
+    // Adjust section buffer when section alignment is required.
+    //
+    if (InputFileAlign != NULL) {
+      //
+      // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
+      //
+      TeOffset = 0;
+      //
+      // The section might be EFI_COMMON_SECTION_HEADER2
+      // But only Type needs to be checked
+      //
+      if (FileSize >= MAX_SECTION_SIZE) {
+        HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
+      } else {
+        HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
+      }
+      fread (&TempSectHeader, 1, HeaderSize, InFile);
+      if (TempSectHeader.Type == EFI_SECTION_TE) {
+        fread (&TeHeader, 1, sizeof (TeHeader), InFile);
+        if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+          TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);
+        }
+      } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {
+        fseek (InFile, 0, SEEK_SET);
+        if (FileSize >= MAX_SECTION_SIZE) {
+          fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile);
+          if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
+            HeaderSize = GuidSectHeader2.DataOffset;
+          }
+        } else {
+          fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);
+          if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
+            HeaderSize = GuidSectHeader.DataOffset;
+          }
+        }
+      }
+
+      fseek (InFile, 0, SEEK_SET);
+
+      //
+      // Revert TeOffset to the converse value relative to Alignment
+      // This is to assure the original PeImage Header at Alignment.
+      //
+      if (TeOffset != 0) {
+        TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);
+        TeOffset = TeOffset % InputFileAlign [Index];
+      }
+
+      //
+      // make sure section data meet its alignment requirement by adding one raw pad section.
+      //
+      if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {
+        Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);
+        Offset = Offset - Size - HeaderSize - TeOffset;
+
+        if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {
+          //
+          // The maximal alignment is 64K, the raw section size must be less than 0xffffff
+          //
+          memset (FileBuffer + Size, 0, Offset);
+          SectHeader          = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);
+          SectHeader->Type    = EFI_SECTION_RAW;
+          SectHeader->Size[0] = (UINT8) (Offset & 0xff);
+          SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);
+          SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);
+        }
+        DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset);
+
+        Size = Size + Offset;
+      }
+    }
+
+    //
+    // Now read the contents of the file into the buffer
+    // Buffer must be enough to contain the file content.
+    //
+    if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {
+      if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
+        Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);
+        fclose (InFile);
+        return EFI_ABORTED;
+      }
+    }
+
+    fclose (InFile);
+    Size += FileSize;
+  }
+
+  //
+  // Set the real required buffer size.
+  //
+  if (Size > *BufferLength) {
+    *BufferLength = Size;
+    return EFI_BUFFER_TOO_SMALL;
+  } else {
+    *BufferLength = Size;
+    return EFI_SUCCESS;
+  }
+}
+
+EFI_STATUS
+GenSectionCompressionSection (
+  CHAR8   **InputFileName,
+  UINT32  *InputFileAlign,
+  UINT32  InputFileNum,
+  UINT8   SectCompSubType,
+  UINT8   **OutFileBuffer
+  )
+/*++
+
+Routine Description:
+
+  Generate an encapsulating section of type EFI_SECTION_COMPRESSION
+  Input file must be already sectioned. The function won't validate
+  the input files' contents. Caller should hand in files already
+  with section header.
+
+Arguments:
+
+  InputFileName  - Name of the input file.
+
+  InputFileAlign - Alignment required by the input file data.
+
+  InputFileNum   - Number of input files. Should be at least 1.
+
+  SectCompSubType - Specify the compression algorithm requested.
+
+  OutFileBuffer   - Buffer pointer to Output file contents
+
+Returns:
+
+  EFI_SUCCESS           on successful return
+  EFI_INVALID_PARAMETER if InputFileNum is less than 1
+  EFI_ABORTED           if unable to open input file.
+  EFI_OUT_OF_RESOURCES  No resource to complete the operation.
+--*/
+{
+  UINT32                  TotalLength;
+  UINT32                  InputLength;
+  UINT32                  CompressedLength;
+  UINT32                  HeaderLength;
+  UINT8                   *FileBuffer;
+  UINT8                   *OutputBuffer;
+  EFI_STATUS              Status;
+  EFI_COMPRESSION_SECTION *CompressionSect;
+  EFI_COMPRESSION_SECTION2 *CompressionSect2;
+  COMPRESS_FUNCTION       CompressFunction;
+
+  InputLength       = 0;
+  FileBuffer        = NULL;
+  OutputBuffer      = NULL;
+  CompressedLength  = 0;
+  TotalLength       = 0;
+  //
+  // read all input file contents into a buffer
+  // first get the size of all file contents
+  //
+  Status = GetSectionContents (
+            InputFileName,
+            InputFileAlign,
+            InputFileNum,
+            FileBuffer,
+            &InputLength
+            );
+
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    FileBuffer = (UINT8 *) malloc (InputLength);
+    if (FileBuffer == NULL) {
+      Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+      return EFI_OUT_OF_RESOURCES;
+    }
+    //
+    // read all input file contents into a buffer
+    //
+    Status = GetSectionContents (
+              InputFileName,
+              InputFileAlign,
+              InputFileNum,
+              FileBuffer,
+              &InputLength
+              );
+  }
+
+  if (EFI_ERROR (Status)) {
+    if (FileBuffer != NULL) {
+      free (FileBuffer);
+    }
+    return Status;
+  }
+
+  if (FileBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CompressFunction = NULL;
+
+  //
+  // Now data is in FileBuffer, compress the data
+  //
+  switch (SectCompSubType) {
+  case EFI_NOT_COMPRESSED:
+    CompressedLength = InputLength;
+    HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
+    if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
+      HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
+    }
+    TotalLength = CompressedLength + HeaderLength;
+    //
+    // Copy file buffer to the none compressed data.
+    //
+    OutputBuffer = malloc (TotalLength);
+    if (OutputBuffer == NULL) {
+      free (FileBuffer);
+      return EFI_OUT_OF_RESOURCES;
+    }
+    memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);
+    free (FileBuffer);
+    FileBuffer = OutputBuffer;
+    break;
+
+  case EFI_STANDARD_COMPRESSION:
+    CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
+    break;
+
+  default:
+    Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");
+    free (FileBuffer);
+    return EFI_ABORTED;
+  }
+
+  if (CompressFunction != NULL) {
+
+    Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
+      if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
+        HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
+      }
+      TotalLength = CompressedLength + HeaderLength;
+      OutputBuffer = malloc (TotalLength);
+      if (!OutputBuffer) {
+        free (FileBuffer);
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);
+    }
+
+    free (FileBuffer);
+    FileBuffer = OutputBuffer;
+
+    if (EFI_ERROR (Status)) {
+      if (FileBuffer != NULL) {
+        free (FileBuffer);
+      }
+
+      return Status;
+    }
+
+    if (FileBuffer == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+
+  DebugMsg (NULL, 0, 9, "comprss file size",
+            "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);
+
+  //if (TotalLength >= MAX_SECTION_SIZE) {
+  //  Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
+  //  if (FileBuffer != NULL) {
+  //    free (FileBuffer);
+  //  }
+  //  if (OutputBuffer != NULL) {
+  //    free (OutputBuffer);
+  //  }
+  //  return STATUS_ERROR;
+  //}
+  VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
+
+  //
+  // Add the section header for the compressed data
+  //
+  if (TotalLength >= MAX_SECTION_SIZE) {
+    CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;
+
+    memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);
+    CompressionSect2->CommonHeader.Type         = EFI_SECTION_COMPRESSION;
+    CompressionSect2->CommonHeader.ExtendedSize = TotalLength;
+    CompressionSect2->CompressionType           = SectCompSubType;
+    CompressionSect2->UncompressedLength        = InputLength;
+  } else {
+    CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;
+
+    CompressionSect->CommonHeader.Type     = EFI_SECTION_COMPRESSION;
+    CompressionSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
+    CompressionSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
+    CompressionSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
+    CompressionSect->CompressionType       = SectCompSubType;
+    CompressionSect->UncompressedLength    = InputLength;
+  }
+
+  //
+  // Set OutFileBuffer
+  //
+  *OutFileBuffer = FileBuffer;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenSectionGuidDefinedSection (
+  CHAR8    **InputFileName,
+  UINT32   *InputFileAlign,
+  UINT32   InputFileNum,
+  EFI_GUID *VendorGuid,
+  UINT16   DataAttribute,
+  UINT32   DataHeaderSize,
+  UINT8    **OutFileBuffer
+  )
+/*++
+
+Routine Description:
+
+  Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
+  Input file must be already sectioned. The function won't validate
+  the input files' contents. Caller should hand in files already
+  with section header.
+
+Arguments:
+
+  InputFileName - Name of the input file.
+
+  InputFileAlign - Alignment required by the input file data.
+
+  InputFileNum  - Number of input files. Should be at least 1.
+
+  VendorGuid    - Specify vendor guid value.
+
+  DataAttribute - Specify attribute for the vendor guid data.
+
+  DataHeaderSize- Guided Data Header Size
+
+  OutFileBuffer   - Buffer pointer to Output file contents
+
+Returns:
+
+  EFI_SUCCESS on successful return
+  EFI_INVALID_PARAMETER if InputFileNum is less than 1
+  EFI_ABORTED if unable to open input file.
+  EFI_OUT_OF_RESOURCES  No resource to complete the operation.
+
+--*/
+{
+  UINT32                TotalLength;
+  UINT32                InputLength;
+  UINT32                Offset;
+  UINT8                 *FileBuffer;
+  UINT32                Crc32Checksum;
+  EFI_STATUS            Status;
+  CRC32_SECTION_HEADER  *Crc32GuidSect;
+  CRC32_SECTION_HEADER2  *Crc32GuidSect2;
+  EFI_GUID_DEFINED_SECTION  *VendorGuidSect;
+  EFI_GUID_DEFINED_SECTION2  *VendorGuidSect2;
+
+  InputLength = 0;
+  Offset      = 0;
+  FileBuffer  = NULL;
+  TotalLength = 0;
+
+  //
+  // read all input file contents into a buffer
+  // first get the size of all file contents
+  //
+  Status = GetSectionContents (
+            InputFileName,
+            InputFileAlign,
+            InputFileNum,
+            FileBuffer,
+            &InputLength
+            );
+
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
+      Offset = sizeof (CRC32_SECTION_HEADER);
+      if (InputLength + Offset >= MAX_SECTION_SIZE) {
+        Offset = sizeof (CRC32_SECTION_HEADER2);
+      }
+    } else {
+      Offset = sizeof (EFI_GUID_DEFINED_SECTION);
+      if (InputLength + Offset >= MAX_SECTION_SIZE) {
+        Offset = sizeof (EFI_GUID_DEFINED_SECTION2);
+      }
+    }
+    TotalLength = InputLength + Offset;
+
+    FileBuffer = (UINT8 *) malloc (InputLength + Offset);
+    if (FileBuffer == NULL) {
+      Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+      return EFI_OUT_OF_RESOURCES;
+    }
+    //
+    // read all input file contents into a buffer
+    //
+    Status = GetSectionContents (
+              InputFileName,
+              InputFileAlign,
+              InputFileNum,
+              FileBuffer + Offset,
+              &InputLength
+              );
+  }
+
+  if (EFI_ERROR (Status)) {
+    if (FileBuffer != NULL) {
+      free (FileBuffer);
+    }
+    Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);
+    return Status;
+  }
+
+  if (InputLength == 0) {
+    if (FileBuffer != NULL) {
+      free (FileBuffer);
+    }
+    Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // InputLength != 0, but FileBuffer == NULL means out of resources.
+  //
+  if (FileBuffer == NULL) {
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Now data is in FileBuffer + Offset
+  //
+  if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
+    //
+    // Default Guid section is CRC32.
+    //
+    Crc32Checksum = 0;
+    CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
+
+    if (TotalLength >= MAX_SECTION_SIZE) {
+      Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) 0xff;
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) 0xff;
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) 0xff;
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;
+      memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
+      Crc32GuidSect2->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
+      Crc32GuidSect2->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER2);
+      Crc32GuidSect2->CRC32Checksum                 = Crc32Checksum;
+      DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);
+    } else {
+      Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
+      Crc32GuidSect->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
+      Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
+      Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
+      Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
+      memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
+      Crc32GuidSect->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
+      Crc32GuidSect->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);
+      Crc32GuidSect->CRC32Checksum                 = Crc32Checksum;
+      DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);
+    }
+  } else {
+    if (TotalLength >= MAX_SECTION_SIZE) {
+      VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;
+      VendorGuidSect2->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
+      VendorGuidSect2->CommonHeader.Size[0]  = (UINT8) 0xff;
+      VendorGuidSect2->CommonHeader.Size[1]  = (UINT8) 0xff;
+      VendorGuidSect2->CommonHeader.Size[2]  = (UINT8) 0xff;
+      VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);
+      memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
+      VendorGuidSect2->Attributes  = DataAttribute;
+      VendorGuidSect2->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);
+      DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);
+    } else {
+      VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
+      VendorGuidSect->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
+      VendorGuidSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
+      VendorGuidSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
+      VendorGuidSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
+      memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
+      VendorGuidSect->Attributes  = DataAttribute;
+      VendorGuidSect->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);
+      DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);
+    }
+  }
+  VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
+
+  //
+  // Set OutFileBuffer
+  //
+  *OutFileBuffer = FileBuffer;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FfsRebaseImageRead (
+    IN      VOID    *FileHandle,
+    IN      UINTN   FileOffset,
+    IN OUT  UINT32  *ReadSize,
+    OUT     VOID    *Buffer
+    )
+  /*++
+
+    Routine Description:
+
+    Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+    Arguments:
+
+   FileHandle - The handle to the PE/COFF file
+
+   FileOffset - The offset, in bytes, into the file to read
+
+   ReadSize   - The number of bytes to read from the file starting at FileOffset
+
+   Buffer     - A pointer to the buffer to read the data into.
+
+   Returns:
+
+   EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+   --*/
+{
+  CHAR8   *Destination8;
+  CHAR8   *Source8;
+  UINT32  Length;
+
+  Destination8  = Buffer;
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+  Length        = *ReadSize;
+  while (Length--) {
+    *(Destination8++) = *(Source8++);
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+GetAlignmentFromFile(char *InFile, UINT32 *Alignment)
+  /*
+    InFile is input file for getting alignment
+    return the alignment
+    */
+{
+  FILE                           *InFileHandle;
+  UINT8                          *PeFileBuffer;
+  UINTN                          PeFileSize;
+  UINT32                         CurSecHdrSize;
+  PE_COFF_LOADER_IMAGE_CONTEXT   ImageContext;
+  EFI_COMMON_SECTION_HEADER      *CommonHeader;
+  EFI_STATUS                     Status;
+
+  InFileHandle        = NULL;
+  PeFileBuffer        = NULL;
+  *Alignment          = 0;
+
+  memset (&ImageContext, 0, sizeof (ImageContext));
+
+  InFileHandle = fopen(LongFilePath(InFile), "rb");
+  if (InFileHandle == NULL){
+    Error (NULL, 0, 0001, "Error opening file", InFile);
+    return EFI_ABORTED;
+  }
+  PeFileSize = _filelength (fileno(InFileHandle));
+  PeFileBuffer = (UINT8 *) malloc (PeFileSize);
+  if (PeFileBuffer == NULL) {
+    fclose (InFileHandle);
+    Error(NULL, 0, 4001, "Resource", "memory cannot be allocated  of %s", InFileHandle);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle);
+  fclose (InFileHandle);
+  CommonHeader = (EFI_COMMON_SECTION_HEADER *) PeFileBuffer;
+  CurSecHdrSize = GetSectionHeaderLength(CommonHeader);
+  ImageContext.Handle = (VOID *) ((UINTN)PeFileBuffer + CurSecHdrSize);
+  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)FfsRebaseImageRead;
+  Status               = PeCoffLoaderGetImageInfo(&ImageContext);
+  if (EFI_ERROR (Status)) {
+    Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile, (int) Status);
+    return Status;
+   }
+  *Alignment = ImageContext.SectionAlignment;
+  // Free the allocated memory resource
+  if (PeFileBuffer != NULL) {
+    free (PeFileBuffer);
+    PeFileBuffer = NULL;
+  }
+  return EFI_SUCCESS;
+}
+
+int
+main (
+  int  argc,
+  char *argv[]
+  )
+/*++
+
+Routine Description:
+
+  Main
+
+Arguments:
+
+  command line parameters
+
+Returns:
+
+  EFI_SUCCESS    Section header successfully generated and section concatenated.
+  EFI_ABORTED    Could not generate the section
+  EFI_OUT_OF_RESOURCES  No resource to complete the operation.
+
+--*/
+{
+  UINT32                    Index;
+  UINT32                    InputFileNum;
+  FILE                      *OutFile;
+  CHAR8                     **InputFileName;
+  CHAR8                     *OutputFileName;
+  CHAR8                     *SectionName;
+  CHAR8                     *CompressionName;
+  CHAR8                     *StringBuffer;
+  EFI_GUID                  VendorGuid = mZeroGuid;
+  int                       VersionNumber;
+  UINT8                     SectType;
+  UINT8                     SectCompSubType;
+  UINT16                    SectGuidAttribute;
+  UINT64                    SectGuidHeaderLength;
+  EFI_VERSION_SECTION       *VersionSect;
+  EFI_USER_INTERFACE_SECTION *UiSect;
+  UINT32                    InputLength;
+  UINT8                     *OutFileBuffer;
+  EFI_STATUS                Status;
+  UINT64                    LogLevel;
+  UINT32                    *InputFileAlign;
+  UINT32                    InputFileAlignNum;
+  EFI_COMMON_SECTION_HEADER *SectionHeader;
+  CHAR8                     *DummyFileName;
+  FILE                      *DummyFile;
+  UINTN                     DummyFileSize;
+  UINT8                     *DummyFileBuffer;
+  FILE                      *InFile;
+  UINT8                     *InFileBuffer;
+  UINTN                     InFileSize;
+
+  InputFileAlign        = NULL;
+  InputFileAlignNum     = 0;
+  InputFileName         = NULL;
+  OutputFileName        = NULL;
+  SectionName           = NULL;
+  CompressionName       = NULL;
+  StringBuffer          = "";
+  OutFile               = NULL;
+  VersionNumber         = 0;
+  InputFileNum          = 0;
+  SectType              = EFI_SECTION_ALL;
+  SectCompSubType       = 0;
+  SectGuidAttribute     = EFI_GUIDED_SECTION_NONE;
+  OutFileBuffer         = NULL;
+  InputLength           = 0;
+  Status                = STATUS_SUCCESS;
+  LogLevel              = 0;
+  SectGuidHeaderLength  = 0;
+  VersionSect           = NULL;
+  UiSect                = NULL;
+  DummyFileSize         = 0;
+  DummyFileName         = NULL;
+  DummyFile             = NULL;
+  DummyFileBuffer       = NULL;
+  InFile                = NULL;
+  InFileSize            = 0;
+  InFileBuffer          = NULL;
+
+  SetUtilityName (UTILITY_NAME);
+
+  if (argc == 1) {
+    Error (NULL, 0, 1001, "Missing options", "No options input");
+    Usage ();
+    return STATUS_ERROR;
+  }
+
+  //
+  // Parse command line
+  //
+  argc --;
+  argv ++;
+
+  if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
+    Version ();
+    Usage ();
+    return STATUS_SUCCESS;
+  }
+
+  if (stricmp (argv[0], "--version") == 0) {
+    Version ();
+    return STATUS_SUCCESS;
+  }
+
+  while (argc > 0) {
+    if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
+      SectionName = argv[1];
+      if (SectionName == NULL) {
+        Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
+        goto Finish;
+      }
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
+      OutputFileName = argv[1];
+      if (OutputFileName == NULL) {
+        Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
+        goto Finish;
+      }
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
+      CompressionName = argv[1];
+      if (CompressionName == NULL) {
+        Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
+        goto Finish;
+      }
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
+      Status = StringToGuid (argv[1], &VendorGuid);
+      if (EFI_ERROR (Status)) {
+        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+        goto Finish;
+      }
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+    if (stricmp (argv[0], "--dummy") == 0) {
+      DummyFileName = argv[1];
+      if (DummyFileName == NULL) {
+        Error (NULL, 0, 1003, "Invalid option value", "Dummy file can't be NULL");
+        goto Finish;
+      }
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
+      if (argv[1] == NULL) {
+        Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");
+        goto Finish;
+      }
+      if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
+        SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
+      } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
+        SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
+      } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
+        //
+        // NONE attribute
+        //
+        SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
+      } else {
+        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+        goto Finish;
+      }
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
+      Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
+      if (EFI_ERROR (Status)) {
+        Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
+        goto Finish;
+      }
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
+      StringBuffer = argv[1];
+      if (StringBuffer == NULL) {
+        Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
+        goto Finish;
+      }
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
+      if (argv[1] == NULL) {
+        Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
+        goto Finish;
+      }
+      //
+      // Verify string is a integrator number
+      //
+      for (Index = 0; Index < strlen (argv[1]); Index++) {
+        if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {
+          Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+          goto Finish;
+        }
+      }
+
+      sscanf (argv[1], "%d", &VersionNumber);
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
+      SetPrintLevel (VERBOSE_LOG_LEVEL);
+      VerboseMsg ("Verbose output Mode Set!");
+      argc --;
+      argv ++;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
+      SetPrintLevel (KEY_LOG_LEVEL);
+      KeyMsg ("Quiet output Mode Set!");
+      argc --;
+      argv ++;
+      continue;
+    }
+
+    if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
+      Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
+      if (EFI_ERROR (Status)) {
+        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+        goto Finish;
+      }
+      if (LogLevel > 9) {
+        Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, current input level is %d", (int) LogLevel);
+        goto Finish;
+      }
+      SetPrintLevel (LogLevel);
+      DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
+      argc -= 2;
+      argv += 2;
+      continue;
+    }
+
+    //
+    // Section File alignment requirement
+    //
+    if (stricmp (argv[0], "--sectionalign") == 0) {
+      if (InputFileAlignNum == 0) {
+        InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
+        if (InputFileAlign == NULL) {
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+          goto Finish;
+        }
+        memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
+      } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {
+        InputFileAlign = (UINT32 *) realloc (
+          InputFileAlign,
+          (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)
+          );
+
+        if (InputFileAlign == NULL) {
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+          goto Finish;
+        }
+        memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));
+      }
+      if (stricmp(argv[1], "0") == 0) {
+        InputFileAlign[InputFileAlignNum] = 0;
+      } else {
+        Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));
+        if (EFI_ERROR (Status)) {
+          Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+          goto Finish;
+        }
+      }
+      argc -= 2;
+      argv += 2;
+      InputFileAlignNum ++;
+      continue;
+    }
+
+    //
+    // Get Input file name
+    //
+    if ((InputFileNum == 0) && (InputFileName == NULL)) {
+      InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
+      if (InputFileName == NULL) {
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+        goto Finish;
+      }
+      memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
+    } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
+      //
+      // InputFileName buffer too small, need to realloc
+      //
+      InputFileName = (CHAR8 **) realloc (
+                                  InputFileName,
+                                  (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
+                                  );
+
+      if (InputFileName == NULL) {
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+        goto Finish;
+      }
+      memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
+    }
+
+    InputFileName[InputFileNum++] = argv[0];
+    argc --;
+    argv ++;
+  }
+
+  if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {
+    Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");
+    goto Finish;
+  }
+  for (Index = 0; Index < InputFileAlignNum; Index++)
+  {
+    if (InputFileAlign[Index] == 0) {
+      Status = GetAlignmentFromFile(InputFileName[Index], &(InputFileAlign[Index]));
+      if (EFI_ERROR(Status)) {
+        Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]);
+        goto Finish;
+      }
+    }
+  }
+
+  VerboseMsg ("%s tool start.", UTILITY_NAME);
+
+  if (DummyFileName != NULL) {
+      //
+      // Open file and read contents
+      //
+      DummyFile = fopen (LongFilePath (DummyFileName), "rb");
+      if (DummyFile == NULL) {
+        Error (NULL, 0, 0001, "Error opening file", DummyFileName);
+        goto Finish;
+      }
+
+      fseek (DummyFile, 0, SEEK_END);
+      DummyFileSize = ftell (DummyFile);
+      fseek (DummyFile, 0, SEEK_SET);
+      DummyFileBuffer = (UINT8 *) malloc (DummyFileSize);
+      if (DummyFileBuffer == NULL) {
+        fclose(DummyFile);
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+        goto Finish;
+      }
+
+      fread(DummyFileBuffer, 1, DummyFileSize, DummyFile);
+      fclose(DummyFile);
+      DebugMsg (NULL, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName, (unsigned) DummyFileSize);
+
+      if (InputFileName == NULL) {
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+        goto Finish;
+      }
+      InFile = fopen(LongFilePath(InputFileName[0]), "rb");
+      if (InFile == NULL) {
+        Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);
+        goto Finish;
+      }
+
+      fseek (InFile, 0, SEEK_END);
+      InFileSize = ftell (InFile);
+      fseek (InFile, 0, SEEK_SET);
+      InFileBuffer = (UINT8 *) malloc (InFileSize);
+      if (InFileBuffer == NULL) {
+        fclose(InFile);
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+        goto Finish;
+      }
+
+      fread(InFileBuffer, 1, InFileSize, InFile);
+      fclose(InFile);
+      DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[0], (unsigned) InFileSize);
+      if (InFileSize > DummyFileSize){
+        if (stricmp((CHAR8 *)DummyFileBuffer, (CHAR8 *)(InFileBuffer + (InFileSize - DummyFileSize))) == 0){
+          SectGuidHeaderLength = InFileSize - DummyFileSize;
+        }
+      }
+      if (SectGuidHeaderLength == 0) {
+        SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
+      }
+      if (DummyFileBuffer != NULL) {
+        free (DummyFileBuffer);
+        DummyFileBuffer = NULL;
+      }
+      if (InFileBuffer != NULL) {
+        free (InFileBuffer);
+      }
+    }
+
+  //
+  // Parse all command line parameters to get the corresponding section type.
+  //
+  VerboseMsg ("Section type is %s", SectionName);
+  if (SectionName == NULL) {
+    //
+    // No specified Section type, default is SECTION_ALL.
+    //
+    SectType = EFI_SECTION_ALL;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
+    SectType     = EFI_SECTION_COMPRESSION;
+    if (CompressionName == NULL) {
+      //
+      // Default is PI_STD compression algorithm.
+      //
+      SectCompSubType = EFI_STANDARD_COMPRESSION;
+    } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
+      SectCompSubType = EFI_NOT_COMPRESSED;
+    } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
+      SectCompSubType = EFI_STANDARD_COMPRESSION;
+    } else {
+      Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
+      goto Finish;
+    }
+    VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
+    SectType     = EFI_SECTION_GUID_DEFINED;
+
+    if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
+      //
+      // NONE attribute, clear attribute value.
+      //
+      SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;
+    }
+    VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+                (unsigned) VendorGuid.Data1,
+                VendorGuid.Data2,
+                VendorGuid.Data3,
+                VendorGuid.Data4[0],
+                VendorGuid.Data4[1],
+                VendorGuid.Data4[2],
+                VendorGuid.Data4[3],
+                VendorGuid.Data4[4],
+                VendorGuid.Data4[5],
+                VendorGuid.Data4[6],
+                VendorGuid.Data4[7]);
+    if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
+      VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
+    }
+    if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
+      VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
+    }
+    if (SectGuidHeaderLength != 0) {
+      VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);
+    }
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
+    SectType = EFI_SECTION_PE32;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
+    SectType = EFI_SECTION_PIC;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
+    SectType = EFI_SECTION_TE;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
+    SectType = EFI_SECTION_DXE_DEPEX;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {
+    SectType = EFI_SECTION_SMM_DEPEX;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
+    SectType = EFI_SECTION_VERSION;
+    if (VersionNumber < 0 || VersionNumber > 65535) {
+      Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);
+      goto Finish;
+    }
+    VerboseMsg ("Version section number is %d", VersionNumber);
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
+    SectType = EFI_SECTION_USER_INTERFACE;
+    if (StringBuffer[0] == '\0') {
+      Error (NULL, 0, 1001, "Missing option", "user interface string");
+      goto Finish;
+    }
+    VerboseMsg ("UI section string name is %s", StringBuffer);
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
+    SectType = EFI_SECTION_COMPATIBILITY16;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
+    SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
+    SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
+    SectType = EFI_SECTION_RAW;
+  } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
+    SectType = EFI_SECTION_PEI_DEPEX;
+  } else {
+    Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
+    goto Finish;
+  }
+
+  //
+  // GuidValue is only required by Guided section.
+  //
+  if ((SectType != EFI_SECTION_GUID_DEFINED) &&
+    (SectionName != NULL) &&
+    (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
+    fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
+  }
+
+  //
+  // Check whether there is input file
+  //
+  if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
+    //
+    // The input file are required for other section type.
+    //
+    if (InputFileNum == 0) {
+      Error (NULL, 0, 1001, "Missing options", "Input files");
+      goto Finish;
+    }
+  }
+  //
+  // Check whether there is output file
+  //
+  for (Index = 0; Index < InputFileNum; Index ++) {
+    VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);
+  }
+  if (OutputFileName == NULL) {
+    Error (NULL, 0, 1001, "Missing options", "Output file");
+    goto Finish;
+    // OutFile = stdout;
+  }
+  VerboseMsg ("Output file name is %s", OutputFileName);
+
+  //
+  // At this point, we've fully validated the command line, and opened appropriate
+  // files, so let's go and do what we've been asked to do...
+  //
+  //
+  // Within this switch, build and write out the section header including any
+  // section type specific pieces.  If there's an input file, it's tacked on later
+  //
+  switch (SectType) {
+  case EFI_SECTION_COMPRESSION:
+    if (InputFileAlign != NULL) {
+      free (InputFileAlign);
+      InputFileAlign = NULL;
+    }
+    Status = GenSectionCompressionSection (
+              InputFileName,
+              InputFileAlign,
+              InputFileNum,
+              SectCompSubType,
+              &OutFileBuffer
+              );
+    break;
+
+  case EFI_SECTION_GUID_DEFINED:
+    if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
+      //
+      // Only process alignment for the default known CRC32 guided section.
+      // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
+      //
+      free (InputFileAlign);
+      InputFileAlign = NULL;
+    }
+    Status = GenSectionGuidDefinedSection (
+              InputFileName,
+              InputFileAlign,
+              InputFileNum,
+              &VendorGuid,
+              SectGuidAttribute,
+              (UINT32) SectGuidHeaderLength,
+              &OutFileBuffer
+              );
+    break;
+
+  case EFI_SECTION_VERSION:
+    Index           = sizeof (EFI_COMMON_SECTION_HEADER);
+    //
+    // 2 bytes for the build number UINT16
+    //
+    Index += 2;
+    //
+    // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
+    //
+    Index += (strlen (StringBuffer) * 2) + 2;
+    OutFileBuffer = (UINT8 *) malloc (Index);
+    if (OutFileBuffer == NULL) {
+      Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+      goto Finish;
+    }
+    VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
+    VersionSect->CommonHeader.Type     = SectType;
+    VersionSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);
+    VersionSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);
+    VersionSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);
+    VersionSect->BuildNumber           = (UINT16) VersionNumber;
+    Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
+    VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
+    break;
+
+  case EFI_SECTION_USER_INTERFACE:
+    Index           = sizeof (EFI_COMMON_SECTION_HEADER);
+    //
+    // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
+    //
+    Index += (strlen (StringBuffer) * 2) + 2;
+    OutFileBuffer = (UINT8 *) malloc (Index);
+    if (OutFileBuffer == NULL) {
+      Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+      goto Finish;
+    }
+    UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
+    UiSect->CommonHeader.Type     = SectType;
+    UiSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);
+    UiSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);
+    UiSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);
+    Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
+    VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
+   break;
+
+  case EFI_SECTION_ALL:
+    //
+    // read all input file contents into a buffer
+    // first get the size of all file contents
+    //
+    Status = GetSectionContents (
+              InputFileName,
+              InputFileAlign,
+              InputFileNum,
+              OutFileBuffer,
+              &InputLength
+              );
+
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      OutFileBuffer = (UINT8 *) malloc (InputLength);
+      if (OutFileBuffer == NULL) {
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
+        goto Finish;
+      }
+      //
+      // read all input file contents into a buffer
+      //
+      Status = GetSectionContents (
+                InputFileName,
+                InputFileAlign,
+                InputFileNum,
+                OutFileBuffer,
+                &InputLength
+                );
+    }
+    VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);
+    break;
+  default:
+    //
+    // All other section types are caught by default (they're all the same)
+    //
+    Status = GenSectionCommonLeafSection (
+              InputFileName,
+              InputFileNum,
+              SectType,
+              &OutFileBuffer
+              );
+    break;
+  }
+
+  if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {
+    Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);
+    goto Finish;
+  }
+
+  //
+  // Get output file length
+  //
+  if (SectType != EFI_SECTION_ALL) {
+    SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;
+    InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;
+    if (InputLength == 0xffffff) {
+      InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
+    }
+  }
+
+  //
+  // Write the output file
+  //
+  OutFile = fopen (LongFilePath (OutputFileName), "wb");
+  if (OutFile == NULL) {
+    Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
+    goto Finish;
+  }
+
+  fwrite (OutFileBuffer, InputLength, 1, OutFile);
+
+Finish:
+  if (InputFileName != NULL) {
+    free (InputFileName);
+  }
+
+  if (InputFileAlign != NULL) {
+    free (InputFileAlign);
+  }
+
+  if (OutFileBuffer != NULL) {
+    free (OutFileBuffer);
+  }
+
+  if (OutFile != NULL) {
+    fclose (OutFile);
+  }
+
+  if (DummyFileBuffer != NULL) {
+    free (DummyFileBuffer);
+  }
+
+  VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
+
+  return GetUtilityStatus ();
+}
-- 
cgit