2010-09-06 04:01:57 +02:00
## @file
# This file include GenVpd class for fix the Vpd type PCD offset, and PcdEntry for describe
# and process each entry of vpd type PCD.
#
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
#
# 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.
#
import os
import StringIO
import StringTable as st
import array
2010-11-15 03:51:34 +01:00
import re
2010-09-06 04:01:57 +02:00
from struct import *
import Common . EdkLogger as EdkLogger
import Common . BuildToolError as BuildToolError
_FORMAT_CHAR = { 1 : ' B ' ,
2 : ' H ' ,
4 : ' I ' ,
8 : ' Q '
}
2010-10-11 08:26:52 +02:00
## The VPD PCD data structure for store and process each VPD PCD entry.
#
# This class contain method to format and pack pcd's value.
#
2010-09-06 04:01:57 +02:00
class PcdEntry :
def __init__ ( self , PcdCName , PcdOffset , PcdSize , PcdValue , Lineno = None , FileName = None , PcdUnpackValue = None ,
PcdBinOffset = None , PcdBinSize = None ) :
self . PcdCName = PcdCName . strip ( )
self . PcdOffset = PcdOffset . strip ( )
self . PcdSize = PcdSize . strip ( )
self . PcdValue = PcdValue . strip ( )
self . Lineno = Lineno . strip ( )
self . FileName = FileName . strip ( )
self . PcdUnpackValue = PcdUnpackValue
self . PcdBinOffset = PcdBinOffset
self . PcdBinSize = PcdBinSize
if self . PcdValue == ' ' :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid PCD format(Name: %s File: %s line: %s ) , no Value specified! " % ( self . PcdCName , self . FileName , self . Lineno ) )
if self . PcdOffset == ' ' :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid PCD format(Name: %s File: %s Line: %s ) , no Offset specified! " % ( self . PcdCName , self . FileName , self . Lineno ) )
if self . PcdSize == ' ' :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid PCD format(Name: %s File: %s Line: %s ), no PcdSize specified! " % ( self . PcdCName , self . FileName , self . Lineno ) )
self . _GenOffsetValue ( )
2010-10-11 08:26:52 +02:00
## Analyze the string value to judge the PCD's datum type euqal to Boolean or not.
#
# @param ValueString PCD's value
# @param Size PCD's size
#
# @retval True PCD's datum type is Boolean
# @retval False PCD's datum type is not Boolean.
#
def _IsBoolean ( self , ValueString , Size ) :
if ( Size == " 1 " ) :
if ValueString . upper ( ) in [ " TRUE " , " FALSE " ] :
return True
elif ValueString in [ " 0 " , " 1 " , " 0x0 " , " 0x1 " , " 0x00 " , " 0x01 " ] :
return True
2010-09-06 04:01:57 +02:00
return False
2010-10-11 08:26:52 +02:00
## Convert the PCD's value from string to integer.
#
# This function will try to convert the Offset value form string to integer
# for both hexadecimal and decimal.
#
2010-09-06 04:01:57 +02:00
def _GenOffsetValue ( self ) :
if self . PcdOffset != " * " :
try :
self . PcdBinOffset = int ( self . PcdOffset )
except :
try :
self . PcdBinOffset = int ( self . PcdOffset , 16 )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid offset value %s for PCD %s (File: %s Line: %s ) " % ( self . PcdOffset , self . PcdCName , self . FileName , self . Lineno ) )
2010-10-11 08:26:52 +02:00
## Pack Boolean type VPD PCD's value form string to binary type.
#
# @param ValueString The boolean type string for pack.
#
#
2010-09-06 04:01:57 +02:00
def _PackBooleanValue ( self , ValueString ) :
2010-10-11 08:26:52 +02:00
if ValueString . upper ( ) == " TRUE " or ValueString in [ " 1 " , " 0x1 " , " 0x01 " ] :
2010-09-06 04:01:57 +02:00
try :
self . PcdValue = pack ( _FORMAT_CHAR [ 1 ] , 1 )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid size or value for PCD %s to pack(File: %s Line: %s ). " % ( self . PcdCName , self . FileName , self . Lineno ) )
else :
try :
self . PcdValue = pack ( _FORMAT_CHAR [ 1 ] , 0 )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
2010-10-11 08:26:52 +02:00
" Invalid size or value for PCD %s to pack(File: %s Line: %s ). " % ( self . PcdCName , self . FileName , self . Lineno ) )
## Pack Integer type VPD PCD's value form string to binary type.
#
# @param ValueString The Integer type string for pack.
#
#
2010-09-06 04:01:57 +02:00
def _PackIntValue ( self , IntValue , Size ) :
if Size not in _FORMAT_CHAR . keys ( ) :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid size %d for PCD %s in integer datum size(File: %s Line: %s ). " % ( Size , self . PcdCName , self . FileName , self . Lineno ) )
2010-10-11 08:26:52 +02:00
if Size == 1 :
if IntValue < 0 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" PCD can ' t be set to negative value %d for PCD %s in UINT8 datum type(File: %s Line: %s ). " % ( IntValue , self . PcdCName , self . FileName , self . Lineno ) )
elif IntValue > = 0x100 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Too large PCD value %d for datum type UINT8 for PCD %s (File: %s Line: %s ). " % ( IntValue , self . PcdCName , self . FileName , self . Lineno ) )
elif Size == 2 :
if IntValue < 0 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" PCD can ' t be set to negative value %d for PCD %s in UINT16 datum type(File: %s Line: %s ). " % ( IntValue , self . PcdCName , self . FileName , self . Lineno ) )
elif IntValue > = 0x10000 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Too large PCD value %d for datum type UINT16 for PCD %s (File: %s Line: %s ). " % ( IntValue , self . PcdCName , self . FileName , self . Lineno ) )
elif Size == 4 :
if IntValue < 0 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" PCD can ' t be set to negative value %d for PCD %s in UINT32 datum type(File: %s Line: %s ). " % ( IntValue , self . PcdCName , self . FileName , self . Lineno ) )
elif IntValue > = 0x100000000 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Too large PCD value %d for datum type UINT32 for PCD %s (File: %s Line: %s ). " % ( IntValue , self . PcdCName , self . FileName , self . Lineno ) )
elif Size == 8 :
if IntValue < 0 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" PCD can ' t be set to negative value %d for PCD %s in UINT32 datum type(File: %s Line: %s ). " % ( IntValue , self . PcdCName , self . FileName , self . Lineno ) )
elif IntValue > = 0x10000000000000000 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Too large PCD value %d for datum type UINT32 for PCD %s (File: %s Line: %s ). " % ( IntValue , self . PcdCName , self . FileName , self . Lineno ) )
else :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid size %d for PCD %s in integer datum size(File: %s Line: %s ). " % ( Size , self . PcdCName , self . FileName , self . Lineno ) )
2010-09-06 04:01:57 +02:00
try :
self . PcdValue = pack ( _FORMAT_CHAR [ Size ] , IntValue )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid size or value for PCD %s to pack(File: %s Line: %s ). " % ( self . PcdCName , self . FileName , self . Lineno ) )
2010-10-11 08:26:52 +02:00
## Pack VOID* type VPD PCD's value form string to binary type.
#
# The VOID* type of string divided into 3 sub-type:
# 1: L"String", Unicode type string.
# 2: "String", Ascii type string.
# 3: {bytearray}, only support byte-array.
#
# @param ValueString The Integer type string for pack.
#
2010-09-06 04:01:57 +02:00
def _PackPtrValue ( self , ValueString , Size ) :
if ValueString . startswith ( ' L " ' ) :
self . _PackUnicode ( ValueString , Size )
elif ValueString . startswith ( ' { ' ) and ValueString . endswith ( ' } ' ) :
self . _PackByteArray ( ValueString , Size )
elif ValueString . startswith ( ' " ' ) and ValueString . endswith ( ' " ' ) :
self . _PackString ( ValueString , Size )
else :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid VOID* type PCD %s value %s (File: %s Line: %s ) " % ( self . PcdCName , ValueString , self . FileName , self . Lineno ) )
2010-10-11 08:26:52 +02:00
## Pack an Ascii PCD value.
#
# An Ascii string for a PCD should be in format as "".
#
2010-09-06 04:01:57 +02:00
def _PackString ( self , ValueString , Size ) :
if ( Size < 0 ) :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid parameter Size %s of PCD %s !(File: %s Line: %s ) " % ( self . PcdBinSize , self . PcdCName , self . FileName , self . Lineno ) )
if ( ValueString == " " ) :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID , " Invalid parameter ValueString %s of PCD %s !(File: %s Line: %s ) " % ( self . PcdUnpackValue , self . PcdCName , self . FileName , self . Lineno ) )
if ( len ( ValueString ) < 2 ) :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID , " For PCD: %s ,ASCII string %s at least contains two!(File: %s Line: %s ) " % ( self . PcdCName , self . PcdUnpackValue , self . FileName , self . Lineno ) )
ValueString = ValueString [ 1 : - 1 ]
if len ( ValueString ) + 1 > Size :
EdkLogger . error ( " BPDG " , BuildToolError . RESOURCE_OVERFLOW ,
" PCD value string %s is exceed to size %d (File: %s Line: %s ) " % ( ValueString , Size , self . FileName , self . Lineno ) )
try :
self . PcdValue = pack ( ' %d s ' % Size , ValueString )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
2010-10-11 08:26:52 +02:00
" Invalid size or value for PCD %s to pack(File: %s Line: %s ). " % ( self . PcdCName , self . FileName , self . Lineno ) )
## Pack a byte-array PCD value.
#
# A byte-array for a PCD should be in format as {0x01, 0x02, ...}.
#
2010-09-06 04:01:57 +02:00
def _PackByteArray ( self , ValueString , Size ) :
if ( Size < 0 ) :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID , " Invalid parameter Size %s of PCD %s !(File: %s Line: %s ) " % ( self . PcdBinSize , self . PcdCName , self . FileName , self . Lineno ) )
if ( ValueString == " " ) :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID , " Invalid parameter ValueString %s of PCD %s !(File: %s Line: %s ) " % ( self . PcdUnpackValue , self . PcdCName , self . FileName , self . Lineno ) )
ValueString = ValueString . strip ( )
ValueString = ValueString . lstrip ( ' { ' ) . strip ( ' } ' )
ValueList = ValueString . split ( ' , ' )
ValueList = [ item . strip ( ) for item in ValueList ]
if len ( ValueList ) > Size :
EdkLogger . error ( " BPDG " , BuildToolError . RESOURCE_OVERFLOW ,
" The byte array %s is too large for size %d (File: %s Line: %s ) " % ( ValueString , Size , self . FileName , self . Lineno ) )
ReturnArray = array . array ( ' B ' )
for Index in xrange ( len ( ValueList ) ) :
Value = None
if ValueList [ Index ] . startswith ( ' 0x ' ) :
# translate hex value
try :
Value = int ( ValueList [ Index ] , 16 )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" The value item %s in byte array %s is an invalid HEX value.(File: %s Line: %s ) " % \
( ValueList [ Index ] , ValueString , self . FileName , self . Lineno ) )
else :
# translate decimal value
try :
Value = int ( ValueList [ Index ] , 10 )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" The value item %s in byte array %s is an invalid DECIMAL value.(File: %s Line: %s ) " % \
( ValueList [ Index ] , ValueString , self . FileName , self . Lineno ) )
if Value > 255 :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" The value item %s in byte array %s do not in range 0 ~ 0xFF(File: %s Line: %s ) " % \
( ValueList [ Index ] , ValueString , self . FileName , self . Lineno ) )
ReturnArray . append ( Value )
for Index in xrange ( len ( ValueList ) , Size ) :
ReturnArray . append ( 0 )
self . PcdValue = ReturnArray . tolist ( )
## Pack a unicode PCD value into byte array.
#
# A unicode string for a PCD should be in format as L"".
#
def _PackUnicode ( self , UnicodeString , Size ) :
if ( Size < 0 ) :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID , " Invalid parameter Size %s of PCD %s !(File: %s Line: %s ) " % \
( self . PcdBinSize , self . PcdCName , self . FileName , self . Lineno ) )
if ( len ( UnicodeString ) < 3 ) :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID , " For PCD: %s ,ASCII string %s at least contains two!(File: %s Line: %s ) " % \
( self . PcdCName , self . PcdUnpackValue , self . FileName , self . Lineno ) )
UnicodeString = UnicodeString [ 2 : - 1 ]
if ( len ( UnicodeString ) + 1 ) * 2 > Size :
EdkLogger . error ( " BPDG " , BuildToolError . RESOURCE_OVERFLOW ,
" The size of unicode string %s is too larger for size %s (File: %s Line: %s ) " % \
( UnicodeString , Size , self . FileName , self . Lineno ) )
ReturnArray = array . array ( ' B ' )
for Value in UnicodeString :
try :
ReturnArray . append ( ord ( Value ) )
ReturnArray . append ( 0 )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID ,
" Invalid unicode character %s in unicode string %s (File: %s Line: %s ) " % \
( Value , UnicodeString , self . FileName , self . Lineno ) )
for Index in range ( len ( UnicodeString ) * 2 , Size ) :
ReturnArray . append ( 0 )
self . PcdValue = ReturnArray . tolist ( )
2010-10-11 08:26:52 +02:00
## The class implementing the BPDG VPD PCD offset fix process
#
# The VPD PCD offset fix process includes:
# 1. Parse the input guided.txt file and store it in the data structure;
# 2. Format the input file data to remove unused lines;
# 3. Fixed offset if needed;
# 4. Generate output file, including guided.map and guided.bin file;
#
class GenVPD :
2010-09-06 04:01:57 +02:00
## Constructor of DscBuildData
#
# Initialize object of GenVPD
# @Param InputFileName The filename include the vpd type pcd information
# @param MapFileName The filename of map file that stores vpd type pcd information.
# This file will be generated by the BPDG tool after fix the offset
# and adjust the offset to make the pcd data aligned.
# @param VpdFileName The filename of Vpd file that hold vpd pcd information.
#
def __init__ ( self , InputFileName , MapFileName , VpdFileName ) :
self . InputFileName = InputFileName
self . MapFileName = MapFileName
self . VpdFileName = VpdFileName
self . FileLinesList = [ ]
self . PcdFixedOffsetSizeList = [ ]
self . PcdUnknownOffsetList = [ ]
try :
fInputfile = open ( InputFileName , " r " , 0 )
try :
self . FileLinesList = fInputfile . readlines ( )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FILE_READ_FAILURE , " File read failed for %s " % InputFileName , None )
finally :
fInputfile . close ( )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FILE_OPEN_FAILURE , " File open failed for %s " % InputFileName , None )
##
# Parser the input file which is generated by the build tool. Convert the value of each pcd's
# from string to it's real format. Also remove the useless line in the input file.
#
def ParserInputFile ( self ) :
count = 0
for line in self . FileLinesList :
# Strip "\r\n" generated by readlines ().
line = line . strip ( )
line = line . rstrip ( os . linesep )
# Skip the comment line
2010-11-15 03:51:34 +01:00
if ( not line . startswith ( " # " ) ) and len ( line ) > 1 :
#
# Enhanced for support "|" character in the string.
#
ValueList = [ ' ' , ' ' , ' ' , ' ' ]
ValueRe = re . compile ( r ' \ s*L? \ " .* \ |.* \ " \ s*$ ' )
PtrValue = ValueRe . findall ( line )
ValueUpdateFlag = False
if len ( PtrValue ) > = 1 :
line = re . sub ( ValueRe , ' ' , line )
ValueUpdateFlag = True
TokenList = line . split ( ' | ' )
ValueList [ 0 : len ( TokenList ) ] = TokenList
if ValueUpdateFlag :
ValueList [ 3 ] = PtrValue [ 0 ]
self . FileLinesList [ count ] = ValueList
2010-09-06 04:01:57 +02:00
# Store the line number
self . FileLinesList [ count ] . append ( str ( count + 1 ) )
elif len ( line ) < = 1 :
# Set the blank line to "None"
self . FileLinesList [ count ] = None
else :
# Set the comment line to "None"
self . FileLinesList [ count ] = None
count + = 1
# The line count contain usage information
count = 0
# Delete useless lines
while ( True ) :
try :
if ( self . FileLinesList [ count ] == None ) :
del ( self . FileLinesList [ count ] )
else :
count + = 1
except :
break
#
# After remove the useless line, if there are no data remain in the file line list,
# Report warning messages to user's.
#
if len ( self . FileLinesList ) == 0 :
EdkLogger . warn ( ' BPDG ' , BuildToolError . RESOURCE_NOT_AVAILABLE ,
" There are no VPD type pcds defined in DSC file, Please check it. " )
# Process the pcds one by one base on the pcd's value and size
count = 0
for line in self . FileLinesList :
if line != None :
PCD = PcdEntry ( line [ 0 ] , line [ 1 ] , line [ 2 ] , line [ 3 ] , line [ 4 ] , self . InputFileName )
# Strip the space char
PCD . PcdCName = PCD . PcdCName . strip ( ' ' )
PCD . PcdOffset = PCD . PcdOffset . strip ( ' ' )
PCD . PcdSize = PCD . PcdSize . strip ( ' ' )
PCD . PcdValue = PCD . PcdValue . strip ( ' ' )
PCD . Lineno = PCD . Lineno . strip ( ' ' )
#
# Store the original pcd value.
# This information will be useful while generate the output map file.
#
PCD . PcdUnpackValue = str ( PCD . PcdValue )
#
# Translate PCD size string to an integer value.
PackSize = None
try :
PackSize = int ( PCD . PcdSize , 10 )
PCD . PcdBinSize = PackSize
except :
try :
PackSize = int ( PCD . PcdSize , 16 )
PCD . PcdBinSize = PackSize
except :
EdkLogger . error ( " BPDG " , BuildToolError . FORMAT_INVALID , " Invalid PCD size value %s at file: %s line: %s " % ( PCD . PcdSize , self . InputFileName , PCD . Lineno ) )
2010-10-11 08:26:52 +02:00
if PCD . _IsBoolean ( PCD . PcdValue , PCD . PcdSize ) :
2010-09-06 04:01:57 +02:00
PCD . _PackBooleanValue ( PCD . PcdValue )
self . FileLinesList [ count ] = PCD
count + = 1
continue
#
# Try to translate value to an integer firstly.
#
IsInteger = True
PackValue = None
try :
PackValue = int ( PCD . PcdValue )
except :
try :
PackValue = int ( PCD . PcdValue , 16 )
except :
IsInteger = False
if IsInteger :
PCD . _PackIntValue ( PackValue , PackSize )
else :
PCD . _PackPtrValue ( PCD . PcdValue , PackSize )
self . FileLinesList [ count ] = PCD
count + = 1
else :
continue
##
# This function used to create a clean list only contain useful information and reorganized to make it
# easy to be sorted
#
def FormatFileLine ( self ) :
for eachPcd in self . FileLinesList :
if eachPcd . PcdOffset != ' * ' :
# Use pcd's Offset value as key, and pcd's Value as value
self . PcdFixedOffsetSizeList . append ( eachPcd )
else :
# Use pcd's CName as key, and pcd's Size as value
self . PcdUnknownOffsetList . append ( eachPcd )
##
# This function is use to fix the offset value which the not specified in the map file.
# Usually it use the star (meaning any offset) character in the offset field
#
def FixVpdOffset ( self ) :
# At first, the offset should start at 0
# Sort fixed offset list in order to find out where has free spaces for the pcd's offset
# value is "*" to insert into.
self . PcdFixedOffsetSizeList . sort ( lambda x , y : cmp ( x . PcdBinOffset , y . PcdBinOffset ) )
#
# Sort the un-fixed pcd's offset by it's size.
#
self . PcdUnknownOffsetList . sort ( lambda x , y : cmp ( x . PcdBinSize , y . PcdBinSize ) )
#
# Process all Offset value are "*"
#
if ( len ( self . PcdFixedOffsetSizeList ) == 0 ) and ( len ( self . PcdUnknownOffsetList ) != 0 ) :
# The offset start from 0
NowOffset = 0
for Pcd in self . PcdUnknownOffsetList :
Pcd . PcdBinOffset = NowOffset
Pcd . PcdOffset = str ( hex ( Pcd . PcdBinOffset ) )
NowOffset + = Pcd . PcdBinSize
self . PcdFixedOffsetSizeList = self . PcdUnknownOffsetList
return
# Check the offset of VPD type pcd's offset start from 0.
if self . PcdFixedOffsetSizeList [ 0 ] . PcdBinOffset != 0 :
EdkLogger . warn ( " BPDG " , " The offset of VPD type pcd should start with 0, please check it. " ,
None )
# Judge whether the offset in fixed pcd offset list is overlapped or not.
lenOfList = len ( self . PcdFixedOffsetSizeList )
count = 0
while ( count < lenOfList - 1 ) :
PcdNow = self . PcdFixedOffsetSizeList [ count ]
PcdNext = self . PcdFixedOffsetSizeList [ count + 1 ]
# Two pcd's offset is same
if PcdNow . PcdBinOffset == PcdNext . PcdBinOffset :
EdkLogger . error ( " BPDG " , BuildToolError . ATTRIBUTE_GET_FAILURE ,
" The offset of %s at line: %s is same with %s at line: %s in file %s " % \
( PcdNow . PcdCName , PcdNow . Lineno , PcdNext . PcdCName , PcdNext . Lineno , PcdNext . FileName ) ,
None )
# Overlapped
if PcdNow . PcdBinOffset + PcdNow . PcdBinSize > PcdNext . PcdBinOffset :
EdkLogger . error ( " BPDG " , BuildToolError . ATTRIBUTE_GET_FAILURE ,
" The offset of %s at line: %s is overlapped with %s at line: %s in file %s " % \
( PcdNow . PcdCName , PcdNow . Lineno , PcdNext . PcdCName , PcdNext . Lineno , PcdNext . FileName ) ,
None )
# Has free space, raise a warning message
if PcdNow . PcdBinOffset + PcdNow . PcdBinSize < PcdNext . PcdBinOffset :
EdkLogger . warn ( " BPDG " , BuildToolError . ATTRIBUTE_GET_FAILURE ,
" The offsets have free space of between %s at line: %s and %s at line: %s in file %s " % \
( PcdNow . PcdCName , PcdNow . Lineno , PcdNext . PcdCName , PcdNext . Lineno , PcdNext . FileName ) ,
None )
count + = 1
LastOffset = self . PcdFixedOffsetSizeList [ 0 ] . PcdBinOffset
FixOffsetSizeListCount = 0
lenOfList = len ( self . PcdFixedOffsetSizeList )
lenOfUnfixedList = len ( self . PcdUnknownOffsetList )
##
# Insert the un-fixed offset pcd's list into fixed offset pcd's list if has free space between those pcds.
#
while ( FixOffsetSizeListCount < lenOfList ) :
eachFixedPcd = self . PcdFixedOffsetSizeList [ FixOffsetSizeListCount ]
NowOffset = eachFixedPcd . PcdBinOffset
# Has free space
if LastOffset < NowOffset :
if lenOfUnfixedList != 0 :
countOfUnfixedList = 0
while ( countOfUnfixedList < lenOfUnfixedList ) :
eachUnfixedPcd = self . PcdUnknownOffsetList [ countOfUnfixedList ]
needFixPcdSize = eachUnfixedPcd . PcdBinSize
# Not been fixed
if eachUnfixedPcd . PcdOffset == ' * ' :
# The offset un-fixed pcd can write into this free space
if needFixPcdSize < = ( NowOffset - LastOffset ) :
# Change the offset value of un-fixed pcd
eachUnfixedPcd . PcdOffset = str ( hex ( LastOffset ) )
eachUnfixedPcd . PcdBinOffset = LastOffset
# Insert this pcd into fixed offset pcd list.
self . PcdFixedOffsetSizeList . insert ( FixOffsetSizeListCount , eachUnfixedPcd )
# Delete the item's offset that has been fixed and added into fixed offset list
self . PcdUnknownOffsetList . pop ( countOfUnfixedList )
# After item added, should enlarge the length of fixed pcd offset list
lenOfList + = 1
FixOffsetSizeListCount + = 1
# Decrease the un-fixed pcd offset list's length
lenOfUnfixedList - = 1
# Modify the last offset value
2010-11-15 03:51:34 +01:00
LastOffset + = needFixPcdSize
2010-09-06 04:01:57 +02:00
else :
2010-11-15 03:51:34 +01:00
# It can not insert into those two pcds, need to check still has other space can store it.
LastOffset = NowOffset + self . PcdFixedOffsetSizeList [ FixOffsetSizeListCount ] . PcdBinSize
2010-09-06 04:01:57 +02:00
FixOffsetSizeListCount + = 1
2010-11-15 03:51:34 +01:00
break
2010-09-06 04:01:57 +02:00
# Set the FixOffsetSizeListCount = lenOfList for quit the loop
else :
FixOffsetSizeListCount = lenOfList
# No free space, smoothly connect with previous pcd.
elif LastOffset == NowOffset :
LastOffset = NowOffset + eachFixedPcd . PcdBinSize
FixOffsetSizeListCount + = 1
# Usually it will not enter into this thunk, if so, means it overlapped.
else :
EdkLogger . error ( " BPDG " , BuildToolError . ATTRIBUTE_NOT_AVAILABLE ,
" The offset value definition has overlapped at pcd: %s , it ' s offset is: %s , in file: %s line: %s " % \
( eachFixedPcd . PcdCName , eachFixedPcd . PcdOffset , eachFixedPcd . InputFileName , eachFixedPcd . Lineno ) ,
None )
FixOffsetSizeListCount + = 1
# Continue to process the un-fixed offset pcd's list, add this time, just append them behind the fixed pcd's offset list.
lenOfUnfixedList = len ( self . PcdUnknownOffsetList )
lenOfList = len ( self . PcdFixedOffsetSizeList )
while ( lenOfUnfixedList > 0 ) :
# Still has items need to process
# The last pcd instance
LastPcd = self . PcdFixedOffsetSizeList [ lenOfList - 1 ]
NeedFixPcd = self . PcdUnknownOffsetList [ 0 ]
NeedFixPcd . PcdBinOffset = LastPcd . PcdBinOffset + LastPcd . PcdBinSize
NeedFixPcd . PcdOffset = str ( hex ( NeedFixPcd . PcdBinOffset ) )
# Insert this pcd into fixed offset pcd list's tail.
self . PcdFixedOffsetSizeList . insert ( lenOfList , NeedFixPcd )
# Delete the item's offset that has been fixed and added into fixed offset list
self . PcdUnknownOffsetList . pop ( 0 )
lenOfList + = 1
lenOfUnfixedList - = 1
##
# Write the final data into output files.
#
def GenerateVpdFile ( self , MapFileName , BinFileName ) :
#Open an VPD file to process
try :
fVpdFile = open ( BinFileName , " wb " , 0 )
except :
# Open failed
EdkLogger . error ( " BPDG " , BuildToolError . FILE_OPEN_FAILURE , " File open failed for %s " % self . VpdFileName , None )
try :
fMapFile = open ( MapFileName , " w " , 0 )
except :
# Open failed
EdkLogger . error ( " BPDG " , BuildToolError . FILE_OPEN_FAILURE , " File open failed for %s " % self . MapFileName , None )
# Use a instance of StringIO to cache data
fStringIO = StringIO . StringIO ( ' ' )
# Write the header of map file.
try :
fMapFile . write ( st . MAP_FILE_COMMENT_TEMPLATE + " \n " )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FILE_WRITE_FAILURE , " Write data to file %s failed, please check whether the file been locked or using by other applications. " % self . MapFileName , None )
for eachPcd in self . PcdFixedOffsetSizeList :
# write map file
try :
fMapFile . write ( " %s | %s | %s | %s \n " % ( eachPcd . PcdCName , eachPcd . PcdOffset , eachPcd . PcdSize , eachPcd . PcdUnpackValue ) )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FILE_WRITE_FAILURE , " Write data to file %s failed, please check whether the file been locked or using by other applications. " % self . MapFileName , None )
# Write Vpd binary file
fStringIO . seek ( eachPcd . PcdBinOffset )
if isinstance ( eachPcd . PcdValue , list ) :
ValueList = [ chr ( Item ) for Item in eachPcd . PcdValue ]
fStringIO . write ( ' ' . join ( ValueList ) )
else :
fStringIO . write ( eachPcd . PcdValue )
try :
fVpdFile . write ( fStringIO . getvalue ( ) )
except :
EdkLogger . error ( " BPDG " , BuildToolError . FILE_WRITE_FAILURE , " Write data to file %s failed, please check whether the file been locked or using by other applications. " % self . VpdFileName , None )
fStringIO . close ( )
fVpdFile . close ( )
fMapFile . close ( )