From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id F257121939304 for ; Tue, 11 Apr 2017 08:17:12 -0700 (PDT) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga104.jf.intel.com with ESMTP; 11 Apr 2017 08:17:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.37,186,1488873600"; d="scan'208";a="72592980" Received: from shwde7172.ccr.corp.intel.com ([10.239.9.14]) by orsmga002.jf.intel.com with ESMTP; 11 Apr 2017 08:17:10 -0700 From: Liming Gao To: edk2-devel@lists.01.org Date: Tue, 11 Apr 2017 23:16:43 +0800 Message-Id: <1491923803-12124-4-git-send-email-liming.gao@intel.com> X-Mailer: git-send-email 2.8.0.windows.1 In-Reply-To: <1491923803-12124-1-git-send-email-liming.gao@intel.com> References: <1491923803-12124-1-git-send-email-liming.gao@intel.com> Subject: [RFC 3/3] TestPkg: Show Structure PCD value assignment X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 Apr 2017 15:17:13 -0000 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Liming Gao --- TestPkg/Include/Guid/Test.h | 31 ++ TestPkg/StructuredPcdValueGenerator.py | 702 +++++++++++++++++++++++++++++++++ TestPkg/TestPkg.dec | 44 +++ TestPkg/TestPkg.dsc | 69 ++++ 4 files changed, 846 insertions(+) create mode 100644 TestPkg/Include/Guid/Test.h create mode 100644 TestPkg/StructuredPcdValueGenerator.py create mode 100644 TestPkg/TestPkg.dec create mode 100644 TestPkg/TestPkg.dsc diff --git a/TestPkg/Include/Guid/Test.h b/TestPkg/Include/Guid/Test.h new file mode 100644 index 0000000..e988954 --- /dev/null +++ b/TestPkg/Include/Guid/Test.h @@ -0,0 +1,31 @@ +//#pragma pack(1) + +#define MacroTest2 10 + +typedef struct { + BOOLEAN Bool; + UINT8 A:4; + UINT8 B:4; + UINT32 Unaligned32; + UINT16 C; + UINT16 D; + UINT32 E; + UINT32 F; + UINT64 G; + UINT64 H; + UINT8 Reserved; + UINT8 Hidden; + UINT8 OneLine8; + UINT16 OneLine16; + UINT32 OneLine32; + UINT64 OneLine64; + BOOLEAN OneLineBoolA; + BOOLEAN OneLineBoolB; + BOOLEAN OneLineBoolC; + BOOLEAN OneLineBoolD; + UINT32 Array[10]; + UINT8 Array2[2]; + UINT8 FlexibleArray[0]; +} TEST; + +//#pragma pack() diff --git a/TestPkg/StructuredPcdValueGenerator.py b/TestPkg/StructuredPcdValueGenerator.py new file mode 100644 index 0000000..a24ccf3 --- /dev/null +++ b/TestPkg/StructuredPcdValueGenerator.py @@ -0,0 +1,702 @@ +# +# Generate C program to convert structure PCD value to byte array. +# + +import os +import sys +import argparse +import subprocess +from collections import OrderedDict +import uuid + +# +# Globals for help information +# +__prog__ = 'StructuredPcdValueGenerator' +__version__ = '%s Version %s' % (__prog__, '0.1 ') +__copyright__ = 'Copyright (c) 2017, Intel Corporation. All rights reserved.' +__usage__ = '%s [options]' % (__prog__) + +# +# Treat CHAR16 as a synonym for UINT16. CHAR16 support is required for VFR C structs +# +PcdValueInitName = 'PcdValueInit' +PcdSupportedBaseTypes = ['BOOLEAN', 'UINT8', 'UINT16', 'UINT32', 'UINT64', 'CHAR16'] +PcdSupportedBaseTypeWidth = {'BOOLEAN':8, 'UINT8':8, 'UINT16':16, 'UINT32':32, 'UINT64':64} +PcdUnsupportedBaseTypes = ['INT8', 'INT16', 'INT32', 'INT64', 'CHAR8', 'UINTN', 'INTN', 'VOID'] + +PcdMainCHeader = ''' +/** + DO NOT EDIT + FILE auto-generated +**/ + +#include +#include +#include +''' + +PcdMainCEntry = ''' +int +main ( + int argc, + char *argv[] + ) +{ + return PcdValueMain (argc, argv); +} +''' + +PcdMakefileHeader = ''' +# +# DO NOT EDIT +# This file is auto-generated by build utility +# + +''' + +PcdMakefileEnd = ''' +!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common + +CFLAGS = $(CFLAGS) /wd4200 /wd4034 + +LIBS = $(LIB_PATH)\Common.lib + +!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app +''' + +PcdGccMakefile = ''' +ARCH ?= IA32 +MAKEROOT ?= $(EDK_TOOLS_PATH)/Source/C +LIBS = -lCommon +''' + +def GetBitField(Value, Start, Width): + Mask = (1 << Width) - 1 + return (Value >> Start) & Mask + +def SetBitField(Value, Start, Width, BitFieldValue): + Mask = (1 << Width) - 1 + if BitFieldValue & (~Mask) <> 0: + raise ValueError + BitFieldValue = BitFieldValue & Mask + Value = (Value & (~(Mask << Start))) | (BitFieldValue << Start) + return Value + +def IntToArray(Value, Size, Stride = 1, ValuesPerLine = 16, AsciiComment = False): + if Stride not in [1,2,4,8]: + return '' + PostFix = '' + if Stride == 8: + PostFix = 'ULL' + Value = Value & ((1 << Size * 8) - 1) + Output = '{\n' + Shift = Stride * 8 + Mask = (1 << Shift) - 1 + NumValues = 0 + Ascii = '' + for Index in range (0, Size, Stride): + Output = Output + '0x%0*X%s' % (Stride * 2, Value & Mask, PostFix) + if Index + Stride < Size: + Output = Output + ', ' + else: + Output = Output + ' ' + for CharIndex in range (0, Stride): + Char = Value & 0xff + if Char in range(0x20, 0x7F): + Ascii = Ascii + chr(Value & 0xff) + else: + Ascii = Ascii + '.' + Value = Value >> 8 + if (NumValues % ValuesPerLine) == (ValuesPerLine - 1): + if AsciiComment: + Output = Output + ' // %s' % (Ascii) + Output = Output + '\n' + Ascii = '' + NumValues = NumValues + 1 + if AsciiComment and (NumValues % ValuesPerLine) <> 0: + for Index in range((NumValues % ValuesPerLine), ValuesPerLine): + Output = Output + ' %*s%*s ' % (Stride * 2, '', len(PostFix), '') + Output = Output + ' // %s\n' % (Ascii) + Output = Output + '}' + return Output + +def IntToCString(Value, ValueSize): + Result = '"' + if not isinstance (Value, str): + for Index in range(0, ValueSize): + Result = Result + '\\x%02x' % (Value & 0xff) + Value = Value >> 8 + Result = Result + '"' + return Result + +def ParseFieldValue (Value): + if type(Value) == type(0): + return Value, (Value.bit_length() + 7) / 8 + if type(Value) <> type(''): + raise ValueError + Value = Value.strip() + if Value.startswith('UINT8') and Value.endswith(')'): + Value, Size = ParseFieldValue(Value.split('(',1)[1][:-1]) + if Size > 1: + raise ValueError + return Value, 1 + if Value.startswith('UINT16') and Value.endswith(')'): + Value, Size = ParseFieldValue(Value.split('(',1)[1][:-1]) + if Size > 2: + raise ValueError + return Value, 2 + if Value.startswith('UINT32') and Value.endswith(')'): + Value, Size = ParseFieldValue(Value.split('(',1)[1][:-1]) + if Size > 4: + raise ValueError + return Value, 4 + if Value.startswith('UINT64') and Value.endswith(')'): + Value, Size = ParseFieldValue(Value.split('(',1)[1][:-1]) + if Size > 8: + raise ValueError + return Value, 8 + if Value.startswith('GUID') and Value.endswith(')'): + Value = Value.split('(',1)[1][:-1].strip() + if Value[0] == '{' and Value[-1] == '}': + Value = Value[1:-1].strip() + Value = Value.split('{',1) + Value = [Item.strip()[2:] for Item in (Value[0] + Value[1][:-1]).split(',')] + Value = '-'.join(Value[0:3]) + '-' + ''.join(Value[3:5]) + '-' + ''.join(Value[5:11]) + if Value[0] == '"' and Value[-1] == '"': + Value = Value[1:-1] + Value = "'" + uuid.UUID(Value).get_bytes_le() + "'" + Value, Size = ParseFieldValue(Value) + return Value, 16 + if Value.startswith('L"') and Value.endswith('"'): + # Unicode String + List = list(Value[2:-1]) + List.reverse() + Value = 0 + for Char in List: + Value = (Value << 16) | ord(Char) + return Value, (len(List) + 1) * 2 + if Value.startswith('"') and Value.endswith('"'): + # ASCII String + List = list(Value[1:-1]) + List.reverse() + Value = 0 + for Char in List: + Value = (Value << 8) | ord(Char) + return Value, len(List) + 1 + if Value.startswith("L'") and Value.endswith("'"): + # Unicode Character Constant + List = list(Value[2:-1]) + List.reverse() + Value = 0 + for Char in List: + Value = (Value << 16) | ord(Char) + return Value, len(List) * 2 + if Value.startswith("'") and Value.endswith("'"): + # Character constant + List = list(Value[1:-1]) + List.reverse() + Value = 0 + for Char in List: + Value = (Value << 8) | ord(Char) + return Value, len(List) + if Value.startswith('{') and Value.endswith('}'): + # Byte array + Value = Value[1:-1] + List = [Item.strip() for Item in Value.split(',')] + List.reverse() + Value = 0 + for Item in List: + ItemValue, Size = ParseFieldValue(Item) + if Size > 1: + raise ValueError + Value = (Value << 8) | ItemValue + return Value, len(List) + if Value.lower().startswith('0x'): + Value = int(Value, 16) + return Value, (Value.bit_length() + 7) / 8 + if Value[0].isdigit(): + Value = int(Value, 10) + return Value, (Value.bit_length() + 7) / 8 + if Value.lower() == 'true': + return 1, 1 + if Value.lower() == 'false': + return 0, 1 + return Value, 1 + +def IsFieldValueAnArray (Value): + Value = Value.strip() + if Value.startswith('GUID') and Value.endswith(')'): + return True + if Value.startswith('L"') and Value.endswith('"'): + return True + if Value[0] == '"' and Value[-1] == '"': + return True + if Value[0] == '{' and Value[-1] == '}': + return True + if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1: + print 'foo = ', list(Value[2:-1]) + return True + if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1: + print 'bar = ', list(Value[1:-1]) + return True + return False + +def ConvertValueToString (Value): + Result = '' + if Value.startswith('L"') and Value.endswith('"'): + for Char in Value[2:-1]: + Result = Result + '\\x%02x\\x00' % (ord(Char)) + Result = Result + '\\x00\\x00' + if Value[0] == '"' and Value[-1] == '"': + for Char in Value[1:-1]: + Result = Result + '\\x%02x' % (ord(Char)) + Result = Result + '\\x00' + if Value[0] == '{' and Value[-1] == '}': + Value = [int(Item.strip(),16) for Item in Value[1:-1].split(',')] + for Item in Value: + Result = Result + '\\x%02x' % (Item) + return Result + +def ExecuteCommand (Command): + try: + Process = subprocess.Popen(Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + except: + print 'ERROR: Can not execute command:', Command + sys.exit(1) + Result = Process.communicate() + if Process.returncode <> 0: + print 'ERROR: Can not collect output from command:', Command + return Result[0], Result[1] + +class StructuredPcdField: + def __init__(self, FieldName, DefaultValue): + self.FieldName = FieldName + self.DefaultValue = DefaultValue + + def __repr__(self): + return self.FieldName + +class StructuredPcd: + def __init__(self, StructuredPcdIncludeFile, Packages, TokenSpaceGuidName, TokenName, TypeName): + self.StructuredPcdIncludeFile = StructuredPcdIncludeFile + self.PackageDecs = Packages + self.SkuName = 'DEFAULT' + self.DefaultStoreName = 'DEFAULT' + self.TokenSpaceGuidName = TokenSpaceGuidName + self.TokenName = TokenName + self.TypeName = TypeName + self.DefaultValues = OrderedDict({}) + self.PcdMode = None + self.OverrideValues = OrderedDict({}) + self.FlexibleFieldName = None + + def __repr__(self): + return self.TypeName + + def AddDefaultValue (self, FieldName, Value, FileName="", LineNo=0): + self.DefaultValues[FieldName] = [Value.strip(), FileName, LineNo] + return self.DefaultValues[FieldName] + + def AddOverrideValue (self, FieldName, Value, FileName="", LineNo=0): + self.OverrideValues[FieldName] = [Value.strip(), FileName, LineNo] + return self.OverrideValues[FieldName] + + def SetPcdMode (self, PcdMode): + self.PcdMode = PcdMode + + def SetFlexibleFieldName (self, FlexibleFieldName): + self.FlexibleFieldName = FlexibleFieldName + +class Build: + def __init__(self, args): + self.args = args + self.DecFile = args.DecFile + self.DscFile = args.DscFile + self.Quiet = args.Quiet + self.StructuredPcds = [] + self.PackagePath = os.path.dirname(self.DecFile) + if os.getenv("WORKSPACE"): + self.OutputPath = os.path.join(os.getenv("WORKSPACE"), 'Build', PcdValueInitName) + else: + self.OutputPath = os.path.dirname(self.DscFile) + + def __repr__(self): + return self.DscFile + + def AddStructuredPcd (self, Include, Packages, TokenSpaceGuidName, TokenName, Type): + Pcd = StructuredPcd(Include, Packages, TokenSpaceGuidName, TokenName, Type) + self.StructuredPcds.append(Pcd) + return Pcd + + def LookupPcd(self, TokenSpaceGuidName, TokenName): + for Pcd in self.StructuredPcds: + if Pcd.TokenSpaceGuidName == TokenSpaceGuidName and Pcd.TokenName == TokenName: + return Pcd + return None + + def LookupPcdByTypeName(self, TypeName): + for Pcd in self.StructuredPcds: + if Pcd.TypeName == TypeName: + return Pcd + return None + + def ParseDecFile (self): + print 'Parse DEC File', self.DecFile + File = open (self.DecFile, mode='r') + DecFileBuffer = File.readlines() + File.close() + DecLineNumber = 0 + Include = None + PcdObject = None + while (DecLineNumber < len (DecFileBuffer)): + Line = DecFileBuffer[DecLineNumber] + DecLineNumber = DecLineNumber + 1 + Line = Line.strip() + if Line.startswith('#'): + continue + if len(Line.split('|')) == 4: + Line = Line [:(len(Line)-1)] + Line = [Item.strip() for Item in Line.strip().split('|')] + Pcd = [Item.strip() for Item in Line[0].split('.',2)] + if len(Pcd) < 2: + print 'Error: PCD field sytnax error', DecLineNumber, Line + sys.exit() + elif len(Pcd) == 2: + TokenSpaceGuidName = Pcd[0] + TokenName = Pcd[1] + Type = Line[2] + Packages = [] + NextLine = DecFileBuffer[DecLineNumber].strip() + DecLineNumber = DecLineNumber + 1 + while (NextLine[0] != "}"): + if NextLine == "": + Include = DecFileBuffer[DecLineNumber].strip() + DecLineNumber = DecLineNumber + 1 + NextLine = DecFileBuffer[DecLineNumber].strip() + if NextLine == "": + DecLineNumber = DecLineNumber + 1 + NextLine = DecFileBuffer[DecLineNumber].strip() + while (NextLine[0] != "}" and NextLine[0] != "<"): + Packages.append (NextLine.strip().replace ('\\', '/')) + DecLineNumber = DecLineNumber + 1 + NextLine = DecFileBuffer[DecLineNumber].strip() + DecLineNumber = DecLineNumber + 1 + PcdObject = self.AddStructuredPcd (Include, Packages, TokenSpaceGuidName, TokenName, Type) + PcdObject.AddDefaultValue(Line[2], Line[1], self.DecFile, DecLineNumber) + elif PcdObject <> None: + Line = [Item.strip() for Item in Line.strip().split('|')] + Pcd = [Item.strip() for Item in Line[0].split('.',2)] + if len (Line) == 2 and len (Pcd) > 2: + if Pcd[0] <> PcdObject.TokenSpaceGuidName or Pcd[1] <> PcdObject.TokenName: + print 'Error: PCD does not match parent Structured PCD', Pcd[0], Pcd[1], TokenSpaceGuidName, TokenName + sys.exit() + PcdObject.AddDefaultValue('.' + Pcd[2], Line[1], self.DecFile, DecLineNumber) + if not self.args.Quiet: + for Pcd in self.StructuredPcds: + print 'Include : ', Pcd.StructuredPcdIncludeFile + print 'Type : ', Pcd.TypeName + print 'SkuName : ', Pcd.SkuName + print 'DefaultStoreName : ', Pcd.DefaultStoreName + print 'TokenSpaceGuid : ', Pcd.TokenSpaceGuidName + print 'TokenName : ', Pcd.TokenName + for Field in Pcd.DefaultValues: + print ' %40s : %s' % (Field, Pcd.DefaultValues[Field][0]) + print '' + + def ParseDscFile (self): + print 'Parse DSC File', self.DscFile + File = open (self.DscFile, mode='r') + DscFileBuffer = File.readlines() + File.close() + PcdMode = None + PcdFieldSettings = OrderedDict({}) + DscLineNumber = 0 + for Line in DscFileBuffer: + DscLineNumber = DscLineNumber + 1 + if Line.startswith('#'): + continue + if Line.startswith('['): + Mode = Line[1:].split('.',1)[0].split(']',1)[0] + continue + Line = [Item.strip() for Item in Line.split('|')] + Pcd = [Item.strip() for Item in Line[0].split('.',2)] + if len(Pcd) >= 2 and len(Line) > 1: + PcdObject = self.LookupPcd (Pcd[0], Pcd[1]) + if not PcdObject: + print 'ERROR: DSC file references structured PCD that is not declared in DEC file', Pcd[0], Pcd[1] + sys.exit() + if len (Pcd) == 2: + PcdObject.AddDefaultValue (PcdObject.TypeName, Line[1], self.DscFile, DscLineNumber) + else: + PcdObject.AddOverrideValue ('.' + Pcd[2], Line[1], self.DscFile, DscLineNumber) + if PcdMode and PcdMode <> Mode: + print '%d: %s: ERROR: PCD %s.%s has more than one mode %s %s.' % (DscLineNumber, self.DscFile, Pcd[0], Pcd[1], PcdMode, Mode) + sys.exit() + PcdMode = Mode + PcdObject.SetPcdMode(Mode) + if not self.args.Quiet: + for Pcd in self.StructuredPcds: + print 'Include : ', Pcd.StructuredPcdIncludeFile + print 'Type : ', Pcd.TypeName + print 'SkuName : ', Pcd.SkuName + print 'DefaultStoreName : ', Pcd.DefaultStoreName + print 'TokenSpaceGuid : ', Pcd.TokenSpaceGuidName + print 'TokenName : ', Pcd.TokenName + print 'PcdMode : ', Pcd.PcdMode + for Field in Pcd.DefaultValues: + print ' D %40s : %s' % (Field, Pcd.DefaultValues[Field][0]) + for Field in Pcd.OverrideValues: + print ' O %40s : %s' % (Field, Pcd.OverrideValues[Field][0]) + print '' + + def GenerateByteArrayValue (self): + # + # Generate/Compile/Run C application to determine if there are any flexible array members + # + InitByteValue = "" + CApp = PcdMainCHeader + + Includes = {} + for Pcd in self.StructuredPcds: + IncludeFile = Pcd.StructuredPcdIncludeFile + if IncludeFile not in Includes: + Includes[IncludeFile] = True + CApp = CApp + '#include <%s>\n' % (IncludeFile) + CApp = CApp + '\n' + + FieldNames = {} + for Pcd in self.StructuredPcds: + CApp = CApp + 'void\n' + CApp = CApp + 'Initialize_%s_%s_%s_%s(\n' % (Pcd.SkuName, Pcd.DefaultStoreName, Pcd.TokenSpaceGuidName, Pcd.TokenName) + CApp = CApp + ' void\n' + CApp = CApp + ' )\n' + CApp = CApp + '{\n' + CApp = CApp + ' UINT32 Size;\n' + CApp = CApp + ' UINT32 FieldSize;\n' + CApp = CApp + ' UINT8 *Value;\n' + CApp = CApp + ' %s *Pcd;\n' % (Pcd.TypeName) + CApp = CApp + ' UINT32 OriginalSize;\n' + CApp = CApp + ' VOID *OriginalPcd;\n' + CApp = CApp + '\n' + InitByteValue = '%s.%s.%s.%s|%s|' %(Pcd.SkuName, Pcd.DefaultStoreName, Pcd.TokenSpaceGuidName, Pcd.TokenName, Pcd.TypeName) + + # + # Get current PCD value and size + # + CApp = CApp + ' OriginalPcd = PcdGetPtr (%s, %s, %s, %s, &OriginalSize);\n' % (Pcd.SkuName, Pcd.DefaultStoreName, Pcd.TokenSpaceGuidName, Pcd.TokenName) + CApp = CApp + ' printf("OriginalSize = %d\\n", OriginalSize);\n' + + + # + # Determine the size of the PCD. For simple structures, sizeof(TYPE) provides + # the correct value. For structures with a flexible array member, the flexible + # array member is detected, and the size is based on the highest index used with + # the flexible array member. The flexible array member must be the last field + # in a structure. The size formula for this case is: + # OFFSET_OF(FlexbleArrayField) + sizeof(FlexibleArray[0]) * (HighestIndex + 1) + # + CApp = CApp + ' Size = sizeof(%s);\n' % (Pcd.TypeName) + CApp = CApp + ' printf("Size = %d\\n", Size);\n' + for FieldList in [Pcd.DefaultValues, Pcd.OverrideValues]: + for FieldName in FieldList: + if not FieldName.startswith('.'): + continue + IsArray = IsFieldValueAnArray(FieldList[FieldName][0]) + if IsArray: + Value, ValueSize = ParseFieldValue (FieldList[FieldName][0]) + CApp = CApp + ' __FLEXIBLE_SIZE(Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s));\n' % (Pcd.TypeName, FieldName[1:], ValueSize, Pcd.TypeName, FieldName[1:]); + CApp = CApp + ' printf("Size = %d\\n", Size);\n' + else: + NewFieldName = '' + while '[' in FieldName: + NewFieldName = NewFieldName + FieldName.split('[',1)[0] + '[0]' + ArrayIndex = int(FieldName.split('[',1)[1].split(']',1)[0]) + FieldName = FieldName.split(']',1)[1] + FieldName = NewFieldName + FieldName + while '[' in FieldName: + FieldName = FieldName.rsplit('[',1)[0] + #if not self.args.Quiet: + # print 'PCD Field: %40s' % (FieldName) + if Pcd.TypeName + FieldName not in FieldNames: + FieldNames[Pcd.TypeName + FieldName] = True + CApp = CApp + ' __FLEXIBLE_SIZE(Size, %s, %s, %d);\n' % (Pcd.TypeName, FieldName[1:], ArrayIndex + 1) + CApp = CApp + ' printf("Size = %d\\n", Size);\n' + CApp = CApp + ' printf("Size = %d\\n", Size);\n' + + # + # Allocate and zero buffer for the PCD + # Must handle cases where current value is smaller, larger, or same size + # Always keep that larger one as the current size + # + CApp = CApp + ' Size = (OriginalSize > Size ? OriginalSize : Size);\n' + CApp = CApp + ' printf("Size = %d\\n", Size);\n' + CApp = CApp + ' Pcd = (%s *)malloc (Size);\n' % (Pcd.TypeName) + CApp = CApp + ' memset (Pcd, 0, Size);\n' + + # + # Copy current PCD value into allocated buffer. + # + CApp = CApp + ' memcpy (Pcd, OriginalPcd, OriginalSize);\n' + + # + # Assign field values in PCD + # + for FieldList in [Pcd.DefaultValues, Pcd.OverrideValues]: + for FieldName in FieldList: + if not FieldName.startswith('.'): + InitByteValue = InitByteValue + '%s\n'%(FieldList[FieldName][0]) + continue + IsArray = IsFieldValueAnArray(FieldList[FieldName][0]) + Value, ValueSize = ParseFieldValue (FieldList[FieldName][0]) + #print FieldName, Value, ValueSize, IntToCString(Value, ValueSize) + if isinstance(Value, str): + CApp = CApp + ' Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName[1:], Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0]) + elif IsArray: + # + # Use memcpy() to copy value into field + # + CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.TypeName, FieldName[1:]) + CApp = CApp + ' printf("FieldSize = %d\\n", FieldSize);\n' + CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0]) + CApp = CApp + ' memcpy (&Pcd->%s[0], Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName[1:], ValueSize, ValueSize) + else: + if ValueSize > 4: + CApp = CApp + ' Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName[1:], Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0]) + else: + CApp = CApp + ' Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName[1:], Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0]) + + # + # Set new PCD value and size + # + CApp = CApp + ' PcdSetPtr (%s, %s, %s, %s, Size, (UINT8 *)Pcd);\n' % (Pcd.SkuName, Pcd.DefaultStoreName, Pcd.TokenSpaceGuidName, Pcd.TokenName) + + # + # Free PCD + # + CApp = CApp + ' free (Pcd);\n' + + CApp = CApp + '}\n' + CApp = CApp + '\n' + + CApp = CApp + 'VOID\n' + CApp = CApp + 'PcdEntryPoint(\n' + CApp = CApp + ' VOID\n' + CApp = CApp + ' )\n' + CApp = CApp + '{\n' + for Pcd in self.StructuredPcds: + CApp = CApp + ' Initialize_%s_%s_%s_%s();\n' % (Pcd.SkuName, Pcd.DefaultStoreName, Pcd.TokenSpaceGuidName, Pcd.TokenName) + CApp = CApp + '}\n' + + CApp = CApp + PcdMainCEntry + '\n' + + if not os.path.exists(self.OutputPath): + os.makedirs(self.OutputPath) + CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName) + File = open (CAppBaseFileName + '.c', mode='w') + File.write(CApp) + File.close() + + MakeApp = PcdMakefileHeader + if sys.platform == "win32": + MakeApp = MakeApp + 'APPNAME = %s\n' %(PcdValueInitName) + 'OBJECTS = %s\%s.obj\n' %(self.OutputPath, PcdValueInitName) + 'INC = $(INC)' + else: + MakeApp = MakeApp + PcdGccMakefile + MakeApp = MakeApp + 'APPNAME = %s\n' %(PcdValueInitName) + 'OBJECTS = %s/%s.o\n' %(self.OutputPath, PcdValueInitName) + \ + 'include $(MAKEROOT)/Makefiles/app.makefile\n' + 'BUILD_CFLAGS += -Wno-error\n' + 'INCLUDE +=' + Packages = {} + for Pcd in self.StructuredPcds: + for PackageDec in Pcd.PackageDecs: + Package = PackageDec.split('/')[0] + if Package not in Packages: + Packages[Package] = True + MakeApp = MakeApp + ' -I $(WORKSPACE)/%s/Include' %(Package) + if Package == 'MdePkg': + MakeApp = MakeApp + ' -I $(WORKSPACE)/%s/Include/Ia32' %(Package) + MakeApp = MakeApp + '\n' + if sys.platform == "win32": + MakeApp = MakeApp + PcdMakefileEnd + MakeFileName = os.path.join(self.OutputPath, 'Makefile') + File = open (MakeFileName, mode='w') + File.write(MakeApp) + File.close() + + InputValueFile = os.path.join(self.OutputPath, 'Input.txt') + OutputValueFile = os.path.join(self.OutputPath, 'Output.txt') + File = open (InputValueFile, mode='w') + File.write(InitByteValue) + File.close() + + if sys.platform == "win32": + StdOut, StdErr = ExecuteCommand ('nmake -f %s' % (MakeFileName)) + else: + StdOut, StdErr = ExecuteCommand ('make -f %s' % (MakeFileName)) + Messages = StdOut.split('\r') + for Message in Messages: + if " error " in Message: + FileInfo = Message.strip().split('(') + if len (FileInfo) > 0: + FileName = FileInfo [0] + FileLine = FileInfo [1].split (')')[0] + else: + FileInfo = Message.strip().split(':') + FileName = FileInfo [0] + FileLine = FileInfo [1] + + File = open (FileName, mode='r') + FileData = File.readlines() + File.close() + print Message + print FileData[int (FileLine) - 1] + return + + PcdValueInitExe = PcdValueInitName + if not sys.platform == "win32": + PcdValueInitExe = os.path.join(os.getenv("EDK_TOOLS_PATH"), 'Source', 'C', 'bin', PcdValueInitName) + + StdOut, StdErr = ExecuteCommand (PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile)) + File = open (OutputValueFile, mode='r') + FileBuffer = File.readlines() + File.close() + + print 'Final Value Output:' + for Pcd in FileBuffer: + PcdValue = Pcd.split ('|') + PcdInfo = PcdValue[0].split ('.') + print 'SkuName : ', PcdInfo[0] + print 'TokenSpaceGuid : ', PcdInfo[2] + print 'TokenName : ', PcdInfo[3] + print 'Value : ', PcdValue[2] + +def main(): + # + # Create command line argument parser object + # + parser = argparse.ArgumentParser(prog=__prog__, version=__version__, usage=__usage__, description=__copyright__, conflict_handler='resolve') + parser.add_argument("-p", "--dec-file", dest='DecFile', help="DEC File", required = True) + parser.add_argument("-d", "--dsc-file", dest='DscFile', help="DSC File", required = True) + parser.add_argument("-v", "--verbose", dest='Verbose', action="store_true", help="increase output messages") + parser.add_argument("-q", "--quiet", dest='Quiet', action="store_true", help="reduce output messages") + parser.add_argument("--debug", dest='Debug', type=int, metavar='[0-9]', choices=range(0,10), default=0, help="set debug level") + + # + # Parse command line arguments + # + args = parser.parse_args() + + # + # Get absolute paths + # + args.DecFile = os.path.abspath(args.DecFile) + args.DscFile = os.path.abspath(args.DscFile) + + # + # + # + BuildObject = Build(args) + BuildObject.ParseDecFile() + BuildObject.ParseDscFile() + BuildObject.GenerateByteArrayValue() + +if __name__ == '__main__': + main() diff --git a/TestPkg/TestPkg.dec b/TestPkg/TestPkg.dec new file mode 100644 index 0000000..622678e --- /dev/null +++ b/TestPkg/TestPkg.dec @@ -0,0 +1,44 @@ +## @file TestPkg.dec +# +# Copyright (c) 2016, 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 that 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. +# +## + + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = TestPkg + PACKAGE_GUID = F05BB314-CD00-4705-BD04-59B1CD9630E1 + PACKAGE_VERSION = 0.1 + +[Includes] + Include + +[LibraryClasses] + +[Guids] + ## MdeModule package token space guid + # Include/Guid/MdeModulePkgTokenSpace.h + gEfiStructuredPcdPkgTokenSpaceGuid = { 0x11a81069, 0xa6a2, 0x420a, { 0xa0, 0xe, 0x30, 0xc5, 0xb, 0xfb, 0xe8, 0x13 } } + +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] + # @Prompt Test Strucutre + gEfiStructuredPcdPkgTokenSpaceGuid.Test|{0xFF, 0xFF}|TEST|0x00010071 { + + Guid/Test.h + + MdePkg/MdePkg.dec + TestPkg/TestPkg.dec + } + gEfiStructuredPcdPkgTokenSpaceGuid.Test.A|2 + gEfiStructuredPcdPkgTokenSpaceGuid.Test.C|20 + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array[4]|1 + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array2[0]|2 + gEfiStructuredPcdPkgTokenSpaceGuid.Test.FlexibleArray[7]|5 diff --git a/TestPkg/TestPkg.dsc b/TestPkg/TestPkg.dsc new file mode 100644 index 0000000..fc61979 --- /dev/null +++ b/TestPkg/TestPkg.dsc @@ -0,0 +1,69 @@ +## @file +# EFI/PI Reference Module Package for All Architectures +# +# (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+# Copyright (c) 2007 - 2016, 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. +# +## + +[Defines] + PLATFORM_NAME = StructuredPcdPkg + PLATFORM_GUID = 35B4419B-4CF6-46FA-9A5D-741D0D29CD61 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/StructuredPcdPkg + SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC|ARM|AARCH64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses] + +################################################################################################### +# +# Components Section - list of the modules and components that will be processed by compilation +# tools and the EDK II tools to generate PE32/PE32+/Coff image files. +# +# Note: The EDK II DSC file is not used to specify how compiled binary images get placed +# into firmware volume images. This section is just a list of modules to compile from +# source into UEFI-compliant binaries. +# It is the FDF file that contains information on combining binary files into firmware +# volume images, whose concept is beyond UEFI and is described in PI specification. +# Binary modules do not need to be listed in this section, as they should be +# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi), +# Logo (Logo.bmp), and etc. +# There may also be modules listed in this section that are not required in the FDF file, +# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be +# generated for it, but the binary will not be put into any firmware volume. +# +################################################################################################### + +[PcdsFixedAtBuild] + gEfiStructuredPcdPkgTokenSpaceGuid.Test|{0xFF, 0xFF} + gEfiStructuredPcdPkgTokenSpaceGuid.Test.A|MacroTest2 + gEfiStructuredPcdPkgTokenSpaceGuid.Test.C|'a' + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array[4]|1 + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array2[0]|2 + gEfiStructuredPcdPkgTokenSpaceGuid.Test.FlexibleArray[7]|5 + gEfiStructuredPcdPkgTokenSpaceGuid.Test.FlexibleArray[4]|L'C' + gEfiStructuredPcdPkgTokenSpaceGuid.Test.FlexibleArray[3]|'b' + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array|"Hello" + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array|L"Hello" + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array|'Hello' + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array|L'Hello' + gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array|GUID("6F08F62E-5C19-498E-9157-B59CE6F362F1") +# gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array|GUID({ 0x827495c7, 0x636f, 0x4e0c, { 0x9c, 0xcc, 0x93, 0x5e, 0xfb, 0x67, 0xf2, 0x7c } }) +# gEfiStructuredPcdPkgTokenSpaceGuid.Test.Array|{1,2,3} + gEfiStructuredPcdPkgTokenSpaceGuid.Test.FlexibleArray|"World" + gEfiStructuredPcdPkgTokenSpaceGuid.Test.FlexibleArray|L"World" +# gEfiStructuredPcdPkgTokenSpaceGuid.Test.FlexibleArray|{4, 5, 6} + + +[Components] -- 2.8.0.windows.1