audk/Tools/CCode/Source/GenBsfFixup/GenBsfFixup.c

525 lines
12 KiB
C

/*++
Copyright (c) 1999 - 2006 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
GenBsfFixup.c
Abstract:
Utility to Fixup the SEC component for IA32. This is an
interim tool in place of the full GenBsfImage support for
IA32.
This tool supports the Synch3 update
--*/
#include "BaseTypes.h"
#include "UefiBaseTypes.h"
#include "EfiImage.h"
#include "FirmwareVolumeHeader.h"
#include "FirmwareVolumeImageFormat.h"
#include "ParseInf.h"
#include "CommonLib.h"
#include "FirmwareFileSystem.h"
#include "FvLib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
//
// BugBug -- this port to the new FFS is really weird.
// A lot of the file-header stuff has been ported, but
// not the section information.
//
#define UTILITY_NAME "GenBsfFixup"
#define UTILITY_MAJOR_VERSION 0
#define UTILITY_MINOR_VERSION 1
UINT32 gFixup;
UINT32
GetOccupiedSize (
IN UINT32 ActualSize,
IN UINT32 Alignment
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
ActualSize - GC_TODO: add argument description
Alignment - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
{
UINT32 OccupiedSize;
OccupiedSize = ActualSize;
while ((OccupiedSize & (Alignment - 1)) != 0) {
OccupiedSize++;
}
return OccupiedSize;
}
static
void
Version (
VOID
)
{
printf ("%s v%d.%d -EDK Utility to Fixup the SEC component for IA32.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
printf ("Copyright (c) 1999-2006 Intel Corporation. All rights reserved.\n");
}
VOID
Usage (
VOID
)
{
Version();
printf ("\nUsage: " UTILITY_NAME " FvVolumeImageFile AddressOfFvInMemory OffsetOfFixup OutputFileName \n");
}
int
ReadHeader (
FILE *In,
UINT32 *FvSize
)
/*++
Routine Description:
Reads in Firmware Volume information from the volume header file.
Arguments:
In: Firmware Volume header file to read from
FvSize: Size of Firmware Volume
Returns:
int: Number of bytes read
--*/
{
EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
EFI_FV_BLOCK_MAP_ENTRY BlockMap;
INT32 SigTemp[2];
INT32 Invert;
INT32 bytesread;
UINT32 size;
size = 0;
Invert = 0;
bytesread = 0;
if (In == NULL) {
printf ("Error: Input file is NULL.\n");
return -1;
}
fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, In);
bytesread = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
SigTemp[0] = VolumeHeader.Signature;
SigTemp[1] = 0;
if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {
Invert = 1;
}
do {
fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, In);
bytesread += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
if (BlockMap.NumBlocks != 0) {
size += BlockMap.NumBlocks * BlockMap.BlockLength;
}
} while (BlockMap.NumBlocks != 0);
*FvSize = size;
rewind (In);
if (Invert == 1) {
bytesread *= -1;
}
return bytesread;
}
UINT32
GetSectionLength (
IN UINT32 *Length
)
/*++
Routine Description:
Converts a UINT8[3] array to a UINT32
Arguments:
Length A pointer to a 3 byte array
Returns:
UINT32: The length.
--*/
{
return *Length & 0x00FFFFFF;
}
int
Readfile (
UINT8 *FvImage,
int bytes,
int Invert
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
FvImage - GC_TODO: add argument description
bytes - GC_TODO: add argument description
Invert - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
{
UINT32 FileLength;
UINT32 OccupiedFileLength;
EFI_FFS_FILE_HEADER *FileHeader;
UINT8 FileState;
UINT8 Checksum;
UINT8 *Ptr;
UINT32 SectionLength;
EFI_COMMON_SECTION_HEADER *SectionHeader;
EFI_IMAGE_NT_HEADERS *PeHeader;
UINT32 PeiCoreOffset;
Ptr = FvImage + bytes;
FileHeader = (EFI_FFS_FILE_HEADER *) Ptr;
FileState = GetFileState ((UINT8) Invert, FileHeader);
switch (FileState) {
case EFI_FILE_HEADER_CONSTRUCTION:
case EFI_FILE_HEADER_INVALID:
return sizeof (EFI_FFS_FILE_HEADER);
case EFI_FILE_HEADER_VALID:
Checksum = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
Checksum = (UINT8) (Checksum - FileHeader->State);
if (Checksum != 0) {
return -1;
}
//
// Now do the fixup stuff - begin
//
if (FileHeader->Type == EFI_FV_FILETYPE_PEI_CORE) {
SectionHeader = (EFI_COMMON_SECTION_HEADER *) FileHeader + sizeof (EFI_FFS_FILE_HEADER);
SectionLength = GetSectionLength ((UINT32 *) &SectionHeader->Size[0]);
printf ("Section length is 0x%X\n", SectionLength);
if (SectionHeader->Type == EFI_SECTION_PE32) {
gFixup = bytes + sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_COMMON_SECTION_HEADER);
PeHeader = (EFI_IMAGE_NT_HEADERS *) Ptr + sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_COMMON_SECTION_HEADER);
if (((EFI_IMAGE_DOS_HEADER *) PeHeader)->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
//
// DOS image header is present, so read the PE header after the DOS image header
//
PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) PeHeader + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) PeHeader)->e_lfanew) & 0x0ffff));
}
PeiCoreOffset = (UINTN) ((UINTN) (PeHeader->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
gFixup += PeiCoreOffset;
}
}
FileLength = GetLength (FileHeader->Size);
OccupiedFileLength = GetOccupiedSize (FileLength, 8);
return OccupiedFileLength;
case EFI_FILE_DATA_VALID:
//
// Calculate header checksum
//
Checksum = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
Checksum = (UINT8) (Checksum - FileHeader->State);
if (Checksum != 0) {
return -1;
}
//
// Determine file length
//
FileLength = GetLength (FileHeader->Size);
OccupiedFileLength = GetOccupiedSize (FileLength, 8);
//
// Determine if file checksum is valid or fixed
//
if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
Checksum = CalculateSum8 (Ptr, FileLength);
Checksum = (UINT8) (Checksum - FileHeader->State);
if (Checksum != 0) {
return -1;
}
} else {
if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
return -1;
}
}
break;
case EFI_FILE_MARKED_FOR_UPDATE:
case EFI_FILE_DELETED:
//
// Calculate header checksum
//
Checksum = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
Checksum = (UINT8) (Checksum - FileHeader->State);
if (Checksum != 0) {
return -1;
}
//
// Determine file length
//
FileLength = GetLength (FileHeader->Size);
OccupiedFileLength = GetOccupiedSize (FileLength, 8);
//
// Determine if file checksum is valid or fixed
//
if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
Checksum = CalculateSum8 (Ptr, FileLength);
Checksum = (UINT8) (Checksum - FileHeader->State);
if (Checksum != 0) {
return -1;
}
} else {
if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
return -1;
}
}
return OccupiedFileLength;
default:
return sizeof (EFI_FFS_FILE_HEADER);
}
return OccupiedFileLength;
}
int
main (
int argc,
char*argv[]
)
/*++
Routine Description:
Runs GenBsfFixup
Arguments:
argc: number of command line arguments
arg[0] = This file name
arg[1] = Firmware Volume Name
arg[2] = Base Address to relocate
arg[3] = Relative offset of the fixup to perform
arg[4] = Output File Name
Returns:
int: 0 code success, -1 code failure
--*/
{
FILE *In;
FILE *Out;
int ByteStart;
int Invert;
int Index;
int cnt;
UINT8 *FvImage;
int ByteRead;
UINT32 FvSize;
UINT64 delta;
UINT32 Idx;
UINT64 FvOffset;
EFI_STATUS Status;
Index = 0;
Invert = 0;
if (argc == 1) {
Usage();
return -1;
}
if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
(strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
Usage();
return -1;
}
if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
Version();
return -1;
}
if (argc != 5) {
Usage();
return -1;
}
In = fopen (argv[1], "rb");
if (In == NULL) {
printf ("Unable to open FV image file \"%s\"\n", argv[1]);
return -1;
}
ByteStart = ReadHeader (In, &FvSize);
if (ByteStart < 0) {
Invert = 1;
ByteStart *= -1;
}
FvImage = malloc (FvSize);
if (FvImage == NULL) {
printf ("Cannot allocate memory\n");
fclose (In);
return -1;
}
ByteRead = fread (FvImage, 1, FvSize, In);
if ((unsigned int) ByteRead != FvSize) {
printf ("Read File error\n");
fclose (In);
return -1;
}
cnt = 0;
while ((unsigned int) ByteStart < FvSize && cnt != -1) {
cnt = Readfile (FvImage, ByteStart, Invert);
if (cnt != -1) {
ByteStart += cnt;
}
if (cnt != sizeof (EFI_FFS_FILE_HEADER)) {
Index++;
}
}
if (cnt == -1) {
printf ("Firmware Volume image corrupted\n");
return -1;
}
fclose (In);
Out = fopen (argv[4], "wb");
if (Out == NULL) {
printf ("Unable to open FV image file \"%s\"\n", argv[4]);
return -1;
}
In = fopen (argv[1], "rb");
if (In == NULL) {
printf ("Unable to open FV image file \"%s\"\n", argv[1]);
return -1;
}
if (gFixup != 0) {
printf ("Fixup of 0x%X\n", gFixup);
Status = AsciiStringToUint64 (argv[2], TRUE, &FvOffset);
gFixup += (UINT32) FvOffset;
ByteStart = ReadHeader (In, &FvSize);
Readfile (FvImage, ByteStart, Invert);
cnt = 0;
Status = AsciiStringToUint64 (argv[3], TRUE, &delta);
fclose (In);
In = fopen (argv[1], "rb");
if (In == NULL) {
printf ("Unable to open FV image file \"%s\"\n", argv[1]);
return -1;
}
for (Idx = 0; Idx < delta - FvOffset; Idx++) {
fputc (fgetc (In), Out);
}
fwrite (&gFixup, sizeof (UINT32), 1, Out);
fseek (In, sizeof (UINT32), SEEK_CUR);
for (Idx = 0; Idx < FvSize - (delta - FvOffset) - sizeof (UINT32); Idx++) {
fputc (fgetc (In), Out);
}
fclose (In);
fclose (Out);
} else {
printf ("There was no fixup to perform\n");
}
free (FvImage);
return 0;
}