blob: 5a9205ab36c1fa5d54e0d5ac7b162b8a5b0c0f11 [file] [log] [blame]
/*++
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;
}