## @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
#
# 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 array
import re
from struct import *
2: 'H',
4: 'I',
8: 'Q'
}
## The VPD PCD data structure for store and process each VPD PCD entry.
#
# This class contain method to format and pack pcd's value.
#
class PcdEntry:
def __init__(self, PcdCName, PcdOffset, PcdSize, PcdValue, Lineno=None, FileName=None, PcdUnpackValue=None,
PcdBinOffset=None, PcdBinSize=None):
"Invalid PCD format(Name: %s File: %s line: %s) , no Value specified!" %(self.PcdCName, self.FileName, self.Lineno))
"Invalid PCD format(Name: %s File: %s Line: %s) , no Offset specified!" %(self.PcdCName, self.FileName, self.Lineno))
"Invalid PCD format(Name: %s File: %s Line: %s), no PcdSize specified!" %(self.PcdCName, self.FileName, self.Lineno))
## 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.
#
if (Size == "1"):
return True
return True
return False
## 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.
#
try:
except:
try:
except:
"Invalid offset value %s for PCD %s (File: %s Line: %s)" % (self.PcdOffset, self.PcdCName, self.FileName, self.Lineno))
## Pack Boolean type VPD PCD's value form string to binary type.
#
# @param ValueString The boolean type string for pack.
#
#
try:
except:
"Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self.PcdCName, self.FileName, self.Lineno))
else:
try:
except:
"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.
#
#
"Invalid size %d for PCD %s in integer datum size(File: %s Line: %s)." % (Size, self.PcdCName, self.FileName, self.Lineno))
if Size == 1:
if IntValue < 0:
"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:
"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:
"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:
"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:
"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:
"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:
"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:
"Too large PCD value %d for datum type UINT32 for PCD %s(File: %s Line: %s)." % (IntValue, self.PcdCName, self.FileName, self.Lineno))
else:
"Invalid size %d for PCD %s in integer datum size(File: %s Line: %s)." % (Size, self.PcdCName, self.FileName, self.Lineno))
try:
except:
"Invalid size or value for PCD %s to pack(File: %s Line: %s)." % (self.PcdCName, self.FileName, self.Lineno))
## 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.
#
else:
"Invalid VOID* type PCD %s value %s (File: %s Line: %s)" % (self.PcdCName, ValueString, self.FileName, self.Lineno))
## Pack an Ascii PCD value.
#
# An Ascii string for a PCD should be in format as "".
#
if (Size < 0):
"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))
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))
"PCD value string %s is exceed to size %d(File: %s Line: %s)" % (ValueString, Size, self.FileName, self.Lineno))
try:
except:
"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, ...}.
#
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))
"The byte array %s is too large for size %d(File: %s Line: %s)" % (ValueString, Size, self.FileName, self.Lineno))
Value = None
# translate hex value
try:
except:
"The value item %s in byte array %s is an invalid HEX value.(File: %s Line: %s)" % \
else:
# translate decimal value
try:
except:
"The value item %s in byte array %s is an invalid DECIMAL value.(File: %s Line: %s)" % \
if Value > 255:
"The value item %s in byte array %s do not in range 0 ~ 0xFF(File: %s Line: %s)" %\
## Pack a unicode PCD value into byte array.
#
# A unicode string for a PCD should be in format as L"".
#
if (Size < 0):
EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "Invalid parameter Size %s of PCD %s!(File: %s Line: %s)" %\
EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "For PCD: %s ,ASCII string %s at least contains two!(File: %s Line: %s)" %\
"The size of unicode string %s is too larger for size %s(File: %s Line: %s)" % \
for Value in UnicodeString:
try:
except:
"Invalid unicode character %s in unicode string %s(File: %s Line: %s)" % \
## 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 :
## 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.
#
self.FileLinesList = []
self.PcdUnknownOffsetList = []
try:
try:
except:
EdkLogger.error("BPDG", BuildToolError.FILE_READ_FAILURE, "File read failed for %s" %InputFileName,None)
finally:
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.
#
count = 0
# Strip "\r\n" generated by readlines ().
# Skip the comment line
#
# Enhanced for support "|" character in the string.
#
if ValueUpdateFlag:
# Store the line number
# Set the blank line to "None"
else :
# Set the comment line to "None"
count += 1
# The line count contain usage information
count = 0
# Delete useless lines
while (True) :
try :
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.
#
"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
if line != None :
# Strip the space char
#
# Store the original pcd value.
# This information will be useful while generate the output map file.
#
#
# Translate PCD size string to an integer value.
PackSize = None
try:
except:
try:
except:
EdkLogger.error("BPDG", BuildToolError.FORMAT_INVALID, "Invalid PCD size value %s at file: %s line: %s" % (PCD.PcdSize, self.InputFileName, PCD.Lineno))
count += 1
continue
#
# Try to translate value to an integer firstly.
#
PackValue = None
try:
except:
try:
except:
if IsInteger:
else:
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
#
# Use pcd's Offset value as key, and pcd's Value as value
else :
# Use pcd's CName as key, and pcd's Size as value
##
# 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
#
# 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.
#
# Sort the un-fixed pcd's offset by it's size.
#
#
# Process all Offset value are "*"
#
# The offset start from 0
NowOffset = 0
return
# Check the offset of VPD type pcd's offset start from 0.
None)
# Judge whether the offset in fixed pcd offset list is overlapped or not.
count = 0
# Two pcd's offset is same
"The offset of %s at line: %s is same with %s at line: %s in file %s" %\
None)
# Overlapped
"The offset of %s at line: %s is overlapped with %s at line: %s in file %s" %\
None)
# Has free space, raise a warning message
"The offsets have free space of between %s at line: %s and %s at line: %s in file %s" %\
None)
count += 1
##
# Insert the un-fixed offset pcd's list into fixed offset pcd's list if has free space between those pcds.
#
while (FixOffsetSizeListCount < lenOfList) :
# Has free space
if LastOffset < NowOffset :
if lenOfUnfixedList != 0 :
while(countOfUnfixedList < lenOfUnfixedList) :
# Not been fixed
# The offset un-fixed pcd can write into this free space
# Change the offset value of un-fixed pcd
# Insert this pcd into fixed offset pcd list.
# Delete the item's offset that has been fixed and added into fixed offset list
# After item added, should enlarge the length of fixed pcd offset list
lenOfList += 1
# Decrease the un-fixed pcd offset list's length
lenOfUnfixedList -= 1
# Modify the last offset value
else :
# It can not insert into those two pcds, need to check still has other space can store it.
break
# Set the FixOffsetSizeListCount = lenOfList for quit the loop
else :
# No free space, smoothly connect with previous pcd.
elif LastOffset == NowOffset :
# Usually it will not enter into this thunk, if so, means it overlapped.
else :
"The offset value definition has overlapped at pcd: %s, it's offset is: %s, in file: %s line: %s" %\
None)
# Continue to process the un-fixed offset pcd's list, add this time, just append them behind the fixed pcd's offset list.
while (lenOfUnfixedList > 0) :
# Still has items need to process
# The last pcd instance
# Insert this pcd into fixed offset pcd list's tail.
# Delete the item's offset that has been fixed and added into fixed offset list
lenOfList += 1
lenOfUnfixedList -= 1
##
# Write the final data into output files.
#
#Open an VPD file to process
try:
except:
# Open failed
EdkLogger.error("BPDG", BuildToolError.FILE_OPEN_FAILURE, "File open failed for %s" %self.VpdFileName,None)
try :
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
# Write the header of map file.
try :
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 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
else:
try :
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)