mirror of https://github.com/acidanthera/audk.git
2789 lines
86 KiB
C
2789 lines
86 KiB
C
/*++
|
|
|
|
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
|
|
FLASH_SUBREGION_DESCRIPTION *Subregions;
|
|
FLASH_SUBREGION_DESCRIPTION *LastSubregion;
|
|
} FLASH_BLOCK_DESCRIPTION;
|
|
|
|
//
|
|
// Information for each flash device will be saved in one of these
|
|
//
|
|
typedef struct _FLASH_DEVICE_DESCRIPTION {
|
|
struct _FLASH_DEVICE_DESCRIPTION *Next; // next flash device in our linked list
|
|
int ErasePolarity; // erase polarity of the flash device
|
|
unsigned int BaseAddress; // base address of the flash device
|
|
unsigned int Size; // total size, in bytes, of the flash device
|
|
WCHAR_T Name[MAX_NAME_LEN]; // name of the flash device
|
|
FLASH_BLOCK_DESCRIPTION *PBlocks; // linked list of physical block descriptors
|
|
FLASH_BLOCK_DESCRIPTION *LastPBlock; // last block in the linked list
|
|
FLASH_BLOCK_DESCRIPTION *Regions; // linked list of flash region descriptors
|
|
FLASH_BLOCK_DESCRIPTION *LastRegion; // last region in the linked list
|
|
} FLASH_DEVICE_DESCRIPTION;
|
|
|
|
//
|
|
// For image definitions, they can specify a file name or raw data bytes. Keep a linked list.
|
|
//
|
|
typedef struct _IMAGE_DEFINITION_ENTRY {
|
|
struct _IMAGE_DEFINITION_ENTRY *Next;
|
|
WCHAR_T RegionName[MAX_NAME_LEN];
|
|
WCHAR_T SubregionName[MAX_NAME_LEN];
|
|
WCHAR_T Name[MAX_NAME_LEN]; // file or data name
|
|
int IsRawData; // non-zero if raw data bytes
|
|
unsigned int RawDataSize;
|
|
char *RawData;
|
|
int Optional; // optional file (don't include if it doesn't exist)
|
|
} IMAGE_DEFINITION_ENTRY;
|
|
|
|
//
|
|
// When we parse an image definition, save all the data for each in one of these
|
|
//
|
|
typedef struct _IMAGE_DEFINITION {
|
|
struct _IMAGE_DEFINITION *Next;
|
|
WCHAR_T Name[MAX_NAME_LEN];
|
|
IMAGE_DEFINITION_ENTRY *Entries;
|
|
IMAGE_DEFINITION_ENTRY *LastEntry;
|
|
} IMAGE_DEFINITION;
|
|
|
|
typedef struct {
|
|
char *BufferStart;
|
|
char *BufferEnd;
|
|
char *BufferPos;
|
|
} BUFFER_DATA;
|
|
|
|
static const char *CIncludeHeader = "/*++\n\n"
|
|
" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n""#ifndef _FLASH_MAP_H_\n"
|
|
"#define _FLASH_MAP_H_\n\n";
|
|
//
|
|
// "#include \"EfiFlashMap.h\"\n\n";
|
|
//
|
|
static const char *CIncludeFooter = "#endif // #ifndef _FLASH_MAP_H_\n\n";
|
|
|
|
static const char *CFlashMapDataFileHeader = "/*++\n\n"
|
|
" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n";
|
|
|
|
static FLASH_DEVICE_DESCRIPTION *mFlashDevices = NULL;
|
|
static IMAGE_DEFINITION *mImageDefinitions = NULL;
|
|
|
|
//
|
|
// Local function prototypes
|
|
//
|
|
static
|
|
BUFFER_DATA *
|
|
CreateBufferData (
|
|
VOID
|
|
);
|
|
|
|
static
|
|
BOOLEAN
|
|
AddBufferDataByte (
|
|
BUFFER_DATA *Buffer,
|
|
char Data
|
|
);
|
|
|
|
static
|
|
void
|
|
FreeBufferData (
|
|
BUFFER_DATA *Buffer,
|
|
BOOLEAN FreeData
|
|
);
|
|
|
|
static
|
|
char *
|
|
GetBufferData (
|
|
BUFFER_DATA *Buffer,
|
|
int *BufferSize
|
|
);
|
|
|
|
static
|
|
FLASH_SUBREGION_DESCRIPTION *
|
|
ParseSubregionDefinition (
|
|
unsigned int SizeLeft
|
|
);
|
|
|
|
void
|
|
FDFConstructor (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Initialization routine for the services that operate on a flash
|
|
definition file.
|
|
|
|
Arguments:
|
|
None.
|
|
|
|
Returns:
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
mFlashDevices = NULL;
|
|
mImageDefinitions = NULL;
|
|
}
|
|
|
|
void
|
|
FDFDestructor (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Finalization/cleanup routine for the services that operate on a flash
|
|
definition file.
|
|
|
|
Arguments:
|
|
None.
|
|
|
|
Returns:
|
|
NA
|
|
|
|
--*/
|
|
{
|
|
FLASH_BLOCK_DESCRIPTION *FBNext;
|
|
FLASH_DEVICE_DESCRIPTION *FDNext;
|
|
IMAGE_DEFINITION *IDNext;
|
|
IMAGE_DEFINITION_ENTRY *IDENext;
|
|
FLASH_SUBREGION_DESCRIPTION *SubNext;
|
|
//
|
|
// Go through all our flash devices and free the memory
|
|
//
|
|
while (mFlashDevices != NULL) {
|
|
//
|
|
// Free the physical block definitions
|
|
//
|
|
while (mFlashDevices->PBlocks != NULL) {
|
|
FBNext = mFlashDevices->PBlocks->Next;
|
|
_free (mFlashDevices->PBlocks);
|
|
mFlashDevices->PBlocks = FBNext;
|
|
}
|
|
//
|
|
// Free the region definitions
|
|
//
|
|
while (mFlashDevices->Regions != NULL) {
|
|
FBNext = mFlashDevices->Regions->Next;
|
|
//
|
|
// First free the subregion definitions
|
|
//
|
|
while (mFlashDevices->Regions->Subregions != NULL) {
|
|
SubNext = mFlashDevices->Regions->Subregions->Next;
|
|
_free (mFlashDevices->Regions->Subregions);
|
|
mFlashDevices->Regions->Subregions = SubNext;
|
|
}
|
|
|
|
_free (mFlashDevices->Regions);
|
|
mFlashDevices->Regions = FBNext;
|
|
}
|
|
|
|
FDNext = mFlashDevices->Next;
|
|
_free (mFlashDevices);
|
|
mFlashDevices = FDNext;
|
|
}
|
|
//
|
|
// Free up the image definitions, and the data
|
|
//
|
|
while (mImageDefinitions != NULL) {
|
|
//
|
|
// Free the entries
|
|
//
|
|
while (mImageDefinitions->Entries != NULL) {
|
|
IDENext = mImageDefinitions->Entries->Next;
|
|
if (mImageDefinitions->Entries->RawData != NULL) {
|
|
_free (mImageDefinitions->Entries->RawData);
|
|
}
|
|
|
|
_free (mImageDefinitions->Entries);
|
|
mImageDefinitions->Entries = IDENext;
|
|
}
|
|
|
|
IDNext = mImageDefinitions->Next;
|
|
_free (mImageDefinitions);
|
|
mImageDefinitions = IDNext;
|
|
}
|
|
}
|
|
|
|
STATUS
|
|
FDFParseFile (
|
|
char *FileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Parse the specified flash definition file, saving the definitions in
|
|
file-static variables for use by other functions.
|
|
|
|
Arguments:
|
|
FileName - name of the input flash definition text file.
|
|
|
|
Returns:
|
|
STATUS_SUCCESS - file parsed with no errors or warnings
|
|
STATUS_WARNING - warnings, but no errors, were encountered while parsing
|
|
STATUS_ERROR - errors were encountered while parsing
|
|
|
|
--*/
|
|
{
|
|
FILE *Fptr;
|
|
STATUS Status;
|
|
unsigned int Num;
|
|
FLASH_DEVICE_DESCRIPTION *FDDesc;
|
|
FLASH_BLOCK_DESCRIPTION *FBlockDesc;
|
|
FLASH_BLOCK_DESCRIPTION *TempBlockDesc;
|
|
FLASH_SUBREGION_DESCRIPTION *Subregion;
|
|
FLASH_SUBREGION_DESCRIPTION *TempSubregion;
|
|
unsigned int BlockSizeLeft;
|
|
unsigned int RegionSizeLeft;
|
|
unsigned int SubregionSizeLeft;
|
|
int ErrorCount;
|
|
int WarningCount;
|
|
IMAGE_DEFINITION *ImageDef;
|
|
IMAGE_DEFINITION_ENTRY *ImageDefEntry;
|
|
IMAGE_DEFINITION_ENTRY *TempImageDefEntry;
|
|
BUFFER_DATA *BufferData;
|
|
char Str[100];
|
|
BOOLEAN PreviousComma;
|
|
|
|
if ((Fptr = fopen (FileName, "r")) == NULL) {
|
|
Error (NULL, 0, 0, FileName, "failed to open input flash definition file for reading");
|
|
return STATUS_ERROR;
|
|
}
|
|
|
|
fclose (Fptr);
|
|
Status = STATUS_SUCCESS;
|
|
ErrorCount = 0;
|
|
WarningCount = 0;
|
|
//
|
|
// Initialize the simple-file-parsing routines
|
|
//
|
|
SFPInit ();
|
|
//
|
|
// Open the file
|
|
//
|
|
if ((Status = SFPOpenFile (FileName)) != STATUS_SUCCESS) {
|
|
return Status;
|
|
}
|
|
//
|
|
// Parse the file. Should start with a series of these:
|
|
// FlashDevice {
|
|
// Name = "FLASH_1234", Size = 0x2004, BaseAddress = 0xFFF0000, ErasePolarity = 1,
|
|
// Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }
|
|
// Block { Name = "BLOCK2", Size = 0x1004, Flags = 0x0002 }
|
|
// Region { Name = "REGION_NAME", Size = 0x2004, Align= 4 }
|
|
// }
|
|
//
|
|
while (SFPIsKeyword ("FlashDevice")) {
|
|
//
|
|
// Allocate memory for new flash device description block
|
|
//
|
|
FDDesc = (FLASH_DEVICE_DESCRIPTION *) _malloc (sizeof (FLASH_DEVICE_DESCRIPTION));
|
|
if (FDDesc == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
memset (FDDesc, 0, sizeof (FLASH_DEVICE_DESCRIPTION));
|
|
//
|
|
// Open brace -- warning if not there
|
|
//
|
|
if (!SFPIsToken ("{")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Name = "DeviceName",
|
|
//
|
|
if (!SFPIsKeyword ("Name")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (FDDesc->Name, sizeof (FDDesc->Name))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of flash device", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following flash device name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Size = 0x20000,
|
|
//
|
|
if (!SFPIsKeyword ("Size")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&FDDesc->Size)) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Check for 0 size
|
|
//
|
|
if (FDDesc->Size == 0) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, FDDesc->Name, "Size field cannot be 0", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
SFPIsToken (",");
|
|
//
|
|
// Parse: BaseAddress = 0xFFF0000,
|
|
//
|
|
if (!SFPIsKeyword ("BaseAddress")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'BaseAddress'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&FDDesc->BaseAddress)) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for BaseAddress", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following BaseAddress value", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: ErasePolarity = 1,
|
|
//
|
|
if (!SFPIsKeyword ("ErasePolarity")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'ErasePolarity'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&Num) || ((Num != 0) && (Num != 1))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric erase polarity value 1 or 0", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
FDDesc->ErasePolarity = Num;
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following erase polarity value", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse array of:
|
|
// Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }
|
|
//
|
|
// Keep track of size to make sure the sum of the physical blocks and region sizes do not
|
|
// exceed the size of the flash device.
|
|
//
|
|
BlockSizeLeft = FDDesc->Size;
|
|
RegionSizeLeft = FDDesc->Size;
|
|
while (SFPIsKeyword ("Block")) {
|
|
//
|
|
// Allocate memory for a new physical block descriptor
|
|
//
|
|
FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));
|
|
if (FBlockDesc == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));
|
|
//
|
|
// Open brace -- warning if not there
|
|
//
|
|
if (!SFPIsToken ("{")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Name = "BlockName",
|
|
//
|
|
if (!SFPIsKeyword ("Name")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of physical block", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Make sure there are no other physical block names with this same name
|
|
//
|
|
for (TempBlockDesc = FDDesc->PBlocks; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {
|
|
if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
TempBlockDesc->Name,
|
|
"physical block with this name already defined"
|
|
);
|
|
ErrorCount++;
|
|
}
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following physical block name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Size = 0x2000,
|
|
//
|
|
if (!SFPIsKeyword ("Size")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&FBlockDesc->Size)) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Make sure the sum of physical blocks so far does not exceed flash device size
|
|
//
|
|
if (BlockSizeLeft < FBlockDesc->Size) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
"sum of physical block sizes exceeds flash device size",
|
|
NULL
|
|
);
|
|
ErrorCount++;
|
|
}
|
|
|
|
BlockSizeLeft -= FBlockDesc->Size;
|
|
SFPIsToken (",");
|
|
//
|
|
// Optional parse: Flags = 0xFFF0000,
|
|
//
|
|
if (SFPIsKeyword ("Flags")) {
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&FBlockDesc->Flags)) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if (!SFPIsToken ("}")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected PhysicalBlock closing brace '}'", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Add the physical block descriptor to the end of the linked list
|
|
//
|
|
if (FDDesc->LastPBlock != NULL) {
|
|
FDDesc->LastPBlock->Next = FBlockDesc;
|
|
} else {
|
|
FDDesc->PBlocks = FBlockDesc;
|
|
}
|
|
|
|
FDDesc->LastPBlock = FBlockDesc;
|
|
}
|
|
//
|
|
// Make sure sum of sizes of physical blocks added up to size of flash device
|
|
//
|
|
if (BlockSizeLeft != 0) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
NULL,
|
|
"sum of sizes of physical blocks (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",
|
|
FDDesc->Size - BlockSizeLeft,
|
|
FDDesc->Size,
|
|
BlockSizeLeft
|
|
);
|
|
ErrorCount++;
|
|
}
|
|
//
|
|
// Parse array of:
|
|
// Region { Name = "REGION_1", Size = 0x2000, Flags = 0x1234, Alignment = 4, Attributes = "str", AreaType = "str" }
|
|
//
|
|
while (SFPIsKeyword ("Region")) {
|
|
//
|
|
// Allocate memory for a new physical block descriptor
|
|
//
|
|
FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));
|
|
if (FBlockDesc == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));
|
|
//
|
|
// Open brace -- warning if not there
|
|
//
|
|
if (!SFPIsToken ("{")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Name = "BlockName",
|
|
//
|
|
if (!SFPIsKeyword ("Name")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Make sure there are no other region names with this same name
|
|
//
|
|
for (TempBlockDesc = FDDesc->Regions; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {
|
|
if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
TempBlockDesc->Name,
|
|
"Region with this name already defined"
|
|
);
|
|
ErrorCount++;
|
|
}
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Size = 0x2000,
|
|
//
|
|
if (!SFPIsKeyword ("Size")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&FBlockDesc->Size)) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
|
|
}
|
|
//
|
|
// Make sure the sum of regions so far does not exceed flash device size
|
|
//
|
|
if (RegionSizeLeft < FBlockDesc->Size) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Region sizes exceeds flash device size", NULL);
|
|
ErrorCount++;
|
|
}
|
|
|
|
RegionSizeLeft -= FBlockDesc->Size;
|
|
//
|
|
// Optional parse: Flags = 0xFFF0000,
|
|
//
|
|
if (SFPIsKeyword ("Flags")) {
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&FBlockDesc->Flags)) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// comma
|
|
//
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
|
|
}
|
|
}
|
|
//
|
|
// Optional parse: Alignment = 4
|
|
//
|
|
if (SFPIsKeyword ("Alignment")) {
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&FBlockDesc->Alignment)) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Alignment value", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// comma
|
|
//
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
|
|
}
|
|
}
|
|
//
|
|
// Parse: Attributes = "String",
|
|
//
|
|
if (!SFPIsKeyword ("Attributes")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (FBlockDesc->Attributes, sizeof (FBlockDesc->Attributes))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
|
|
}
|
|
//
|
|
// Parse: AreaType = "String",
|
|
//
|
|
if (!SFPIsKeyword ("AreaType")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (FBlockDesc->AreaType, sizeof (FBlockDesc->AreaType))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
PreviousComma = SFPIsToken (",");
|
|
//
|
|
// Parse optional Subregion definitions
|
|
//
|
|
SubregionSizeLeft = FBlockDesc->Size;
|
|
while (SFPIsToken ("Subregion")) {
|
|
if (!PreviousComma) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'Subregion'", NULL);
|
|
WarningCount++;
|
|
PreviousComma = TRUE;
|
|
}
|
|
|
|
Subregion = ParseSubregionDefinition (SubregionSizeLeft);
|
|
if (Subregion == NULL) {
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
SubregionSizeLeft -= Subregion->Size;
|
|
//
|
|
// Add it to the end of our list
|
|
//
|
|
if (FBlockDesc->Subregions == NULL) {
|
|
FBlockDesc->Subregions = Subregion;
|
|
} else {
|
|
FBlockDesc->LastSubregion->Next = Subregion;
|
|
}
|
|
|
|
FBlockDesc->LastSubregion = Subregion;
|
|
//
|
|
// Make sure all subregion names are unique. We do this each time
|
|
// through so that we catch the error immediately after it happens, in
|
|
// which case the reported line number is at least close to where the
|
|
// problem lies. We don't exit on the error because we can continue parsing
|
|
// the script to perhaps catch other errors or warnings.
|
|
//
|
|
for (Subregion = FBlockDesc->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
|
|
for (TempSubregion = Subregion->Next; TempSubregion != NULL; TempSubregion = TempSubregion->Next) {
|
|
if (strcmp (Subregion->Name, TempSubregion->Name) == 0) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, Subregion->Name, "duplicate Subregion name");
|
|
ErrorCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!SFPIsToken ("}")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Region closing brace '}'", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Add the region descriptor to the end of the linked list
|
|
//
|
|
if (FDDesc->LastRegion != NULL) {
|
|
FDDesc->LastRegion->Next = FBlockDesc;
|
|
} else {
|
|
FDDesc->Regions = FBlockDesc;
|
|
}
|
|
|
|
FDDesc->LastRegion = FBlockDesc;
|
|
}
|
|
//
|
|
// Make sure sum of sizes of regions adds up to size of flash device
|
|
//
|
|
if (RegionSizeLeft != 0) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
NULL,
|
|
"sum of sizes of Regions (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",
|
|
FDDesc->Size - RegionSizeLeft,
|
|
FDDesc->Size,
|
|
RegionSizeLeft
|
|
);
|
|
ErrorCount++;
|
|
}
|
|
//
|
|
// Look for closing brace
|
|
//
|
|
if (!SFPIsToken ("}")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected FlashDevice closing brace '}'", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Add this flash description to the list
|
|
//
|
|
FDDesc->Next = mFlashDevices;
|
|
mFlashDevices = FDDesc;
|
|
}
|
|
|
|
while (SFPIsKeyword ("FlashDeviceImage")) {
|
|
//
|
|
// Allocate memory for a new FD image definition
|
|
//
|
|
ImageDef = (IMAGE_DEFINITION *) _malloc (sizeof (IMAGE_DEFINITION));
|
|
if (ImageDef == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
memset (ImageDef, 0, sizeof (IMAGE_DEFINITION));
|
|
//
|
|
// Open brace -- warning if not there
|
|
//
|
|
if (!SFPIsToken ("{")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Name = "ImageName",
|
|
//
|
|
if (!SFPIsKeyword ("Name")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (ImageDef->Name, sizeof (ImageDef->Name))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of image", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following image name", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
while (1) {
|
|
//
|
|
// Parse: File { Name = "FV\FvOem.fv", Region = "REGION_OEM", Optional = TRUE }
|
|
//
|
|
if (SFPIsKeyword ("File")) {
|
|
ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));
|
|
if (ImageDefEntry == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));
|
|
//
|
|
// Open brace -- warning if not there
|
|
//
|
|
if (!SFPIsToken ("{")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Name = "FileName.txt"
|
|
//
|
|
if (!SFPIsKeyword ("Name")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of file", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following file name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Region = "REGION_NAME"
|
|
//
|
|
if (!SFPIsKeyword ("Region")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse optional: Subregion = "SUBREGION_NAME"
|
|
//
|
|
if (SFPIsKeyword ("Subregion")) {
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// For a given region, you can only place data using the region name, or the subregion names.
|
|
// In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that
|
|
// here by checking that any previous entries with the same Region name had a Subregion specified
|
|
// as well.
|
|
//
|
|
for (TempImageDefEntry = ImageDef->Entries;
|
|
TempImageDefEntry != NULL;
|
|
TempImageDefEntry = TempImageDefEntry->Next
|
|
) {
|
|
if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {
|
|
if (TempImageDefEntry->SubregionName[0] == 0) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
TempImageDefEntry->RegionName,
|
|
"data already placed on a region-basis in the region, can't place data using subregions"
|
|
);
|
|
ErrorCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Optional parse: Optional = TRUE | FALSE
|
|
//
|
|
if (SFPIsKeyword ("Optional")) {
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPIsKeyword ("TRUE")) {
|
|
ImageDefEntry->Optional = 1;
|
|
} else if (SFPIsKeyword ("FALSE")) {
|
|
//
|
|
// Already set to 0
|
|
//
|
|
} else {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
SFPIsToken (",");
|
|
}
|
|
//
|
|
// Closing brace
|
|
//
|
|
if (!SFPIsToken ("}")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace to File entry", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Add the entry to the end of the list
|
|
//
|
|
if (ImageDef->LastEntry != NULL) {
|
|
ImageDef->LastEntry->Next = ImageDefEntry;
|
|
} else {
|
|
ImageDef->Entries = ImageDefEntry;
|
|
}
|
|
|
|
ImageDef->LastEntry = ImageDefEntry;
|
|
} else if (SFPIsKeyword ("RawData")) {
|
|
//
|
|
// Parse: RawData { Name = "PadBytes", Region = "REGION_1", Data = { 0x78, 0x56, 0x34, 0x12 }}
|
|
//
|
|
ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));
|
|
if (ImageDefEntry == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));
|
|
ImageDefEntry->IsRawData = 1;
|
|
//
|
|
// Open brace -- warning if not there
|
|
//
|
|
if (!SFPIsToken ("{")) {
|
|
Warning (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
"expected '{' opening brace for RawData definition",
|
|
NULL
|
|
);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Name = "PadBytes"
|
|
//
|
|
if (!SFPIsKeyword ("Name")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of raw data", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following raw data name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Region = "REGION_NAME"
|
|
//
|
|
if (!SFPIsKeyword ("Region")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse optional: Subregion = "SUBREGION_NAME"
|
|
//
|
|
if (SFPIsKeyword ("Subregion")) {
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// For a given region, you can only place data using the region name, or the subregion names.
|
|
// In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that
|
|
// here by checking that any previous entries with the same Region name had a Subregion specified
|
|
// as well.
|
|
//
|
|
for (TempImageDefEntry = ImageDef->Entries;
|
|
TempImageDefEntry != NULL;
|
|
TempImageDefEntry = TempImageDefEntry->Next
|
|
) {
|
|
if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {
|
|
if (TempImageDefEntry->SubregionName[0] == 0) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
TempImageDefEntry->RegionName,
|
|
"data already placed on a region-basis in the region, can't place data using subregions"
|
|
);
|
|
ErrorCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Parse: Data = { 0x78, 0x56, 0x34, 0x12 }
|
|
//
|
|
if (!SFPIsKeyword ("Data")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Data'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPIsToken ("{")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '{' preceeding data list", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if ((BufferData = CreateBufferData ()) == NULL) {
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Read bytes from input file until closing brace
|
|
//
|
|
while (!SFPIsToken ("}")) {
|
|
if (!SFPGetNumber (&Num)) {
|
|
SFPGetNextToken (Str, sizeof (Str));
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected data value", Str);
|
|
ErrorCount++;
|
|
FreeBufferData (BufferData, TRUE);
|
|
goto Done;
|
|
} else {
|
|
//
|
|
// Only allow bytes
|
|
//
|
|
if (Num > 0xFF) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "only values 0-255 (0x00-0xFF) allowed", NULL);
|
|
ErrorCount++;
|
|
FreeBufferData (BufferData, TRUE);
|
|
goto Done;
|
|
}
|
|
|
|
AddBufferDataByte (BufferData, (char) Num);
|
|
SFPIsToken (",");
|
|
}
|
|
}
|
|
//
|
|
// Now get the data and save it in our image entry
|
|
//
|
|
ImageDefEntry->RawData = GetBufferData (BufferData, &ImageDefEntry->RawDataSize);
|
|
FreeBufferData (BufferData, 0);
|
|
//
|
|
// Closing brace for RawData {}
|
|
//
|
|
if (!SFPIsToken ("}")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace for RawData", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Add the entry to the end of the list
|
|
//
|
|
if (ImageDef->LastEntry != NULL) {
|
|
ImageDef->LastEntry->Next = ImageDefEntry;
|
|
} else {
|
|
ImageDef->Entries = ImageDefEntry;
|
|
}
|
|
|
|
ImageDef->LastEntry = ImageDefEntry;
|
|
} else if (SFPIsToken ("}")) {
|
|
//
|
|
// Closing brace for FDImage {}
|
|
//
|
|
break;
|
|
} else {
|
|
SFPGetNextToken (Str, sizeof (Str));
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "unrecognized token", Str);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
}
|
|
//
|
|
// Add this image definition to our global list
|
|
//
|
|
ImageDef->Next = mImageDefinitions;
|
|
mImageDefinitions = ImageDef;
|
|
}
|
|
//
|
|
// Check for end-of-file
|
|
//
|
|
if (!SFPIsEOF ()) {
|
|
SFPGetNextToken (Str, sizeof (Str));
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected end-of-file", Str);
|
|
ErrorCount++;
|
|
}
|
|
|
|
Done:
|
|
SFPCloseFile ();
|
|
if (ErrorCount != 0) {
|
|
return STATUS_ERROR;
|
|
} else if (WarningCount != 0) {
|
|
return STATUS_WARNING;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
FLASH_SUBREGION_DESCRIPTION *
|
|
ParseSubregionDefinition (
|
|
unsigned int SizeLeft
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse Subregion definitions from the input flash definition file. Format:
|
|
|
|
Subregion {
|
|
CreateHob = TRUE,
|
|
Name = "FOO",
|
|
Size = 0xA000,
|
|
Attributes = "EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV",
|
|
AreaType = "EFI_FLASH_AREA_EFI_VARIABLES",
|
|
NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD (or "EFI_SOME_GUID"),
|
|
AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)
|
|
FileSystemGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)
|
|
}
|
|
|
|
NOTE: The caller has already parsed the "Subregion" token, so start with the opening brace.
|
|
|
|
Arguments:
|
|
|
|
SizeLeft - in the flash definition file, a Region can be broken up into
|
|
one or more subregions. As we parse the subregion definitions,
|
|
the caller keeps track of how much space is left in the region
|
|
that we're parsing subregions for. SizeLeft is that size, and
|
|
so the size of the subregion we're now parsing better not
|
|
exceed the size left.
|
|
Returns:
|
|
|
|
NULL - unrecoverable errors detected while parsing the subregion definition
|
|
|
|
pointer to a subregion definition created from the parsed subregion
|
|
|
|
--*/
|
|
{
|
|
FLASH_SUBREGION_DESCRIPTION *Subregion;
|
|
int ErrorCount;
|
|
int WarningCount;
|
|
unsigned int Number;
|
|
BOOLEAN PreviousComma;
|
|
//
|
|
// Allocate memory for the new subregion descriptor
|
|
//
|
|
ErrorCount = 0;
|
|
WarningCount = 0;
|
|
Subregion = (FLASH_SUBREGION_DESCRIPTION *) _malloc (sizeof (FLASH_SUBREGION_DESCRIPTION));
|
|
if (Subregion == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
memset (Subregion, 0, sizeof (FLASH_SUBREGION_DESCRIPTION));
|
|
//
|
|
// Open brace -- warning if not there
|
|
//
|
|
if (!SFPIsToken ("{")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: CreateHob = TRUE | FALSE,
|
|
//
|
|
if (!SFPIsKeyword ("CreateHob")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'CreateHob'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (SFPIsToken ("TRUE")) {
|
|
Subregion->CreateHob = 1;
|
|
} else if (SFPIsToken ("FALSE")) {
|
|
//
|
|
// Subregion->CreateHob = 0; -- not required since we did a memset earlier
|
|
//
|
|
} else {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following CreateHob value", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Name = "Name",
|
|
//
|
|
if (!SFPIsKeyword ("Name")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetQuotedString (Subregion->Name, sizeof (Subregion->Name))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion name", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Parse: Size = 0x2000,
|
|
//
|
|
if (!SFPIsKeyword ("Size")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPGetNumber (&Subregion->Size)) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Check that the size does not exceed the size left passed in
|
|
//
|
|
if (Subregion->Size > SizeLeft) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Subregion sizes exceeds Region size", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following Size value", NULL);
|
|
}
|
|
//
|
|
// Parse: Attributes = Number | "String",
|
|
//
|
|
if (!SFPIsKeyword ("Attributes")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (SFPGetNumber (&Number)) {
|
|
sprintf (Subregion->Attributes, "0x%X", Number);
|
|
} else if (!SFPGetQuotedString (Subregion->Attributes, sizeof (Subregion->Attributes))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
|
|
}
|
|
//
|
|
// Parse: AreaType = Number | "String",
|
|
// AreaType is a UINT8, so error if it exceeds the size
|
|
//
|
|
if (!SFPIsKeyword ("AreaType")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (SFPGetNumber (&Number)) {
|
|
if (Number > 0xFF) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "AreaType value exceeds 255", NULL);
|
|
ErrorCount++;
|
|
}
|
|
|
|
sprintf (Subregion->AreaType, "0x%X", Number & 0x00FF);
|
|
} else if (!SFPGetQuotedString (Subregion->AreaType, sizeof (Subregion->AreaType))) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken (",")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following AreaType value", NULL);
|
|
}
|
|
//
|
|
// Parse the three GUIDs (last two are optional)
|
|
//
|
|
// NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD, (or "EFI_SOME_GUID")
|
|
// AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")
|
|
// FileSysteGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")
|
|
//
|
|
if (!SFPIsKeyword ("NameGuid")) {
|
|
Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'NameGuid'", NULL);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Allow a GUID or a quoted string identifier, which we'll just copy as a string
|
|
//
|
|
if (SFPGetQuotedString (Subregion->NameGuidString, sizeof (Subregion->NameGuidString))) {
|
|
//
|
|
// Nothing else to do
|
|
//
|
|
} else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->NameGuid)) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
"expected NameGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
|
|
NULL
|
|
);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Comma following NameGuid is optional if they don't specify AreaTypeGuid or FileSystemGuid
|
|
//
|
|
PreviousComma = SFPIsToken (",");
|
|
if (SFPIsKeyword ("AreaTypeGuid")) {
|
|
//
|
|
// Check for preceeding comma now
|
|
//
|
|
if (!PreviousComma) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'AreaTypeGuid'", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (SFPGetQuotedString (Subregion->AreaTypeGuidString, sizeof (Subregion->AreaTypeGuidString))) {
|
|
//
|
|
// Nothing else to do
|
|
//
|
|
} else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->AreaTypeGuid)) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
"expected AreaTypeGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
|
|
NULL
|
|
);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
PreviousComma = SFPIsToken (",");
|
|
}
|
|
|
|
if (SFPIsKeyword ("FileSystemGuid")) {
|
|
//
|
|
// Check for preceeding comma now
|
|
//
|
|
if (!PreviousComma) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'FileSystemGuid'", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
if (!SFPIsToken ("=")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
|
|
WarningCount++;
|
|
}
|
|
//
|
|
// Allow a GUID or a quoted string identifier, which we'll just copy as a string
|
|
//
|
|
if (SFPGetQuotedString (Subregion->FileSystemGuidString, sizeof (Subregion->FileSystemGuidString))) {
|
|
//
|
|
// Nothing else to do
|
|
//
|
|
} else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->FileSystemGuid)) {
|
|
Error (
|
|
SFPGetFileName (),
|
|
SFPGetLineNumber (),
|
|
0,
|
|
"expected FileSystemGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
|
|
NULL
|
|
);
|
|
ErrorCount++;
|
|
goto Done;
|
|
}
|
|
|
|
SFPIsToken (",");
|
|
}
|
|
//
|
|
// Look for subregion closing brace
|
|
//
|
|
if (!SFPIsToken ("}")) {
|
|
Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion closing brace '}'", NULL);
|
|
WarningCount++;
|
|
}
|
|
|
|
Done:
|
|
//
|
|
// If any errors were encountered, then delete the subregion definition
|
|
//
|
|
if (ErrorCount != 0) {
|
|
_free (Subregion);
|
|
Subregion = NULL;
|
|
}
|
|
|
|
return Subregion;
|
|
}
|
|
|
|
STATUS
|
|
FDFCreateCIncludeFile (
|
|
char *FlashDeviceName,
|
|
char *FileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Create a header file with #define definitions per an already-parsed
|
|
flash definition file.
|
|
|
|
Arguments:
|
|
FlashDeviceName - name of flash device (from the flash definition file)
|
|
to use
|
|
FileName - name of output file to create
|
|
|
|
Returns:
|
|
STATUS_SUCCESS - no errors or warnings
|
|
STATUS_WARNING - warnings, but no errors, were encountered
|
|
STATUS_ERROR - errors were encountered
|
|
|
|
--*/
|
|
{
|
|
FILE *OutFptr;
|
|
FLASH_BLOCK_DESCRIPTION *FBlock;
|
|
FLASH_DEVICE_DESCRIPTION *FDev;
|
|
FLASH_SUBREGION_DESCRIPTION *Subregion;
|
|
unsigned int Offset;
|
|
unsigned int SubregionOffset;
|
|
int CreateHobs;
|
|
//
|
|
// Find the definition we're supposed to use
|
|
//
|
|
for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
|
|
if (strcmp (FDev->Name, FlashDeviceName) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (FDev == NULL) {
|
|
Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
|
|
return STATUS_ERROR;
|
|
}
|
|
|
|
if ((OutFptr = fopen (FileName, "w")) == NULL) {
|
|
Error (NULL, 0, 0, FileName, "failed to open output file for writing");
|
|
return STATUS_ERROR;
|
|
}
|
|
//
|
|
// Write a header
|
|
//
|
|
fprintf (OutFptr, CIncludeHeader);
|
|
//
|
|
// Write flash block base and size defines
|
|
//
|
|
fprintf (OutFptr, "#define FLASH_BASE 0x%08X\n", FDev->BaseAddress);
|
|
fprintf (OutFptr, "#define FLASH_SIZE 0x%08X\n\n", FDev->Size);
|
|
//
|
|
// Write flash regions base, size and offset defines
|
|
//
|
|
Offset = 0;
|
|
CreateHobs = 0;
|
|
for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
|
|
fprintf (
|
|
OutFptr,
|
|
"#define FLASH_REGION_%s_BASE %*c0x%08X\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 40 - strlen (FBlock->Name),
|
|
' ',
|
|
Offset + FDev->BaseAddress
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"#define FLASH_REGION_%s_SIZE %*c0x%08X\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 40 - strlen (FBlock->Name),
|
|
' ',
|
|
FBlock->Size
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"#define FLASH_REGION_%s_OFFSET %*c0x%08X\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 40 - strlen (FBlock->Name),
|
|
' ',
|
|
Offset
|
|
);
|
|
//
|
|
// Create defines for any subregions
|
|
//
|
|
SubregionOffset = 0;
|
|
for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
|
|
fprintf (
|
|
OutFptr,
|
|
"#define FLASH_REGION_%s_SUBREGION_%s_BASE %*c0x%08X\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
FDev->BaseAddress + Offset + SubregionOffset
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"#define FLASH_REGION_%s_SUBREGION_%s_SIZE %*c0x%08X\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
Subregion->Size
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"#define FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c0x%08X\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
Offset + SubregionOffset
|
|
);
|
|
SubregionOffset += Subregion->Size;
|
|
if (Subregion->CreateHob != 0) {
|
|
CreateHobs = 1;
|
|
}
|
|
}
|
|
|
|
Offset += FBlock->Size;
|
|
}
|
|
//
|
|
// Now create a #define for the flash map data definition
|
|
//
|
|
fprintf (OutFptr, "\n\n#define EFI_FLASH_AREA_DATA_DEFINITION \\\n");
|
|
//
|
|
// Emit entry for each region
|
|
//
|
|
Offset = 0;
|
|
for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
|
|
fprintf (OutFptr, " /* %s region */\\\n", FBlock->Name);
|
|
fprintf (OutFptr, " {\\\n");
|
|
fprintf (OutFptr, " FLASH_REGION_%s_BASE,\\\n", FBlock->Name);
|
|
fprintf (OutFptr, " FLASH_REGION_%s_SIZE,\\\n", FBlock->Name);
|
|
fprintf (OutFptr, " %s,\\\n", FBlock->Attributes);
|
|
fprintf (OutFptr, " %s,\\\n },\\\n", FBlock->AreaType);
|
|
}
|
|
|
|
fprintf (OutFptr, "\n\n");
|
|
//
|
|
// Now walk the list again to create the EFI_HOB_FLASH_MAP_ENTRY_TYPE definition
|
|
//
|
|
if (CreateHobs != 0) {
|
|
fprintf (OutFptr, "//\n// EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\n//\n");
|
|
fprintf (OutFptr, "#define EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION");
|
|
for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
|
|
//
|
|
// See if the block has subregions, and that the CreateHobs flag is set
|
|
// for any of them.
|
|
//
|
|
CreateHobs = 0;
|
|
for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
|
|
if (Subregion->CreateHob != 0) {
|
|
CreateHobs = 1;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// If any of the subregions had the CreateHobs flag set, then create the entries in the
|
|
// output file
|
|
//
|
|
if (CreateHobs != 0) {
|
|
for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
|
|
if (Subregion->CreateHob != 0) {
|
|
fprintf (OutFptr, " \\\n");
|
|
fprintf (OutFptr, " /* %s.%s Subregion */\\\n", FBlock->Name, Subregion->Name);
|
|
fprintf (OutFptr, " {\\\n");
|
|
fprintf (OutFptr, " {EFI_HOB_TYPE_GUID_EXTENSION,\\\n");
|
|
fprintf (OutFptr, " sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\\\n");
|
|
fprintf (OutFptr, " 0},\\\n");
|
|
//
|
|
// The NameGuid may have been specified in the input flash definition file as a GUID, or
|
|
// as a quoted string. Do the right one.
|
|
//
|
|
if (Subregion->NameGuidString[0] != 0) {
|
|
fprintf (OutFptr, " %s, \\\n", Subregion->NameGuidString);
|
|
} else {
|
|
fprintf (
|
|
OutFptr,
|
|
" { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",
|
|
Subregion->NameGuid.Data1,
|
|
(unsigned int) Subregion->NameGuid.Data2,
|
|
(unsigned int) Subregion->NameGuid.Data3,
|
|
(unsigned int) Subregion->NameGuid.Data4[0],
|
|
(unsigned int) Subregion->NameGuid.Data4[1],
|
|
(unsigned int) Subregion->NameGuid.Data4[2],
|
|
(unsigned int) Subregion->NameGuid.Data4[3],
|
|
(unsigned int) Subregion->NameGuid.Data4[4],
|
|
(unsigned int) Subregion->NameGuid.Data4[5],
|
|
(unsigned int) Subregion->NameGuid.Data4[6],
|
|
(unsigned int) Subregion->NameGuid.Data4[7]
|
|
);
|
|
}
|
|
|
|
fprintf (OutFptr, " {0, 0, 0},\\\n");
|
|
fprintf (OutFptr, " %s,\\\n", Subregion->AreaType);
|
|
//
|
|
// The AreaTypeGuid may have been specified in the input flash definition file as a GUID, or
|
|
// as a quoted string. Do the right one.
|
|
//
|
|
if (Subregion->AreaTypeGuidString[0] != 0) {
|
|
fprintf (OutFptr, " %s, \\\n", Subregion->AreaTypeGuidString);
|
|
} else {
|
|
fprintf (
|
|
OutFptr,
|
|
" { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",
|
|
Subregion->AreaTypeGuid.Data1,
|
|
(unsigned int) Subregion->AreaTypeGuid.Data2,
|
|
(unsigned int) Subregion->AreaTypeGuid.Data3,
|
|
(unsigned int) Subregion->AreaTypeGuid.Data4[0],
|
|
(unsigned int) Subregion->AreaTypeGuid.Data4[1],
|
|
(unsigned int) Subregion->AreaTypeGuid.Data4[2],
|
|
(unsigned int) Subregion->AreaTypeGuid.Data4[3],
|
|
(unsigned int) Subregion->AreaTypeGuid.Data4[4],
|
|
(unsigned int) Subregion->AreaTypeGuid.Data4[5],
|
|
(unsigned int) Subregion->AreaTypeGuid.Data4[6],
|
|
(unsigned int) Subregion->AreaTypeGuid.Data4[7]
|
|
);
|
|
}
|
|
|
|
fprintf (OutFptr, " 1,\\\n");
|
|
fprintf (OutFptr, " {{\\\n");
|
|
fprintf (OutFptr, " %s,\\\n", Subregion->Attributes);
|
|
fprintf (OutFptr, " 0,\\\n");
|
|
fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_BASE,\\\n", FBlock->Name, Subregion->Name);
|
|
fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_SIZE,\\\n", FBlock->Name, Subregion->Name);
|
|
//
|
|
// The FileSystemGuid may have been specified in the input flash definition file as a GUID, or
|
|
// as a quoted string. Do the right one.
|
|
//
|
|
if (Subregion->FileSystemGuidString[0] != 0) {
|
|
fprintf (OutFptr, " %s, \\\n", Subregion->FileSystemGuidString);
|
|
} else {
|
|
fprintf (
|
|
OutFptr,
|
|
" { 0x%08X, 0x%04X, 0x%04X, {0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}},\\\n",
|
|
Subregion->FileSystemGuid.Data1,
|
|
(unsigned int) Subregion->FileSystemGuid.Data2,
|
|
(unsigned int) Subregion->FileSystemGuid.Data3,
|
|
(unsigned int) Subregion->FileSystemGuid.Data4[0],
|
|
(unsigned int) Subregion->FileSystemGuid.Data4[1],
|
|
(unsigned int) Subregion->FileSystemGuid.Data4[2],
|
|
(unsigned int) Subregion->FileSystemGuid.Data4[3],
|
|
(unsigned int) Subregion->FileSystemGuid.Data4[4],
|
|
(unsigned int) Subregion->FileSystemGuid.Data4[5],
|
|
(unsigned int) Subregion->FileSystemGuid.Data4[6],
|
|
(unsigned int) Subregion->FileSystemGuid.Data4[7]
|
|
);
|
|
}
|
|
|
|
fprintf (OutFptr, " }},\\\n");
|
|
fprintf (OutFptr, " },");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf (OutFptr, "\n\n");
|
|
}
|
|
|
|
//
|
|
// Write the file's closing #endif
|
|
//
|
|
fprintf (OutFptr, CIncludeFooter);
|
|
fclose (OutFptr);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
STATUS
|
|
FDFCreateAsmIncludeFile (
|
|
char *FlashDeviceName,
|
|
char *FileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Create an assembly header file with equate definitions per an already-parsed
|
|
flash definition file.
|
|
|
|
Arguments:
|
|
FlashDeviceName - name of flash device (from the flash definition file)
|
|
to use
|
|
FileName - name of output file to create
|
|
|
|
Returns:
|
|
STATUS_SUCCESS - no errors or warnings
|
|
STATUS_WARNING - warnings, but no errors, were encountered
|
|
STATUS_ERROR - errors were encountered
|
|
|
|
--*/
|
|
{
|
|
FILE *OutFptr;
|
|
FLASH_BLOCK_DESCRIPTION *FBlock;
|
|
FLASH_DEVICE_DESCRIPTION *FDev;
|
|
unsigned int Offset;
|
|
FLASH_SUBREGION_DESCRIPTION *Subregion;
|
|
unsigned int SubregionOffset;
|
|
//
|
|
// Find the definition we're supposed to use
|
|
//
|
|
for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
|
|
if (strcmp (FDev->Name, FlashDeviceName) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (FDev == NULL) {
|
|
Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
|
|
return STATUS_ERROR;
|
|
}
|
|
|
|
if ((OutFptr = fopen (FileName, "w")) == NULL) {
|
|
Error (NULL, 0, 0, FileName, "failed to open output file for writing");
|
|
return STATUS_ERROR;
|
|
}
|
|
//
|
|
// Write a header
|
|
//
|
|
fprintf (OutFptr, "\n\n");
|
|
//
|
|
// Write flash block size and offset defines
|
|
//
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_BASE %*cequ 0%08Xh\n",
|
|
COLUMN2_START - 40,
|
|
' ',
|
|
FDev->BaseAddress
|
|
);
|
|
fprintf (OutFptr, "FLASH_SIZE %*cequ 0%08Xh\n", COLUMN2_START - 40, ' ', FDev->Size);
|
|
//
|
|
// Write flash region size and offset defines
|
|
//
|
|
fprintf (OutFptr, "\n");
|
|
Offset = 0;
|
|
for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_BASE %*cequ 0%08Xh\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 20 - strlen (FBlock->Name),
|
|
' ',
|
|
FDev->BaseAddress + Offset
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SIZE %*cequ 0%08Xh\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 20 - strlen (FBlock->Name),
|
|
' ',
|
|
FBlock->Size
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_OFFSET %*cequ 0%08Xh\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 20 - strlen (FBlock->Name),
|
|
' ',
|
|
Offset
|
|
);
|
|
//
|
|
// Create defines for any subregions
|
|
//
|
|
SubregionOffset = 0;
|
|
for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SUBREGION_%s_BASE %*cequ 0%08Xh\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
FDev->BaseAddress + Offset + SubregionOffset
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SUBREGION_%s_SIZE %*cequ 0%08Xh\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
Subregion->Size
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SUBREGION_%s_OFFSET %*cequ 0%08Xh\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
Offset + SubregionOffset
|
|
);
|
|
SubregionOffset += Subregion->Size;
|
|
}
|
|
|
|
Offset += FBlock->Size;
|
|
}
|
|
|
|
//
|
|
// Write closing \n
|
|
//
|
|
fprintf (OutFptr, "\n\n");
|
|
fclose (OutFptr);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
STATUS
|
|
FDFCreateSymbols (
|
|
char *FlashDeviceName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Using the given flash device name, add symbols to the global symbol table. This
|
|
allows other functions to use the symbol definitions for other purposes.
|
|
|
|
Arguments:
|
|
FlashDeviceName - name of flash device (from the flash definition file)
|
|
to use
|
|
|
|
Returns:
|
|
STATUS_SUCCESS - no errors or warnings
|
|
STATUS_WARNING - warnings, but no errors, were encountered
|
|
STATUS_ERROR - errors were encountered
|
|
|
|
--*/
|
|
{
|
|
FLASH_BLOCK_DESCRIPTION *FBlock;
|
|
FLASH_DEVICE_DESCRIPTION *FDev;
|
|
unsigned int Offset;
|
|
char SymName[120];
|
|
char SymValue[120];
|
|
FLASH_SUBREGION_DESCRIPTION *Subregion;
|
|
unsigned int SubregionOffset;
|
|
//
|
|
// Find the definition we're supposed to use
|
|
//
|
|
for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
|
|
if (strcmp (FDev->Name, FlashDeviceName) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (FDev == NULL) {
|
|
Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
|
|
return STATUS_ERROR;
|
|
}
|
|
|
|
sprintf (SymValue, "0x%08X", FDev->BaseAddress);
|
|
SymbolAdd ("FLASH_BASE", SymValue, 0);
|
|
sprintf (SymValue, "0x%08X", FDev->Size);
|
|
SymbolAdd ("FLASH_SIZE", SymValue, 0);
|
|
//
|
|
// Add flash block size and offset defines
|
|
//
|
|
// Offset = 0;
|
|
// for (FBlock = FDev->PBlocks; FBlock != NULL; FBlock = FBlock->Next) {
|
|
// sprintf (SymName, "FLASH_BLOCK_%s_BASE", FBlock->Name);
|
|
// sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);
|
|
// SymbolAdd (SymName, SymValue, 0);
|
|
// sprintf (SymName, "FLASH_BLOCK_%s_SIZE", FBlock->Name);
|
|
// sprintf (SymValue, "0x%08X", FBlock->Size);
|
|
// SymbolAdd (SymName, SymValue, 0);
|
|
// sprintf (SymName, "FLASH_BLOCK_%s_OFFSET", FBlock->Name);
|
|
// sprintf (SymValue, "0x%08X", Offset);
|
|
// SymbolAdd (SymName, SymValue, 0);
|
|
// Offset += FBlock->Size;
|
|
// }
|
|
//
|
|
// Add flash region block base, size, and offset defines
|
|
//
|
|
Offset = 0;
|
|
for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
|
|
sprintf (SymName, "FLASH_REGION_%s_BASE", FBlock->Name);
|
|
sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);
|
|
SymbolAdd (SymName, SymValue, 0);
|
|
sprintf (SymName, "FLASH_REGION_%s_SIZE", FBlock->Name);
|
|
sprintf (SymValue, "0x%08X", FBlock->Size);
|
|
SymbolAdd (SymName, SymValue, 0);
|
|
sprintf (SymName, "FLASH_REGION_%s_OFFSET", FBlock->Name);
|
|
sprintf (SymValue, "0x%08X", Offset);
|
|
SymbolAdd (SymName, SymValue, 0);
|
|
//
|
|
// Add subregion symbols
|
|
//
|
|
if (FBlock->Subregions != NULL) {
|
|
SubregionOffset = 0;
|
|
for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
|
|
sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_BASE", FBlock->Name, Subregion->Name);
|
|
sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset + SubregionOffset);
|
|
SymbolAdd (SymName, SymValue, 0);
|
|
sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_SIZE", FBlock->Name, Subregion->Name);
|
|
sprintf (SymValue, "0x%08X", Subregion->Size);
|
|
SymbolAdd (SymName, SymValue, 0);
|
|
sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_OFFSET", FBlock->Name, Subregion->Name);
|
|
sprintf (SymValue, "0x%08X", Offset + SubregionOffset);
|
|
SymbolAdd (SymName, SymValue, 0);
|
|
SubregionOffset += Subregion->Size;
|
|
}
|
|
}
|
|
|
|
Offset += FBlock->Size;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
STATUS
|
|
FDFCreateImage (
|
|
char *FlashDeviceName,
|
|
char *ImageName,
|
|
char *FileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Create a flash image using the given device and image names.
|
|
|
|
Arguments:
|
|
FlashDeviceName - name of flash device (from the flash definition file)
|
|
to use
|
|
ImageName - name of image (from the flash definition file) to create
|
|
FileName - name of output file to create
|
|
|
|
Returns:
|
|
STATUS_SUCCESS - no errors or warnings
|
|
STATUS_WARNING - warnings, but no errors, were encountered
|
|
STATUS_ERROR - errors were encountered
|
|
|
|
--*/
|
|
{
|
|
STATUS Status;
|
|
FILE *OutFptr;
|
|
FLASH_BLOCK_DESCRIPTION *RegionDef;
|
|
FLASH_DEVICE_DESCRIPTION *FDev;
|
|
IMAGE_DEFINITION *ImageDef;
|
|
unsigned int Offset;
|
|
char *Buffer;
|
|
FILE *InFptr;
|
|
long FileSize;
|
|
IMAGE_DEFINITION_ENTRY *IDefEntry;
|
|
FLASH_SUBREGION_DESCRIPTION *SubregionDef;
|
|
//
|
|
// Find the flash definition we're supposed to use
|
|
//
|
|
InFptr = NULL;
|
|
Status = STATUS_ERROR;
|
|
for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
|
|
if (strcmp (FDev->Name, FlashDeviceName) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (FDev == NULL) {
|
|
Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");
|
|
return STATUS_ERROR;
|
|
}
|
|
//
|
|
// Find the image name we're supposed to create
|
|
//
|
|
for (ImageDef = mImageDefinitions; ImageDef != NULL; ImageDef = ImageDef->Next) {
|
|
if (strcmp (ImageDef->Name, ImageName) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ImageDef == NULL) {
|
|
Error (NULL, 0, 0, ImageName, "image definition not found in image definitions");
|
|
return STATUS_ERROR;
|
|
}
|
|
//
|
|
// Open the output file
|
|
//
|
|
if ((OutFptr = fopen (FileName, "wb")) == NULL) {
|
|
Error (NULL, 0, 0, FileName, "failed to open output file for writing");
|
|
return STATUS_ERROR;
|
|
}
|
|
//
|
|
// Allocate a buffer to copy the input data to
|
|
//
|
|
Buffer = (char *) _malloc (FDev->Size);
|
|
if (Buffer == NULL) {
|
|
Error (NULL, 0, 0, (INT8 *) "failed to allocate memory", NULL);
|
|
goto Done;
|
|
}
|
|
//
|
|
// Set contents of buffer to the erased value
|
|
//
|
|
if (FDev->ErasePolarity) {
|
|
memset (Buffer, 0xFF, FDev->Size);
|
|
} else {
|
|
memset (Buffer, 0, FDev->Size);
|
|
}
|
|
//
|
|
// Set all region and subregion size-left fields to the size of the region/subregion
|
|
//
|
|
for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {
|
|
RegionDef->SizeLeft = RegionDef->Size;
|
|
for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {
|
|
SubregionDef->SizeLeft = SubregionDef->Size;
|
|
}
|
|
}
|
|
//
|
|
// Now go through the image list, read files into the buffer.
|
|
//
|
|
for (IDefEntry = ImageDef->Entries; IDefEntry != NULL; IDefEntry = IDefEntry->Next) {
|
|
//
|
|
// If it's a file name, open the file, get the size, find the corresponding
|
|
// flash region it's in, and copy the data.
|
|
//
|
|
if (IDefEntry->IsRawData == 0) {
|
|
if ((InFptr = fopen (IDefEntry->Name, "rb")) == NULL) {
|
|
Error (NULL, 0, 0, IDefEntry->Name, "failed to open input file for reading");
|
|
goto Done;
|
|
}
|
|
|
|
fseek (InFptr, 0, SEEK_END);
|
|
FileSize = ftell (InFptr);
|
|
fseek (InFptr, 0, SEEK_SET);
|
|
} else {
|
|
FileSize = IDefEntry->RawDataSize;
|
|
}
|
|
//
|
|
// Find the region/subregion it's in, see if we have space left
|
|
//
|
|
Offset = 0;
|
|
for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {
|
|
if (strcmp (RegionDef->Name, IDefEntry->RegionName) == 0) {
|
|
break;
|
|
}
|
|
|
|
Offset += RegionDef->Size;
|
|
}
|
|
|
|
if (RegionDef == NULL) {
|
|
Error (NULL, 0, 0, IDefEntry->RegionName, "Region name not found in FlashDevice %s definition", FDev->Name);
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Check for subregion
|
|
//
|
|
if (IDefEntry->SubregionName[0] != 0) {
|
|
for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {
|
|
if (strcmp (SubregionDef->Name, IDefEntry->SubregionName) == 0) {
|
|
break;
|
|
}
|
|
|
|
Offset += SubregionDef->Size;
|
|
}
|
|
|
|
if (SubregionDef == NULL) {
|
|
Error (
|
|
NULL,
|
|
0,
|
|
0,
|
|
IDefEntry->SubregionName,
|
|
"Subregion name not found in FlashDevice %s.%s Region definition",
|
|
FDev->Name,
|
|
RegionDef->Name
|
|
);
|
|
goto Done;
|
|
}
|
|
//
|
|
// Enough space in the subregion?
|
|
//
|
|
if (SubregionDef->SizeLeft < (unsigned int) FileSize) {
|
|
Error (
|
|
NULL,
|
|
0,
|
|
0,
|
|
IDefEntry->Name,
|
|
"insufficient space in Subregion (at least 0x%X additional bytes required)",
|
|
FileSize - SubregionDef->SizeLeft
|
|
);
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Read the file into the buffer if it's a file. Otherwise copy the raw data
|
|
//
|
|
if (IDefEntry->IsRawData == 0) {
|
|
if (fread (Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft), FileSize, 1, InFptr) != 1) {
|
|
Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");
|
|
goto Done;
|
|
}
|
|
|
|
fclose (InFptr);
|
|
InFptr = NULL;
|
|
} else {
|
|
memcpy (
|
|
Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft),
|
|
IDefEntry->RawData,
|
|
IDefEntry->RawDataSize
|
|
);
|
|
}
|
|
|
|
SubregionDef->SizeLeft -= FileSize;
|
|
//
|
|
// Align based on the Region alignment requirements.
|
|
//
|
|
if (RegionDef->Alignment != 0) {
|
|
while (((unsigned int) (SubregionDef->Size - SubregionDef->SizeLeft) &~RegionDef->Alignment) != 0) {
|
|
if (SubregionDef->SizeLeft == 0) {
|
|
break;
|
|
}
|
|
|
|
SubregionDef->SizeLeft--;
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// Placing data in a region. Check for enough space in the region left.
|
|
//
|
|
if (RegionDef->SizeLeft < (unsigned int) FileSize) {
|
|
Error (
|
|
NULL,
|
|
0,
|
|
0,
|
|
IDefEntry->Name,
|
|
"insufficient space in Region (at least 0x%X additional bytes required)",
|
|
FileSize - RegionDef->SizeLeft
|
|
);
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Read the file into the buffer if it's a file. Otherwise copy the raw data
|
|
//
|
|
if (IDefEntry->IsRawData == 0) {
|
|
if (fread (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), FileSize, 1, InFptr) != 1) {
|
|
Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");
|
|
goto Done;
|
|
}
|
|
|
|
fclose (InFptr);
|
|
InFptr = NULL;
|
|
} else {
|
|
memcpy (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), IDefEntry->RawData, IDefEntry->RawDataSize);
|
|
}
|
|
|
|
RegionDef->SizeLeft -= FileSize;
|
|
//
|
|
// Align
|
|
//
|
|
if (RegionDef->Alignment != 0) {
|
|
while (((unsigned int) (RegionDef->Size - RegionDef->SizeLeft) &~RegionDef->Alignment) != 0) {
|
|
if (RegionDef->SizeLeft == 0) {
|
|
break;
|
|
}
|
|
|
|
RegionDef->SizeLeft--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fwrite (Buffer, FDev->Size, 1, OutFptr) != 1) {
|
|
Error (NULL, 0, 0, "failed to write buffer contents to output file", NULL);
|
|
goto Done;
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
Done:
|
|
if (InFptr != NULL) {
|
|
fclose (InFptr);
|
|
}
|
|
|
|
if (Buffer != NULL) {
|
|
_free (Buffer);
|
|
}
|
|
|
|
if (OutFptr != NULL) {
|
|
fclose (OutFptr);
|
|
if (Status == STATUS_ERROR) {
|
|
remove (FileName);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATUS
|
|
FDFCreateDscFile (
|
|
char *FlashDeviceName,
|
|
char *FileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Create a DSC-style output file with equates for flash management.
|
|
|
|
Arguments:
|
|
FlashDeviceName - name of flash device (from the flash definition file)
|
|
to use
|
|
FileName - name of output file to create
|
|
|
|
Returns:
|
|
STATUS_SUCCESS - no errors or warnings
|
|
STATUS_WARNING - warnings, but no errors, were encountered
|
|
STATUS_ERROR - errors were encountered
|
|
|
|
--*/
|
|
{
|
|
FILE *OutFptr;
|
|
FLASH_BLOCK_DESCRIPTION *FBlock;
|
|
FLASH_DEVICE_DESCRIPTION *FDev;
|
|
unsigned int Offset;
|
|
FLASH_SUBREGION_DESCRIPTION *Subregion;
|
|
unsigned int SubregionOffset;
|
|
//
|
|
// Find the definition we're supposed to use
|
|
//
|
|
for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
|
|
if (strcmp (FDev->Name, FlashDeviceName) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (FDev == NULL) {
|
|
Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");
|
|
return STATUS_ERROR;
|
|
}
|
|
|
|
if ((OutFptr = fopen (FileName, "w")) == NULL) {
|
|
Error (NULL, 0, 0, FileName, "failed to open output file for writing");
|
|
return STATUS_ERROR;
|
|
}
|
|
//
|
|
// Write the flash base address and size
|
|
//
|
|
fprintf (OutFptr, "\n");
|
|
fprintf (OutFptr, "FLASH_BASE = 0x%08X\n", FDev->BaseAddress);
|
|
fprintf (OutFptr, "FLASH_SIZE = 0x%08X\n\n", FDev->Size);
|
|
//
|
|
// Write flash block size and offset defines
|
|
//
|
|
Offset = 0;
|
|
for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_BASE %*c= 0x%08X\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 40 - strlen (FBlock->Name),
|
|
' ',
|
|
Offset + FDev->BaseAddress
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SIZE %*c= 0x%08X\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 40 - strlen (FBlock->Name),
|
|
' ',
|
|
FBlock->Size
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SIZE_BLOCKS %*c= 0x%x\n",
|
|
FBlock->Name,
|
|
COLUMN2_START - 40 - strlen (FBlock->Name),
|
|
' ',
|
|
(FBlock->Size)/(FDev->PBlocks->Size)
|
|
);
|
|
//
|
|
// Create defines for any subregions
|
|
//
|
|
SubregionOffset = 0;
|
|
for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SUBREGION_%s_BASE %*c= 0x%08X\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
FDev->BaseAddress + Offset + SubregionOffset
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SUBREGION_%s_SIZE %*c= 0x%08X\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
Subregion->Size
|
|
);
|
|
fprintf (
|
|
OutFptr,
|
|
"FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c= 0x%08X\n",
|
|
FBlock->Name,
|
|
Subregion->Name,
|
|
COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
|
|
' ',
|
|
Offset + SubregionOffset
|
|
);
|
|
|
|
SubregionOffset += Subregion->Size;
|
|
}
|
|
|
|
Offset += FBlock->Size;
|
|
}
|
|
//
|
|
// Close file
|
|
//
|
|
fprintf (OutFptr, "\n");
|
|
fclose (OutFptr);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
The following buffer management routines are used to encapsulate functionality
|
|
for managing a growable data buffer.
|
|
|
|
Arguments:
|
|
BUFFER_DATA - structure that is used to maintain a data buffer
|
|
|
|
Returns:
|
|
NA
|
|
|
|
--*/
|
|
static
|
|
BUFFER_DATA *
|
|
CreateBufferData (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a growable data buffer with default buffer length.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
NULL - error occured during data buffer creation
|
|
Not NULL - the pointer to the newly created data buffer
|
|
|
|
--*/
|
|
{
|
|
BUFFER_DATA *BD;
|
|
BD = (BUFFER_DATA *) _malloc (sizeof (BUFFER_DATA));
|
|
if (BD == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
return NULL;
|
|
}
|
|
|
|
memset (BD, 0, sizeof (BUFFER_DATA));
|
|
BD->BufferStart = (char *) _malloc (BUFFER_SIZE);
|
|
if (BD->BufferStart == NULL) {
|
|
_free (BD);
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
return NULL;
|
|
}
|
|
|
|
BD->BufferEnd = BD->BufferStart + BUFFER_SIZE;
|
|
BD->BufferPos = BD->BufferStart;
|
|
return BD;
|
|
}
|
|
|
|
static
|
|
BOOLEAN
|
|
AddBufferDataByte (
|
|
BUFFER_DATA *Buffer,
|
|
char Data
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add a single byte to a growable data buffer, growing the buffer if required.
|
|
|
|
Arguments:
|
|
|
|
Buffer - pointer to the growable data buffer to add a single byte to
|
|
Data - value of the single byte data to be added
|
|
|
|
Returns:
|
|
|
|
TRUE - the single byte data was successfully added
|
|
FALSE - error occurred, the single byte data was not added
|
|
|
|
--*/
|
|
{
|
|
int Size;
|
|
char *NewBuffer;
|
|
//
|
|
// See if we have to grow the buffer
|
|
//
|
|
if (Buffer->BufferPos >= Buffer->BufferEnd) {
|
|
Size = (int) Buffer->BufferEnd - (int) Buffer->BufferStart;
|
|
NewBuffer = (char *) _malloc (Size + BUFFER_SIZE);
|
|
if (NewBuffer == NULL) {
|
|
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
|
|
return FALSE;
|
|
}
|
|
|
|
memcpy (NewBuffer, Buffer->BufferStart, Size);
|
|
_free (Buffer->BufferStart);
|
|
Buffer->BufferStart = NewBuffer;
|
|
Buffer->BufferPos = Buffer->BufferStart + Size;
|
|
Buffer->BufferEnd = Buffer->BufferStart + Size + BUFFER_SIZE;
|
|
}
|
|
|
|
*Buffer->BufferPos = Data;
|
|
Buffer->BufferPos++;
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
void
|
|
FreeBufferData (
|
|
BUFFER_DATA *Buffer,
|
|
BOOLEAN FreeData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free memory used to manage a growable data buffer.
|
|
|
|
Arguments:
|
|
|
|
Buffer - pointer to the growable data buffer to be destructed
|
|
FreeData - TRUE, free memory containing the buffered data
|
|
FALSE, do not free the buffered data memory
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if (Buffer != NULL) {
|
|
if (FreeData && (Buffer->BufferStart != NULL)) {
|
|
_free (Buffer->BufferStart);
|
|
}
|
|
|
|
_free (Buffer);
|
|
}
|
|
}
|
|
|
|
static
|
|
char *
|
|
GetBufferData (
|
|
BUFFER_DATA *Buffer,
|
|
int *BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return a pointer and size of the data in a growable data buffer.
|
|
|
|
Arguments:
|
|
|
|
Buffer - pointer to the growable data buffer
|
|
BufferSize - size of the data in the growable data buffer
|
|
|
|
Returns:
|
|
|
|
pointer of the data in the growable data buffer
|
|
|
|
--*/
|
|
{
|
|
*BufferSize = (int) Buffer->BufferPos - (int) Buffer->BufferStart;
|
|
return Buffer->BufferStart;
|
|
}
|
|
|
|
STATUS
|
|
FDDiscover (
|
|
char *FDFileName,
|
|
unsigned int BaseAddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Walk a binary image and see if you find anything that looks like a
|
|
firmware volume.
|
|
|
|
Arguments:
|
|
FDFileName - name of input FD image to parse
|
|
BaseAddr - base address of input FD image
|
|
|
|
Returns:
|
|
STATUS_SUCCESS - no errors or warnings
|
|
STATUS_WARNING - warnings, but no errors, were encountered
|
|
STATUS_ERROR - errors were encountered
|
|
|
|
NOTE:
|
|
This routine is used for debug purposes only.
|
|
|
|
--*/
|
|
{
|
|
FILE *InFptr;
|
|
long FileSize;
|
|
long Offset;
|
|
EFI_FIRMWARE_VOLUME_HEADER FVHeader;
|
|
EFI_GUID
|
|
FileSystemGuid = { 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF };
|
|
|
|
if ((InFptr = fopen (FDFileName, "rb")) == NULL) {
|
|
Error (NULL, 0, 0, FDFileName, "failed to open file for reading");
|
|
return STATUS_ERROR;
|
|
}
|
|
|
|
fseek (InFptr, 0, SEEK_END);
|
|
FileSize = ftell (InFptr);
|
|
fseek (InFptr, 0, SEEK_SET);
|
|
Offset = 0;
|
|
while (Offset < FileSize) {
|
|
fseek (InFptr, Offset, SEEK_SET);
|
|
//
|
|
// Read the contents of the file, see if it's an FV header
|
|
//
|
|
if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) == 1) {
|
|
//
|
|
// Check version and GUID
|
|
//
|
|
if ((FVHeader.Revision == EFI_FVH_REVISION) && (FVHeader.Signature == EFI_FVH_SIGNATURE)) {
|
|
fprintf (stdout, "FV header at 0x%08X FVSize=0x%08X ", Offset + BaseAddr, (UINT32) FVHeader.FvLength);
|
|
if (memcmp (&FVHeader.FileSystemGuid, &FileSystemGuid, sizeof (EFI_GUID)) == 0) {
|
|
fprintf (stdout, "standard FFS file system\n");
|
|
} else {
|
|
fprintf (stdout, "non-standard FFS file system\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
Offset += 16 * 1024;
|
|
}
|
|
|
|
fclose (InFptr);
|
|
return STATUS_SUCCESS;
|
|
}
|