/*++ | |
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 <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <Common/UefiBaseTypes.h> | |
#include <Common/FirmwareVolumeHeader.h> | |
#include <Common/MultiPhase.h> | |
#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 | |
EFI_GUID AreaTypeGuid; | |
WCHAR_T AreaTypeGuidString[MAX_NAME_LEN]; | |
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 attribute "AreaTypeGuid" | |
// | |
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 (FBlockDesc->AreaTypeGuidString, sizeof (FBlockDesc->AreaTypeGuidString))) { | |
// | |
// Nothing else to do | |
// | |
} else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &FBlockDesc->AreaTypeGuid)) { | |
Error ( | |
SFPGetFileName (), | |
SFPGetLineNumber (), | |
0, | |
"expected AreaTypeGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC", | |
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", FBlock->AreaType); | |
fprintf (OutFptr, " 0, 0, 0,\\\n"); | |
// | |
// 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 (FBlock->AreaTypeGuidString[0] != 0) { | |
fprintf (OutFptr, " %s, \\\n", FBlock->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", | |
FBlock->AreaTypeGuid.Data1, | |
(unsigned int) FBlock->AreaTypeGuid.Data2, | |
(unsigned int) FBlock->AreaTypeGuid.Data3, | |
(unsigned int) FBlock->AreaTypeGuid.Data4[0], | |
(unsigned int) FBlock->AreaTypeGuid.Data4[1], | |
(unsigned int) FBlock->AreaTypeGuid.Data4[2], | |
(unsigned int) FBlock->AreaTypeGuid.Data4[3], | |
(unsigned int) FBlock->AreaTypeGuid.Data4[4], | |
(unsigned int) FBlock->AreaTypeGuid.Data4[5], | |
(unsigned int) FBlock->AreaTypeGuid.Data4[6], | |
(unsigned int) FBlock->AreaTypeGuid.Data4[7] | |
); | |
} | |
fprintf (OutFptr, " },\\\n"); | |
} | |
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; | |
} |