Check In tool source code based on Build tool project revision r1655.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
329
BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c
Normal file
329
BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/** @file
|
||||
|
||||
Copyright 2006 - 2008, 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:
|
||||
|
||||
efildrimage.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Creates and EFILDR image.
|
||||
This tool combines several PE Image files together using following format denoted as EBNF:
|
||||
FILE := EFILDR_HEADER
|
||||
EFILDR_IMAGE +
|
||||
<PeImageFileContent> +
|
||||
The order of EFILDR_IMAGE is same as the order of placing PeImageFileContent.
|
||||
|
||||
Revision History
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ParseInf.h"
|
||||
#include "CommonLib.h"
|
||||
#include "EfiUtilityMsgs.h"
|
||||
|
||||
#define MAX_PE_IMAGES 63
|
||||
#define FILE_TYPE_FIXED_LOADER 0
|
||||
#define FILE_TYPE_RELOCATABLE_PE_IMAGE 1
|
||||
|
||||
typedef struct {
|
||||
UINT32 CheckSum;
|
||||
UINT32 Offset;
|
||||
UINT32 Length;
|
||||
UINT8 FileName[52];
|
||||
} EFILDR_IMAGE;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
UINT32 HeaderCheckSum;
|
||||
UINT32 FileLength;
|
||||
UINT32 NumberOfImages;
|
||||
} EFILDR_HEADER;
|
||||
|
||||
//
|
||||
// Utility Name
|
||||
//
|
||||
#define UTILITY_NAME "EfiLdrImage"
|
||||
|
||||
//
|
||||
// Utility version information
|
||||
//
|
||||
#define UTILITY_MAJOR_VERSION 0
|
||||
#define UTILITY_MINOR_VERSION 1
|
||||
|
||||
void
|
||||
Version (
|
||||
void
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Displays the standard utility information to SDTOUT
|
||||
|
||||
Arguments:
|
||||
|
||||
None
|
||||
|
||||
Returns:
|
||||
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
printf ("%s v%d.%d -Utility to break a file into two pieces at the request offset.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
|
||||
printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
Usage (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
CountVerboseLevel (
|
||||
IN CONST CHAR8* VerboseLevelString,
|
||||
IN CONST UINT64 Length,
|
||||
OUT UINT64 *ReturnValue
|
||||
)
|
||||
{
|
||||
UINT64 i = 0;
|
||||
for (;i < Length; ++i) {
|
||||
if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
++(*ReturnValue);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
UINT64
|
||||
FCopyFile (
|
||||
FILE *in,
|
||||
FILE *out
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
Write all the content of input file to output file.
|
||||
|
||||
Arguments:
|
||||
in - input file pointer
|
||||
out - output file pointer
|
||||
|
||||
Return:
|
||||
UINT64 : file size of input file
|
||||
--*/
|
||||
{
|
||||
UINT64 filesize, offset, length;
|
||||
CHAR8 Buffer[8*1024];
|
||||
|
||||
fseek (in, 0, SEEK_END);
|
||||
filesize = ftell(in);
|
||||
|
||||
fseek (in, 0, SEEK_SET);
|
||||
|
||||
offset = 0;
|
||||
while (offset < filesize) {
|
||||
length = sizeof(Buffer);
|
||||
if (filesize-offset < length) {
|
||||
length = filesize-offset;
|
||||
}
|
||||
|
||||
fread (Buffer, length, 1, in);
|
||||
fwrite (Buffer, length, 1, out);
|
||||
offset += length;
|
||||
}
|
||||
|
||||
return filesize;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (
|
||||
int argc,
|
||||
char *argv[]
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Returns:
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT64 i;
|
||||
UINT64 filesize;
|
||||
FILE *fpIn, *fpOut;
|
||||
EFILDR_HEADER EfiLdrHeader;
|
||||
EFILDR_IMAGE EfiLdrImage[MAX_PE_IMAGES];
|
||||
CHAR8* OutputFileName = NULL;
|
||||
CHAR8* InputFileNames[MAX_PE_IMAGES + 1];
|
||||
UINT8 InputFileCount = 0;
|
||||
BOOLEAN QuietFlag = FALSE;
|
||||
UINT64 DebugLevel = 0;
|
||||
UINT64 VerboseLevel = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
SetUtilityName (UTILITY_NAME);
|
||||
|
||||
if (argc == 1) {
|
||||
Usage();
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
argc --;
|
||||
argv ++;
|
||||
|
||||
if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
|
||||
Usage();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (stricmp (argv[0], "--version") == 0) {
|
||||
Version();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
while (argc > 0) {
|
||||
|
||||
if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
|
||||
OutputFileName = argv[1];
|
||||
if (OutputFileName == NULL) {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
|
||||
QuietFlag = TRUE;
|
||||
argc --;
|
||||
argv ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {
|
||||
VerboseLevel = 1;
|
||||
if (strlen(argv[0]) > 2) {
|
||||
Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Error (NULL, 0, 1003, "Invalid option value", argv[0]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
argc --;
|
||||
argv ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
|
||||
Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Don't recognize the paramter, should be regarded as the input file name.
|
||||
//
|
||||
InputFileNames[InputFileCount] = argv[0];
|
||||
InputFileCount++;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (InputFileCount == 0) {
|
||||
Error (NULL, 0, 1001, "Missing option", "No input file");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
//
|
||||
// Open output file for write
|
||||
//
|
||||
if (OutputFileName == NULL) {
|
||||
Error (NULL, 0, 1001, "Missing option", "No output file");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
fpOut = fopen(OutputFileName, "w+b");
|
||||
if (!fpOut) {
|
||||
Error (NULL, 0, 0001, "Could not open output file", OutputFileName);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader));
|
||||
memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (InputFileCount));
|
||||
|
||||
memcpy (&EfiLdrHeader.Signature, "EFIL", 4);
|
||||
EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(InputFileCount);
|
||||
|
||||
//
|
||||
// Skip the file header first
|
||||
//
|
||||
fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET);
|
||||
|
||||
//
|
||||
// copy all the input files to the output file
|
||||
//
|
||||
for(i=0;i<InputFileCount;i++) {
|
||||
//
|
||||
// Copy the content of PeImage file to output file
|
||||
//
|
||||
fpIn = fopen (InputFileNames[i], "rb");
|
||||
if (!fpIn) {
|
||||
Error (NULL, 0, 0001, "Could not open input file", InputFileNames[i]);
|
||||
fclose (fpOut);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
filesize = FCopyFile (fpIn, fpOut);
|
||||
fclose(fpIn);
|
||||
|
||||
//
|
||||
// And in the same time update the EfiLdrHeader and EfiLdrImage array
|
||||
//
|
||||
EfiLdrImage[i].Offset = EfiLdrHeader.FileLength;
|
||||
EfiLdrImage[i].Length = filesize;
|
||||
strncpy ((CHAR8*) EfiLdrImage[i].FileName, InputFileNames[i], sizeof (EfiLdrImage[i].FileName) - 1);
|
||||
EfiLdrHeader.FileLength += filesize;
|
||||
EfiLdrHeader.NumberOfImages++;
|
||||
}
|
||||
|
||||
//
|
||||
// Write the image header to the output file finally
|
||||
//
|
||||
fseek (fpOut, 0, SEEK_SET);
|
||||
fwrite (&EfiLdrHeader, sizeof(EFILDR_HEADER) , 1, fpOut);
|
||||
fwrite (&EfiLdrImage , sizeof(EFILDR_IMAGE)*(InputFileCount), 1, fpOut);
|
||||
|
||||
fclose (fpOut);
|
||||
printf ("Created %s\n", OutputFileName);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user