gensection.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 938 行 · 第 1/2 页

C
938
字号
/*++

Copyright (c) 2004 - 2006, Intel Corporation                                                         
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name:

  GenSection.c

Abstract:

  Creates output file that is a properly formed section per the FV spec.

--*/

#include "TianoCommon.h"
#include "EfiImageFormat.h"
#include "Compress.h"
#include "EfiCustomizedCompress.h"
#include "Crc32.h"
#include "EfiUtilityMsgs.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "GenSection.h"

#include EFI_PROTOCOL_DEFINITION (GuidedSectionExtraction)

#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;
  fpos_t  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);
    fgetpos (InFile, &FileSize);
    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) TianoCompress;
    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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?