(2) Remove unused library class EdkPeCoffLoaderX64Lib and library instance EdkPeCoffLoaderX64Lib, because current BasePeCoffLib can supports IA32, EBC, & X64 images all. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2069 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			939 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			939 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2004, Intel Corporation                                                         
 | 
						|
All rights reserved. This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  GenSection.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  Creates output file that is a properly formed section per the FV spec.
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include <Common/UefiBaseTypes.h>
 | 
						|
#include <Common/FirmwareVolumeImageFormat.h>
 | 
						|
#include <Protocol/GuidedSectionExtraction.h>
 | 
						|
 | 
						|
#include "CommonLib.h"
 | 
						|
#include "Compress.h"
 | 
						|
#include "EfiCustomizedCompress.h"
 | 
						|
#include "Crc32.h"
 | 
						|
#include "EfiUtilityMsgs.h"
 | 
						|
#include "GenSection.h"
 | 
						|
 | 
						|
 | 
						|
#define UTILITY_NAME            "GenSection"
 | 
						|
 | 
						|
#define PARAMETER_NOT_SPECIFIED "Parameter not specified"
 | 
						|
#define MAXIMUM_INPUT_FILE_NUM  10
 | 
						|
 | 
						|
char      *SectionTypeName[] = {
 | 
						|
  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
 | 
						|
};
 | 
						|
 | 
						|
char      *CompressionTypeName[]    = { "NONE", "STANDARD" };
 | 
						|
char      *GUIDedSectionTypeName[]  = { "CRC32" };
 | 
						|
EFI_GUID  gEfiCrc32SectionGuid      = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
 | 
						|
 | 
						|
static
 | 
						|
VOID
 | 
						|
PrintUsageMessage (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN SectionType;
 | 
						|
  UINTN DisplayCount;
 | 
						|
 | 
						|
  printf ("Usage: "UTILITY_NAME "  -i InputFile -o OutputFile -s SectionType [SectionType params]\n\n");
 | 
						|
  printf ("    Where SectionType is one of the following section types:\n\n");
 | 
						|
 | 
						|
  DisplayCount = 0;
 | 
						|
  for (SectionType = 0; SectionType <= EFI_SECTION_LAST_SECTION_TYPE; SectionType++) {
 | 
						|
    if (SectionTypeName[SectionType] != NULL) {
 | 
						|
      printf ("       %s\n", SectionTypeName[SectionType]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  printf ("\n    and SectionType dependent parameters are as follows:\n\n");
 | 
						|
  printf (
 | 
						|
    "       %s:       -t < %s | %s >\n",
 | 
						|
    SectionTypeName[EFI_SECTION_COMPRESSION],
 | 
						|
    CompressionTypeName[EFI_NOT_COMPRESSED],
 | 
						|
    CompressionTypeName[EFI_STANDARD_COMPRESSION]
 | 
						|
    );
 | 
						|
  printf (
 | 
						|
    "       %s:      -t < %s >\n""                          // Currently only CRC32 is supported\n\n",
 | 
						|
    SectionTypeName[EFI_SECTION_GUID_DEFINED],
 | 
						|
    GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]
 | 
						|
    );
 | 
						|
  printf (
 | 
						|
    "       %s:           -v VersionNumber\n""                          [-a \"Version string\"]\n\n",
 | 
						|
    SectionTypeName[EFI_SECTION_VERSION]
 | 
						|
    );
 | 
						|
  printf (
 | 
						|
    "       %s:    -a \"Human readable name\"\n\n",
 | 
						|
    SectionTypeName[EFI_SECTION_USER_INTERFACE]
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
Ascii2UnicodeWriteString (
 | 
						|
  char    *String,
 | 
						|
  FILE    *OutFile,
 | 
						|
  BOOLEAN WriteLangCode
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Index;
 | 
						|
  UINT8 AsciiNull;
 | 
						|
  //
 | 
						|
  // BUGBUG need to get correct language code...
 | 
						|
  //
 | 
						|
  char  *EnglishLangCode = "eng";
 | 
						|
  AsciiNull = 0;
 | 
						|
  //
 | 
						|
  // first write the language code (english only)
 | 
						|
  //
 | 
						|
  if (WriteLangCode) {
 | 
						|
    fwrite (EnglishLangCode, 1, 4, OutFile);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Next, write out the string... Convert ASCII to Unicode in the process.
 | 
						|
  //
 | 
						|
  Index = 0;
 | 
						|
  do {
 | 
						|
    fwrite (&String[Index], 1, 1, OutFile);
 | 
						|
    fwrite (&AsciiNull, 1, 1, OutFile);
 | 
						|
  } while (String[Index++] != 0);
 | 
						|
}
 | 
						|
 | 
						|
STATUS
 | 
						|
GenSectionCommonLeafSection (
 | 
						|
  char    **InputFileName,
 | 
						|
  int     InputFileNum,
 | 
						|
  UINTN   SectionType,
 | 
						|
  FILE    *OutFile
 | 
						|
  )
 | 
						|
/*++
 | 
						|
        
 | 
						|
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
 | 
						|
 | 
						|
  OutFile        - Output file handle
 | 
						|
 | 
						|
Returns:
 | 
						|
                       
 | 
						|
  STATUS_ERROR            - can't continue
 | 
						|
  STATUS_SUCCESS          - successful return
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINT64                    InputFileLength;
 | 
						|
  FILE                      *InFile;
 | 
						|
  UINT8                     *Buffer;
 | 
						|
  INTN                      TotalLength;
 | 
						|
  EFI_COMMON_SECTION_HEADER CommonSect;
 | 
						|
  STATUS                    Status;
 | 
						|
 | 
						|
  if (InputFileNum > 1) {
 | 
						|
    Error (NULL, 0, 0, "invalid parameter", "more than one input file specified");
 | 
						|
    return STATUS_ERROR;
 | 
						|
  } else if (InputFileNum < 1) {
 | 
						|
    Error (NULL, 0, 0, "no input file specified", NULL);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Open the input file
 | 
						|
  //
 | 
						|
  InFile = fopen (InputFileName[0], "rb");
 | 
						|
  if (InFile == NULL) {
 | 
						|
    Error (NULL, 0, 0, InputFileName[0], "failed to open input file");
 | 
						|
    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);
 | 
						|
  fgetpos (InFile, &InputFileLength);
 | 
						|
  fseek (InFile, 0, SEEK_SET);
 | 
						|
  //
 | 
						|
  // Fill in the fields in the local section header structure
 | 
						|
  //
 | 
						|
  CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
 | 
						|
  TotalLength     = sizeof (CommonSect) + (INTN) InputFileLength;
 | 
						|
  //
 | 
						|
  // Size must fit in 3 bytes
 | 
						|
  //
 | 
						|
  if (TotalLength >= 0x1000000) {
 | 
						|
    Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit", TotalLength);
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Now copy the size into the section header and write out the section header
 | 
						|
  //
 | 
						|
  memcpy (&CommonSect.Size, &TotalLength, 3);
 | 
						|
  fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
 | 
						|
  //
 | 
						|
  // Allocate a buffer to read in the contents of the input file. Then
 | 
						|
  // read it in as one block and write it to the output file.
 | 
						|
  //
 | 
						|
  if (InputFileLength != 0) {
 | 
						|
    Buffer = (UINT8 *) malloc ((size_t) InputFileLength);
 | 
						|
    if (Buffer == NULL) {
 | 
						|
      Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) {
 | 
						|
      Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) {
 | 
						|
      Error (NULL, 0, 0, "failed to write to output file", NULL);
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = STATUS_SUCCESS;
 | 
						|
Done:
 | 
						|
  fclose (InFile);
 | 
						|
  if (Buffer != NULL) {
 | 
						|
    free (Buffer);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GetSectionContents (
 | 
						|
  char    **InputFileName,
 | 
						|
  int     InputFileNum,
 | 
						|
  UINT8   *FileBuffer,
 | 
						|
  UINTN   *BufferLength
 | 
						|
  )
 | 
						|
/*++
 | 
						|
        
 | 
						|
Routine Description:
 | 
						|
           
 | 
						|
  Get the contents of all section files specified in InputFileName
 | 
						|
  into FileBuffer.
 | 
						|
            
 | 
						|
Arguments:
 | 
						|
               
 | 
						|
  InputFileName  - Name of the input file.
 | 
						|
                
 | 
						|
  InputFileNum   - Number of input files. Should be at least 1.
 | 
						|
 | 
						|
  FileBuffer     - Output buffer to contain data
 | 
						|
 | 
						|
  BufferLength   - Actual length of the data 
 | 
						|
 | 
						|
Returns:
 | 
						|
                       
 | 
						|
  EFI_SUCCESS on successful return
 | 
						|
  EFI_INVALID_PARAMETER if InputFileNum is less than 1
 | 
						|
  EFI_ABORTED if unable to open input file.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN   Size;
 | 
						|
  UINTN   FileSize;
 | 
						|
  INTN    Index;
 | 
						|
  FILE    *InFile;
 | 
						|
 | 
						|
  if (InputFileNum < 1) {
 | 
						|
    Error (NULL, 0, 0, "must specify at least one input file", NULL);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Size = 0;
 | 
						|
  //
 | 
						|
  // Go through our array of file names and copy their contents
 | 
						|
  // to the output buffer.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < InputFileNum; Index++) {
 | 
						|
    InFile = fopen (InputFileName[Index], "rb");
 | 
						|
    if (InFile == NULL) {
 | 
						|
      Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");
 | 
						|
      return EFI_ABORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    fseek (InFile, 0, SEEK_END);
 | 
						|
    FileSize = ftell (InFile);
 | 
						|
    fseek (InFile, 0, SEEK_SET);
 | 
						|
    //
 | 
						|
    // Now read the contents of the file into the buffer
 | 
						|
    //
 | 
						|
    if (FileSize > 0) {
 | 
						|
      if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
 | 
						|
        Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");
 | 
						|
        fclose (InFile);
 | 
						|
        return EFI_ABORTED;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    fclose (InFile);
 | 
						|
    Size += (UINTN) FileSize;
 | 
						|
    //
 | 
						|
    // make sure section ends on a DWORD boundary
 | 
						|
    //
 | 
						|
    while ((Size & 0x03) != 0) {
 | 
						|
      FileBuffer[Size] = 0;
 | 
						|
      Size++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *BufferLength = Size;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GenSectionCompressionSection (
 | 
						|
  char    **InputFileName,
 | 
						|
  int     InputFileNum,
 | 
						|
  UINTN   SectionType,
 | 
						|
  UINTN   SectionSubType,
 | 
						|
  FILE    *OutFile
 | 
						|
  )
 | 
						|
/*++
 | 
						|
        
 | 
						|
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.
 | 
						|
                
 | 
						|
  InputFileNum   - Number of input files. Should be at least 1.
 | 
						|
 | 
						|
  SectionType    - Section type to generate. Should be 
 | 
						|
                   EFI_SECTION_COMPRESSION
 | 
						|
 | 
						|
  SectionSubType - Specify the compression algorithm requested. 
 | 
						|
  
 | 
						|
  OutFile        - Output file handle
 | 
						|
 | 
						|
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.
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                   TotalLength;
 | 
						|
  UINTN                   InputLength;
 | 
						|
  UINTN                   CompressedLength;
 | 
						|
  UINT8                   *FileBuffer;
 | 
						|
  UINT8                   *OutputBuffer;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_COMPRESSION_SECTION CompressionSect;
 | 
						|
  COMPRESS_FUNCTION       CompressFunction;
 | 
						|
 | 
						|
  if (SectionType != EFI_SECTION_COMPRESSION) {
 | 
						|
    Error (NULL, 0, 0, "parameter must be EFI_SECTION_COMPRESSION", NULL);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  InputLength       = 0;
 | 
						|
  FileBuffer        = NULL;
 | 
						|
  OutputBuffer      = NULL;
 | 
						|
  CompressedLength  = 0;
 | 
						|
  FileBuffer        = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
 | 
						|
  if (FileBuffer == NULL) {
 | 
						|
    Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // read all input file contents into a buffer
 | 
						|
  //
 | 
						|
  Status = GetSectionContents (
 | 
						|
            InputFileName,
 | 
						|
            InputFileNum,
 | 
						|
            FileBuffer,
 | 
						|
            &InputLength
 | 
						|
            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    free (FileBuffer);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  CompressFunction = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Now data is in FileBuffer, compress the data
 | 
						|
  //
 | 
						|
  switch (SectionSubType) {
 | 
						|
  case EFI_NOT_COMPRESSED:
 | 
						|
    CompressedLength = InputLength;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_STANDARD_COMPRESSION:
 | 
						|
    CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_CUSTOMIZED_COMPRESSION:
 | 
						|
    CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress;
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    Error (NULL, 0, 0, "unknown compression type", NULL);
 | 
						|
    free (FileBuffer);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CompressFunction != NULL) {
 | 
						|
 | 
						|
    Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
 | 
						|
    if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
      OutputBuffer = malloc (CompressedLength);
 | 
						|
      if (!OutputBuffer) {
 | 
						|
        free (FileBuffer);
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
 | 
						|
    }
 | 
						|
 | 
						|
    free (FileBuffer);
 | 
						|
    FileBuffer = OutputBuffer;
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      if (FileBuffer != NULL) {
 | 
						|
        free (FileBuffer);
 | 
						|
      }
 | 
						|
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);
 | 
						|
  //
 | 
						|
  // Add the section header for the compressed data
 | 
						|
  //
 | 
						|
  CompressionSect.CommonHeader.Type     = (EFI_SECTION_TYPE) SectionType;
 | 
						|
  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       = (UINT8) SectionSubType;
 | 
						|
  CompressionSect.UncompressedLength    = InputLength;
 | 
						|
 | 
						|
  fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);
 | 
						|
  fwrite (FileBuffer, CompressedLength, 1, OutFile);
 | 
						|
  free (FileBuffer);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GenSectionGuidDefinedSection (
 | 
						|
  char    **InputFileName,
 | 
						|
  int     InputFileNum,
 | 
						|
  UINTN   SectionType,
 | 
						|
  UINTN   SectionSubType,
 | 
						|
  FILE    *OutFile
 | 
						|
  )
 | 
						|
/*++
 | 
						|
        
 | 
						|
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.
 | 
						|
                
 | 
						|
  InputFileNum   - Number of input files. Should be at least 1.
 | 
						|
 | 
						|
  SectionType    - Section type to generate. Should be 
 | 
						|
                   EFI_SECTION_GUID_DEFINED
 | 
						|
 | 
						|
  SectionSubType - Specify the authentication algorithm requested. 
 | 
						|
  
 | 
						|
  OutFile        - Output file handle
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  INTN                  TotalLength;
 | 
						|
  INTN                  InputLength;
 | 
						|
  UINT8                 *FileBuffer;
 | 
						|
  UINT32                Crc32Checksum;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  CRC32_SECTION_HEADER  Crc32GuidSect;
 | 
						|
 | 
						|
  if (SectionType != EFI_SECTION_GUID_DEFINED) {
 | 
						|
    Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  InputLength = 0;
 | 
						|
  FileBuffer  = NULL;
 | 
						|
  FileBuffer  = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
 | 
						|
  if (FileBuffer == NULL) {
 | 
						|
    Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // read all input file contents into a buffer
 | 
						|
  //
 | 
						|
  Status = GetSectionContents (
 | 
						|
            InputFileName,
 | 
						|
            InputFileNum,
 | 
						|
            FileBuffer,
 | 
						|
            &InputLength
 | 
						|
            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    free (FileBuffer);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Now data is in FileBuffer, compress the data
 | 
						|
  //
 | 
						|
  switch (SectionSubType) {
 | 
						|
  case EFI_SECTION_CRC32_GUID_DEFINED:
 | 
						|
    Crc32Checksum = 0;
 | 
						|
    CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      free (FileBuffer);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE;
 | 
						|
    Crc32GuidSect.GuidSectionHeader.CommonHeader.Type     = (EFI_SECTION_TYPE) SectionType;
 | 
						|
    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), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
 | 
						|
    Crc32GuidSect.GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
 | 
						|
    Crc32GuidSect.GuidSectionHeader.DataOffset  = CRC32_SECTION_HEADER_SIZE;
 | 
						|
    Crc32GuidSect.CRC32Checksum                 = Crc32Checksum;
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type");
 | 
						|
    free (FileBuffer);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);
 | 
						|
  fwrite (FileBuffer, InputLength, 1, OutFile);
 | 
						|
 | 
						|
  free (FileBuffer);
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  INTN                      Index;
 | 
						|
  INTN                      VersionNumber;
 | 
						|
  UINTN                     SectionType;
 | 
						|
  UINTN                     SectionSubType;
 | 
						|
  BOOLEAN                   InputFileRequired;
 | 
						|
  BOOLEAN                   SubTypeRequired;
 | 
						|
  FILE                      *InFile;
 | 
						|
  FILE                      *OutFile;
 | 
						|
  INTN                      InputFileNum;
 | 
						|
 | 
						|
  char                      **InputFileName;
 | 
						|
  char                      *OutputFileName;
 | 
						|
  char                      AuxString[500] = { 0 };
 | 
						|
 | 
						|
  char                      *ParamSectionType;
 | 
						|
  char                      *ParamSectionSubType;
 | 
						|
  char                      *ParamLength;
 | 
						|
  char                      *ParamVersion;
 | 
						|
  char                      *ParamDigitalSignature;
 | 
						|
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_COMMON_SECTION_HEADER CommonSect;
 | 
						|
 | 
						|
  InputFileName         = NULL;
 | 
						|
  OutputFileName        = PARAMETER_NOT_SPECIFIED;
 | 
						|
  ParamSectionType      = PARAMETER_NOT_SPECIFIED;
 | 
						|
  ParamSectionSubType   = PARAMETER_NOT_SPECIFIED;
 | 
						|
  ParamLength           = PARAMETER_NOT_SPECIFIED;
 | 
						|
  ParamVersion          = PARAMETER_NOT_SPECIFIED;
 | 
						|
  ParamDigitalSignature = PARAMETER_NOT_SPECIFIED;
 | 
						|
  Status                = EFI_SUCCESS;
 | 
						|
 | 
						|
  VersionNumber         = 0;
 | 
						|
  SectionType           = 0;
 | 
						|
  SectionSubType        = 0;
 | 
						|
  InputFileRequired     = TRUE;
 | 
						|
  SubTypeRequired       = FALSE;
 | 
						|
  InFile                = NULL;
 | 
						|
  OutFile               = NULL;
 | 
						|
  InputFileNum          = 0;
 | 
						|
  Status                = EFI_SUCCESS;
 | 
						|
 | 
						|
  SetUtilityName (UTILITY_NAME);
 | 
						|
  if (argc == 1) {
 | 
						|
    PrintUsageMessage ();
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Parse command line
 | 
						|
  //
 | 
						|
  Index = 1;
 | 
						|
  while (Index < argc) {
 | 
						|
    if (strcmpi (argv[Index], "-i") == 0) {
 | 
						|
      //
 | 
						|
      // Input File found
 | 
						|
      //
 | 
						|
      Index++;
 | 
						|
      InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *));
 | 
						|
      if (InputFileName == NULL) {
 | 
						|
        Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
 | 
						|
      InputFileName[InputFileNum] = argv[Index];
 | 
						|
      InputFileNum++;
 | 
						|
      Index++;
 | 
						|
      //
 | 
						|
      // Parse subsequent parameters until another switch is encountered
 | 
						|
      //
 | 
						|
      while ((Index < argc) && (argv[Index][0] != '-')) {
 | 
						|
        if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) {
 | 
						|
          //
 | 
						|
          // InputFileName buffer too small, need to realloc
 | 
						|
          //
 | 
						|
          InputFileName = (char **) realloc (
 | 
						|
                                      InputFileName,
 | 
						|
                                      (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *)
 | 
						|
                                      );
 | 
						|
          if (InputFileName == NULL) {
 | 
						|
            Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
 | 
						|
            return EFI_OUT_OF_RESOURCES;
 | 
						|
          }
 | 
						|
 | 
						|
          memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
 | 
						|
        }
 | 
						|
 | 
						|
        InputFileName[InputFileNum] = argv[Index];
 | 
						|
        InputFileNum++;
 | 
						|
        Index++;
 | 
						|
      }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    if (strcmpi (argv[Index], "-o") == 0) {
 | 
						|
      //
 | 
						|
      // Output file found
 | 
						|
      //
 | 
						|
      Index++;
 | 
						|
      OutputFileName = argv[Index];
 | 
						|
    } else if (strcmpi (argv[Index], "-s") == 0) {
 | 
						|
      //
 | 
						|
      // Section Type found
 | 
						|
      //
 | 
						|
      Index++;
 | 
						|
      ParamSectionType = argv[Index];
 | 
						|
    } else if (strcmpi (argv[Index], "-t") == 0) {
 | 
						|
      //
 | 
						|
      // Compression or Authentication type
 | 
						|
      //
 | 
						|
      Index++;
 | 
						|
      ParamSectionSubType = argv[Index];
 | 
						|
    } else if (strcmpi (argv[Index], "-l") == 0) {
 | 
						|
      //
 | 
						|
      // Length
 | 
						|
      //
 | 
						|
      Index++;
 | 
						|
      ParamLength = argv[Index];
 | 
						|
    } else if (strcmpi (argv[Index], "-v") == 0) {
 | 
						|
      //
 | 
						|
      // VersionNumber
 | 
						|
      //
 | 
						|
      Index++;
 | 
						|
      ParamVersion = argv[Index];
 | 
						|
    } else if (strcmpi (argv[Index], "-a") == 0) {
 | 
						|
      //
 | 
						|
      // Aux string
 | 
						|
      //
 | 
						|
      Index++;
 | 
						|
      //
 | 
						|
      // Note, the MSVC C-Start parses out and consolidates quoted strings from the command
 | 
						|
      // line.  Quote characters are stripped.  If this tool is ported to other environments
 | 
						|
      // this will need to be taken into account
 | 
						|
      //
 | 
						|
      strncpy (AuxString, argv[Index], 499);
 | 
						|
    } else if (strcmpi (argv[Index], "-d") == 0) {
 | 
						|
      //
 | 
						|
      // Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1)
 | 
						|
      //
 | 
						|
      Index++;
 | 
						|
      ParamDigitalSignature = argv[Index];
 | 
						|
    } else if (strcmpi (argv[Index], "-?") == 0) {
 | 
						|
      PrintUsageMessage ();
 | 
						|
      return STATUS_ERROR;
 | 
						|
    } else {
 | 
						|
      Error (NULL, 0, 0, argv[Index], "unknown option");
 | 
						|
      return GetUtilityStatus ();
 | 
						|
    }
 | 
						|
 | 
						|
    Index++;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // At this point, all command line parameters are verified as not being totally
 | 
						|
  // bogus.  Next verify the command line parameters are complete and make
 | 
						|
  // sense...
 | 
						|
  //
 | 
						|
  if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
 | 
						|
    SectionType     = EFI_SECTION_COMPRESSION;
 | 
						|
    SubTypeRequired = TRUE;
 | 
						|
    if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
 | 
						|
      SectionSubType = EFI_NOT_COMPRESSED;
 | 
						|
    } else if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
 | 
						|
      SectionSubType = EFI_STANDARD_COMPRESSION;
 | 
						|
    } else {
 | 
						|
      Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type");
 | 
						|
      PrintUsageMessage ();
 | 
						|
      return GetUtilityStatus ();
 | 
						|
    }
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
 | 
						|
    SectionType     = EFI_SECTION_GUID_DEFINED;
 | 
						|
    SubTypeRequired = TRUE;
 | 
						|
    if (stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) {
 | 
						|
      SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED;
 | 
						|
    } else {
 | 
						|
      Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType);
 | 
						|
      PrintUsageMessage ();
 | 
						|
      return GetUtilityStatus ();
 | 
						|
    }
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_PE32;
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_PIC;
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_TE;
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_DXE_DEPEX;
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) {
 | 
						|
    SectionType       = EFI_SECTION_VERSION;
 | 
						|
    InputFileRequired = FALSE;
 | 
						|
    Index             = sscanf (ParamVersion, "%d", &VersionNumber);
 | 
						|
    if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) {
 | 
						|
      Error (NULL, 0, 0, ParamVersion, "illegal version number");
 | 
						|
      PrintUsageMessage ();
 | 
						|
      return GetUtilityStatus ();
 | 
						|
    }
 | 
						|
 | 
						|
    if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
 | 
						|
      AuxString[0] = 0;
 | 
						|
    }
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
 | 
						|
    SectionType       = EFI_SECTION_USER_INTERFACE;
 | 
						|
    InputFileRequired = FALSE;
 | 
						|
    if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
 | 
						|
      Error (NULL, 0, 0, "user interface string not specified", NULL);
 | 
						|
      PrintUsageMessage ();
 | 
						|
      return GetUtilityStatus ();
 | 
						|
    }
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_COMPATIBILITY16;
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_RAW;
 | 
						|
  } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
 | 
						|
    SectionType = EFI_SECTION_PEI_DEPEX;
 | 
						|
  } else {
 | 
						|
    Error (NULL, 0, 0, ParamSectionType, "unknown section type");
 | 
						|
    PrintUsageMessage ();
 | 
						|
    return GetUtilityStatus ();
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Open output file
 | 
						|
  //
 | 
						|
  OutFile = fopen (OutputFileName, "wb");
 | 
						|
  if (OutFile == NULL) {
 | 
						|
    Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
 | 
						|
    if (InFile != NULL) {
 | 
						|
      fclose (InFile);
 | 
						|
    }
 | 
						|
 | 
						|
    return GetUtilityStatus ();
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // 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 (SectionType) {
 | 
						|
  case EFI_SECTION_COMPRESSION:
 | 
						|
    Status = GenSectionCompressionSection (
 | 
						|
              InputFileName,
 | 
						|
              InputFileNum,
 | 
						|
              SectionType,
 | 
						|
              SectionSubType,
 | 
						|
              OutFile
 | 
						|
              );
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_SECTION_GUID_DEFINED:
 | 
						|
    Status = GenSectionGuidDefinedSection (
 | 
						|
              InputFileName,
 | 
						|
              InputFileNum,
 | 
						|
              SectionType,
 | 
						|
              SectionSubType,
 | 
						|
              OutFile
 | 
						|
              );
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_SECTION_VERSION:
 | 
						|
    CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
 | 
						|
 | 
						|
    Index           = sizeof (CommonSect);
 | 
						|
    //
 | 
						|
    // 2 characters for the build number
 | 
						|
    //
 | 
						|
    Index += 2;
 | 
						|
    //
 | 
						|
    // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
 | 
						|
    //
 | 
						|
    Index += (strlen (AuxString) * 2) + 2;
 | 
						|
    memcpy (&CommonSect.Size, &Index, 3);
 | 
						|
    fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
 | 
						|
    fwrite (&VersionNumber, 2, 1, OutFile);
 | 
						|
    Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_SECTION_USER_INTERFACE:
 | 
						|
    CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
 | 
						|
    Index           = sizeof (CommonSect);
 | 
						|
    //
 | 
						|
    // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
 | 
						|
    //
 | 
						|
    Index += (strlen (AuxString) * 2) + 2;
 | 
						|
    memcpy (&CommonSect.Size, &Index, 3);
 | 
						|
    fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
 | 
						|
    Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    //
 | 
						|
    // All other section types are caught by default (they're all the same)
 | 
						|
    //
 | 
						|
    Status = GenSectionCommonLeafSection (
 | 
						|
              InputFileName,
 | 
						|
              InputFileNum,
 | 
						|
              SectionType,
 | 
						|
              OutFile
 | 
						|
              );
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  if (InputFileName != NULL) {
 | 
						|
    free (InputFileName);
 | 
						|
  }
 | 
						|
 | 
						|
  fclose (OutFile);
 | 
						|
  //
 | 
						|
  // If we had errors, then delete the output file
 | 
						|
  //
 | 
						|
  if (GetUtilityStatus () == STATUS_ERROR) {
 | 
						|
    remove (OutputFileName);
 | 
						|
  }
 | 
						|
 | 
						|
  return GetUtilityStatus ();
 | 
						|
}
 |