mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-25 17:23:53 +02:00 
			
		
		
		
	2. Removed the unnecessary library and include path from MSA files git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@541 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 "EfiCompress.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) Compress;
 | |
|     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 ();
 | |
| }
 |