[edk2] [RFC 3/3] TestPkg: Show Structure PCD value assignment

Liming Gao posted 3 patches 7 years, 6 months ago
[edk2] [RFC 3/3] TestPkg: Show Structure PCD value assignment
Posted by Liming Gao 7 years, 6 months ago
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Liming Gao <liming.gao@intel.com>
---
 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 <stdio.h>
+#include <stdlib.h>
+#include <PcdValueCommon.h>
+'''
+
+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 == "<HeaderFiles>":
+                        Include = DecFileBuffer[DecLineNumber].strip()
+                        DecLineNumber = DecLineNumber + 1
+                        NextLine = DecFileBuffer[DecLineNumber].strip()
+                    if NextLine == "<Packages>":
+                        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.<BR>
+# 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 {
+    <HeaderFiles>
+      Guid/Test.h
+    <Packages>
+      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.<BR>
+# Copyright (c) 2007 - 2016, 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.
+#
+##
+
+[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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel