git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11094 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			400 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			400 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++ 
 | 
						|
 | 
						|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
 | 
						|
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:
 | 
						|
  EfiCompressMain.c
 | 
						|
  
 | 
						|
Abstract:
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <ctype.h>
 | 
						|
#include <assert.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include "TianoCommon.h"
 | 
						|
#include "Compress.h"
 | 
						|
 | 
						|
#define UTILITY_VERSION "v1.0"
 | 
						|
#define UTILITY_NAME    "EfiCompress"
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  EFI_COMPRESS   = 1,
 | 
						|
  TIANO_COMPRESS = 2
 | 
						|
} COMPRESS_TYPE;
 | 
						|
 | 
						|
typedef struct _COMPRESS_ACTION_LIST {
 | 
						|
  struct _COMPRESS_ACTION_LIST   *NextAction;
 | 
						|
  INT32                          CompressType;
 | 
						|
  CHAR8                          *InFileName;
 | 
						|
  CHAR8                          *OutFileName;
 | 
						|
} COMPRESS_ACTION_LIST;
 | 
						|
 | 
						|
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
ParseCommandLine (
 | 
						|
  INT32                 argc,
 | 
						|
  CHAR8                 *argv[],
 | 
						|
  COMPRESS_ACTION_LIST  **ActionListHead
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Parse command line options
 | 
						|
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
  argc    - number of arguments passed into the command line.
 | 
						|
  argv[]  - files to compress and files to output compressed data to.
 | 
						|
  Options - Point to COMMAND_LINE_OPTIONS, receiving command line options.
 | 
						|
 | 
						|
Returns:
 | 
						|
  
 | 
						|
  BOOLEAN: TRUE for a successful parse.
 | 
						|
--*/
 | 
						|
;
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
Usage (
 | 
						|
  CHAR8 *ExeName
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Print usage.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
  ExeName  - Application's full path
 | 
						|
 | 
						|
--*/
 | 
						|
;
 | 
						|
 | 
						|
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
ProcessFile (
 | 
						|
  CHAR8         *InFileName,
 | 
						|
  CHAR8         *OutFileName,
 | 
						|
  COMPRESS_TYPE CompressType
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  
 | 
						|
  Compress InFileName to OutFileName using algorithm specified by CompressType.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
  InFileName    - Input file to compress
 | 
						|
  OutFileName   - Output file compress to
 | 
						|
  CompressType  - Compress algorithm, can be EFI_COMPRESS or TIANO_COMPRESS
 | 
						|
 | 
						|
Returns:
 | 
						|
  
 | 
						|
  BOOLEAN: TRUE for compress file successfully
 | 
						|
 | 
						|
--*/
 | 
						|
;
 | 
						|
 | 
						|
int
 | 
						|
main (
 | 
						|
  INT32 argc,
 | 
						|
  CHAR8 *argv[]
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Compresses the input files
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  argc   - number of arguments passed into the command line.
 | 
						|
  argv[] - files to compress and files to output compressed data to.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  int: 0 for successful execution of the function.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  COMPRESS_ACTION_LIST *ActionList;
 | 
						|
  COMPRESS_ACTION_LIST *NextAction;
 | 
						|
  UINT32               ActionCount;
 | 
						|
  UINT32               SuccessCount;
 | 
						|
 | 
						|
  ActionList            = NULL;
 | 
						|
  ActionCount          = SuccessCount = 0;
 | 
						|
 | 
						|
  if (!ParseCommandLine (argc, argv, &ActionList)) {
 | 
						|
    Usage (*argv);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  while (ActionList != NULL) {
 | 
						|
    ++ActionCount;
 | 
						|
    if (ProcessFile (
 | 
						|
          ActionList->InFileName, 
 | 
						|
          ActionList->OutFileName, 
 | 
						|
          ActionList->CompressType)
 | 
						|
        ) {
 | 
						|
      ++SuccessCount;
 | 
						|
    }
 | 
						|
    NextAction = ActionList;
 | 
						|
    ActionList = ActionList->NextAction;
 | 
						|
    free (NextAction);
 | 
						|
  }
 | 
						|
 | 
						|
  fprintf (stdout, "\nCompressed %d files, %d succeed!\n", ActionCount, SuccessCount);
 | 
						|
  if (SuccessCount < ActionCount) {
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
ParseCommandLine (
 | 
						|
  INT32                 argc,
 | 
						|
  CHAR8                 *argv[],
 | 
						|
  COMPRESS_ACTION_LIST  **ActionListHead
 | 
						|
  )
 | 
						|
{
 | 
						|
  COMPRESS_TYPE         CurrentType;
 | 
						|
 | 
						|
  COMPRESS_ACTION_LIST  **Action;
 | 
						|
  
 | 
						|
  Action           =    ActionListHead;
 | 
						|
  CurrentType      =    EFI_COMPRESS;     // default compress algorithm
 | 
						|
 | 
						|
  // Skip Exe Name
 | 
						|
  --argc;
 | 
						|
  ++argv;
 | 
						|
 | 
						|
  while (argc > 0) {
 | 
						|
    if (strcmp (*argv, "-h") == 0 || strcmp (*argv, "-?") == 0) {
 | 
						|
      //
 | 
						|
      // 1. Directly return, help message will be printed.
 | 
						|
      //
 | 
						|
      return FALSE;
 | 
						|
    
 | 
						|
    } else if (strncmp (*argv, "-t", 2) == 0) {
 | 
						|
      //
 | 
						|
      // 2. Specifying CompressType
 | 
						|
      //
 | 
						|
      if (_stricmp ((*argv)+2, "EFI") == 0) {
 | 
						|
        CurrentType = EFI_COMPRESS;
 | 
						|
      } else if (_stricmp ((*argv)+2, "Tiano") == 0) {
 | 
						|
        CurrentType = TIANO_COMPRESS;
 | 
						|
      } else {
 | 
						|
        fprintf (stdout, "  ERROR: CompressType %s not supported!\n", (*argv)+2);
 | 
						|
        return FALSE;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // 3. Current parameter is *FileName
 | 
						|
      //
 | 
						|
      if (*Action == NULL) { 
 | 
						|
        //
 | 
						|
        // need to create a new action item
 | 
						|
        //
 | 
						|
        *Action = (COMPRESS_ACTION_LIST*) malloc (sizeof **Action);
 | 
						|
        if (*Action == NULL) {
 | 
						|
          fprintf (stdout, "  ERROR: malloc failed!\n");
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
        memset (*Action, 0, sizeof **Action);
 | 
						|
        (*Action)->CompressType = CurrentType;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Assignment to InFileName and OutFileName in order
 | 
						|
      // 
 | 
						|
      if ((*Action)->InFileName == NULL) {
 | 
						|
        (*Action)->InFileName  = *argv;
 | 
						|
      } else {
 | 
						|
        (*Action)->OutFileName = *argv;
 | 
						|
        Action                 = &(*Action)->NextAction;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    --argc;
 | 
						|
    ++argv;
 | 
						|
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (*Action != NULL) {
 | 
						|
    assert ((*Action)->InFileName != NULL);
 | 
						|
    fprintf (stdout, "  ERROR: Compress OutFileName not specified with InFileName: %s!\n", (*Action)->InFileName);
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (*ActionListHead == NULL) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
ProcessFile (
 | 
						|
  CHAR8         *InFileName,
 | 
						|
  CHAR8         *OutFileName,
 | 
						|
  COMPRESS_TYPE CompressType
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  FILE                *InFileP;
 | 
						|
  FILE                *OutFileP;
 | 
						|
  UINT32              SrcSize;
 | 
						|
  UINT32              DstSize;
 | 
						|
  UINT8               *SrcBuffer;
 | 
						|
  UINT8               *DstBuffer;
 | 
						|
  COMPRESS_FUNCTION   CompressFunc;
 | 
						|
 | 
						|
  SrcBuffer     =     DstBuffer = NULL;
 | 
						|
  InFileP       =     OutFileP  = NULL;
 | 
						|
 | 
						|
  fprintf (stdout, "%s --> %s\n", InFileName, OutFileName);
 | 
						|
 | 
						|
  if ((OutFileP = fopen (OutFileName, "wb")) == NULL) {
 | 
						|
    fprintf (stdout, "  ERROR: Can't open output file %s for write!\n", OutFileName);
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((InFileP = fopen (InFileName, "rb")) == NULL) {
 | 
						|
    fprintf (stdout, "  ERROR: Can't open input file %s for read!\n", InFileName);
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Get the size of source file
 | 
						|
  //
 | 
						|
  fseek (InFileP, 0, SEEK_END);
 | 
						|
  SrcSize = ftell (InFileP);
 | 
						|
  rewind (InFileP);
 | 
						|
  //
 | 
						|
  // Read in the source data
 | 
						|
  //
 | 
						|
  if ((SrcBuffer = malloc (SrcSize)) == NULL) {
 | 
						|
    fprintf (stdout, "  ERROR: Can't allocate memory!\n");
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  if (fread (SrcBuffer, 1, SrcSize, InFileP) != SrcSize) {
 | 
						|
    fprintf (stdout, "  ERROR: Can't read from source!\n");
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Choose the right compress algorithm
 | 
						|
  //
 | 
						|
  CompressFunc = (CompressType == EFI_COMPRESS) ? EfiCompress : TianoCompress;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get destination data size and do the compression
 | 
						|
  //
 | 
						|
  DstSize = 0;
 | 
						|
  Status = CompressFunc (SrcBuffer, SrcSize, DstBuffer, &DstSize);
 | 
						|
  if (Status != EFI_BUFFER_TOO_SMALL) {
 | 
						|
    fprintf (stdout, "  Error: Compress failed: %x!\n", Status);
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
  if ((DstBuffer = malloc (DstSize)) == NULL) {
 | 
						|
    fprintf (stdout, "  ERROR: Can't allocate memory!\n");
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = CompressFunc (SrcBuffer, SrcSize, DstBuffer, &DstSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    fprintf (stdout, "  ERROR: Compress Error!\n");
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  fprintf (stdout, "  Orig Size = %ld\tComp Size = %ld\n", SrcSize, DstSize);
 | 
						|
 | 
						|
  if (DstBuffer == NULL) {
 | 
						|
    fprintf (stdout, "  ERROR: No destination to write to!\n");
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Write out the result
 | 
						|
  //
 | 
						|
  if (fwrite (DstBuffer, 1, DstSize, OutFileP) != DstSize) {
 | 
						|
    fprintf (stdout, "  ERROR: Can't write to destination file!\n");
 | 
						|
    goto ErrorHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
 | 
						|
ErrorHandle:
 | 
						|
  if (SrcBuffer) {
 | 
						|
    free (SrcBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  if (DstBuffer) {
 | 
						|
    free (DstBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  if (InFileP) {
 | 
						|
    fclose (InFileP);
 | 
						|
  }
 | 
						|
 | 
						|
  if (OutFileP) {
 | 
						|
    fclose (OutFileP);
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
Usage (
 | 
						|
  CHAR8 *ExeName
 | 
						|
  )
 | 
						|
{
 | 
						|
  int         Index;
 | 
						|
  const char  *Str[] = {
 | 
						|
    UTILITY_NAME" "UTILITY_VERSION" - Intel EFI Compress Utility",
 | 
						|
    "  Copyright (C), 2006 - 2008 Intel Corporation",
 | 
						|
    
 | 
						|
#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
 | 
						|
    "  Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
 | 
						|
#endif
 | 
						|
    "",
 | 
						|
    "Usage:",
 | 
						|
    "  "UTILITY_NAME" [OPTION] SOURCE DEST ...",
 | 
						|
    "Description:",
 | 
						|
    "  Compress a list of SOURCE(s) to accordingly DEST(s) using the specified",
 | 
						|
    "  compress algorithm.",
 | 
						|
    "Options:",
 | 
						|
    "  -tCompressAlgo   Optional compress algorithm (EFI | Tiano), case insensitive.",
 | 
						|
    "                   If ommitted, compress type specified ahead is used,",
 | 
						|
    "                   default is EFI\n"
 | 
						|
    "                   e.g.: EfiCompress a.in a.out -tTiano b.in b.out \\",
 | 
						|
    "                                     c.in c.out -tEFI d.in d.out",
 | 
						|
    "                   a.in and d.in are compressed using EFI compress algorithm",
 | 
						|
    "                   b.in and c.in are compressed using Tiano compress algorithm",
 | 
						|
    NULL
 | 
						|
  };
 | 
						|
  for (Index = 0; Str[Index] != NULL; Index++) {
 | 
						|
    fprintf (stdout, "%s\n", Str[Index]);
 | 
						|
  }
 | 
						|
  
 | 
						|
}
 |