--- /dev/null
+/*++ \r
+\r
+Copyright 2006 - 2007, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+ EfiCompressMain.c\r
+ \r
+Abstract:\r
+\r
+--*/\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <assert.h>\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include "TianoCommon.h"\r
+#include "Compress.h"\r
+\r
+typedef enum {\r
+ EFI_COMPRESS = 1,\r
+ TIANO_COMPRESS = 2\r
+} COMPRESS_TYPE;\r
+\r
+typedef struct _COMPRESS_ACTION_LIST {\r
+ struct _COMPRESS_ACTION_LIST *NextAction;\r
+ INT32 CompressType;\r
+ CHAR8 *InFileName;\r
+ CHAR8 *OutFileName;\r
+} COMPRESS_ACTION_LIST;\r
+\r
+\r
+STATIC\r
+BOOLEAN\r
+ParseCommandLine (\r
+ INT32 argc,\r
+ CHAR8 *argv[],\r
+ COMPRESS_ACTION_LIST **ActionListHead\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Parse command line options\r
+\r
+Arguments:\r
+ \r
+ argc - number of arguments passed into the command line.\r
+ argv[] - files to compress and files to output compressed data to.\r
+ Options - Point to COMMAND_LINE_OPTIONS, receiving command line options.\r
+\r
+Returns:\r
+ \r
+ BOOLEAN: TRUE for a successful parse.\r
+--*/\r
+;\r
+\r
+STATIC\r
+VOID\r
+Usage (\r
+ CHAR8 *ExeName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Print usage.\r
+\r
+Arguments:\r
+ \r
+ ExeName - Application's full path\r
+\r
+--*/\r
+;\r
+\r
+\r
+STATIC\r
+BOOLEAN\r
+ProcessFile (\r
+ CHAR8 *InFileName,\r
+ CHAR8 *OutFileName,\r
+ COMPRESS_TYPE CompressType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Compress InFileName to OutFileName using algorithm specified by CompressType.\r
+\r
+Arguments:\r
+ \r
+ InFileName - Input file to compress\r
+ OutFileName - Output file compress to\r
+ CompressType - Compress algorithm, can be EFI_COMPRESS or TIANO_COMPRESS\r
+\r
+Returns:\r
+ \r
+ BOOLEAN: TRUE for compress file successfully\r
+\r
+--*/\r
+;\r
+\r
+int\r
+main (\r
+ INT32 argc,\r
+ CHAR8 *argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Compresses the input files\r
+\r
+Arguments:\r
+\r
+ argc - number of arguments passed into the command line.\r
+ argv[] - files to compress and files to output compressed data to.\r
+\r
+Returns:\r
+\r
+ int: 0 for successful execution of the function.\r
+\r
+--*/\r
+{\r
+ COMPRESS_ACTION_LIST *ActionList;\r
+ COMPRESS_ACTION_LIST *NextAction;\r
+ UINT32 ActionCount;\r
+ UINT32 SuccessCount;\r
+\r
+ ActionList = NULL;\r
+ ActionCount = SuccessCount = 0;\r
+\r
+ if (!ParseCommandLine (argc, argv, &ActionList)) {\r
+ Usage (*argv);\r
+ return 1;\r
+ }\r
+\r
+ while (ActionList != NULL) {\r
+ ++ActionCount;\r
+ if (ProcessFile (\r
+ ActionList->InFileName, \r
+ ActionList->OutFileName, \r
+ ActionList->CompressType)\r
+ ) {\r
+ ++SuccessCount;\r
+ }\r
+ NextAction = ActionList;\r
+ ActionList = ActionList->NextAction;\r
+ free (NextAction);\r
+ }\r
+\r
+ fprintf (stdout, "\nCompressed %d files, %d succeed!\n", ActionCount, SuccessCount);\r
+ if (SuccessCount < ActionCount) {\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+ParseCommandLine (\r
+ INT32 argc,\r
+ CHAR8 *argv[],\r
+ COMPRESS_ACTION_LIST **ActionListHead\r
+ )\r
+{\r
+ COMPRESS_TYPE CurrentType;\r
+\r
+ COMPRESS_ACTION_LIST **Action;\r
+ \r
+ Action = ActionListHead;\r
+ CurrentType = EFI_COMPRESS; // default compress algorithm\r
+\r
+ // Skip Exe Name\r
+ --argc;\r
+ ++argv;\r
+\r
+ while (argc > 0) {\r
+ if (strcmp (*argv, "-h") == 0 || strcmp (*argv, "-?") == 0) {\r
+ //\r
+ // 1. Directly return, help message will be printed.\r
+ //\r
+ return FALSE;\r
+ \r
+ } else if (strncmp (*argv, "-t", 2) == 0) {\r
+ //\r
+ // 2. Specifying CompressType\r
+ //\r
+ if (_stricmp ((*argv)+2, "EFI") == 0) {\r
+ CurrentType = EFI_COMPRESS;\r
+ } else if (_stricmp ((*argv)+2, "Tiano") == 0) {\r
+ CurrentType = TIANO_COMPRESS;\r
+ } else {\r
+ fprintf (stdout, " ERROR: CompressType %s not supported!\n", (*argv)+2);\r
+ return FALSE;\r
+ }\r
+ } else {\r
+ //\r
+ // 3. Current parameter is *FileName\r
+ //\r
+ if (*Action == NULL) { \r
+ //\r
+ // need to create a new action item\r
+ //\r
+ *Action = (COMPRESS_ACTION_LIST*) malloc (sizeof **Action);\r
+ if (*Action == NULL) {\r
+ fprintf (stdout, " ERROR: malloc failed!\n");\r
+ return FALSE;\r
+ }\r
+ memset (*Action, 0, sizeof **Action);\r
+ (*Action)->CompressType = CurrentType;\r
+ }\r
+\r
+ //\r
+ // Assignment to InFileName and OutFileName in order\r
+ // \r
+ if ((*Action)->InFileName == NULL) {\r
+ (*Action)->InFileName = *argv;\r
+ } else {\r
+ (*Action)->OutFileName = *argv;\r
+ Action = &(*Action)->NextAction;\r
+ }\r
+ }\r
+\r
+ --argc;\r
+ ++argv;\r
+\r
+ }\r
+ \r
+ if (*Action != NULL) {\r
+ assert ((*Action)->InFileName != NULL);\r
+ fprintf (stdout, " ERROR: Compress OutFileName not specified with InFileName: %s!\n", (*Action)->InFileName);\r
+ return FALSE;\r
+ }\r
+\r
+ if (*ActionListHead == NULL) {\r
+ return FALSE;\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+ProcessFile (\r
+ CHAR8 *InFileName,\r
+ CHAR8 *OutFileName,\r
+ COMPRESS_TYPE CompressType\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ FILE *InFileP;\r
+ FILE *OutFileP;\r
+ UINT32 SrcSize;\r
+ UINT32 DstSize;\r
+ UINT8 *SrcBuffer;\r
+ UINT8 *DstBuffer;\r
+ COMPRESS_FUNCTION CompressFunc;\r
+\r
+ SrcBuffer = DstBuffer = NULL;\r
+ InFileP = OutFileP = NULL;\r
+\r
+ fprintf (stdout, "%s --> %s\n", InFileName, OutFileName);\r
+\r
+ if ((OutFileP = fopen (OutFileName, "wb")) == NULL) {\r
+ fprintf (stdout, " ERROR: Can't open output file %s for write!\n", OutFileName);\r
+ goto ErrorHandle;\r
+ }\r
+\r
+ if ((InFileP = fopen (InFileName, "rb")) == NULL) {\r
+ fprintf (stdout, " ERROR: Can't open input file %s for read!\n", InFileName);\r
+ goto ErrorHandle;\r
+ }\r
+ \r
+ //\r
+ // Get the size of source file\r
+ //\r
+ fseek (InFileP, 0, SEEK_END);\r
+ SrcSize = ftell (InFileP);\r
+ rewind (InFileP);\r
+ //\r
+ // Read in the source data\r
+ //\r
+ if ((SrcBuffer = malloc (SrcSize)) == NULL) {\r
+ fprintf (stdout, " ERROR: Can't allocate memory!\n");\r
+ goto ErrorHandle;\r
+ }\r
+\r
+ if (fread (SrcBuffer, 1, SrcSize, InFileP) != SrcSize) {\r
+ fprintf (stdout, " ERROR: Can't read from source!\n");\r
+ goto ErrorHandle;\r
+ }\r
+\r
+ //\r
+ // Choose the right compress algorithm\r
+ //\r
+ CompressFunc = (CompressType == EFI_COMPRESS) ? EfiCompress : TianoCompress;\r
+\r
+ //\r
+ // Get destination data size and do the compression\r
+ //\r
+ DstSize = 0;\r
+ Status = CompressFunc (SrcBuffer, SrcSize, DstBuffer, &DstSize);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ fprintf (stdout, " Error: Compress failed: %x!\n", Status);\r
+ goto ErrorHandle;\r
+ }\r
+ if ((DstBuffer = malloc (DstSize)) == NULL) {\r
+ fprintf (stdout, " ERROR: Can't allocate memory!\n");\r
+ goto ErrorHandle;\r
+ }\r
+\r
+ Status = CompressFunc (SrcBuffer, SrcSize, DstBuffer, &DstSize);\r
+ if (EFI_ERROR (Status)) {\r
+ fprintf (stdout, " ERROR: Compress Error!\n");\r
+ goto ErrorHandle;\r
+ }\r
+\r
+ fprintf (stdout, " Orig Size = %ld\tComp Size = %ld\n", SrcSize, DstSize);\r
+\r
+ if (DstBuffer == NULL) {\r
+ fprintf (stdout, " ERROR: No destination to write to!\n");\r
+ goto ErrorHandle;\r
+ }\r
+\r
+ //\r
+ // Write out the result\r
+ //\r
+ if (fwrite (DstBuffer, 1, DstSize, OutFileP) != DstSize) {\r
+ fprintf (stdout, " ERROR: Can't write to destination file!\n");\r
+ goto ErrorHandle;\r
+ }\r
+\r
+ return TRUE;\r
+\r
+ErrorHandle:\r
+ if (SrcBuffer) {\r
+ free (SrcBuffer);\r
+ }\r
+\r
+ if (DstBuffer) {\r
+ free (DstBuffer);\r
+ }\r
+\r
+ if (InFileP) {\r
+ fclose (InFileP);\r
+ }\r
+\r
+ if (OutFileP) {\r
+ fclose (OutFileP);\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+VOID\r
+Usage (\r
+ CHAR8 *ExeName\r
+ )\r
+{\r
+ fprintf (\r
+ stdout, \r
+ "\n"\r
+ "Usage: %s [-tCompressType] InFileName OutFileName\n"\r
+ " %*c [[-tCompressType] InFileName OutFileName ...]\n"\r
+ "\n"\r
+ "where:\n"\r
+ " CompressType - optional compress algorithm (EFI | Tiano), case insensitive.\n"\r
+ " If ommitted, compress type specified ahead is used, \n"\r
+ " default is EFI\n"\r
+ " e.g.: EfiCompress a.in a.out -tTiano b.in b.out \\ \n"\r
+ " c.in c.out -tEFI d.in d.out\n"\r
+ " a.in and d.in are compressed using EFI compress algorithm\n"\r
+ " b.in and c.in are compressed using Tiano compress algorithm\n"\r
+ " InFileName - input file path\n"\r
+ " OutFileName - output file path\n",\r
+ ExeName, strlen(ExeName), ' '\r
+ );\r
+}\r