mirror of https://github.com/acidanthera/audk.git
525 lines
12 KiB
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;
|
|
}
|