/*++ 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 #include #include #include // // 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; }