From 604371b98d3ad2472e96be8d126df92b2fcf68df Mon Sep 17 00:00:00 2001 From: lhauch Date: Thu, 5 Oct 2006 23:24:16 +0000 Subject: More moves for Tool Packages git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1676 6f19259b-4bc3-4df7-8a09-765794883524 --- Tools/CCode/Source/FlashMap/FlashDefFile.c | 2788 ++++++++++++++++++++++++++++ Tools/CCode/Source/FlashMap/FlashDefFile.h | 281 +++ Tools/CCode/Source/FlashMap/FlashMap.c | 769 ++++++++ Tools/CCode/Source/FlashMap/Microcode.c | 304 +++ Tools/CCode/Source/FlashMap/Microcode.h | 87 + Tools/CCode/Source/FlashMap/Symbols.c | 648 +++++++ Tools/CCode/Source/FlashMap/Symbols.h | 124 ++ Tools/CCode/Source/FlashMap/build.xml | 76 + 8 files changed, 5077 insertions(+) create mode 100644 Tools/CCode/Source/FlashMap/FlashDefFile.c create mode 100644 Tools/CCode/Source/FlashMap/FlashDefFile.h create mode 100644 Tools/CCode/Source/FlashMap/FlashMap.c create mode 100644 Tools/CCode/Source/FlashMap/Microcode.c create mode 100644 Tools/CCode/Source/FlashMap/Microcode.h create mode 100644 Tools/CCode/Source/FlashMap/Symbols.c create mode 100644 Tools/CCode/Source/FlashMap/Symbols.h create mode 100644 Tools/CCode/Source/FlashMap/build.xml (limited to 'Tools/CCode/Source/FlashMap') diff --git a/Tools/CCode/Source/FlashMap/FlashDefFile.c b/Tools/CCode/Source/FlashMap/FlashDefFile.c new file mode 100644 index 0000000000..cdbf7886ec --- /dev/null +++ b/Tools/CCode/Source/FlashMap/FlashDefFile.c @@ -0,0 +1,2788 @@ +/*++ + +Copyright (c) 2004-2006 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: + + FlashDefFile.c + +Abstract: + + Utility for flash management in the Intel Platform Innovation Framework + for EFI build environment. + +--*/ + +#include +#include +#include + +#include +#include +#include + +#include "EfiUtilityMsgs.h" +#include "FlashDefFile.h" +#include "SimpleFileParsing.h" +#include "Symbols.h" + +// +// #include "TrackMallocFree.h" +// +#define WCHAR_T char +#define MAX_STRING_LEN 256 +#define MAX_NAME_LEN 128 +#define BUFFER_SIZE 1024 +#define MAX_ATTR_LEN 128 +#define MAX_AREATYPE_LEN 128 +#define COLUMN2_START 60 +#define COLUMN3_START 70 +// +// Information for each subregions defined in the fdf file will be saved in these +// +typedef struct _FLASH_SUBREGION_DESCRIPTION { + struct _FLASH_SUBREGION_DESCRIPTION *Next; + int CreateHob; // to add to the auto-created HOB array + WCHAR_T Name[MAX_NAME_LEN]; // each subregion within a region must have a unique name + unsigned int Size; // size, in bytes, of this subregion + unsigned int SizeLeft; // used when creating the image + WCHAR_T Attributes[MAX_ATTR_LEN]; // subregion attributes used in the output HOB + WCHAR_T AreaType[MAX_AREATYPE_LEN]; // subregion area type used in the output HOB + EFI_GUID NameGuid; // used in the output HOB + WCHAR_T NameGuidString[MAX_NAME_LEN]; + EFI_GUID AreaTypeGuid; // used in the output HOB + WCHAR_T AreaTypeGuidString[MAX_NAME_LEN]; + EFI_GUID FileSystemGuid; // used in the output HOB + WCHAR_T FileSystemGuidString[MAX_NAME_LEN]; +} FLASH_SUBREGION_DESCRIPTION; + +// +// Information for each block in a flash device will be saved in one of these. +// We'll also use it for region definitions. +// +typedef struct _FLASH_BLOCK_DESCRIPTION { + struct _FLASH_BLOCK_DESCRIPTION *Next; // next block in the linked list + WCHAR_T Name[MAX_NAME_LEN]; // each block must have a unique name + unsigned int Size; // size, in bytes, of this block + unsigned int SizeLeft; // for use when creating image + unsigned int Flags; // user-defined flags for the block + unsigned int Alignment; // power of 2 alignment + WCHAR_T Attributes[MAX_ATTR_LEN]; // only used for Region definitions + WCHAR_T AreaType[MAX_AREATYPE_LEN]; // only used for Region definitions + FLASH_SUBREGION_DESCRIPTION *Subregions; + FLASH_SUBREGION_DESCRIPTION *LastSubregion; +} FLASH_BLOCK_DESCRIPTION; + +// +// Information for each flash device will be saved in one of these +// +typedef struct _FLASH_DEVICE_DESCRIPTION { + struct _FLASH_DEVICE_DESCRIPTION *Next; // next flash device in our linked list + int ErasePolarity; // erase polarity of the flash device + unsigned int BaseAddress; // base address of the flash device + unsigned int Size; // total size, in bytes, of the flash device + WCHAR_T Name[MAX_NAME_LEN]; // name of the flash device + FLASH_BLOCK_DESCRIPTION *PBlocks; // linked list of physical block descriptors + FLASH_BLOCK_DESCRIPTION *LastPBlock; // last block in the linked list + FLASH_BLOCK_DESCRIPTION *Regions; // linked list of flash region descriptors + FLASH_BLOCK_DESCRIPTION *LastRegion; // last region in the linked list +} FLASH_DEVICE_DESCRIPTION; + +// +// For image definitions, they can specify a file name or raw data bytes. Keep a linked list. +// +typedef struct _IMAGE_DEFINITION_ENTRY { + struct _IMAGE_DEFINITION_ENTRY *Next; + WCHAR_T RegionName[MAX_NAME_LEN]; + WCHAR_T SubregionName[MAX_NAME_LEN]; + WCHAR_T Name[MAX_NAME_LEN]; // file or data name + int IsRawData; // non-zero if raw data bytes + unsigned int RawDataSize; + char *RawData; + int Optional; // optional file (don't include if it doesn't exist) +} IMAGE_DEFINITION_ENTRY; + +// +// When we parse an image definition, save all the data for each in one of these +// +typedef struct _IMAGE_DEFINITION { + struct _IMAGE_DEFINITION *Next; + WCHAR_T Name[MAX_NAME_LEN]; + IMAGE_DEFINITION_ENTRY *Entries; + IMAGE_DEFINITION_ENTRY *LastEntry; +} IMAGE_DEFINITION; + +typedef struct { + char *BufferStart; + char *BufferEnd; + char *BufferPos; +} BUFFER_DATA; + +static const char *CIncludeHeader = "/*++\n\n" +" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n""#ifndef _FLASH_MAP_H_\n" +"#define _FLASH_MAP_H_\n\n"; +// +// "#include \"EfiFlashMap.h\"\n\n"; +// +static const char *CIncludeFooter = "#endif // #ifndef _FLASH_MAP_H_\n\n"; + +static const char *CFlashMapDataFileHeader = "/*++\n\n" +" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n"; + +static FLASH_DEVICE_DESCRIPTION *mFlashDevices = NULL; +static IMAGE_DEFINITION *mImageDefinitions = NULL; + +// +// Local function prototypes +// +static +BUFFER_DATA * +CreateBufferData ( + VOID + ); + +static +BOOLEAN +AddBufferDataByte ( + BUFFER_DATA *Buffer, + char Data + ); + +static +void +FreeBufferData ( + BUFFER_DATA *Buffer, + BOOLEAN FreeData + ); + +static +char * +GetBufferData ( + BUFFER_DATA *Buffer, + int *BufferSize + ); + +static +FLASH_SUBREGION_DESCRIPTION * +ParseSubregionDefinition ( + unsigned int SizeLeft + ); + +void +FDFConstructor ( + VOID + ) +/*++ + +Routine Description: + Initialization routine for the services that operate on a flash + definition file. + +Arguments: + None. + +Returns: + NA + +--*/ +{ + mFlashDevices = NULL; + mImageDefinitions = NULL; +} + +void +FDFDestructor ( + VOID + ) +/*++ + +Routine Description: + Finalization/cleanup routine for the services that operate on a flash + definition file. + +Arguments: + None. + +Returns: + NA + +--*/ +{ + FLASH_BLOCK_DESCRIPTION *FBNext; + FLASH_DEVICE_DESCRIPTION *FDNext; + IMAGE_DEFINITION *IDNext; + IMAGE_DEFINITION_ENTRY *IDENext; + FLASH_SUBREGION_DESCRIPTION *SubNext; + // + // Go through all our flash devices and free the memory + // + while (mFlashDevices != NULL) { + // + // Free the physical block definitions + // + while (mFlashDevices->PBlocks != NULL) { + FBNext = mFlashDevices->PBlocks->Next; + _free (mFlashDevices->PBlocks); + mFlashDevices->PBlocks = FBNext; + } + // + // Free the region definitions + // + while (mFlashDevices->Regions != NULL) { + FBNext = mFlashDevices->Regions->Next; + // + // First free the subregion definitions + // + while (mFlashDevices->Regions->Subregions != NULL) { + SubNext = mFlashDevices->Regions->Subregions->Next; + _free (mFlashDevices->Regions->Subregions); + mFlashDevices->Regions->Subregions = SubNext; + } + + _free (mFlashDevices->Regions); + mFlashDevices->Regions = FBNext; + } + + FDNext = mFlashDevices->Next; + _free (mFlashDevices); + mFlashDevices = FDNext; + } + // + // Free up the image definitions, and the data + // + while (mImageDefinitions != NULL) { + // + // Free the entries + // + while (mImageDefinitions->Entries != NULL) { + IDENext = mImageDefinitions->Entries->Next; + if (mImageDefinitions->Entries->RawData != NULL) { + _free (mImageDefinitions->Entries->RawData); + } + + _free (mImageDefinitions->Entries); + mImageDefinitions->Entries = IDENext; + } + + IDNext = mImageDefinitions->Next; + _free (mImageDefinitions); + mImageDefinitions = IDNext; + } +} + +STATUS +FDFParseFile ( + char *FileName + ) +/*++ + +Routine Description: + Parse the specified flash definition file, saving the definitions in + file-static variables for use by other functions. + +Arguments: + FileName - name of the input flash definition text file. + +Returns: + STATUS_SUCCESS - file parsed with no errors or warnings + STATUS_WARNING - warnings, but no errors, were encountered while parsing + STATUS_ERROR - errors were encountered while parsing + +--*/ +{ + FILE *Fptr; + STATUS Status; + unsigned int Num; + FLASH_DEVICE_DESCRIPTION *FDDesc; + FLASH_BLOCK_DESCRIPTION *FBlockDesc; + FLASH_BLOCK_DESCRIPTION *TempBlockDesc; + FLASH_SUBREGION_DESCRIPTION *Subregion; + FLASH_SUBREGION_DESCRIPTION *TempSubregion; + unsigned int BlockSizeLeft; + unsigned int RegionSizeLeft; + unsigned int SubregionSizeLeft; + int ErrorCount; + int WarningCount; + IMAGE_DEFINITION *ImageDef; + IMAGE_DEFINITION_ENTRY *ImageDefEntry; + IMAGE_DEFINITION_ENTRY *TempImageDefEntry; + BUFFER_DATA *BufferData; + char Str[100]; + BOOLEAN PreviousComma; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open input flash definition file for reading"); + return STATUS_ERROR; + } + + fclose (Fptr); + Status = STATUS_SUCCESS; + ErrorCount = 0; + WarningCount = 0; + // + // Initialize the simple-file-parsing routines + // + SFPInit (); + // + // Open the file + // + if ((Status = SFPOpenFile (FileName)) != STATUS_SUCCESS) { + return Status; + } + // + // Parse the file. Should start with a series of these: + // FlashDevice { + // Name = "FLASH_1234", Size = 0x2004, BaseAddress = 0xFFF0000, ErasePolarity = 1, + // Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 } + // Block { Name = "BLOCK2", Size = 0x1004, Flags = 0x0002 } + // Region { Name = "REGION_NAME", Size = 0x2004, Align= 4 } + // } + // + while (SFPIsKeyword ("FlashDevice")) { + // + // Allocate memory for new flash device description block + // + FDDesc = (FLASH_DEVICE_DESCRIPTION *) _malloc (sizeof (FLASH_DEVICE_DESCRIPTION)); + if (FDDesc == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + ErrorCount++; + goto Done; + } + + memset (FDDesc, 0, sizeof (FLASH_DEVICE_DESCRIPTION)); + // + // Open brace -- warning if not there + // + if (!SFPIsToken ("{")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL); + WarningCount++; + } + // + // Parse: Name = "DeviceName", + // + if (!SFPIsKeyword ("Name")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (FDDesc->Name, sizeof (FDDesc->Name))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of flash device", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following flash device name", NULL); + WarningCount++; + } + // + // Parse: Size = 0x20000, + // + if (!SFPIsKeyword ("Size")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&FDDesc->Size)) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL); + ErrorCount++; + goto Done; + } + // + // Check for 0 size + // + if (FDDesc->Size == 0) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, FDDesc->Name, "Size field cannot be 0", NULL); + ErrorCount++; + goto Done; + } + + SFPIsToken (","); + // + // Parse: BaseAddress = 0xFFF0000, + // + if (!SFPIsKeyword ("BaseAddress")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'BaseAddress'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&FDDesc->BaseAddress)) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for BaseAddress", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following BaseAddress value", NULL); + WarningCount++; + } + // + // Parse: ErasePolarity = 1, + // + if (!SFPIsKeyword ("ErasePolarity")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'ErasePolarity'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&Num) || ((Num != 0) && (Num != 1))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric erase polarity value 1 or 0", NULL); + ErrorCount++; + goto Done; + } + + FDDesc->ErasePolarity = Num; + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following erase polarity value", NULL); + WarningCount++; + } + // + // Parse array of: + // Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 } + // + // Keep track of size to make sure the sum of the physical blocks and region sizes do not + // exceed the size of the flash device. + // + BlockSizeLeft = FDDesc->Size; + RegionSizeLeft = FDDesc->Size; + while (SFPIsKeyword ("Block")) { + // + // Allocate memory for a new physical block descriptor + // + FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION)); + if (FBlockDesc == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + ErrorCount++; + goto Done; + } + + memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION)); + // + // Open brace -- warning if not there + // + if (!SFPIsToken ("{")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL); + WarningCount++; + } + // + // Parse: Name = "BlockName", + // + if (!SFPIsKeyword ("Name")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of physical block", NULL); + ErrorCount++; + goto Done; + } + // + // Make sure there are no other physical block names with this same name + // + for (TempBlockDesc = FDDesc->PBlocks; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) { + if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + TempBlockDesc->Name, + "physical block with this name already defined" + ); + ErrorCount++; + } + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following physical block name", NULL); + WarningCount++; + } + // + // Parse: Size = 0x2000, + // + if (!SFPIsKeyword ("Size")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&FBlockDesc->Size)) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL); + ErrorCount++; + goto Done; + } + // + // Make sure the sum of physical blocks so far does not exceed flash device size + // + if (BlockSizeLeft < FBlockDesc->Size) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + "sum of physical block sizes exceeds flash device size", + NULL + ); + ErrorCount++; + } + + BlockSizeLeft -= FBlockDesc->Size; + SFPIsToken (","); + // + // Optional parse: Flags = 0xFFF0000, + // + if (SFPIsKeyword ("Flags")) { + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&FBlockDesc->Flags)) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL); + ErrorCount++; + goto Done; + } + } + + if (!SFPIsToken ("}")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected PhysicalBlock closing brace '}'", NULL); + WarningCount++; + } + // + // Add the physical block descriptor to the end of the linked list + // + if (FDDesc->LastPBlock != NULL) { + FDDesc->LastPBlock->Next = FBlockDesc; + } else { + FDDesc->PBlocks = FBlockDesc; + } + + FDDesc->LastPBlock = FBlockDesc; + } + // + // Make sure sum of sizes of physical blocks added up to size of flash device + // + if (BlockSizeLeft != 0) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + NULL, + "sum of sizes of physical blocks (0x%08X) != flash device size (0x%08X) : delta = 0x%08X", + FDDesc->Size - BlockSizeLeft, + FDDesc->Size, + BlockSizeLeft + ); + ErrorCount++; + } + // + // Parse array of: + // Region { Name = "REGION_1", Size = 0x2000, Flags = 0x1234, Alignment = 4, Attributes = "str", AreaType = "str" } + // + while (SFPIsKeyword ("Region")) { + // + // Allocate memory for a new physical block descriptor + // + FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION)); + if (FBlockDesc == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + ErrorCount++; + goto Done; + } + + memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION)); + // + // Open brace -- warning if not there + // + if (!SFPIsToken ("{")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL); + WarningCount++; + } + // + // Parse: Name = "BlockName", + // + if (!SFPIsKeyword ("Name")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL); + ErrorCount++; + goto Done; + } + // + // Make sure there are no other region names with this same name + // + for (TempBlockDesc = FDDesc->Regions; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) { + if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + TempBlockDesc->Name, + "Region with this name already defined" + ); + ErrorCount++; + } + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL); + WarningCount++; + } + // + // Parse: Size = 0x2000, + // + if (!SFPIsKeyword ("Size")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&FBlockDesc->Size)) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL); + } + // + // Make sure the sum of regions so far does not exceed flash device size + // + if (RegionSizeLeft < FBlockDesc->Size) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Region sizes exceeds flash device size", NULL); + ErrorCount++; + } + + RegionSizeLeft -= FBlockDesc->Size; + // + // Optional parse: Flags = 0xFFF0000, + // + if (SFPIsKeyword ("Flags")) { + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&FBlockDesc->Flags)) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL); + ErrorCount++; + goto Done; + } + // + // comma + // + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL); + } + } + // + // Optional parse: Alignment = 4 + // + if (SFPIsKeyword ("Alignment")) { + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&FBlockDesc->Alignment)) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Alignment value", NULL); + ErrorCount++; + goto Done; + } + // + // comma + // + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL); + } + } + // + // Parse: Attributes = "String", + // + if (!SFPIsKeyword ("Attributes")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (FBlockDesc->Attributes, sizeof (FBlockDesc->Attributes))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL); + } + // + // Parse: AreaType = "String", + // + if (!SFPIsKeyword ("AreaType")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (FBlockDesc->AreaType, sizeof (FBlockDesc->AreaType))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL); + ErrorCount++; + goto Done; + } + + PreviousComma = SFPIsToken (","); + // + // Parse optional Subregion definitions + // + SubregionSizeLeft = FBlockDesc->Size; + while (SFPIsToken ("Subregion")) { + if (!PreviousComma) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'Subregion'", NULL); + WarningCount++; + PreviousComma = TRUE; + } + + Subregion = ParseSubregionDefinition (SubregionSizeLeft); + if (Subregion == NULL) { + ErrorCount++; + goto Done; + } + + SubregionSizeLeft -= Subregion->Size; + // + // Add it to the end of our list + // + if (FBlockDesc->Subregions == NULL) { + FBlockDesc->Subregions = Subregion; + } else { + FBlockDesc->LastSubregion->Next = Subregion; + } + + FBlockDesc->LastSubregion = Subregion; + // + // Make sure all subregion names are unique. We do this each time + // through so that we catch the error immediately after it happens, in + // which case the reported line number is at least close to where the + // problem lies. We don't exit on the error because we can continue parsing + // the script to perhaps catch other errors or warnings. + // + for (Subregion = FBlockDesc->Subregions; Subregion != NULL; Subregion = Subregion->Next) { + for (TempSubregion = Subregion->Next; TempSubregion != NULL; TempSubregion = TempSubregion->Next) { + if (strcmp (Subregion->Name, TempSubregion->Name) == 0) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, Subregion->Name, "duplicate Subregion name"); + ErrorCount++; + } + } + } + } + + if (!SFPIsToken ("}")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Region closing brace '}'", NULL); + WarningCount++; + } + // + // Add the region descriptor to the end of the linked list + // + if (FDDesc->LastRegion != NULL) { + FDDesc->LastRegion->Next = FBlockDesc; + } else { + FDDesc->Regions = FBlockDesc; + } + + FDDesc->LastRegion = FBlockDesc; + } + // + // Make sure sum of sizes of regions adds up to size of flash device + // + if (RegionSizeLeft != 0) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + NULL, + "sum of sizes of Regions (0x%08X) != flash device size (0x%08X) : delta = 0x%08X", + FDDesc->Size - RegionSizeLeft, + FDDesc->Size, + RegionSizeLeft + ); + ErrorCount++; + } + // + // Look for closing brace + // + if (!SFPIsToken ("}")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected FlashDevice closing brace '}'", NULL); + WarningCount++; + } + // + // Add this flash description to the list + // + FDDesc->Next = mFlashDevices; + mFlashDevices = FDDesc; + } + + while (SFPIsKeyword ("FlashDeviceImage")) { + // + // Allocate memory for a new FD image definition + // + ImageDef = (IMAGE_DEFINITION *) _malloc (sizeof (IMAGE_DEFINITION)); + if (ImageDef == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + ErrorCount++; + goto Done; + } + + memset (ImageDef, 0, sizeof (IMAGE_DEFINITION)); + // + // Open brace -- warning if not there + // + if (!SFPIsToken ("{")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL); + WarningCount++; + } + // + // Parse: Name = "ImageName", + // + if (!SFPIsKeyword ("Name")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (ImageDef->Name, sizeof (ImageDef->Name))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of image", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following image name", NULL); + WarningCount++; + } + + while (1) { + // + // Parse: File { Name = "FV\FvOem.fv", Region = "REGION_OEM", Optional = TRUE } + // + if (SFPIsKeyword ("File")) { + ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY)); + if (ImageDefEntry == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + ErrorCount++; + goto Done; + } + + memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY)); + // + // Open brace -- warning if not there + // + if (!SFPIsToken ("{")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL); + WarningCount++; + } + // + // Parse: Name = "FileName.txt" + // + if (!SFPIsKeyword ("Name")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of file", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following file name", NULL); + WarningCount++; + } + // + // Parse: Region = "REGION_NAME" + // + if (!SFPIsKeyword ("Region")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL); + WarningCount++; + } + // + // Parse optional: Subregion = "SUBREGION_NAME" + // + if (SFPIsKeyword ("Subregion")) { + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL); + WarningCount++; + } + // + // For a given region, you can only place data using the region name, or the subregion names. + // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that + // here by checking that any previous entries with the same Region name had a Subregion specified + // as well. + // + for (TempImageDefEntry = ImageDef->Entries; + TempImageDefEntry != NULL; + TempImageDefEntry = TempImageDefEntry->Next + ) { + if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) { + if (TempImageDefEntry->SubregionName[0] == 0) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + TempImageDefEntry->RegionName, + "data already placed on a region-basis in the region, can't place data using subregions" + ); + ErrorCount++; + } + } + } + } + // + // Optional parse: Optional = TRUE | FALSE + // + if (SFPIsKeyword ("Optional")) { + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPIsKeyword ("TRUE")) { + ImageDefEntry->Optional = 1; + } else if (SFPIsKeyword ("FALSE")) { + // + // Already set to 0 + // + } else { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + ErrorCount++; + goto Done; + } + + SFPIsToken (","); + } + // + // Closing brace + // + if (!SFPIsToken ("}")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace to File entry", NULL); + ErrorCount++; + goto Done; + } + // + // Add the entry to the end of the list + // + if (ImageDef->LastEntry != NULL) { + ImageDef->LastEntry->Next = ImageDefEntry; + } else { + ImageDef->Entries = ImageDefEntry; + } + + ImageDef->LastEntry = ImageDefEntry; + } else if (SFPIsKeyword ("RawData")) { + // + // Parse: RawData { Name = "PadBytes", Region = "REGION_1", Data = { 0x78, 0x56, 0x34, 0x12 }} + // + ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY)); + if (ImageDefEntry == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + ErrorCount++; + goto Done; + } + + memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY)); + ImageDefEntry->IsRawData = 1; + // + // Open brace -- warning if not there + // + if (!SFPIsToken ("{")) { + Warning ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + "expected '{' opening brace for RawData definition", + NULL + ); + WarningCount++; + } + // + // Parse: Name = "PadBytes" + // + if (!SFPIsKeyword ("Name")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of raw data", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following raw data name", NULL); + WarningCount++; + } + // + // Parse: Region = "REGION_NAME" + // + if (!SFPIsKeyword ("Region")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL); + WarningCount++; + } + // + // Parse optional: Subregion = "SUBREGION_NAME" + // + if (SFPIsKeyword ("Subregion")) { + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL); + WarningCount++; + } + // + // For a given region, you can only place data using the region name, or the subregion names. + // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that + // here by checking that any previous entries with the same Region name had a Subregion specified + // as well. + // + for (TempImageDefEntry = ImageDef->Entries; + TempImageDefEntry != NULL; + TempImageDefEntry = TempImageDefEntry->Next + ) { + if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) { + if (TempImageDefEntry->SubregionName[0] == 0) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + TempImageDefEntry->RegionName, + "data already placed on a region-basis in the region, can't place data using subregions" + ); + ErrorCount++; + } + } + } + } + // + // Parse: Data = { 0x78, 0x56, 0x34, 0x12 } + // + if (!SFPIsKeyword ("Data")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Data'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPIsToken ("{")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '{' preceeding data list", NULL); + WarningCount++; + } + + if ((BufferData = CreateBufferData ()) == NULL) { + ErrorCount++; + goto Done; + } + // + // Read bytes from input file until closing brace + // + while (!SFPIsToken ("}")) { + if (!SFPGetNumber (&Num)) { + SFPGetNextToken (Str, sizeof (Str)); + Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected data value", Str); + ErrorCount++; + FreeBufferData (BufferData, TRUE); + goto Done; + } else { + // + // Only allow bytes + // + if (Num > 0xFF) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "only values 0-255 (0x00-0xFF) allowed", NULL); + ErrorCount++; + FreeBufferData (BufferData, TRUE); + goto Done; + } + + AddBufferDataByte (BufferData, (char) Num); + SFPIsToken (","); + } + } + // + // Now get the data and save it in our image entry + // + ImageDefEntry->RawData = GetBufferData (BufferData, &ImageDefEntry->RawDataSize); + FreeBufferData (BufferData, 0); + // + // Closing brace for RawData {} + // + if (!SFPIsToken ("}")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace for RawData", NULL); + ErrorCount++; + goto Done; + } + // + // Add the entry to the end of the list + // + if (ImageDef->LastEntry != NULL) { + ImageDef->LastEntry->Next = ImageDefEntry; + } else { + ImageDef->Entries = ImageDefEntry; + } + + ImageDef->LastEntry = ImageDefEntry; + } else if (SFPIsToken ("}")) { + // + // Closing brace for FDImage {} + // + break; + } else { + SFPGetNextToken (Str, sizeof (Str)); + Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "unrecognized token", Str); + ErrorCount++; + goto Done; + } + } + // + // Add this image definition to our global list + // + ImageDef->Next = mImageDefinitions; + mImageDefinitions = ImageDef; + } + // + // Check for end-of-file + // + if (!SFPIsEOF ()) { + SFPGetNextToken (Str, sizeof (Str)); + Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected end-of-file", Str); + ErrorCount++; + } + +Done: + SFPCloseFile (); + if (ErrorCount != 0) { + return STATUS_ERROR; + } else if (WarningCount != 0) { + return STATUS_WARNING; + } + + return STATUS_SUCCESS; +} + +static +FLASH_SUBREGION_DESCRIPTION * +ParseSubregionDefinition ( + unsigned int SizeLeft + ) +/*++ + +Routine Description: + + Parse Subregion definitions from the input flash definition file. Format: + + Subregion { + CreateHob = TRUE, + Name = "FOO", + Size = 0xA000, + Attributes = "EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV", + AreaType = "EFI_FLASH_AREA_EFI_VARIABLES", + NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD (or "EFI_SOME_GUID"), + AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional) + FileSystemGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional) + } + + NOTE: The caller has already parsed the "Subregion" token, so start with the opening brace. + +Arguments: + + SizeLeft - in the flash definition file, a Region can be broken up into + one or more subregions. As we parse the subregion definitions, + the caller keeps track of how much space is left in the region + that we're parsing subregions for. SizeLeft is that size, and + so the size of the subregion we're now parsing better not + exceed the size left. + Returns: + + NULL - unrecoverable errors detected while parsing the subregion definition + + pointer to a subregion definition created from the parsed subregion + +--*/ +{ + FLASH_SUBREGION_DESCRIPTION *Subregion; + int ErrorCount; + int WarningCount; + unsigned int Number; + BOOLEAN PreviousComma; + // + // Allocate memory for the new subregion descriptor + // + ErrorCount = 0; + WarningCount = 0; + Subregion = (FLASH_SUBREGION_DESCRIPTION *) _malloc (sizeof (FLASH_SUBREGION_DESCRIPTION)); + if (Subregion == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + ErrorCount++; + goto Done; + } + + memset (Subregion, 0, sizeof (FLASH_SUBREGION_DESCRIPTION)); + // + // Open brace -- warning if not there + // + if (!SFPIsToken ("{")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL); + WarningCount++; + } + // + // Parse: CreateHob = TRUE | FALSE, + // + if (!SFPIsKeyword ("CreateHob")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'CreateHob'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (SFPIsToken ("TRUE")) { + Subregion->CreateHob = 1; + } else if (SFPIsToken ("FALSE")) { + // + // Subregion->CreateHob = 0; -- not required since we did a memset earlier + // + } else { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following CreateHob value", NULL); + WarningCount++; + } + // + // Parse: Name = "Name", + // + if (!SFPIsKeyword ("Name")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetQuotedString (Subregion->Name, sizeof (Subregion->Name))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion name", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL); + WarningCount++; + } + // + // Parse: Size = 0x2000, + // + if (!SFPIsKeyword ("Size")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (!SFPGetNumber (&Subregion->Size)) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL); + ErrorCount++; + goto Done; + } + + // + // Check that the size does not exceed the size left passed in + // + if (Subregion->Size > SizeLeft) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Subregion sizes exceeds Region size", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following Size value", NULL); + } + // + // Parse: Attributes = Number | "String", + // + if (!SFPIsKeyword ("Attributes")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (SFPGetNumber (&Number)) { + sprintf (Subregion->Attributes, "0x%X", Number); + } else if (!SFPGetQuotedString (Subregion->Attributes, sizeof (Subregion->Attributes))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL); + } + // + // Parse: AreaType = Number | "String", + // AreaType is a UINT8, so error if it exceeds the size + // + if (!SFPIsKeyword ("AreaType")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (SFPGetNumber (&Number)) { + if (Number > 0xFF) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "AreaType value exceeds 255", NULL); + ErrorCount++; + } + + sprintf (Subregion->AreaType, "0x%X", Number & 0x00FF); + } else if (!SFPGetQuotedString (Subregion->AreaType, sizeof (Subregion->AreaType))) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken (",")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following AreaType value", NULL); + } + // + // Parse the three GUIDs (last two are optional) + // + // NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD, (or "EFI_SOME_GUID") + // AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") + // FileSysteGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") + // + if (!SFPIsKeyword ("NameGuid")) { + Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'NameGuid'", NULL); + ErrorCount++; + goto Done; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + // + // Allow a GUID or a quoted string identifier, which we'll just copy as a string + // + if (SFPGetQuotedString (Subregion->NameGuidString, sizeof (Subregion->NameGuidString))) { + // + // Nothing else to do + // + } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->NameGuid)) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + "expected NameGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC", + NULL + ); + ErrorCount++; + goto Done; + } + // + // Comma following NameGuid is optional if they don't specify AreaTypeGuid or FileSystemGuid + // + PreviousComma = SFPIsToken (","); + if (SFPIsKeyword ("AreaTypeGuid")) { + // + // Check for preceeding comma now + // + if (!PreviousComma) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'AreaTypeGuid'", NULL); + WarningCount++; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + + if (SFPGetQuotedString (Subregion->AreaTypeGuidString, sizeof (Subregion->AreaTypeGuidString))) { + // + // Nothing else to do + // + } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->AreaTypeGuid)) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + "expected AreaTypeGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC", + NULL + ); + ErrorCount++; + goto Done; + } + + PreviousComma = SFPIsToken (","); + } + + if (SFPIsKeyword ("FileSystemGuid")) { + // + // Check for preceeding comma now + // + if (!PreviousComma) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'FileSystemGuid'", NULL); + WarningCount++; + } + + if (!SFPIsToken ("=")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL); + WarningCount++; + } + // + // Allow a GUID or a quoted string identifier, which we'll just copy as a string + // + if (SFPGetQuotedString (Subregion->FileSystemGuidString, sizeof (Subregion->FileSystemGuidString))) { + // + // Nothing else to do + // + } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->FileSystemGuid)) { + Error ( + SFPGetFileName (), + SFPGetLineNumber (), + 0, + "expected FileSystemGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC", + NULL + ); + ErrorCount++; + goto Done; + } + + SFPIsToken (","); + } + // + // Look for subregion closing brace + // + if (!SFPIsToken ("}")) { + Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion closing brace '}'", NULL); + WarningCount++; + } + +Done: + // + // If any errors were encountered, then delete the subregion definition + // + if (ErrorCount != 0) { + _free (Subregion); + Subregion = NULL; + } + + return Subregion; +} + +STATUS +FDFCreateCIncludeFile ( + char *FlashDeviceName, + char *FileName + ) +/*++ + +Routine Description: + Create a header file with #define definitions per an already-parsed + flash definition file. + +Arguments: + FlashDeviceName - name of flash device (from the flash definition file) + to use + FileName - name of output file to create + +Returns: + STATUS_SUCCESS - no errors or warnings + STATUS_WARNING - warnings, but no errors, were encountered + STATUS_ERROR - errors were encountered + +--*/ +{ + FILE *OutFptr; + FLASH_BLOCK_DESCRIPTION *FBlock; + FLASH_DEVICE_DESCRIPTION *FDev; + FLASH_SUBREGION_DESCRIPTION *Subregion; + unsigned int Offset; + unsigned int SubregionOffset; + int CreateHobs; + // + // Find the definition we're supposed to use + // + for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) { + if (strcmp (FDev->Name, FlashDeviceName) == 0) { + break; + } + } + + if (FDev == NULL) { + Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions"); + return STATUS_ERROR; + } + + if ((OutFptr = fopen (FileName, "w")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + // + // Write a header + // + fprintf (OutFptr, CIncludeHeader); + // + // Write flash block base and size defines + // + fprintf (OutFptr, "#define FLASH_BASE 0x%08X\n", FDev->BaseAddress); + fprintf (OutFptr, "#define FLASH_SIZE 0x%08X\n\n", FDev->Size); + // + // Write flash regions base, size and offset defines + // + Offset = 0; + CreateHobs = 0; + for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) { + fprintf ( + OutFptr, + "#define FLASH_REGION_%s_BASE %*c0x%08X\n", + FBlock->Name, + COLUMN2_START - 40 - strlen (FBlock->Name), + ' ', + Offset + FDev->BaseAddress + ); + fprintf ( + OutFptr, + "#define FLASH_REGION_%s_SIZE %*c0x%08X\n", + FBlock->Name, + COLUMN2_START - 40 - strlen (FBlock->Name), + ' ', + FBlock->Size + ); + fprintf ( + OutFptr, + "#define FLASH_REGION_%s_OFFSET %*c0x%08X\n", + FBlock->Name, + COLUMN2_START - 40 - strlen (FBlock->Name), + ' ', + Offset + ); + // + // Create defines for any subregions + // + SubregionOffset = 0; + for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) { + fprintf ( + OutFptr, + "#define FLASH_REGION_%s_SUBREGION_%s_BASE %*c0x%08X\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + FDev->BaseAddress + Offset + SubregionOffset + ); + fprintf ( + OutFptr, + "#define FLASH_REGION_%s_SUBREGION_%s_SIZE %*c0x%08X\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + Subregion->Size + ); + fprintf ( + OutFptr, + "#define FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c0x%08X\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + Offset + SubregionOffset + ); + SubregionOffset += Subregion->Size; + if (Subregion->CreateHob != 0) { + CreateHobs = 1; + } + } + + Offset += FBlock->Size; + } + // + // Now create a #define for the flash map data definition + // + fprintf (OutFptr, "\n\n#define EFI_FLASH_AREA_DATA_DEFINITION \\\n"); + // + // Emit entry for each region + // + Offset = 0; + for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) { + fprintf (OutFptr, " /* %s region */\\\n", FBlock->Name); + fprintf (OutFptr, " {\\\n"); + fprintf (OutFptr, " FLASH_REGION_%s_BASE,\\\n", FBlock->Name); + fprintf (OutFptr, " FLASH_REGION_%s_SIZE,\\\n", FBlock->Name); + fprintf (OutFptr, " %s,\\\n", FBlock->Attributes); + fprintf (OutFptr, " %s,\\\n },\\\n", FBlock->AreaType); + } + + fprintf (OutFptr, "\n\n"); + // + // Now walk the list again to create the EFI_HOB_FLASH_MAP_ENTRY_TYPE definition + // + if (CreateHobs != 0) { + fprintf (OutFptr, "//\n// EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\n//\n"); + fprintf (OutFptr, "#define EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION"); + for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) { + // + // See if the block has subregions, and that the CreateHobs flag is set + // for any of them. + // + CreateHobs = 0; + for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) { + if (Subregion->CreateHob != 0) { + CreateHobs = 1; + break; + } + } + // + // If any of the subregions had the CreateHobs flag set, then create the entries in the + // output file + // + if (CreateHobs != 0) { + for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) { + if (Subregion->CreateHob != 0) { + fprintf (OutFptr, " \\\n"); + fprintf (OutFptr, " /* %s.%s Subregion */\\\n", FBlock->Name, Subregion->Name); + fprintf (OutFptr, " {\\\n"); + fprintf (OutFptr, " EFI_HOB_TYPE_GUID_EXTENSION,\\\n"); + fprintf (OutFptr, " sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\\\n"); + fprintf (OutFptr, " 0,\\\n"); + // + // The NameGuid may have been specified in the input flash definition file as a GUID, or + // as a quoted string. Do the right one. + // + if (Subregion->NameGuidString[0] != 0) { + fprintf (OutFptr, " %s, \\\n", Subregion->NameGuidString); + } else { + fprintf ( + OutFptr, + " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n", + Subregion->NameGuid.Data1, + (unsigned int) Subregion->NameGuid.Data2, + (unsigned int) Subregion->NameGuid.Data3, + (unsigned int) Subregion->NameGuid.Data4[0], + (unsigned int) Subregion->NameGuid.Data4[1], + (unsigned int) Subregion->NameGuid.Data4[2], + (unsigned int) Subregion->NameGuid.Data4[3], + (unsigned int) Subregion->NameGuid.Data4[4], + (unsigned int) Subregion->NameGuid.Data4[5], + (unsigned int) Subregion->NameGuid.Data4[6], + (unsigned int) Subregion->NameGuid.Data4[7] + ); + } + + fprintf (OutFptr, " 0, 0, 0,\\\n"); + fprintf (OutFptr, " %s,\\\n", Subregion->AreaType); + // + // The AreaTypeGuid may have been specified in the input flash definition file as a GUID, or + // as a quoted string. Do the right one. + // + if (Subregion->AreaTypeGuidString[0] != 0) { + fprintf (OutFptr, " %s, \\\n", Subregion->AreaTypeGuidString); + } else { + fprintf ( + OutFptr, + " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n", + Subregion->AreaTypeGuid.Data1, + (unsigned int) Subregion->AreaTypeGuid.Data2, + (unsigned int) Subregion->AreaTypeGuid.Data3, + (unsigned int) Subregion->AreaTypeGuid.Data4[0], + (unsigned int) Subregion->AreaTypeGuid.Data4[1], + (unsigned int) Subregion->AreaTypeGuid.Data4[2], + (unsigned int) Subregion->AreaTypeGuid.Data4[3], + (unsigned int) Subregion->AreaTypeGuid.Data4[4], + (unsigned int) Subregion->AreaTypeGuid.Data4[5], + (unsigned int) Subregion->AreaTypeGuid.Data4[6], + (unsigned int) Subregion->AreaTypeGuid.Data4[7] + ); + } + + fprintf (OutFptr, " 1,\\\n"); + fprintf (OutFptr, " {\\\n"); + fprintf (OutFptr, " %s,\\\n", Subregion->Attributes); + fprintf (OutFptr, " 0,\\\n"); + fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_BASE,\\\n", FBlock->Name, Subregion->Name); + fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_SIZE,\\\n", FBlock->Name, Subregion->Name); + // + // The FileSystemGuid may have been specified in the input flash definition file as a GUID, or + // as a quoted string. Do the right one. + // + if (Subregion->FileSystemGuidString[0] != 0) { + fprintf (OutFptr, " %s, \\\n", Subregion->FileSystemGuidString); + } else { + fprintf ( + OutFptr, + " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n", + Subregion->FileSystemGuid.Data1, + (unsigned int) Subregion->FileSystemGuid.Data2, + (unsigned int) Subregion->FileSystemGuid.Data3, + (unsigned int) Subregion->FileSystemGuid.Data4[0], + (unsigned int) Subregion->FileSystemGuid.Data4[1], + (unsigned int) Subregion->FileSystemGuid.Data4[2], + (unsigned int) Subregion->FileSystemGuid.Data4[3], + (unsigned int) Subregion->FileSystemGuid.Data4[4], + (unsigned int) Subregion->FileSystemGuid.Data4[5], + (unsigned int) Subregion->FileSystemGuid.Data4[6], + (unsigned int) Subregion->FileSystemGuid.Data4[7] + ); + } + + fprintf (OutFptr, " },\\\n"); + fprintf (OutFptr, " },"); + } + } + } + } + + fprintf (OutFptr, "\n\n"); + } + + // + // Write the file's closing #endif + // + fprintf (OutFptr, CIncludeFooter); + fclose (OutFptr); + return STATUS_SUCCESS; +} + +STATUS +FDFCreateAsmIncludeFile ( + char *FlashDeviceName, + char *FileName + ) +/*++ + +Routine Description: + Create an assembly header file with equate definitions per an already-parsed + flash definition file. + +Arguments: + FlashDeviceName - name of flash device (from the flash definition file) + to use + FileName - name of output file to create + +Returns: + STATUS_SUCCESS - no errors or warnings + STATUS_WARNING - warnings, but no errors, were encountered + STATUS_ERROR - errors were encountered + +--*/ +{ + FILE *OutFptr; + FLASH_BLOCK_DESCRIPTION *FBlock; + FLASH_DEVICE_DESCRIPTION *FDev; + unsigned int Offset; + FLASH_SUBREGION_DESCRIPTION *Subregion; + unsigned int SubregionOffset; + // + // Find the definition we're supposed to use + // + for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) { + if (strcmp (FDev->Name, FlashDeviceName) == 0) { + break; + } + } + + if (FDev == NULL) { + Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions"); + return STATUS_ERROR; + } + + if ((OutFptr = fopen (FileName, "w")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + // + // Write a header + // + fprintf (OutFptr, "\n\n"); + // + // Write flash block size and offset defines + // + fprintf ( + OutFptr, + "FLASH_BASE %*cequ 0%08Xh\n", + COLUMN2_START - 40, + ' ', + FDev->BaseAddress + ); + fprintf (OutFptr, "FLASH_SIZE %*cequ 0%08Xh\n", COLUMN2_START - 40, ' ', FDev->Size); + // + // Write flash region size and offset defines + // + fprintf (OutFptr, "\n"); + Offset = 0; + for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) { + fprintf ( + OutFptr, + "FLASH_REGION_%s_BASE %*cequ 0%08Xh\n", + FBlock->Name, + COLUMN2_START - 20 - strlen (FBlock->Name), + ' ', + FDev->BaseAddress + Offset + ); + fprintf ( + OutFptr, + "FLASH_REGION_%s_SIZE %*cequ 0%08Xh\n", + FBlock->Name, + COLUMN2_START - 20 - strlen (FBlock->Name), + ' ', + FBlock->Size + ); + fprintf ( + OutFptr, + "FLASH_REGION_%s_OFFSET %*cequ 0%08Xh\n", + FBlock->Name, + COLUMN2_START - 20 - strlen (FBlock->Name), + ' ', + Offset + ); + // + // Create defines for any subregions + // + SubregionOffset = 0; + for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) { + fprintf ( + OutFptr, + "FLASH_REGION_%s_SUBREGION_%s_BASE %*cequ 0%08Xh\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + FDev->BaseAddress + Offset + SubregionOffset + ); + fprintf ( + OutFptr, + "FLASH_REGION_%s_SUBREGION_%s_SIZE %*cequ 0%08Xh\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + Subregion->Size + ); + fprintf ( + OutFptr, + "FLASH_REGION_%s_SUBREGION_%s_OFFSET %*cequ 0%08Xh\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + Offset + SubregionOffset + ); + SubregionOffset += Subregion->Size; + } + + Offset += FBlock->Size; + } + + // + // Write closing \n + // + fprintf (OutFptr, "\n\n"); + fclose (OutFptr); + return STATUS_SUCCESS; +} + +STATUS +FDFCreateSymbols ( + char *FlashDeviceName + ) +/*++ + +Routine Description: + Using the given flash device name, add symbols to the global symbol table. This + allows other functions to use the symbol definitions for other purposes. + +Arguments: + FlashDeviceName - name of flash device (from the flash definition file) + to use + +Returns: + STATUS_SUCCESS - no errors or warnings + STATUS_WARNING - warnings, but no errors, were encountered + STATUS_ERROR - errors were encountered + +--*/ +{ + FLASH_BLOCK_DESCRIPTION *FBlock; + FLASH_DEVICE_DESCRIPTION *FDev; + unsigned int Offset; + char SymName[120]; + char SymValue[120]; + FLASH_SUBREGION_DESCRIPTION *Subregion; + unsigned int SubregionOffset; + // + // Find the definition we're supposed to use + // + for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) { + if (strcmp (FDev->Name, FlashDeviceName) == 0) { + break; + } + } + + if (FDev == NULL) { + Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions"); + return STATUS_ERROR; + } + + sprintf (SymValue, "0x%08X", FDev->BaseAddress); + SymbolAdd ("FLASH_BASE", SymValue, 0); + sprintf (SymValue, "0x%08X", FDev->Size); + SymbolAdd ("FLASH_SIZE", SymValue, 0); + // + // Add flash block size and offset defines + // + // Offset = 0; + // for (FBlock = FDev->PBlocks; FBlock != NULL; FBlock = FBlock->Next) { + // sprintf (SymName, "FLASH_BLOCK_%s_BASE", FBlock->Name); + // sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset); + // SymbolAdd (SymName, SymValue, 0); + // sprintf (SymName, "FLASH_BLOCK_%s_SIZE", FBlock->Name); + // sprintf (SymValue, "0x%08X", FBlock->Size); + // SymbolAdd (SymName, SymValue, 0); + // sprintf (SymName, "FLASH_BLOCK_%s_OFFSET", FBlock->Name); + // sprintf (SymValue, "0x%08X", Offset); + // SymbolAdd (SymName, SymValue, 0); + // Offset += FBlock->Size; + // } + // + // Add flash region block base, size, and offset defines + // + Offset = 0; + for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) { + sprintf (SymName, "FLASH_REGION_%s_BASE", FBlock->Name); + sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset); + SymbolAdd (SymName, SymValue, 0); + sprintf (SymName, "FLASH_REGION_%s_SIZE", FBlock->Name); + sprintf (SymValue, "0x%08X", FBlock->Size); + SymbolAdd (SymName, SymValue, 0); + sprintf (SymName, "FLASH_REGION_%s_OFFSET", FBlock->Name); + sprintf (SymValue, "0x%08X", Offset); + SymbolAdd (SymName, SymValue, 0); + // + // Add subregion symbols + // + if (FBlock->Subregions != NULL) { + SubregionOffset = 0; + for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) { + sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_BASE", FBlock->Name, Subregion->Name); + sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset + SubregionOffset); + SymbolAdd (SymName, SymValue, 0); + sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_SIZE", FBlock->Name, Subregion->Name); + sprintf (SymValue, "0x%08X", Subregion->Size); + SymbolAdd (SymName, SymValue, 0); + sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_OFFSET", FBlock->Name, Subregion->Name); + sprintf (SymValue, "0x%08X", Offset + SubregionOffset); + SymbolAdd (SymName, SymValue, 0); + SubregionOffset += Subregion->Size; + } + } + + Offset += FBlock->Size; + } + + return STATUS_SUCCESS; +} + +STATUS +FDFCreateImage ( + char *FlashDeviceName, + char *ImageName, + char *FileName + ) +/*++ + +Routine Description: + Create a flash image using the given device and image names. + +Arguments: + FlashDeviceName - name of flash device (from the flash definition file) + to use + ImageName - name of image (from the flash definition file) to create + FileName - name of output file to create + +Returns: + STATUS_SUCCESS - no errors or warnings + STATUS_WARNING - warnings, but no errors, were encountered + STATUS_ERROR - errors were encountered + +--*/ +{ + STATUS Status; + FILE *OutFptr; + FLASH_BLOCK_DESCRIPTION *RegionDef; + FLASH_DEVICE_DESCRIPTION *FDev; + IMAGE_DEFINITION *ImageDef; + unsigned int Offset; + char *Buffer; + FILE *InFptr; + long FileSize; + IMAGE_DEFINITION_ENTRY *IDefEntry; + FLASH_SUBREGION_DESCRIPTION *SubregionDef; + // + // Find the flash definition we're supposed to use + // + InFptr = NULL; + Status = STATUS_ERROR; + for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) { + if (strcmp (FDev->Name, FlashDeviceName) == 0) { + break; + } + } + + if (FDev == NULL) { + Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions"); + return STATUS_ERROR; + } + // + // Find the image name we're supposed to create + // + for (ImageDef = mImageDefinitions; ImageDef != NULL; ImageDef = ImageDef->Next) { + if (strcmp (ImageDef->Name, ImageName) == 0) { + break; + } + } + + if (ImageDef == NULL) { + Error (NULL, 0, 0, ImageName, "image definition not found in image definitions"); + return STATUS_ERROR; + } + // + // Open the output file + // + if ((OutFptr = fopen (FileName, "wb")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + // + // Allocate a buffer to copy the input data to + // + Buffer = (char *) _malloc (FDev->Size); + if (Buffer == NULL) { + Error (NULL, 0, 0, (INT8 *) "failed to allocate memory", NULL); + goto Done; + } + // + // Set contents of buffer to the erased value + // + if (FDev->ErasePolarity) { + memset (Buffer, 0xFF, FDev->Size); + } else { + memset (Buffer, 0, FDev->Size); + } + // + // Set all region and subregion size-left fields to the size of the region/subregion + // + for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) { + RegionDef->SizeLeft = RegionDef->Size; + for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) { + SubregionDef->SizeLeft = SubregionDef->Size; + } + } + // + // Now go through the image list, read files into the buffer. + // + for (IDefEntry = ImageDef->Entries; IDefEntry != NULL; IDefEntry = IDefEntry->Next) { + // + // If it's a file name, open the file, get the size, find the corresponding + // flash region it's in, and copy the data. + // + if (IDefEntry->IsRawData == 0) { + if ((InFptr = fopen (IDefEntry->Name, "rb")) == NULL) { + Error (NULL, 0, 0, IDefEntry->Name, "failed to open input file for reading"); + goto Done; + } + + fseek (InFptr, 0, SEEK_END); + FileSize = ftell (InFptr); + fseek (InFptr, 0, SEEK_SET); + } else { + FileSize = IDefEntry->RawDataSize; + } + // + // Find the region/subregion it's in, see if we have space left + // + Offset = 0; + for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) { + if (strcmp (RegionDef->Name, IDefEntry->RegionName) == 0) { + break; + } + + Offset += RegionDef->Size; + } + + if (RegionDef == NULL) { + Error (NULL, 0, 0, IDefEntry->RegionName, "Region name not found in FlashDevice %s definition", FDev->Name); + goto Done; + } + + // + // Check for subregion + // + if (IDefEntry->SubregionName[0] != 0) { + for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) { + if (strcmp (SubregionDef->Name, IDefEntry->SubregionName) == 0) { + break; + } + + Offset += SubregionDef->Size; + } + + if (SubregionDef == NULL) { + Error ( + NULL, + 0, + 0, + IDefEntry->SubregionName, + "Subregion name not found in FlashDevice %s.%s Region definition", + FDev->Name, + RegionDef->Name + ); + goto Done; + } + // + // Enough space in the subregion? + // + if (SubregionDef->SizeLeft < (unsigned int) FileSize) { + Error ( + NULL, + 0, + 0, + IDefEntry->Name, + "insufficient space in Subregion (at least 0x%X additional bytes required)", + FileSize - SubregionDef->SizeLeft + ); + goto Done; + } + + // + // Read the file into the buffer if it's a file. Otherwise copy the raw data + // + if (IDefEntry->IsRawData == 0) { + if (fread (Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft), FileSize, 1, InFptr) != 1) { + Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents"); + goto Done; + } + + fclose (InFptr); + InFptr = NULL; + } else { + memcpy ( + Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft), + IDefEntry->RawData, + IDefEntry->RawDataSize + ); + } + + SubregionDef->SizeLeft -= FileSize; + // + // Align based on the Region alignment requirements. + // + if (RegionDef->Alignment != 0) { + while (((unsigned int) (SubregionDef->Size - SubregionDef->SizeLeft) &~RegionDef->Alignment) != 0) { + if (SubregionDef->SizeLeft == 0) { + break; + } + + SubregionDef->SizeLeft--; + } + } + } else { + // + // Placing data in a region. Check for enough space in the region left. + // + if (RegionDef->SizeLeft < (unsigned int) FileSize) { + Error ( + NULL, + 0, + 0, + IDefEntry->Name, + "insufficient space in Region (at least 0x%X additional bytes required)", + FileSize - RegionDef->SizeLeft + ); + goto Done; + } + + // + // Read the file into the buffer if it's a file. Otherwise copy the raw data + // + if (IDefEntry->IsRawData == 0) { + if (fread (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), FileSize, 1, InFptr) != 1) { + Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents"); + goto Done; + } + + fclose (InFptr); + InFptr = NULL; + } else { + memcpy (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), IDefEntry->RawData, IDefEntry->RawDataSize); + } + + RegionDef->SizeLeft -= FileSize; + // + // Align + // + if (RegionDef->Alignment != 0) { + while (((unsigned int) (RegionDef->Size - RegionDef->SizeLeft) &~RegionDef->Alignment) != 0) { + if (RegionDef->SizeLeft == 0) { + break; + } + + RegionDef->SizeLeft--; + } + } + } + } + + if (fwrite (Buffer, FDev->Size, 1, OutFptr) != 1) { + Error (NULL, 0, 0, "failed to write buffer contents to output file", NULL); + goto Done; + } + + Status = STATUS_SUCCESS; +Done: + if (InFptr != NULL) { + fclose (InFptr); + } + + if (Buffer != NULL) { + _free (Buffer); + } + + if (OutFptr != NULL) { + fclose (OutFptr); + if (Status == STATUS_ERROR) { + remove (FileName); + } + } + + return Status; +} + +STATUS +FDFCreateDscFile ( + char *FlashDeviceName, + char *FileName + ) +/*++ + +Routine Description: + Create a DSC-style output file with equates for flash management. + +Arguments: + FlashDeviceName - name of flash device (from the flash definition file) + to use + FileName - name of output file to create + +Returns: + STATUS_SUCCESS - no errors or warnings + STATUS_WARNING - warnings, but no errors, were encountered + STATUS_ERROR - errors were encountered + +--*/ +{ + FILE *OutFptr; + FLASH_BLOCK_DESCRIPTION *FBlock; + FLASH_DEVICE_DESCRIPTION *FDev; + unsigned int Offset; + FLASH_SUBREGION_DESCRIPTION *Subregion; + unsigned int SubregionOffset; + // + // Find the definition we're supposed to use + // + for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) { + if (strcmp (FDev->Name, FlashDeviceName) == 0) { + break; + } + } + + if (FDev == NULL) { + Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions"); + return STATUS_ERROR; + } + + if ((OutFptr = fopen (FileName, "w")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + // + // Write the flash base address and size + // + fprintf (OutFptr, "\n"); + fprintf (OutFptr, "FLASH_BASE = 0x%08X\n", FDev->BaseAddress); + fprintf (OutFptr, "FLASH_SIZE = 0x%08X\n\n", FDev->Size); + // + // Write flash block size and offset defines + // + Offset = 0; + for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) { + fprintf ( + OutFptr, + "FLASH_REGION_%s_BASE %*c= 0x%08X\n", + FBlock->Name, + COLUMN2_START - 40 - strlen (FBlock->Name), + ' ', + Offset + FDev->BaseAddress + ); + fprintf ( + OutFptr, + "FLASH_REGION_%s_SIZE %*c= 0x%08X\n", + FBlock->Name, + COLUMN2_START - 40 - strlen (FBlock->Name), + ' ', + FBlock->Size + ); + fprintf ( + OutFptr, + "FLASH_REGION_%s_SIZE_BLOCKS %*c= 0x%x\n", + FBlock->Name, + COLUMN2_START - 40 - strlen (FBlock->Name), + ' ', + (FBlock->Size)/(FDev->PBlocks->Size) + ); + // + // Create defines for any subregions + // + SubregionOffset = 0; + for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) { + fprintf ( + OutFptr, + "FLASH_REGION_%s_SUBREGION_%s_BASE %*c= 0x%08X\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + FDev->BaseAddress + Offset + SubregionOffset + ); + fprintf ( + OutFptr, + "FLASH_REGION_%s_SUBREGION_%s_SIZE %*c= 0x%08X\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + Subregion->Size + ); + fprintf ( + OutFptr, + "FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c= 0x%08X\n", + FBlock->Name, + Subregion->Name, + COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name), + ' ', + Offset + SubregionOffset + ); + + SubregionOffset += Subregion->Size; + } + + Offset += FBlock->Size; + } + // + // Close file + // + fprintf (OutFptr, "\n"); + fclose (OutFptr); + return STATUS_SUCCESS; +} + + +/*++ + +Routine Description: + The following buffer management routines are used to encapsulate functionality + for managing a growable data buffer. + +Arguments: + BUFFER_DATA - structure that is used to maintain a data buffer + +Returns: + NA + +--*/ +static +BUFFER_DATA * +CreateBufferData ( + VOID + ) +/*++ + +Routine Description: + + Create a growable data buffer with default buffer length. + +Arguments: + + None + +Returns: + + NULL - error occured during data buffer creation + Not NULL - the pointer to the newly created data buffer + +--*/ +{ + BUFFER_DATA *BD; + BD = (BUFFER_DATA *) _malloc (sizeof (BUFFER_DATA)); + if (BD == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return NULL; + } + + memset (BD, 0, sizeof (BUFFER_DATA)); + BD->BufferStart = (char *) _malloc (BUFFER_SIZE); + if (BD->BufferStart == NULL) { + _free (BD); + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return NULL; + } + + BD->BufferEnd = BD->BufferStart + BUFFER_SIZE; + BD->BufferPos = BD->BufferStart; + return BD; +} + +static +BOOLEAN +AddBufferDataByte ( + BUFFER_DATA *Buffer, + char Data + ) +/*++ + +Routine Description: + + Add a single byte to a growable data buffer, growing the buffer if required. + +Arguments: + + Buffer - pointer to the growable data buffer to add a single byte to + Data - value of the single byte data to be added + +Returns: + + TRUE - the single byte data was successfully added + FALSE - error occurred, the single byte data was not added + +--*/ +{ + int Size; + char *NewBuffer; + // + // See if we have to grow the buffer + // + if (Buffer->BufferPos >= Buffer->BufferEnd) { + Size = (int) Buffer->BufferEnd - (int) Buffer->BufferStart; + NewBuffer = (char *) _malloc (Size + BUFFER_SIZE); + if (NewBuffer == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return FALSE; + } + + memcpy (NewBuffer, Buffer->BufferStart, Size); + _free (Buffer->BufferStart); + Buffer->BufferStart = NewBuffer; + Buffer->BufferPos = Buffer->BufferStart + Size; + Buffer->BufferEnd = Buffer->BufferStart + Size + BUFFER_SIZE; + } + + *Buffer->BufferPos = Data; + Buffer->BufferPos++; + return TRUE; +} + +static +void +FreeBufferData ( + BUFFER_DATA *Buffer, + BOOLEAN FreeData + ) +/*++ + +Routine Description: + + Free memory used to manage a growable data buffer. + +Arguments: + + Buffer - pointer to the growable data buffer to be destructed + FreeData - TRUE, free memory containing the buffered data + FALSE, do not free the buffered data memory + +Returns: + + None + +--*/ +{ + if (Buffer != NULL) { + if (FreeData && (Buffer->BufferStart != NULL)) { + _free (Buffer->BufferStart); + } + + _free (Buffer); + } +} + +static +char * +GetBufferData ( + BUFFER_DATA *Buffer, + int *BufferSize + ) +/*++ + +Routine Description: + + Return a pointer and size of the data in a growable data buffer. + +Arguments: + + Buffer - pointer to the growable data buffer + BufferSize - size of the data in the growable data buffer + +Returns: + + pointer of the data in the growable data buffer + +--*/ +{ + *BufferSize = (int) Buffer->BufferPos - (int) Buffer->BufferStart; + return Buffer->BufferStart; +} + +STATUS +FDDiscover ( + char *FDFileName, + unsigned int BaseAddr + ) +/*++ + +Routine Description: + Walk a binary image and see if you find anything that looks like a + firmware volume. + +Arguments: + FDFileName - name of input FD image to parse + BaseAddr - base address of input FD image + +Returns: + STATUS_SUCCESS - no errors or warnings + STATUS_WARNING - warnings, but no errors, were encountered + STATUS_ERROR - errors were encountered + +NOTE: + This routine is used for debug purposes only. + +--*/ +{ + FILE *InFptr; + long FileSize; + long Offset; + EFI_FIRMWARE_VOLUME_HEADER FVHeader; + EFI_GUID + FileSystemGuid = { 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF }; + + if ((InFptr = fopen (FDFileName, "rb")) == NULL) { + Error (NULL, 0, 0, FDFileName, "failed to open file for reading"); + return STATUS_ERROR; + } + + fseek (InFptr, 0, SEEK_END); + FileSize = ftell (InFptr); + fseek (InFptr, 0, SEEK_SET); + Offset = 0; + while (Offset < FileSize) { + fseek (InFptr, Offset, SEEK_SET); + // + // Read the contents of the file, see if it's an FV header + // + if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) == 1) { + // + // Check version and GUID + // + if ((FVHeader.Revision == EFI_FVH_REVISION) && (FVHeader.Signature == EFI_FVH_SIGNATURE)) { + fprintf (stdout, "FV header at 0x%08X FVSize=0x%08X ", Offset + BaseAddr, (UINT32) FVHeader.FvLength); + if (memcmp (&FVHeader.FileSystemGuid, &FileSystemGuid, sizeof (EFI_GUID)) == 0) { + fprintf (stdout, "standard FFS file system\n"); + } else { + fprintf (stdout, "non-standard FFS file system\n"); + } + } + } + + Offset += 16 * 1024; + } + + fclose (InFptr); + return STATUS_SUCCESS; +} diff --git a/Tools/CCode/Source/FlashMap/FlashDefFile.h b/Tools/CCode/Source/FlashMap/FlashDefFile.h new file mode 100644 index 0000000000..0e2ea2c920 --- /dev/null +++ b/Tools/CCode/Source/FlashMap/FlashDefFile.h @@ -0,0 +1,281 @@ +/*++ + +Copyright (c) 2004-2006 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: + + FlashDefFile.h + +Abstract: + + Header file for flash management utility in the Intel Platform + Innovation Framework for EFI build environment. + +--*/ + +#ifndef _FLASH_DEF_FILE_H_ +#define _FLASH_DEF_FILE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +void +FDFConstructor ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +; + +void +FDFDestructor ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDFParseFile ( + char *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FileName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDFCreateCIncludeFile ( + char *FlashDeviceName, + char *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FlashDeviceName - GC_TODO: add argument description + FileName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDFCreateCFlashMapDataFile ( + char *FlashDeviceName, + char *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FlashDeviceName - GC_TODO: add argument description + FileName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDFCreateAsmIncludeFile ( + char *FlashDeviceName, + char *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FlashDeviceName - GC_TODO: add argument description + FileName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDFParseFile ( + char *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FileName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDFCreateImage ( + char *FlashDeviceName, + char *ImageName, + char *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FlashDeviceName - GC_TODO: add argument description + ImageName - GC_TODO: add argument description + FileName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDFCreateDscFile ( + char *FlashDeviceName, + char *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FlashDeviceName - GC_TODO: add argument description + FileName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDFCreateSymbols ( + char *FlashDeviceName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FlashDeviceName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +FDDiscover ( + char *FDFileName, + unsigned int BaseAddr + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FDFileName - GC_TODO: add argument description + BaseAddr - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef _FLASH_DEF_FILE_H_ diff --git a/Tools/CCode/Source/FlashMap/FlashMap.c b/Tools/CCode/Source/FlashMap/FlashMap.c new file mode 100644 index 0000000000..88f5003d2d --- /dev/null +++ b/Tools/CCode/Source/FlashMap/FlashMap.c @@ -0,0 +1,769 @@ +/*++ + +Copyright (c) 2004-2006 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: + + FlashMap.c + +Abstract: + + Utility for flash management in the Intel Platform Innovation Framework + for EFI build environment. + +--*/ + +#include +#include +#include +#include + +#include + +#include "EfiUtilityMsgs.h" +#include "Microcode.h" +#include "FlashDefFile.h" +#include "Symbols.h" + +#define UTILITY_NAME "FlashMap" + +typedef struct _STRING_LIST { + struct _STRING_LIST *Next; + char *Str; +} STRING_LIST; + +// +// Keep our globals in one of these structures +// +static struct { + char *CIncludeFileName; + char *FlashDevice; + char *FlashDeviceImage; + char *MCIFileName; + char *MCOFileName; + char *ImageOutFileName; + char *DscFileName; + char *AsmIncludeFileName; + char *FlashDefinitionFileName; + char *StringReplaceInFileName; + char *StringReplaceOutFileName; + char *DiscoverFDImageName; + char MicrocodePadByteValue; + unsigned int MicrocodeAlignment; + STRING_LIST *MCIFileNames; + STRING_LIST *LastMCIFileNames; + unsigned int BaseAddress; +} mGlobals; + +#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF +#define DEFAULT_MC_ALIGNMENT 16 + +static +STATUS +ProcessCommandLine ( + int argc, + char *argv[] + ); + +static +STATUS +MergeMicrocodeFiles ( + char *OutFileName, + STRING_LIST *FileNames, + unsigned int Alignment, + char PadByteValue + ); + +static +void +Usage ( + VOID + ); + +char* +NormalizePath ( + char* OldPathName + ); + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + Parse the command line arguments and then call worker functions to do the work + +Arguments: + argc - number of elements in argv + argv - array of command-line arguments + +Returns: + STATUS_SUCCESS - no problems encountered while processing + STATUS_WARNING - warnings, but no errors, were encountered while processing + STATUS_ERROR - errors were encountered while processing + +--*/ +{ + STATUS Status; + + SetUtilityName (UTILITY_NAME); + Status = ProcessCommandLine (argc, argv); + if (Status != STATUS_SUCCESS) { + return Status; + } + // + // Check for discovery of an FD (command line option) + // + if (mGlobals.DiscoverFDImageName != NULL) { + Status = FDDiscover (mGlobals.DiscoverFDImageName, mGlobals.BaseAddress); + goto Done; + } + // + // If they're doing microcode file parsing, then do that + // + if (mGlobals.MCIFileName != NULL) { + MicrocodeConstructor (); + MicrocodeParseFile (mGlobals.MCIFileName, mGlobals.MCOFileName); + MicrocodeDestructor (); + } + // + // If they're doing microcode file merging, then do that now + // + if (mGlobals.MCIFileNames != NULL) { + MergeMicrocodeFiles ( + mGlobals.MCOFileName, + mGlobals.MCIFileNames, + mGlobals.MicrocodeAlignment, + mGlobals.MicrocodePadByteValue + ); + } + // + // If using a flash definition file, then process that and return + // + if (mGlobals.FlashDefinitionFileName != NULL) { + FDFConstructor (); + SymbolsConstructor (); + Status = FDFParseFile (mGlobals.FlashDefinitionFileName); + if (GetUtilityStatus () != STATUS_ERROR) { + // + // If they want us to do a string-replace on a file, then add the symbol definitions to + // the symbol table, and then do the string replace. + // + if (mGlobals.StringReplaceInFileName != NULL) { + Status = FDFCreateSymbols (mGlobals.FlashDevice); + Status = SymbolsFileStringsReplace (mGlobals.StringReplaceInFileName, mGlobals.StringReplaceOutFileName); + } + // + // If they want us to create a .h defines file or .c flashmap data file, then do so now + // + if (mGlobals.CIncludeFileName != NULL) { + Status = FDFCreateCIncludeFile (mGlobals.FlashDevice, mGlobals.CIncludeFileName); + } + if (mGlobals.AsmIncludeFileName != NULL) { + Status = FDFCreateAsmIncludeFile (mGlobals.FlashDevice, mGlobals.AsmIncludeFileName); + } + // + // If they want us to create an image, do that now + // + if (mGlobals.ImageOutFileName != NULL) { + Status = FDFCreateImage (mGlobals.FlashDevice, mGlobals.FlashDeviceImage, mGlobals.ImageOutFileName); + } + // + // If they want to create an output DSC file, do that now + // + if (mGlobals.DscFileName != NULL) { + Status = FDFCreateDscFile (mGlobals.FlashDevice, mGlobals.DscFileName); + } + } + SymbolsDestructor (); + FDFDestructor (); + } +Done: + // + // Free up memory + // + while (mGlobals.MCIFileNames != NULL) { + mGlobals.LastMCIFileNames = mGlobals.MCIFileNames->Next; + _free (mGlobals.MCIFileNames); + mGlobals.MCIFileNames = mGlobals.LastMCIFileNames; + } + return GetUtilityStatus (); +} + +static +STATUS +MergeMicrocodeFiles ( + char *OutFileName, + STRING_LIST *FileNames, + unsigned int Alignment, + char PadByteValue + ) +/*++ + +Routine Description: + + Merge binary microcode files into a single file, taking into consideration + the alignment and pad value. + +Arguments: + + OutFileName - name of the output file to create + FileNames - linked list of input microcode files to merge + Alignment - alignment for each microcode file in the output image + PadByteValue - value to use when padding to meet alignment requirements + +Returns: + + STATUS_SUCCESS - merge completed successfully or with acceptable warnings + STATUS_ERROR - merge failed, output file not created + +--*/ +{ + long FileSize; + long TotalFileSize; + FILE *InFptr; + FILE *OutFptr; + char *Buffer; + STATUS Status; + + // + // Open the output file + // + if ((OutFptr = fopen (OutFileName, "wb")) == NULL) { + Error (NULL, 0, 0, OutFileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + // + // Walk the list of files + // + Status = STATUS_ERROR; + Buffer = NULL; + InFptr = NULL; + TotalFileSize = 0; + while (FileNames != NULL) { + // + // Open the file, determine the size, then read it in and write + // it back out. + // + if ((InFptr = fopen (NormalizePath(FileNames->Str), "rb")) == NULL) { + Error (NULL, 0, 0, NormalizePath(FileNames->Str), "failed to open input file for reading"); + goto Done; + } + fseek (InFptr, 0, SEEK_END); + FileSize = ftell (InFptr); + fseek (InFptr, 0, SEEK_SET); + if (FileSize != 0) { + Buffer = (char *) _malloc (FileSize); + if (Buffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + goto Done; + } + if (fread (Buffer, FileSize, 1, InFptr) != 1) { + Error (NULL, 0, 0, FileNames->Str, "failed to read file contents"); + goto Done; + } + // + // Align + // + if (Alignment != 0) { + while ((TotalFileSize % Alignment) != 0) { + if (fwrite (&PadByteValue, 1, 1, OutFptr) != 1) { + Error (NULL, 0, 0, OutFileName, "failed to write pad bytes to output file"); + goto Done; + } + TotalFileSize++; + } + } + TotalFileSize += FileSize; + if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { + Error (NULL, 0, 0, OutFileName, "failed to write to output file"); + goto Done; + } + _free (Buffer); + Buffer = NULL; + } else { + Warning (NULL, 0, 0, FileNames->Str, "0-size file encountered"); + } + fclose (InFptr); + InFptr = NULL; + FileNames = FileNames->Next; + } + Status = STATUS_SUCCESS; +Done: + fclose (OutFptr); + if (InFptr != NULL) { + fclose (InFptr); + } + if (Buffer != NULL) { + _free (Buffer); + } + if (Status == STATUS_ERROR) { + remove (OutFileName); + } + return Status; +} + +static +STATUS +ProcessCommandLine ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + Process the command line arguments + +Arguments: + argc - Standard C entry point arguments + argv[] - Standard C entry point arguments + +Returns: + STATUS_SUCCESS - no problems encountered while processing + STATUS_WARNING - warnings, but no errors, were encountered while processing + STATUS_ERROR - errors were encountered while processing + +--*/ +{ + int ThingsToDo; + unsigned int Temp; + STRING_LIST *Str; + // + // Skip program name arg, process others + // + argc--; + argv++; + if (argc == 0) { + Usage (); + return STATUS_ERROR; + } + // + // Clear out our globals, then start walking the arguments + // + memset ((void *) &mGlobals, 0, sizeof (mGlobals)); + mGlobals.MicrocodePadByteValue = DEFAULT_MC_PAD_BYTE_VALUE; + mGlobals.MicrocodeAlignment = DEFAULT_MC_ALIGNMENT; + ThingsToDo = 0; + while (argc > 0) { + if (strcmp (argv[0], "-?") == 0) { + Usage (); + return STATUS_ERROR; + } else if (strcmp (argv[0], "-hfile") == 0) { + // + // -hfile FileName + // + // Used to specify an output C #include file to create that contains + // #define statements for all the flashmap region offsets and sizes. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires an output file name"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.CIncludeFileName = argv[0]; + ThingsToDo++; + } else if (strcmp (argv[0], "-flashdevice") == 0) { + // + // -flashdevice FLASH_DEVICE_NAME + // + // Used to select which flash device definition to operate on. + // Check for additional argument + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires a flash device name to use"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.FlashDevice = argv[0]; + } else if (strcmp (argv[0], "-mco") == 0) { + // + // -mco OutFileName + // + // Used to specify a microcode output binary file to create. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an output microcode file name to create"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.MCOFileName = argv[0]; + ThingsToDo++; + } else if (strcmp (argv[0], "-asmincfile") == 0) { + // + // -asmincfile FileName + // + // Used to specify the name of the output assembly include file that contains + // equates for the flash region addresses and sizes. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires an output ASM include file name to create"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.AsmIncludeFileName = argv[0]; + ThingsToDo++; + } else if (strcmp (argv[0], "-mci") == 0) { + // + // -mci FileName + // + // Used to specify an input microcode text file to parse. + // Check for additional argument + // + if (argc < 2) { + Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an input microcode text file name to parse"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.MCIFileName = argv[0]; + } else if (strcmp (argv[0], "-flashdeviceimage") == 0) { + // + // -flashdeviceimage FlashDeviceImage + // + // Used to specify which flash device image definition from the input flash definition file + // to create. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires the name of a flash definition image to use"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.FlashDeviceImage = argv[0]; + } else if (strcmp (argv[0], "-imageout") == 0) { + // + // -imageout FileName + // + // Used to specify the name of the output FD image file to create. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires an output image filename to create"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.ImageOutFileName = argv[0]; + ThingsToDo++; + } else if (strcmp (argv[0], "-dsc") == 0) { + // + // -dsc FileName + // + // Used to specify the name of the output DSC file to create. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires an output DSC filename to create"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.DscFileName = argv[0]; + ThingsToDo++; + } else if (strcmp (argv[0], "-fdf") == 0) { + // + // -fdf FileName + // + // Used to specify the name of the input flash definition file. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires an input flash definition file name"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.FlashDefinitionFileName = argv[0]; + } else if (strcmp (argv[0], "-discover") == 0) { + // + // -discover FDFileName + // + // Debug functionality used to scan an existing FD image, trying to find + // firmware volumes at 64K boundaries. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires an input FD image file name"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.DiscoverFDImageName = argv[0]; + ThingsToDo++; + } else if (strcmp (argv[0], "-baseaddr") == 0) { + // + // -baseaddr Addr + // + // Used to specify a base address when doing a discover of an FD image. + // Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires a base address"); + return STATUS_ERROR; + } + argc--; + argv++; + if (tolower (argv[0][1]) == 'x') { + sscanf (argv[0] + 2, "%x", &mGlobals.BaseAddress); + } else { + sscanf (argv[0], "%d", &mGlobals.BaseAddress); + } + } else if (strcmp (argv[0], "-padvalue") == 0) { + // + // -padvalue Value + // + // Used to specify the value to pad with when aligning data while + // creating an FD image. Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires a byte value"); + return STATUS_ERROR; + } + argc--; + argv++; + if (tolower (argv[0][1]) == 'x') { + sscanf (argv[0] + 2, "%x", &Temp); + mGlobals.MicrocodePadByteValue = (char) Temp; + } else { + sscanf (argv[0], "%d", &Temp); + mGlobals.MicrocodePadByteValue = (char) Temp; + } + } else if (strcmp (argv[0], "-align") == 0) { + // + // -align Alignment + // + // Used to specify how each data file is aligned in the region + // when creating an FD image. Check for additional argument. + // + if (argc < 2) { + Error (NULL, 0, 0, argv[0], "option requires an alignment"); + return STATUS_ERROR; + } + argc--; + argv++; + if (tolower (argv[0][1]) == 'x') { + sscanf (argv[0] + 2, "%x", &mGlobals.MicrocodeAlignment); + } else { + sscanf (argv[0], "%d", &mGlobals.MicrocodeAlignment); + } + } else if (strcmp (argv[0], "-mcmerge") == 0) { + // + // -mcmerge FileName(s) + // + // Used to concatenate multiple microde binary files. Can specify + // multiple file names with the one -mcmerge flag. Check for additional argument. + // + if ((argc < 2) || (argv[1][0] == '-')) { + Error (NULL, 0, 0, argv[0], "option requires one or more input file names"); + return STATUS_ERROR; + } + // + // Take input files until another option or end of list + // + ThingsToDo++; + while ((argc > 1) && (argv[1][0] != '-')) { + Str = (STRING_LIST *) _malloc (sizeof (STRING_LIST)); + if (Str == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + memset (Str, 0, sizeof (STRING_LIST)); + Str->Str = argv[1]; + if (mGlobals.MCIFileNames == NULL) { + mGlobals.MCIFileNames = Str; + } else { + mGlobals.LastMCIFileNames->Next = Str; + } + mGlobals.LastMCIFileNames = Str; + argc--; + argv++; + } + } else if (strcmp (argv[0], "-strsub") == 0) { + // + // -strsub SrcFile DestFile + // + // Used to perform string substitutions on a file, writing the result to a new + // file. Check for two additional arguments. + // + if (argc < 3) { + Error (NULL, 0, 0, argv[0], "option requires input and output file names for string substitution"); + return STATUS_ERROR; + } + argc--; + argv++; + mGlobals.StringReplaceInFileName = argv[0]; + argc--; + argv++; + mGlobals.StringReplaceOutFileName = argv[0]; + ThingsToDo++; + } else { + Error (NULL, 0, 0, argv[0], "invalid option"); + return STATUS_ERROR; + } + argc--; + argv++; + } + // + // If no outputs requested, then report an error + // + if (ThingsToDo == 0) { + Error (NULL, 0, 0, "nothing to do", NULL); + return STATUS_ERROR; + } + // + // If they want an asm file, #include file, or C file to be created, then they have to specify a + // flash device name and flash definition file name. + // + if ((mGlobals.CIncludeFileName != NULL) && + ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) { + Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL); + return STATUS_ERROR; + } + if ((mGlobals.AsmIncludeFileName != NULL) && + ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) { + Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL); + return STATUS_ERROR; + } + // + // If they want a dsc file to be created, then they have to specify a + // flash device name and a flash definition file name + // + if (mGlobals.DscFileName != NULL) { + if (mGlobals.FlashDevice == NULL) { + Error (NULL, 0, 0, "must specify -flashdevice with -dsc", NULL); + return STATUS_ERROR; + } + if (mGlobals.FlashDefinitionFileName == NULL) { + Error (NULL, 0, 0, "must specify -fdf with -dsc", NULL); + return STATUS_ERROR; + } + } + // + // If they specified an output microcode file name, then they have to specify an input + // file name, and vice versa. + // + if ((mGlobals.MCIFileName != NULL) && (mGlobals.MCOFileName == NULL)) { + Error (NULL, 0, 0, "must specify output microcode file name", NULL); + return STATUS_ERROR; + } + if ((mGlobals.MCOFileName != NULL) && (mGlobals.MCIFileName == NULL) && (mGlobals.MCIFileNames == NULL)) { + Error (NULL, 0, 0, "must specify input microcode file name", NULL); + return STATUS_ERROR; + } + // + // If doing merge, then have to specify output file name + // + if ((mGlobals.MCIFileNames != NULL) && (mGlobals.MCOFileName == NULL)) { + Error (NULL, 0, 0, "must specify output microcode file name", NULL); + return STATUS_ERROR; + } + // + // If they want an output image to be created, then they have to specify + // the flash device and the flash device image to use. + // + if (mGlobals.ImageOutFileName != NULL) { + if (mGlobals.FlashDevice == NULL) { + Error (NULL, 0, 0, "must specify -flashdevice with -imageout", NULL); + return STATUS_ERROR; + } + if (mGlobals.FlashDeviceImage == NULL) { + Error (NULL, 0, 0, "must specify -flashdeviceimage with -imageout", NULL); + return STATUS_ERROR; + } + if (mGlobals.FlashDefinitionFileName == NULL) { + Error (NULL, 0, 0, "must specify -c or -fdf with -imageout", NULL); + return STATUS_ERROR; + } + } + return STATUS_SUCCESS; +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + Print utility command line help + +Arguments: + None + +Returns: + NA + +--*/ +{ + int i; + char *Msg[] = { + "Usage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice", + " -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile", + " -discover FDImage -dsc DscFile -asmincfile AsmIncFile", + " -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile", + " -baseaddr BaseAddr -align Alignment -padvalue PadValue", + " -mcmerge MCIFile(s)", + " where", + " FlashDefFile - input Flash Definition File", + " FlashDevice - flash device to use (from flash definition file)", + " FlashDeviceImage - flash device image to use (from flash definition file)", + " MCIFile - input microcode file to parse", + " MCOFile - output binary microcode image to create from MCIFile", + " HFile - output #include file to create", + " FDImage - name of input FDImage file to scan", + " ImageOutFile - output image file to create", + " DscFile - output DSC file to create", + " AsmIncFile - output ASM include file to create", + " InStrFile - input file to replace symbol names, writing result to OutStrFile", + " BaseAddr - base address of FDImage (used with -discover)", + " Alignment - alignment to use when merging microcode binaries", + " PadValue - byte value to use as pad value when aligning microcode binaries", + " MCIFile(s) - one or more microcode binary files to merge/concatenate", + "", + NULL + }; + for (i = 0; Msg[i] != NULL; i++) { + fprintf (stdout, "%s\n", Msg[i]); + } +} + +char* +NormalizePath ( + char* OldPathName + ) +{ + char* Visitor; + + if (OldPathName == NULL) { + return NULL; + } + + Visitor = OldPathName; + while (*Visitor != '\0') { + if (*Visitor == '\\') { + *Visitor = '/'; + } + Visitor++; + } + + return OldPathName; +} + diff --git a/Tools/CCode/Source/FlashMap/Microcode.c b/Tools/CCode/Source/FlashMap/Microcode.c new file mode 100644 index 0000000000..23353254a4 --- /dev/null +++ b/Tools/CCode/Source/FlashMap/Microcode.c @@ -0,0 +1,304 @@ +/*++ + +Copyright (c) 2004-2006 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: + + Microcode.c + +Abstract: + + Utility for working with microcode patch files in the Intel + Platform Innovation Framework for EFI build environment. + +--*/ + +#include +#include // for memset() +#include +#include // for malloc() + +#include "EfiUtilityMsgs.h" +#include "Microcode.h" + +#define MAX_LINE_LEN 256 + +// +// Structure definition for a microcode header +// +typedef struct { + unsigned int HeaderVersion; + unsigned int PatchId; + unsigned int Date; + unsigned int CpuId; + unsigned int Checksum; + unsigned int LoaderVersion; + unsigned int PlatformId; + unsigned int DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid + unsigned int TotalSize; // number of bytes + unsigned int Reserved[3]; +} MICROCODE_IMAGE_HEADER; + +static +STATUS +MicrocodeReadData ( + FILE *InFptr, + unsigned int *Data + ); + +void +MicrocodeConstructor ( + void + ) +/*++ + +Routine Description: + + Constructor of module Microcode + +Arguments: + + None + +Returns: + + None + +--*/ +{ +} + +void +MicrocodeDestructor ( + void + ) +/*++ + +Routine Description: + + Destructor of module Microcode + +Arguments: + + None + +Returns: + + None + +--*/ +{ +} + +static +STATUS +MicrocodeReadData ( + FILE *InFptr, + unsigned int *Data + ) +/*++ + +Routine Description: + Read a 32-bit microcode data value from a text file and convert to raw binary form. + +Arguments: + InFptr - file pointer to input text file + Data - pointer to where to return the data parsed + +Returns: + STATUS_SUCCESS - no errors or warnings, Data contains valid information + STATUS_ERROR - errors were encountered + +--*/ +{ + char Line[MAX_LINE_LEN]; + char *cptr; + + Line[MAX_LINE_LEN - 1] = 0; + *Data = 0; + if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) { + return STATUS_ERROR; + } + // + // If it was a binary file, then it may have overwritten our null terminator + // + if (Line[MAX_LINE_LEN - 1] != 0) { + return STATUS_ERROR; + } + // + // Look for + // dd 000000001h ; comment + // dd XXXXXXXX + // DD XXXXXXXXX + // DD XXXXXXXXX + // + for (cptr = Line; *cptr && isspace(*cptr); cptr++) { + } + if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) { + // + // Skip blanks and look for a hex digit + // + cptr += 3; + for (; *cptr && isspace(*cptr); cptr++) { + } + if (isxdigit (*cptr)) { + if (sscanf (cptr, "%X", Data) != 1) { + return STATUS_ERROR; + } + } + return STATUS_SUCCESS; + } + return STATUS_ERROR; +} + +STATUS +MicrocodeParseFile ( + char *InFileName, + char *OutFileName + ) +/*++ + +Routine Description: + Parse a microcode text file, and write the binary results to an output file. + +Arguments: + InFileName - input text file to parse + OutFileName - output file to write raw binary data from parsed input file + +Returns: + STATUS_SUCCESS - no errors or warnings + STATUS_ERROR - errors were encountered + +--*/ +{ + FILE *InFptr; + FILE *OutFptr; + STATUS Status; + MICROCODE_IMAGE_HEADER *Header; + unsigned int Size; + unsigned int Size2; + unsigned int Data; + unsigned int Checksum; + char *Buffer; + char *Ptr; + unsigned int TotalSize; + + Status = STATUS_ERROR; + InFptr = NULL; + OutFptr = NULL; + Buffer = NULL; + // + // Open the input text file + // + if ((InFptr = fopen (InFileName, "r")) == NULL) { + Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading"); + return STATUS_ERROR; + } + // + // Make two passes on the input file. The first pass is to determine how + // much data is in the file so we can allocate a working buffer. Then + // we'll allocate a buffer and re-read the file into the buffer for processing. + // + Size = 0; + do { + Status = MicrocodeReadData (InFptr, &Data); + if (Status == STATUS_SUCCESS) { + Size += sizeof (Data); + } + } while (Status == STATUS_SUCCESS); + // + // Error if no data. + // + if (Size == 0) { + Error (NULL, 0, 0, InFileName, "no parse-able data found in file"); + goto Done; + } + if (Size < sizeof (MICROCODE_IMAGE_HEADER)) { + Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header"); + goto Done; + } + // + // Allocate a buffer for the data + // + Buffer = (char *) _malloc (Size); + if (Buffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + goto Done; + } + // + // Re-read the file, storing the data into our buffer + // + fseek (InFptr, 0, SEEK_SET); + Ptr = Buffer; + do { + Status = MicrocodeReadData (InFptr, &Data); + if (Status == STATUS_SUCCESS) { + *(unsigned int *) Ptr = Data; + Ptr += sizeof (Data); + } + } while (Status == STATUS_SUCCESS); + // + // Can't do much checking on the header because, per the spec, the + // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K, + // and the TotalSize field is invalid (actually missing). Thus we can't + // even verify the Reserved fields are 0. + // + Header = (MICROCODE_IMAGE_HEADER *) Buffer; + if (Header->DataSize == 0) { + TotalSize = 2048; + } else { + TotalSize = Header->TotalSize; + } + if (TotalSize != Size) { + Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize); + goto Done; + } + // + // Checksum the contents + // + Ptr = Buffer; + Checksum = 0; + Size2 = 0; + while (Size2 < Size) { + Checksum += *(unsigned int *) Ptr; + Ptr += 4; + Size2 += 4; + } + if (Checksum != 0) { + Error (NULL, 0, 0, InFileName, "checksum failed on file contents"); + goto Done; + } + // + // Open the output file and write the buffer contents + // + if ((OutFptr = fopen (OutFileName, "wb")) == NULL) { + Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing"); + goto Done; + } + if (fwrite (Buffer, Size, 1, OutFptr) != 1) { + Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file"); + goto Done; + } + Status = STATUS_SUCCESS; +Done: + if (Buffer != NULL) { + free (Buffer); + } + if (InFptr != NULL) { + fclose (InFptr); + } + if (OutFptr != NULL) { + fclose (OutFptr); + if (Status == STATUS_ERROR) { + remove (OutFileName); + } + } + return Status; +} diff --git a/Tools/CCode/Source/FlashMap/Microcode.h b/Tools/CCode/Source/FlashMap/Microcode.h new file mode 100644 index 0000000000..f85313e978 --- /dev/null +++ b/Tools/CCode/Source/FlashMap/Microcode.h @@ -0,0 +1,87 @@ +/*++ + +Copyright (c) 2004-2006 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: + + Microcode.h + +Abstract: + + Header file for flash management utility in the Intel Platform + Innovation Framework for EFI build environment. + +--*/ + +#ifndef _MICROCODE_H_ +#define _MICROCODE_H_ + +void +MicrocodeConstructor ( + void + ); +/*++ + +Routine Description: + + Constructor of module Microcode + +Arguments: + + None + +Returns: + + None + +--*/ + +void +MicrocodeDestructor ( + void + ); +/*++ + +Routine Description: + + Destructor of module Microcode + +Arguments: + + None + +Returns: + + None + +--*/ + +STATUS +MicrocodeParseFile ( + char *InFileName, + char *OutFileName + ); +/*++ + +Routine Description: + Parse a microcode text file, and write the binary results to an output file. + +Arguments: + InFileName - input text file to parse + OutFileName - output file to write raw binary data from parsed input file + +Returns: + STATUS_SUCCESS - no errors or warnings + STATUS_ERROR - errors were encountered + +--*/ + + +#endif // #ifndef _MICROCODE_H_ diff --git a/Tools/CCode/Source/FlashMap/Symbols.c b/Tools/CCode/Source/FlashMap/Symbols.c new file mode 100644 index 0000000000..8e408144db --- /dev/null +++ b/Tools/CCode/Source/FlashMap/Symbols.c @@ -0,0 +1,648 @@ +/*++ + +Copyright (c) 2004-2006 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: + + Symbol.c + +Abstract: + + Class-like implementation for a symbol table. + +--*/ + +// GC_TODO: fix comment to set correct module name: Symbols.c +#include +#include +#include +// +// for isspace() +// +#include + +#include + +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "Symbols.h" + +#define MAX_LINE_LEN 512 + +// +// Linked list to keep track of all symbols +// +typedef struct _SYMBOL { + struct _SYMBOL *Next; + int Type; + char *Name; + char *Value; +} SYMBOL; + +static +SYMBOL * +FreeSymbols ( + SYMBOL *Syms + ); + +static +int +ExpandMacros ( + char *SourceLine, + char *DestLine, + int LineLen + ); + +static SYMBOL *mSymbolTable = NULL; + +void +SymbolsConstructor ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +{ + SymbolsDestructor (); +} + +void +SymbolsDestructor ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +{ + mSymbolTable = FreeSymbols (mSymbolTable); +} + +char * +GetSymbolValue ( + char *SymbolName + ) +/*++ + +Routine Description: + + Look up a symbol in our symbol table. + +Arguments: + + SymbolName + +Returns: + + Pointer to the value of the symbol if found + NULL if the symbol is not found + +--*/ +// GC_TODO: SymbolName - add argument and description to function comment +{ + SYMBOL *Symbol; + // + // Walk the symbol table + // + Symbol = mSymbolTable; + while (Symbol) { + if (stricmp (SymbolName, Symbol->Name) == 0) { + return Symbol->Value; + } + + Symbol = Symbol->Next; + } + + return NULL; +} + +int +SymbolAdd ( + char *Name, + char *Value, + int Mode + ) +/*++ + +Routine Description: + + Add a symbol name/value to the symbol table + +Arguments: + + Name - name of symbol to add + Value - value of symbol to add + Mode - currrently unused + +Returns: + + Length of symbol added. + +Notes: + If Value == NULL, then this routine will assume that the Name field + looks something like "MySymName = MySymValue", and will try to parse + it that way and add the symbol name/pair from the string. + +--*/ +{ + SYMBOL *Symbol; + + SYMBOL *NewSymbol; + int Len; + char *Start; + char *Cptr; + char CSave; + char *SaveCptr; + + Len = 0; + SaveCptr = NULL; + CSave = 0; + // + // If value pointer is null, then they passed us a line something like: + // varname = value, or simply var = + // + if (Value == NULL) { + Start = Name; + while (*Name && isspace (*Name)) { + Name++; + } + + if (Name == NULL) { + return -1; + } + // + // Find the end of the name. Either space or a '='. + // + for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++) + ; + if (Value == NULL) { + return -1; + } + // + // Look for the '=' + // + Cptr = Value; + while (*Value && (*Value != '=')) { + Value++; + } + + if (Value == NULL) { + return -1; + } + // + // Now truncate the name + // + *Cptr = 0; + // + // Skip over the = and then any spaces + // + Value++; + while (*Value && isspace (*Value)) { + Value++; + + } + // + // Find end of string, checking for quoted string + // + if (*Value == '\"') { + Value++; + for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++) + ; + } else { + for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++) + ; + } + // + // Null terminate the value string + // + CSave = *Cptr; + SaveCptr = Cptr; + *Cptr = 0; + Len = (int) (Cptr - Start); + } + // + // We now have a symbol name and a value. Look for an existing variable + // and overwrite it. + // + Symbol = mSymbolTable; + while (Symbol) { + // + // Check for symbol name match + // + if (stricmp (Name, Symbol->Name) == 0) { + _free (Symbol->Value); + Symbol->Value = (char *) _malloc (strlen (Value) + 1); + if (Symbol->Value == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return -1; + } + + strcpy (Symbol->Value, Value); + // + // If value == "NULL", then make it a 0-length string + // + if (stricmp (Symbol->Value, "NULL") == 0) { + Symbol->Value[0] = 0; + } + + return Len; + } + + Symbol = Symbol->Next; + } + // + // Does not exist, create a new one + // + NewSymbol = (SYMBOL *) _malloc (sizeof (SYMBOL)); + if (NewSymbol == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation failure"); + return -1; + } + + memset ((char *) NewSymbol, 0, sizeof (SYMBOL)); + NewSymbol->Name = (char *) _malloc (strlen (Name) + 1); + if (NewSymbol->Name == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation failure"); + _free (NewSymbol); + return -1; + } + + NewSymbol->Value = (char *) _malloc (strlen (Value) + 1); + if (NewSymbol->Value == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation failure"); + _free (NewSymbol->Name); + _free (NewSymbol); + return -1; + } + + strcpy (NewSymbol->Name, Name); + strcpy (NewSymbol->Value, Value); + // + // Remove trailing spaces + // + Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1; + while (Cptr > NewSymbol->Value) { + if (isspace (*Cptr)) { + *Cptr = 0; + Cptr--; + } else { + break; + } + } + // + // Add it to the head of the list. + // + NewSymbol->Next = mSymbolTable; + mSymbolTable = NewSymbol; + // + // If value == "NULL", then make it a 0-length string + // + if (stricmp (NewSymbol->Value, "NULL") == 0) { + NewSymbol->Value[0] = 0; + } + // + // Restore the terminator we inserted if they passed in var=value + // + if (SaveCptr != NULL) { + *SaveCptr = CSave; + } + _free (NewSymbol->Value); + _free (NewSymbol->Name); + _free (NewSymbol); + return Len; +} + +static +STATUS +RemoveSymbol ( + char *Name, + char SymbolType + ) +/*++ + +Routine Description: + + Remove a symbol name/value from the symbol table + +Arguments: + + Name - name of symbol to remove + SymbolType - type of symbol to remove + +Returns: + + STATUS_SUCCESS - matching symbol found and removed + STATUS_ERROR - matching symbol not found in symbol table + +--*/ +{ + SYMBOL *Symbol; + + SYMBOL *PrevSymbol; + + PrevSymbol = NULL; + Symbol = mSymbolTable; + // + // Walk the linked list of symbols in the symbol table looking + // for a match of both symbol name and type. + // + while (Symbol) { + if ((stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) { + // + // If the symbol has a value associated with it, free the memory + // allocated for the value. + // Then free the memory allocated for the symbols string name. + // + if (Symbol->Value) { + _free (Symbol->Value); + } + + _free (Symbol->Name); + // + // Link the previous symbol to the next symbol to effectively + // remove this symbol from the linked list. + // + if (PrevSymbol) { + PrevSymbol->Next = Symbol->Next; + } else { + mSymbolTable = Symbol->Next; + } + + _free (Symbol); + return STATUS_SUCCESS; + } + + PrevSymbol = Symbol; + Symbol = Symbol->Next; + } + + return STATUS_WARNING; +} + +static +SYMBOL * +FreeSymbols ( + SYMBOL *Syms + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Syms - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + SYMBOL *Next; + while (Syms) { + if (Syms->Name != NULL) { + _free (Syms->Name); + } + + if (Syms->Value != NULL) { + _free (Syms->Value); + } + + Next = Syms->Next; + _free (Syms); + Syms = Next; + } + + return Syms; +} + +static +int +ExpandMacros ( + char *SourceLine, + char *DestLine, + int LineLen + ) +/*++ + +Routine Description: + + Given a line of text, replace all variables of format $(NAME) with values + from our symbol table. + +Arguments: + + SourceLine - input line of text to do symbol replacements on + DestLine - on output, SourceLine with symbols replaced + LineLen - length of DestLine, so we don't exceed its allocated length + +Returns: + + STATUS_SUCCESS - no problems encountered + STATUS_WARNING - missing closing parenthesis on a symbol reference in SourceLine + STATUS_ERROR - memory allocation failure + +--*/ +{ + static int NestDepth = 0; + char *FromPtr; + char *ToPtr; + char *SaveStart; + char *Cptr; + char *value; + int Expanded; + int ExpandedCount; + INT8 *LocalDestLine; + STATUS Status; + int LocalLineLen; + + NestDepth++; + Status = STATUS_SUCCESS; + LocalDestLine = (char *) _malloc (LineLen); + if (LocalDestLine == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL); + return STATUS_ERROR; + } + + FromPtr = SourceLine; + ToPtr = LocalDestLine; + // + // Walk the entire line, replacing $(MACRO_NAME). + // + LocalLineLen = LineLen; + ExpandedCount = 0; + while (*FromPtr && (LocalLineLen > 0)) { + if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) { + // + // Save the start in case it's undefined, in which case we copy it as-is. + // + SaveStart = FromPtr; + Expanded = 0; + // + // Macro expansion time. Find the end (no spaces allowed) + // + FromPtr += 2; + for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++) + ; + if (*Cptr) { + // + // Truncate the string at the closing parenthesis for ease-of-use. + // Then copy the string directly to the destination line in case we don't find + // a definition for it. + // + *Cptr = 0; + strcpy (ToPtr, SaveStart); + if ((value = GetSymbolValue (FromPtr)) != NULL) { + strcpy (ToPtr, value); + LocalLineLen -= strlen (value); + ToPtr += strlen (value); + Expanded = 1; + ExpandedCount++; + } + + if (!Expanded) { + // + // Restore closing parenthesis, and advance to next character + // + *Cptr = ')'; + FromPtr = SaveStart + 1; + ToPtr++; + } else { + FromPtr = Cptr + 1; + } + } else { + Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on macro"); + strcpy (ToPtr, FromPtr); + Status = STATUS_WARNING; + goto Done; + } + } else { + *ToPtr = *FromPtr; + FromPtr++; + ToPtr++; + LocalLineLen--; + } + } + + if (*FromPtr == 0) { + *ToPtr = 0; + } + + // + // If we expanded at least one string successfully, then make a recursive call to try again. + // + if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (NestDepth < 10)) { + Status = ExpandMacros (LocalDestLine, DestLine, LineLen); + _free (LocalDestLine); + NestDepth = 0; + return Status; + } + +Done: + if (Status != STATUS_ERROR) { + strcpy (DestLine, LocalDestLine); + } + + NestDepth = 0; + _free (LocalDestLine); + return Status; +} + +STATUS +SymbolsFileStringsReplace ( + char *InFileName, + char *OutFileName + ) +/*++ + +Routine Description: + + Given input and output file names, read in the input file, replace variable + references of format $(NAME) with appropriate values from our symbol table, + and write the result out to the output file. + +Arguments: + + InFileName - name of input text file to replace variable references + OutFileName - name of output text file to write results to + +Returns: + + STATUS_SUCCESS - no problems encountered + STATUS_ERROR - failed to open input or output file + +--*/ +{ + STATUS Status; + FILE *InFptr; + FILE *OutFptr; + char Line[MAX_LINE_LEN]; + char OutLine[MAX_LINE_LEN]; + + Status = STATUS_ERROR; + // + // Open input and output files + // + InFptr = NULL; + OutFptr = NULL; + if ((InFptr = fopen (InFileName, "r")) == NULL) { + Error (NULL, 0, 0, InFileName, "failed to open input file for reading"); + goto Done; + } + + if ((OutFptr = fopen (OutFileName, "w")) == NULL) { + Error (NULL, 0, 0, OutFileName, "failed to open output file for writing"); + goto Done; + } + // + // Read lines from input file until done + // + while (fgets (Line, sizeof (Line), InFptr) != NULL) { + ExpandMacros (Line, OutLine, sizeof (OutLine)); + fprintf (OutFptr, OutLine); + } + + Status = STATUS_SUCCESS; +Done: + if (InFptr != NULL) { + fclose (InFptr); + } + + if (OutFptr != NULL) { + fclose (OutFptr); + } + + return Status; +} diff --git a/Tools/CCode/Source/FlashMap/Symbols.h b/Tools/CCode/Source/FlashMap/Symbols.h new file mode 100644 index 0000000000..a3cadff268 --- /dev/null +++ b/Tools/CCode/Source/FlashMap/Symbols.h @@ -0,0 +1,124 @@ +/*++ + +Copyright (c) 2004-2006 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: + + Symbols.h + +Abstract: + + Defines and prototypes for a class-like symbol table service. + +--*/ + +#ifndef _SYMBOLS_H_ +#define _SYMBOLS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +int +SymbolAdd ( + char *Name, + char *Value, + int Mode + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Name - GC_TODO: add argument description + Value - GC_TODO: add argument description + Mode - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +STATUS +SymbolsFileStringsReplace ( + char *InFileName, + char *OutFileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + InFileName - GC_TODO: add argument description + OutFileName - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +void +SymbolsConstructor ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +; + +void +SymbolsDestructor ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +; + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef _SYMBOLS_H_ diff --git a/Tools/CCode/Source/FlashMap/build.xml b/Tools/CCode/Source/FlashMap/build.xml new file mode 100644 index 0000000000..680c1820b0 --- /dev/null +++ b/Tools/CCode/Source/FlashMap/build.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3