public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [RFC 0/3] Structure PCD value assignment in DEC/DSC
@ 2017-04-11 15:16 Liming Gao
  2017-04-11 15:16 ` [RFC 1/3] BaseTools: Update Makefile to work at absolute path Liming Gao
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Liming Gao @ 2017-04-11 15:16 UTC (permalink / raw)
  To: edk2-devel

Requirment: Map VOID* PCD to C structure
1. When PCD is configured as DynamicHii, it will be map to one EFI variable. If PCD is VOID*, it can map to the 
whole EFI variable. Most EFI variable data are defined as C structure. 
2. Some PCDs are designed as C style structure, such as gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters.

Current limitation:
1. VOID* PCD Value must be byte array. Its value is hard to be specified. 
2. If single PCD is defined to map one field in structure, its offset and width will be required when this PCD 
is configured as DynamicHii or DynamicVpd. If the structure is big, it will require lots of PCDs to map its 
each field. If the structure has the bit field, its bit field can't match PCD. 

Proposal:
Enhance EDKII Build system to support VOID* PCD be mapped to C structure in DEC or DSC. PCD value can be specified
by structure field as C language style in DEC and DSC. Then, its value will be converted to byte array and assigned
to VOID* PCD. This is a pure build enhancement, and no change in PCD driver.
1. New syntax in DEC and DSC defines PCD with C structure. 
  a. PCD Data type will be C structure name.
  b. C structure header file and the dependent packages are required to be listed. 
  c. Example in DEC [PcdsFixedAtBuild] section:
    gStructuredPcdPkgTokenSpaceGuid.PcdTest|{0xFF}|TEST|0x00010080 {
        <HeaderFile>
          Guid/Test.h
        <Packages>
          MdePkg/MdePkg.dec
          MdeModulePkg/MdeModulePkg.dec
    }
2. Set the value to the structure fields like normal PCD in DEC/DSC/FDF. 
  a. If the field value is not specified, its default value will be zero. 
  b. Example in DEC/DSC [PcdsFixedAtBuild] section:
    gStructuredPcdPkgTokenSpaceGuid.PcdTest.Bool|TRUE
    gStructuredPcdPkgTokenSpaceGuid.PcdTest.Array[1].Foo|"ABC"
    gStructuredPcdPkgTokenSpaceGuid.PcdTest.C|0xFEDC
    gStructuredPcdPkgTokenSpaceGuid.PcdTest.D|2222
3. Pre AutoGen phase, Build tool will prepare the value for structure PCD. 
  a. Generate C file (name as pcdc file) and its Makefile to include PCD value initialization. 
    i. Parse PCD field values in DEC/DSC/FDF to generate pcdc file.
    ii. Developer provides their pcdc files to customize PCD value in one module INF.
  b. Compile C file to the executable tool like BaseTools C tools.
  c. Run the executable file to output the byte array PCD value. 
  d. Build tool gets the byte array PCD value and generate AutoGen code, continue to normal edk2 build process. 
4. Pcdc file will include the different functions to initialize the different PCD value on the different SKU 
  a. BaseTools CommonLib adds the generic APIs to parse Args, Get/Set PCD value.
  b. Pcdc file is compiled and run by Build tool, user doesn't need aware it.
5. Report
  a. Error report will point to the specified value in DEC or DSC when the value can't be assigned to structure field.
  b. Build Report will print Structure PCD value with byte array and field value both. 
6. C Structure requirement
  a. Structure field data type can't be VOID* or UINTN. its size must be same at the crossing ARCHs. 
  b. Structure field can be bits, union, nest structure, structure array, enum, pack, unpack. 
  c. Structure field value can be MACRO, Enum or constant value. 

Patch:
This patches add TestPkg to show StructurePcd Value Assignment usage in DEC and DSC.

Python StructuredPcdValueGenerator.py is added to show structure PCD usage. Its logic will be 
integrated into BaseTools later. This script bases on Package dec and Package dsc 
to convert structure PCD value to byte array. It depends on BaseTools C source CommonLib.
Before run this script, BaseTools are required to be compiled first. This script will
generate $(WORKSPACE)\Build\PcdValueInit\PcdValueInit.c with the structure PCD field value,
and generate $(WORKSPACE)\Build\PcdValueInit\Makefile to compile it to the executable file. 
It also generates $(WORKSPACE)\Build\PcdValueInit\Input.txt to include the initial PCD value
from its declartion in dec file. Last, run the generated executable file with Input.txt, and 
output the final PCD value in $(WORKSPACE)\Build\PcdValueInit\Output.txt.

In Windows:
1. enter into edk2
2. type edksetup.bat --nt32
3. nmake -f BaseTools\Makefile
4. C:\Python27\python.exe TestPkg\StructuredPcdValueGenerator.py -p TestPkg\TestPkg.dec -d TestPkg\TestPkg.dsc

In Linux:
1. enter into edk2
2. . edksetup.sh BaseTools
3. cd BaseTools
4. make
5. cd edk2
6. python TestPkg/StructuredPcdValueGenerator.py -p TestPkg/TestPkg.dec -d TestPkg/TestPkg.dsc

After run StructuredPcdValueGenerator.py, Structure PCD value will output as byte array.

Liming Gao (3):
  BaseTools: Update Makefile to work at absolute path
  BaseTools: Add PcdValueCommon logic into CommonLib
  TestPkg: Show Structure PCD value assignment

 BaseTools/Source/C/Common/GNUmakefile      |   3 +-
 BaseTools/Source/C/Common/Makefile         |   3 +-
 BaseTools/Source/C/Common/PcdValueCommon.c | 601 ++++++++++++++++++++++++
 BaseTools/Source/C/Common/PcdValueCommon.h |  78 ++++
 BaseTools/Source/C/Makefiles/app.makefile  |   2 +-
 BaseTools/Source/C/Makefiles/lib.makefile  |   2 +
 BaseTools/Source/C/Makefiles/ms.app        |   4 +-
 TestPkg/Include/Guid/Test.h                |  31 ++
 TestPkg/StructuredPcdValueGenerator.py     | 702 +++++++++++++++++++++++++++++
 TestPkg/TestPkg.dec                        |  44 ++
 TestPkg/TestPkg.dsc                        |  69 +++
 11 files changed, 1534 insertions(+), 5 deletions(-)
 create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.c
 create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.h
 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

-- 
2.8.0.windows.1



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC 1/3] BaseTools: Update Makefile to work at absolute path
  2017-04-11 15:16 [RFC 0/3] Structure PCD value assignment in DEC/DSC Liming Gao
@ 2017-04-11 15:16 ` Liming Gao
  2017-04-11 15:16 ` [RFC 2/3] BaseTools: Add PcdValueCommon logic into CommonLib Liming Gao
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Liming Gao @ 2017-04-11 15:16 UTC (permalink / raw)
  To: edk2-devel

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Liming Gao <liming.gao@intel.com>
---
 BaseTools/Source/C/Makefiles/app.makefile | 2 +-
 BaseTools/Source/C/Makefiles/ms.app       | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/BaseTools/Source/C/Makefiles/app.makefile b/BaseTools/Source/C/Makefiles/app.makefile
index e414551..6017b2d 100644
--- a/BaseTools/Source/C/Makefiles/app.makefile
+++ b/BaseTools/Source/C/Makefiles/app.makefile
@@ -23,6 +23,6 @@ all: $(MAKEROOT)/bin $(APPLICATION)
 $(APPLICATION): $(OBJECTS) 
 	$(LINKER) -o $(APPLICATION) $(BUILD_LFLAGS) $(OBJECTS) -L$(MAKEROOT)/libs $(LIBS)
 
-$(OBJECTS): ../Include/Common/BuildVersion.h
+$(OBJECTS): $(MAKEROOT)/Include/Common/BuildVersion.h
 
 include $(MAKEROOT)/Makefiles/footer.makefile
diff --git a/BaseTools/Source/C/Makefiles/ms.app b/BaseTools/Source/C/Makefiles/ms.app
index 93d51f9..37b7446 100644
--- a/BaseTools/Source/C/Makefiles/ms.app
+++ b/BaseTools/Source/C/Makefiles/ms.app
@@ -19,7 +19,7 @@ $(APPLICATION) : $(OBJECTS)
 	-@if not exist $(BIN_PATH) mkdir $(BIN_PATH)
 	$(LD) /nologo /debug /OPT:REF /OPT:ICF=10 /incremental:no /nodefaultlib:libc.lib /out:$@ $(LIBS) $**
 
-$(OBJECTS) : ..\Include\Common\BuildVersion.h
+$(OBJECTS) : $(SOURCE_PATH)\Include\Common\BuildVersion.h
 
 .PHONY:clean
 .PHONY:cleanall
@@ -30,5 +30,5 @@ clean:
 cleanall:
 	del /f /q $(OBJECTS) $(APPLICATION) *.pdb $(BIN_PATH)\$(APPNAME).pdb > nul
 
-!INCLUDE ..\Makefiles\ms.rule
+!INCLUDE $(SOURCE_PATH)\Makefiles\ms.rule
 
-- 
2.8.0.windows.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC 2/3] BaseTools: Add PcdValueCommon logic into CommonLib
  2017-04-11 15:16 [RFC 0/3] Structure PCD value assignment in DEC/DSC Liming Gao
  2017-04-11 15:16 ` [RFC 1/3] BaseTools: Update Makefile to work at absolute path Liming Gao
@ 2017-04-11 15:16 ` Liming Gao
  2017-04-11 15:16 ` [RFC 3/3] TestPkg: Show Structure PCD value assignment Liming Gao
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Liming Gao @ 2017-04-11 15:16 UTC (permalink / raw)
  To: edk2-devel

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Liming Gao <liming.gao@intel.com>
---
 BaseTools/Source/C/Common/GNUmakefile      |   3 +-
 BaseTools/Source/C/Common/Makefile         |   3 +-
 BaseTools/Source/C/Common/PcdValueCommon.c | 601 +++++++++++++++++++++++++++++
 BaseTools/Source/C/Common/PcdValueCommon.h |  78 ++++
 BaseTools/Source/C/Makefiles/lib.makefile  |   2 +
 5 files changed, 685 insertions(+), 2 deletions(-)
 create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.c
 create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.h

diff --git a/BaseTools/Source/C/Common/GNUmakefile b/BaseTools/Source/C/Common/GNUmakefile
index a193557..574d556 100644
--- a/BaseTools/Source/C/Common/GNUmakefile
+++ b/BaseTools/Source/C/Common/GNUmakefile
@@ -35,6 +35,7 @@ OBJECTS = \
   PeCoffLoaderEx.o \
   SimpleFileParsing.o \
   StringFuncs.o \
-  TianoCompress.o
+  TianoCompress.o \
+  PcdValueCommon.o
 
 include $(MAKEROOT)/Makefiles/lib.makefile
diff --git a/BaseTools/Source/C/Common/Makefile b/BaseTools/Source/C/Common/Makefile
index 41119b1..beb94c7 100644
--- a/BaseTools/Source/C/Common/Makefile
+++ b/BaseTools/Source/C/Common/Makefile
@@ -34,7 +34,8 @@ OBJECTS = \
   PeCoffLoaderEx.obj \
   SimpleFileParsing.obj \
   StringFuncs.obj \
-  TianoCompress.obj
+  TianoCompress.obj \
+  PcdValueCommon.obj
 
 !INCLUDE ..\Makefiles\ms.lib
 
diff --git a/BaseTools/Source/C/Common/PcdValueCommon.c b/BaseTools/Source/C/Common/PcdValueCommon.c
new file mode 100644
index 0000000..05b1328
--- /dev/null
+++ b/BaseTools/Source/C/Common/PcdValueCommon.c
@@ -0,0 +1,601 @@
+/** @file
+This file contains the PcdValue structure definition.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+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.
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "CommonLib.h"
+#include "PcdValueCommon.h"
+
+typedef enum {
+  PcdDataTypeBoolean,
+  PcdDataTypeUint8,
+  PcdDataTypeUint16,
+  PcdDataTypeUint32,
+  PcdDataTypeUint64,
+  PcdDataTypePointer
+} PCD_DATA_TYPE;
+
+typedef struct {
+  CHAR8          *SkuName;
+  CHAR8          *DefaultValueName;
+  CHAR8          *TokenSpaceGuidName;
+  CHAR8          *TokenName;
+  CHAR8          *DataType;
+  CHAR8          *Value;
+  PCD_DATA_TYPE  PcdDataType;
+} PCD_ENTRY;
+
+PCD_ENTRY  *PcdList;
+UINT32     PcdListLength;
+
+VOID
+STATIC
+RecordToken (
+  UINT8   *FileBuffer,
+  UINT32  PcdIndex,
+  UINT32  TokenIndex,
+  UINT32  TokenStart,
+  UINT32  TokenEnd
+  )
+{
+  UINT8  *Token;
+  
+  Token = malloc (TokenEnd - TokenStart + 1);
+  memcpy (Token, &FileBuffer[TokenStart], TokenEnd - TokenStart);
+  Token[TokenEnd - TokenStart] = 0;
+  switch (TokenIndex) {
+  case 0:
+    PcdList[PcdIndex].SkuName = Token;
+    break;
+  case 1:
+    PcdList[PcdIndex].DefaultValueName = Token;
+    break;
+  case 2:
+    PcdList[PcdIndex].TokenSpaceGuidName = Token;
+    break;
+  case 3:
+    PcdList[PcdIndex].TokenName = Token;
+    break;
+  case 4:
+    PcdList[PcdIndex].DataType = Token;
+    if (strcmp (Token, "BOOLEAN") == 0) {
+      PcdList[PcdIndex].PcdDataType = PcdDataTypeBoolean;
+    } else if (strcmp (Token, "UINT8") == 0) {
+      PcdList[PcdIndex].PcdDataType = PcdDataTypeUint8;
+    } else if (strcmp (Token, "UINT16") == 0) {
+      PcdList[PcdIndex].PcdDataType = PcdDataTypeUint16;
+    } else if (strcmp (Token, "UINT32") == 0) {
+      PcdList[PcdIndex].PcdDataType = PcdDataTypeUint32;
+    } else if (strcmp (Token, "UINT64") == 0) {
+      PcdList[PcdIndex].PcdDataType = PcdDataTypeUint64;
+    } else {
+      PcdList[PcdIndex].PcdDataType = PcdDataTypePointer;
+    }
+    break;
+  case 5:
+    PcdList[PcdIndex].Value = Token;
+    break;
+  }
+}
+
+int
+STATIC
+LookupPcdIndex (
+  CHAR8  *SkuName             OPTIONAL,
+  CHAR8  *DefaultValueName    OPTIONAL,
+  CHAR8  *TokenSpaceGuidName,
+  CHAR8  *TokenName
+  )
+{
+  UINT32  Index;
+  
+  if (SkuName == NULL) {
+    SkuName = "DEFAULT";
+  }
+  if (DefaultValueName == NULL) {
+    DefaultValueName = "DEFAULT";
+  }
+  for (Index = 0; Index < PcdListLength; Index++) {
+    if (strcmp(PcdList[Index].TokenSpaceGuidName, TokenSpaceGuidName) != 0) {
+      continue;
+    }
+    if (strcmp(PcdList[Index].TokenName, TokenName) != 0) {
+      continue;
+    }
+    if (strcmp(PcdList[Index].SkuName, SkuName) != 0) {
+      continue;
+    }
+    if (strcmp(PcdList[Index].DefaultValueName, DefaultValueName) != 0) {
+      continue;
+    }
+    return Index;
+  }
+  return -1;
+}
+
+UINT64
+__PcdGet (
+  CHAR8  *SkuName             OPTIONAL,
+  CHAR8  *DefaultValueName    OPTIONAL,
+  CHAR8  *TokenSpaceGuidName,
+  CHAR8  *TokenName
+  )
+{
+  int    Index;
+  UINT8  *End;
+  
+  Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+  if (Index < 0) {
+    fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+    exit (EXIT_FAILURE);
+  }
+  switch (PcdList[Index].PcdDataType) {
+  case PcdDataTypeBoolean:
+  case PcdDataTypeUint8:
+  case PcdDataTypeUint16:
+  case PcdDataTypeUint32:
+    return (UINT64)strtoul(PcdList[Index].Value, &End, 16);
+    break;
+  case PcdDataTypeUint64:
+    return (UINT64)strtoull(PcdList[Index].Value, &End, 16);
+    break;
+  case PcdDataTypePointer:
+    fprintf (stderr, "PCD %s.%s.%s.%s is structure.  Use PcdGetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+    exit (EXIT_FAILURE);
+    break;
+  }
+  return 0;
+}
+
+VOID
+__PcdSet (
+  CHAR8   *SkuName             OPTIONAL,
+  CHAR8   *DefaultValueName    OPTIONAL,
+  CHAR8   *TokenSpaceGuidName,
+  CHAR8   *TokenName,
+  UINT64  Value
+  )
+{
+  int    Index;
+  
+  Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+  if (Index < 0) {
+    fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+    exit (EXIT_FAILURE);
+  }
+  free(PcdList[Index].Value);
+  PcdList[Index].Value = malloc(20);
+  switch (PcdList[Index].PcdDataType) {
+  case PcdDataTypeBoolean:
+    if (Value == 0) {
+      strcpy (PcdList[Index].Value, "0x00");
+    } else {
+      strcpy (PcdList[Index].Value, "0x01");
+    }
+    break;
+  case PcdDataTypeUint8:
+    sprintf(PcdList[Index].Value, "0x%02x", (UINT8)(Value & 0xff));
+    break;
+  case PcdDataTypeUint16:
+    sprintf(PcdList[Index].Value, "0x%04x", (UINT16)(Value & 0xffff));
+    break;
+  case PcdDataTypeUint32:
+    sprintf(PcdList[Index].Value, "0x%08x", (UINT32)(Value & 0xffffffff));
+    break;
+  case PcdDataTypeUint64:
+    sprintf(PcdList[Index].Value, "0x%016llx", Value);
+    break;
+  case PcdDataTypePointer:
+    fprintf (stderr, "PCD %s.%s.%s.%s is structure.  Use PcdSetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+    exit (EXIT_FAILURE);
+    break;
+  }
+}
+
+VOID *
+__PcdGetPtr (
+  CHAR8   *SkuName             OPTIONAL,
+  CHAR8   *DefaultValueName    OPTIONAL,
+  CHAR8   *TokenSpaceGuidName,
+  CHAR8   *TokenName,
+  UINT32  *Size
+  )
+{
+  int    Index;
+  UINT8   *Value;
+  UINT8   *Buffer;
+  UINT8   *End;
+  UINT8   Byte;
+  
+  Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+  if (Index < 0) {
+    fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+    exit (EXIT_FAILURE);
+  }
+  switch (PcdList[Index].PcdDataType) {
+  case PcdDataTypeBoolean:
+  case PcdDataTypeUint8:
+  case PcdDataTypeUint16:
+  case PcdDataTypeUint32:
+  case PcdDataTypeUint64:
+    fprintf (stderr, "PCD %s.%s.%s.%s is a value.  Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+    exit (EXIT_FAILURE);
+    break;
+  case PcdDataTypePointer:
+    Value = &PcdList[Index].Value[1];
+    printf ("Value = %s\n", PcdList[Index].Value);
+    for (*Size = 0, Byte = (UINT8) strtoul(Value, &End, 16); Value != End; Byte = (UINT8) strtoul(Value, &End, 16), *Size = *Size + 1) {
+      printf("%x\n", Byte); 
+      Value = End + 1;
+    }
+    Buffer = malloc(*Size);
+    Value = &PcdList[Index].Value[1];
+    for (*Size = 0, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16); Value != End; Buffer[*Size] = (UINT8) strtoul(Value, &End, 16), *Size = *Size + 1) {
+      Value = End + 1;
+    }
+    return Buffer;
+  }
+  *Size = 0;
+  return 0;
+}
+
+VOID
+__PcdSetPtr (
+  CHAR8   *SkuName             OPTIONAL,
+  CHAR8   *DefaultValueName    OPTIONAL,
+  CHAR8   *TokenSpaceGuidName,
+  CHAR8   *TokenName,
+  UINT32  Size,
+  UINT8   *Value
+  )
+{
+  int    Index;
+  UINT32  ValueIndex;
+  
+  Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+  if (Index < 0) {
+    fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+    exit (EXIT_FAILURE);
+  }
+  switch (PcdList[Index].PcdDataType) {
+  case PcdDataTypeBoolean:
+  case PcdDataTypeUint8:
+  case PcdDataTypeUint16:
+  case PcdDataTypeUint32:
+  case PcdDataTypeUint64:
+    fprintf (stderr, "PCD %s.%s.%s.%s is a value.  Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+    exit (EXIT_FAILURE);
+    break;
+  case PcdDataTypePointer:
+    free(PcdList[Index].Value);
+    PcdList[Index].Value = malloc(Size * 5 + 3);
+    PcdList[Index].Value[0] = '{';
+    for (ValueIndex = 0; ValueIndex < Size; ValueIndex++) {
+      printf("Value[%d] = %02x\n", ValueIndex, Value[ValueIndex]);
+      sprintf(&PcdList[Index].Value[1 + ValueIndex * 5], "0x%02x,", Value[ValueIndex]);
+    }
+    PcdList[Index].Value[1 + Size * 5 - 1] = '}';
+    PcdList[Index].Value[1 + Size * 5    ] = 0;
+    break;
+  }
+}
+
+VOID
+STATIC
+ReadInputFile (
+  CHAR8   *InputFileName,
+  UINT8   **FileBuffer,
+  UINT32  *FileSize
+  )
+{
+  FILE    *InputFile;
+  UINT32  BytesRead;
+  
+  //
+  // Open Input file and read file data.
+  //
+  InputFile = fopen (InputFileName, "rb");
+  if (InputFile == NULL) {
+    fprintf (stderr, "Error opening file %s\n", InputFileName);
+    exit (EXIT_FAILURE);
+  }
+  
+  //
+  // Go to the end so that we can determine the file size
+  //
+  if (fseek (InputFile, 0, SEEK_END)) {
+    fprintf (stderr, "Error reading input file %s\n", InputFileName);
+    fclose (InputFile);
+    exit (EXIT_FAILURE);
+  }
+  
+  //
+  // Get the file size
+  //
+  *FileSize = ftell (InputFile);
+  if (*FileSize == -1) {
+    fprintf (stderr, "Error parsing the input file %s\n", InputFileName);
+    fclose (InputFile);
+    exit (EXIT_FAILURE);
+  }
+  
+  //
+  // Allocate a buffer
+  //
+  *FileBuffer = malloc (*FileSize);
+  if (*FileBuffer == NULL) {
+    fprintf (stderr, "Can not allocate buffer for input input file %s\n", InputFileName);
+    fclose (InputFile);
+    exit (EXIT_FAILURE);
+  }
+  
+  //
+  // Reset to the beginning of the file
+  //
+  if (fseek (InputFile, 0, SEEK_SET)) {
+    fprintf (stderr, "Error reading the input file %s\n", InputFileName);
+    fclose (InputFile);
+    free (*FileBuffer);
+    exit (EXIT_FAILURE);
+  }
+
+  //
+  // Read all of the file contents.
+  //
+  BytesRead = fread (*FileBuffer, sizeof (UINT8), *FileSize, InputFile);
+  if (BytesRead != *FileSize * sizeof (UINT8)) {
+    fprintf (stderr, "Error reading the input file %s\n", InputFileName);
+    fclose (InputFile);
+    free (*FileBuffer);
+    exit (EXIT_FAILURE);
+  }
+
+  //
+  // Close the file
+  //
+  fclose (InputFile);
+}
+
+VOID
+STATIC
+ParseFile (
+  UINT8   *FileBuffer,
+  UINT32  FileSize
+  )
+{
+  UINT32  Index;
+  UINT32  NumLines;
+  UINT32  TokenIndex;
+  UINT32  TokenStart;
+
+  for (Index = 0, NumLines = 0; Index < FileSize; Index++) {
+    if (FileBuffer[Index] == '\n') {
+      NumLines++;
+    }
+  }
+  PcdList = malloc((NumLines + 1) * sizeof(PcdList[0]));
+  
+  for (Index = 0, TokenIndex = 0, PcdListLength = 0, TokenStart = 0; Index < FileSize; Index++) {
+    if (FileBuffer[Index] == ' ') {
+      continue;
+    }
+    if (FileBuffer[Index] == '|' || FileBuffer[Index] == '.' || FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
+      RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
+      if (FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
+        if (TokenIndex != 0) {
+          PcdListLength++;
+          TokenIndex = 0;
+        }
+      } else {
+        TokenIndex++;
+      }
+      TokenStart = Index + 1;
+      continue;
+    }
+  }
+  if (Index > TokenStart) {
+    RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
+    if (TokenIndex != 0) {
+      PcdListLength++;
+    }
+  }
+}
+
+VOID
+STATIC
+WriteOutputFile (
+  CHAR8   *OutputFileName
+  )
+{
+  FILE    *OutputFile;
+  UINT32  Index;
+  
+  //
+  // Open output file
+  //
+  OutputFile = fopen (OutputFileName, "wb");
+  if (OutputFile == NULL) {
+    fprintf (stderr, "Error opening file %s\n", OutputFileName);
+    exit (EXIT_FAILURE);
+  }
+
+  for (Index = 0; Index < PcdListLength; Index++) {
+    fprintf (
+      OutputFile, 
+      "%s.%s.%s.%s|%s|%s\n", 
+      PcdList[Index].SkuName,
+      PcdList[Index].DefaultValueName,
+      PcdList[Index].TokenSpaceGuidName,
+      PcdList[Index].TokenName,
+      PcdList[Index].DataType,
+      PcdList[Index].Value
+      );
+  }
+
+  //
+  // Done, write output file.
+  //
+  if (OutputFile != NULL) {
+    fclose (OutputFile);
+  }
+}
+
+VOID
+STATIC
+Usage (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+  None
+
+Returns:
+
+  None
+
+--*/
+{
+  fprintf (stdout, "Usage: -i <input_file> -o <output_file>\n\n");
+  fprintf (stdout, "optional arguments:\n");
+  fprintf (stdout, "  -h, --help            Show this help message and exit\n");
+  fprintf (stdout, "  -i INPUT_FILENAME, --input INPUT_FILENAME\n\
+                        PCD Database Input file name\n");
+  fprintf (stdout, "  -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\
+                        PCD Database Output file name\n");
+}
+
+VOID
+STATIC
+ParseArguments (
+  int    argc,
+  char   *argv[],
+  CHAR8  **InputFileName,
+  CHAR8  **OutputFileName
+  )
+{
+  if (argc == 1) {
+    fprintf (stderr, "Missing options\n");
+    exit (EXIT_FAILURE);
+  }
+
+  //
+  // Parse command line
+  //
+  argc--;
+  argv++;
+
+  if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
+    Usage ();
+    exit (EXIT_SUCCESS);
+  }
+
+  while (argc > 0) {
+    if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--input") == 0)) {
+      if (argv[1] == NULL || argv[1][0] == '-') {
+        fprintf (stderr, "Invalid option value.  Input File name is missing for -i option\n");
+        exit (EXIT_FAILURE);
+      }
+      *InputFileName = argv[1];
+      argc -= 2;
+      argv += 2;
+      continue; 
+    }
+    
+    if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
+      if (argv[1] == NULL || argv[1][0] == '-') {
+        fprintf (stderr, "Invalid option value.  Output File name is missing for -i option\n");
+        exit (EXIT_FAILURE);
+      }
+      *OutputFileName = argv[1];
+      argc -= 2;
+      argv += 2;
+      continue; 
+    }
+    
+    if (argv[0][0] == '-') {
+      fprintf (stderr, "Unknown option %s\n", argv[0]);
+      exit (EXIT_FAILURE);
+    }
+    argc --;
+    argv ++;
+  }
+  
+  //
+  // Check Input paramters
+  //
+  if (*InputFileName == NULL) {
+    fprintf (stderr, "Missing option.  Input files is not specified\n");
+    exit (EXIT_FAILURE);
+  } else {
+    printf ("Input file name is %s\n", *InputFileName);
+  }
+
+  if (*OutputFileName == NULL) {
+    fprintf (stderr, "Missing option.  Output file is not specified\n");
+    exit (EXIT_FAILURE);
+  } else {
+    printf ("Output file name is %s\n", *OutputFileName);
+  }
+}
+
+int
+PcdValueMain (
+  int   argc,
+  char  *argv[]
+  )
+{
+  CHAR8   *InputFileName;
+  CHAR8   *OutputFileName;
+  UINT8   *FileBuffer;
+  UINT32  FileSize;
+  
+  printf ("PCD tool start.\n");
+  
+  //
+  //
+  //
+  ParseArguments (argc, argv, &InputFileName, &OutputFileName);
+
+  //
+  // Open Input file and read file data.
+  //
+  ReadInputFile (InputFileName, &FileBuffer, &FileSize);
+  
+  //
+  //
+  //
+  ParseFile (FileBuffer, FileSize);
+  
+  //
+  // Customize PCD values in the PCD Database
+  //
+  PcdEntryPoint ();
+
+  //
+  //
+  //
+  WriteOutputFile (OutputFileName);
+  
+  printf ("PCD tool done.\n");
+  
+  exit (EXIT_SUCCESS);
+}
diff --git a/BaseTools/Source/C/Common/PcdValueCommon.h b/BaseTools/Source/C/Common/PcdValueCommon.h
new file mode 100644
index 0000000..768d7a9
--- /dev/null
+++ b/BaseTools/Source/C/Common/PcdValueCommon.h
@@ -0,0 +1,78 @@
+/** @file
+Header file for CalcuateCrc32 routine
+
+Copyright (c) 2004 - 2014, 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.             
+
+**/
+
+#ifndef _PCD_VALUE_COMMON_H
+#define _PCD_VALUE_COMMON_H
+
+#include <Common/UefiBaseTypes.h>
+
+#define __FIELD_SIZE(TYPE, Field) (sizeof((TYPE *)0)->Field)
+#define __ARRAY_ELEMENT_SIZE(TYPE, Field) (sizeof((TYPE *)0)->Field[0])
+#define __OFFSET_OF(TYPE, Field) ((UINT32) &(((TYPE *)0)->Field))
+#define __FLEXIBLE_SIZE(Size, TYPE, Field, MaxIndex)   if (__FIELD_SIZE(TYPE, Field) == 0) Size = (__OFFSET_OF(TYPE, Field) + __ARRAY_ELEMENT_SIZE(TYPE, Field) * (MaxIndex))
+
+VOID
+PcdEntryPoint (
+  VOID
+  );
+
+int
+PcdValueMain (
+  int   argc,
+  char  *argv[]
+  );
+
+VOID
+__PcdSet (
+  CHAR8   *SkuName             OPTIONAL,
+  CHAR8   *DefaultValueName    OPTIONAL,
+  CHAR8   *TokenSpaceGuidName,
+  CHAR8   *TokenName,
+  UINT64  Value
+  );
+
+VOID
+__PcdSet (
+  CHAR8   *SkuName             OPTIONAL,
+  CHAR8   *DefaultValueName    OPTIONAL,
+  CHAR8   *TokenSpaceGuidName,
+  CHAR8   *TokenName,
+  UINT64  Value
+  );
+
+VOID *
+__PcdGetPtr (
+  CHAR8   *SkuName             OPTIONAL,
+  CHAR8   *DefaultValueName    OPTIONAL,
+  CHAR8   *TokenSpaceGuidName,
+  CHAR8   *TokenName,
+  UINT32  *Size
+  );
+
+VOID
+__PcdSetPtr (
+  CHAR8   *SkuName             OPTIONAL,
+  CHAR8   *DefaultValueName    OPTIONAL,
+  CHAR8   *TokenSpaceGuidName,
+  CHAR8   *TokenName,
+  UINT32  Size,
+  UINT8   *Value
+  );
+
+#define PcdGet(A, B, C, D)  __PcdGet(#A, #B, #C, #D)
+#define PcdSet(A, B, C, D, Value)  __PcdSet(#A, #B, #C, #D, Value)
+#define PcdGetPtr(A, B, C, D, Size)  __PcdGetPtr(#A, #B, #C, #D, Size)
+#define PcdSetPtr(A, B, C, D, Size, Value)  __PcdSetPtr(#A, #B, #C, #D, Size, Value)
+
+#endif
diff --git a/BaseTools/Source/C/Makefiles/lib.makefile b/BaseTools/Source/C/Makefiles/lib.makefile
index bba76be..c592806 100644
--- a/BaseTools/Source/C/Makefiles/lib.makefile
+++ b/BaseTools/Source/C/Makefiles/lib.makefile
@@ -13,6 +13,8 @@
 
 include $(MAKEROOT)/Makefiles/header.makefile
 
+BUILD_CFLAGS += -Wno-error
+
 LIBRARY = $(MAKEROOT)/libs/lib$(LIBNAME).a
 
 all: $(MAKEROOT)/libs $(LIBRARY) 
-- 
2.8.0.windows.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC 3/3] TestPkg: Show Structure PCD value assignment
  2017-04-11 15:16 [RFC 0/3] Structure PCD value assignment in DEC/DSC Liming Gao
  2017-04-11 15:16 ` [RFC 1/3] BaseTools: Update Makefile to work at absolute path Liming Gao
  2017-04-11 15:16 ` [RFC 2/3] BaseTools: Add PcdValueCommon logic into CommonLib Liming Gao
@ 2017-04-11 15:16 ` Liming Gao
  2017-04-11 15:24 ` [RFC 0/3] Structure PCD value assignment in DEC/DSC Laszlo Ersek
  2017-05-05  6:00 ` Tim Lewis
  4 siblings, 0 replies; 7+ messages in thread
From: Liming Gao @ 2017-04-11 15:16 UTC (permalink / raw)
  To: edk2-devel

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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC 0/3] Structure PCD value assignment in DEC/DSC
  2017-04-11 15:16 [RFC 0/3] Structure PCD value assignment in DEC/DSC Liming Gao
                   ` (2 preceding siblings ...)
  2017-04-11 15:16 ` [RFC 3/3] TestPkg: Show Structure PCD value assignment Liming Gao
@ 2017-04-11 15:24 ` Laszlo Ersek
  2017-04-11 16:46   ` Kinney, Michael D
  2017-05-05  6:00 ` Tim Lewis
  4 siblings, 1 reply; 7+ messages in thread
From: Laszlo Ersek @ 2017-04-11 15:24 UTC (permalink / raw)
  To: Liming Gao, edk2-devel

On 04/11/17 17:16, Liming Gao wrote:
> Requirment: Map VOID* PCD to C structure
> 1. When PCD is configured as DynamicHii, it will be map to one EFI variable. If PCD is VOID*, it can map to the 
> whole EFI variable. Most EFI variable data are defined as C structure. 
> 2. Some PCDs are designed as C style structure, such as gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters.
> 
> Current limitation:
> 1. VOID* PCD Value must be byte array. Its value is hard to be specified. 
> 2. If single PCD is defined to map one field in structure, its offset and width will be required when this PCD 
> is configured as DynamicHii or DynamicVpd. If the structure is big, it will require lots of PCDs to map its 
> each field. If the structure has the bit field, its bit field can't match PCD. 
> 
> Proposal:
> Enhance EDKII Build system to support VOID* PCD be mapped to C structure in DEC or DSC. PCD value can be specified
> by structure field as C language style in DEC and DSC. Then, its value will be converted to byte array and assigned
> to VOID* PCD. This is a pure build enhancement, and no change in PCD driver.
> 1. New syntax in DEC and DSC defines PCD with C structure. 
>   a. PCD Data type will be C structure name.
>   b. C structure header file and the dependent packages are required to be listed. 
>   c. Example in DEC [PcdsFixedAtBuild] section:
>     gStructuredPcdPkgTokenSpaceGuid.PcdTest|{0xFF}|TEST|0x00010080 {
>         <HeaderFile>
>           Guid/Test.h
>         <Packages>
>           MdePkg/MdePkg.dec
>           MdeModulePkg/MdeModulePkg.dec
>     }
> 2. Set the value to the structure fields like normal PCD in DEC/DSC/FDF. 
>   a. If the field value is not specified, its default value will be zero. 
>   b. Example in DEC/DSC [PcdsFixedAtBuild] section:
>     gStructuredPcdPkgTokenSpaceGuid.PcdTest.Bool|TRUE
>     gStructuredPcdPkgTokenSpaceGuid.PcdTest.Array[1].Foo|"ABC"
>     gStructuredPcdPkgTokenSpaceGuid.PcdTest.C|0xFEDC
>     gStructuredPcdPkgTokenSpaceGuid.PcdTest.D|2222
> 3. Pre AutoGen phase, Build tool will prepare the value for structure PCD. 
>   a. Generate C file (name as pcdc file) and its Makefile to include PCD value initialization. 
>     i. Parse PCD field values in DEC/DSC/FDF to generate pcdc file.
>     ii. Developer provides their pcdc files to customize PCD value in one module INF.
>   b. Compile C file to the executable tool like BaseTools C tools.
>   c. Run the executable file to output the byte array PCD value. 
>   d. Build tool gets the byte array PCD value and generate AutoGen code, continue to normal edk2 build process. 
> 4. Pcdc file will include the different functions to initialize the different PCD value on the different SKU 
>   a. BaseTools CommonLib adds the generic APIs to parse Args, Get/Set PCD value.
>   b. Pcdc file is compiled and run by Build tool, user doesn't need aware it.
> 5. Report
>   a. Error report will point to the specified value in DEC or DSC when the value can't be assigned to structure field.
>   b. Build Report will print Structure PCD value with byte array and field value both. 
> 6. C Structure requirement
>   a. Structure field data type can't be VOID* or UINTN. its size must be same at the crossing ARCHs. 
>   b. Structure field can be bits, union, nest structure, structure array, enum, pack, unpack. 
>   c. Structure field value can be MACRO, Enum or constant value. 

My only request at this point is to please file two BZs:
- one for the feature itself (apparently the requirement exists already),
- another one for the DEC spec, to document the feature.

Thank you,
Laszlo

> 
> Patch:
> This patches add TestPkg to show StructurePcd Value Assignment usage in DEC and DSC.
> 
> Python StructuredPcdValueGenerator.py is added to show structure PCD usage. Its logic will be 
> integrated into BaseTools later. This script bases on Package dec and Package dsc 
> to convert structure PCD value to byte array. It depends on BaseTools C source CommonLib.
> Before run this script, BaseTools are required to be compiled first. This script will
> generate $(WORKSPACE)\Build\PcdValueInit\PcdValueInit.c with the structure PCD field value,
> and generate $(WORKSPACE)\Build\PcdValueInit\Makefile to compile it to the executable file. 
> It also generates $(WORKSPACE)\Build\PcdValueInit\Input.txt to include the initial PCD value
> from its declartion in dec file. Last, run the generated executable file with Input.txt, and 
> output the final PCD value in $(WORKSPACE)\Build\PcdValueInit\Output.txt.
> 
> In Windows:
> 1. enter into edk2
> 2. type edksetup.bat --nt32
> 3. nmake -f BaseTools\Makefile
> 4. C:\Python27\python.exe TestPkg\StructuredPcdValueGenerator.py -p TestPkg\TestPkg.dec -d TestPkg\TestPkg.dsc
> 
> In Linux:
> 1. enter into edk2
> 2. . edksetup.sh BaseTools
> 3. cd BaseTools
> 4. make
> 5. cd edk2
> 6. python TestPkg/StructuredPcdValueGenerator.py -p TestPkg/TestPkg.dec -d TestPkg/TestPkg.dsc
> 
> After run StructuredPcdValueGenerator.py, Structure PCD value will output as byte array.
> 
> Liming Gao (3):
>   BaseTools: Update Makefile to work at absolute path
>   BaseTools: Add PcdValueCommon logic into CommonLib
>   TestPkg: Show Structure PCD value assignment
> 
>  BaseTools/Source/C/Common/GNUmakefile      |   3 +-
>  BaseTools/Source/C/Common/Makefile         |   3 +-
>  BaseTools/Source/C/Common/PcdValueCommon.c | 601 ++++++++++++++++++++++++
>  BaseTools/Source/C/Common/PcdValueCommon.h |  78 ++++
>  BaseTools/Source/C/Makefiles/app.makefile  |   2 +-
>  BaseTools/Source/C/Makefiles/lib.makefile  |   2 +
>  BaseTools/Source/C/Makefiles/ms.app        |   4 +-
>  TestPkg/Include/Guid/Test.h                |  31 ++
>  TestPkg/StructuredPcdValueGenerator.py     | 702 +++++++++++++++++++++++++++++
>  TestPkg/TestPkg.dec                        |  44 ++
>  TestPkg/TestPkg.dsc                        |  69 +++
>  11 files changed, 1534 insertions(+), 5 deletions(-)
>  create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.c
>  create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.h
>  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
> 



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC 0/3] Structure PCD value assignment in DEC/DSC
  2017-04-11 15:24 ` [RFC 0/3] Structure PCD value assignment in DEC/DSC Laszlo Ersek
@ 2017-04-11 16:46   ` Kinney, Michael D
  0 siblings, 0 replies; 7+ messages in thread
From: Kinney, Michael D @ 2017-04-11 16:46 UTC (permalink / raw)
  To: Laszlo Ersek, Gao, Liming, edk2-devel@lists.01.org,
	Kinney, Michael D

Hi Laszlo,

I agree that the feature request should go into Bugzilla right away.

I would like to the discussion on the RFC conclude before we enter
spec and code Bugzilla entries, because based on feedback to the RFC
the specific spec and tool changes may need some adjustments.

Thanks,

Mike


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Laszlo
> Ersek
> Sent: Tuesday, April 11, 2017 8:24 AM
> To: Gao, Liming <liming.gao@intel.com>; edk2-devel@lists.01.org
> Subject: Re: [edk2] [RFC 0/3] Structure PCD value assignment in DEC/DSC
> 
> On 04/11/17 17:16, Liming Gao wrote:
> > Requirment: Map VOID* PCD to C structure
> > 1. When PCD is configured as DynamicHii, it will be map to one EFI variable. If
> PCD is VOID*, it can map to the
> > whole EFI variable. Most EFI variable data are defined as C structure.
> > 2. Some PCDs are designed as C style structure, such as
> gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters.
> >
> > Current limitation:
> > 1. VOID* PCD Value must be byte array. Its value is hard to be specified.
> > 2. If single PCD is defined to map one field in structure, its offset and width
> will be required when this PCD
> > is configured as DynamicHii or DynamicVpd. If the structure is big, it will
> require lots of PCDs to map its
> > each field. If the structure has the bit field, its bit field can't match PCD.
> >
> > Proposal:
> > Enhance EDKII Build system to support VOID* PCD be mapped to C structure in DEC
> or DSC. PCD value can be specified
> > by structure field as C language style in DEC and DSC. Then, its value will be
> converted to byte array and assigned
> > to VOID* PCD. This is a pure build enhancement, and no change in PCD driver.
> > 1. New syntax in DEC and DSC defines PCD with C structure.
> >   a. PCD Data type will be C structure name.
> >   b. C structure header file and the dependent packages are required to be
> listed.
> >   c. Example in DEC [PcdsFixedAtBuild] section:
> >     gStructuredPcdPkgTokenSpaceGuid.PcdTest|{0xFF}|TEST|0x00010080 {
> >         <HeaderFile>
> >           Guid/Test.h
> >         <Packages>
> >           MdePkg/MdePkg.dec
> >           MdeModulePkg/MdeModulePkg.dec
> >     }
> > 2. Set the value to the structure fields like normal PCD in DEC/DSC/FDF.
> >   a. If the field value is not specified, its default value will be zero.
> >   b. Example in DEC/DSC [PcdsFixedAtBuild] section:
> >     gStructuredPcdPkgTokenSpaceGuid.PcdTest.Bool|TRUE
> >     gStructuredPcdPkgTokenSpaceGuid.PcdTest.Array[1].Foo|"ABC"
> >     gStructuredPcdPkgTokenSpaceGuid.PcdTest.C|0xFEDC
> >     gStructuredPcdPkgTokenSpaceGuid.PcdTest.D|2222
> > 3. Pre AutoGen phase, Build tool will prepare the value for structure PCD.
> >   a. Generate C file (name as pcdc file) and its Makefile to include PCD value
> initialization.
> >     i. Parse PCD field values in DEC/DSC/FDF to generate pcdc file.
> >     ii. Developer provides their pcdc files to customize PCD value in one
> module INF.
> >   b. Compile C file to the executable tool like BaseTools C tools.
> >   c. Run the executable file to output the byte array PCD value.
> >   d. Build tool gets the byte array PCD value and generate AutoGen code,
> continue to normal edk2 build process.
> > 4. Pcdc file will include the different functions to initialize the different
> PCD value on the different SKU
> >   a. BaseTools CommonLib adds the generic APIs to parse Args, Get/Set PCD
> value.
> >   b. Pcdc file is compiled and run by Build tool, user doesn't need aware it.
> > 5. Report
> >   a. Error report will point to the specified value in DEC or DSC when the
> value can't be assigned to structure field.
> >   b. Build Report will print Structure PCD value with byte array and field
> value both.
> > 6. C Structure requirement
> >   a. Structure field data type can't be VOID* or UINTN. its size must be same
> at the crossing ARCHs.
> >   b. Structure field can be bits, union, nest structure, structure array, enum,
> pack, unpack.
> >   c. Structure field value can be MACRO, Enum or constant value.
> 
> My only request at this point is to please file two BZs:
> - one for the feature itself (apparently the requirement exists already),
> - another one for the DEC spec, to document the feature.
> 
> Thank you,
> Laszlo
> 
> >
> > Patch:
> > This patches add TestPkg to show StructurePcd Value Assignment usage in DEC and
> DSC.
> >
> > Python StructuredPcdValueGenerator.py is added to show structure PCD usage. Its
> logic will be
> > integrated into BaseTools later. This script bases on Package dec and Package
> dsc
> > to convert structure PCD value to byte array. It depends on BaseTools C source
> CommonLib.
> > Before run this script, BaseTools are required to be compiled first. This
> script will
> > generate $(WORKSPACE)\Build\PcdValueInit\PcdValueInit.c with the structure PCD
> field value,
> > and generate $(WORKSPACE)\Build\PcdValueInit\Makefile to compile it to the
> executable file.
> > It also generates $(WORKSPACE)\Build\PcdValueInit\Input.txt to include the
> initial PCD value
> > from its declartion in dec file. Last, run the generated executable file with
> Input.txt, and
> > output the final PCD value in $(WORKSPACE)\Build\PcdValueInit\Output.txt.
> >
> > In Windows:
> > 1. enter into edk2
> > 2. type edksetup.bat --nt32
> > 3. nmake -f BaseTools\Makefile
> > 4. C:\Python27\python.exe TestPkg\StructuredPcdValueGenerator.py -p
> TestPkg\TestPkg.dec -d TestPkg\TestPkg.dsc
> >
> > In Linux:
> > 1. enter into edk2
> > 2. . edksetup.sh BaseTools
> > 3. cd BaseTools
> > 4. make
> > 5. cd edk2
> > 6. python TestPkg/StructuredPcdValueGenerator.py -p TestPkg/TestPkg.dec -d
> TestPkg/TestPkg.dsc
> >
> > After run StructuredPcdValueGenerator.py, Structure PCD value will output as
> byte array.
> >
> > Liming Gao (3):
> >   BaseTools: Update Makefile to work at absolute path
> >   BaseTools: Add PcdValueCommon logic into CommonLib
> >   TestPkg: Show Structure PCD value assignment
> >
> >  BaseTools/Source/C/Common/GNUmakefile      |   3 +-
> >  BaseTools/Source/C/Common/Makefile         |   3 +-
> >  BaseTools/Source/C/Common/PcdValueCommon.c | 601 ++++++++++++++++++++++++
> >  BaseTools/Source/C/Common/PcdValueCommon.h |  78 ++++
> >  BaseTools/Source/C/Makefiles/app.makefile  |   2 +-
> >  BaseTools/Source/C/Makefiles/lib.makefile  |   2 +
> >  BaseTools/Source/C/Makefiles/ms.app        |   4 +-
> >  TestPkg/Include/Guid/Test.h                |  31 ++
> >  TestPkg/StructuredPcdValueGenerator.py     | 702 +++++++++++++++++++++++++++++
> >  TestPkg/TestPkg.dec                        |  44 ++
> >  TestPkg/TestPkg.dsc                        |  69 +++
> >  11 files changed, 1534 insertions(+), 5 deletions(-)
> >  create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.c
> >  create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.h
> >  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
> >
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC 0/3] Structure PCD value assignment in DEC/DSC
  2017-04-11 15:16 [RFC 0/3] Structure PCD value assignment in DEC/DSC Liming Gao
                   ` (3 preceding siblings ...)
  2017-04-11 15:24 ` [RFC 0/3] Structure PCD value assignment in DEC/DSC Laszlo Ersek
@ 2017-05-05  6:00 ` Tim Lewis
  4 siblings, 0 replies; 7+ messages in thread
From: Tim Lewis @ 2017-05-05  6:00 UTC (permalink / raw)
  To: Gao, Liming, edk2-devel@lists.01.org

Mike --

Sorry for the delay. We have reviewed this RFC internally and we believe it is a useful change. 

Thanks,

Tim

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Gao, Liming
Sent: Tuesday, April 11, 2017 8:17 AM
To: edk2-devel@lists.01.org
Subject: [edk2] [RFC 0/3] Structure PCD value assignment in DEC/DSC

Requirment: Map VOID* PCD to C structure 1. When PCD is configured as DynamicHii, it will be map to one EFI variable. If PCD is VOID*, it can map to the whole EFI variable. Most EFI variable data are defined as C structure.
2. Some PCDs are designed as C style structure, such as gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters.

Current limitation:
1. VOID* PCD Value must be byte array. Its value is hard to be specified.
2. If single PCD is defined to map one field in structure, its offset and width will be required when this PCD is configured as DynamicHii or DynamicVpd. If the structure is big, it will require lots of PCDs to map its each field. If the structure has the bit field, its bit field can't match PCD.

Proposal:
Enhance EDKII Build system to support VOID* PCD be mapped to C structure in DEC or DSC. PCD value can be specified by structure field as C language style in DEC and DSC. Then, its value will be converted to byte array and assigned to VOID* PCD. This is a pure build enhancement, and no change in PCD driver.
1. New syntax in DEC and DSC defines PCD with C structure.
  a. PCD Data type will be C structure name.
  b. C structure header file and the dependent packages are required to be listed.
  c. Example in DEC [PcdsFixedAtBuild] section:
    gStructuredPcdPkgTokenSpaceGuid.PcdTest|{0xFF}|TEST|0x00010080 {
        <HeaderFile>
          Guid/Test.h
        <Packages>
          MdePkg/MdePkg.dec
          MdeModulePkg/MdeModulePkg.dec
    }
2. Set the value to the structure fields like normal PCD in DEC/DSC/FDF.
  a. If the field value is not specified, its default value will be zero.
  b. Example in DEC/DSC [PcdsFixedAtBuild] section:
    gStructuredPcdPkgTokenSpaceGuid.PcdTest.Bool|TRUE
    gStructuredPcdPkgTokenSpaceGuid.PcdTest.Array[1].Foo|"ABC"
    gStructuredPcdPkgTokenSpaceGuid.PcdTest.C|0xFEDC
    gStructuredPcdPkgTokenSpaceGuid.PcdTest.D|2222
3. Pre AutoGen phase, Build tool will prepare the value for structure PCD.
  a. Generate C file (name as pcdc file) and its Makefile to include PCD value initialization.
    i. Parse PCD field values in DEC/DSC/FDF to generate pcdc file.
    ii. Developer provides their pcdc files to customize PCD value in one module INF.
  b. Compile C file to the executable tool like BaseTools C tools.
  c. Run the executable file to output the byte array PCD value.
  d. Build tool gets the byte array PCD value and generate AutoGen code, continue to normal edk2 build process.
4. Pcdc file will include the different functions to initialize the different PCD value on the different SKU
  a. BaseTools CommonLib adds the generic APIs to parse Args, Get/Set PCD value.
  b. Pcdc file is compiled and run by Build tool, user doesn't need aware it.
5. Report
  a. Error report will point to the specified value in DEC or DSC when the value can't be assigned to structure field.
  b. Build Report will print Structure PCD value with byte array and field value both.
6. C Structure requirement
  a. Structure field data type can't be VOID* or UINTN. its size must be same at the crossing ARCHs.
  b. Structure field can be bits, union, nest structure, structure array, enum, pack, unpack.
  c. Structure field value can be MACRO, Enum or constant value.

Patch:
This patches add TestPkg to show StructurePcd Value Assignment usage in DEC and DSC.

Python StructuredPcdValueGenerator.py is added to show structure PCD usage. Its logic will be integrated into BaseTools later. This script bases on Package dec and Package dsc to convert structure PCD value to byte array. It depends on BaseTools C source CommonLib.
Before run this script, BaseTools are required to be compiled first. This script will generate $(WORKSPACE)\Build\PcdValueInit\PcdValueInit.c with the structure PCD field value, and generate $(WORKSPACE)\Build\PcdValueInit\Makefile to compile it to the executable file.
It also generates $(WORKSPACE)\Build\PcdValueInit\Input.txt to include the initial PCD value from its declartion in dec file. Last, run the generated executable file with Input.txt, and output the final PCD value in $(WORKSPACE)\Build\PcdValueInit\Output.txt.

In Windows:
1. enter into edk2
2. type edksetup.bat --nt32
3. nmake -f BaseTools\Makefile
4. C:\Python27\python.exe TestPkg\StructuredPcdValueGenerator.py -p TestPkg\TestPkg.dec -d TestPkg\TestPkg.dsc

In Linux:
1. enter into edk2
2. . edksetup.sh BaseTools
3. cd BaseTools
4. make
5. cd edk2
6. python TestPkg/StructuredPcdValueGenerator.py -p TestPkg/TestPkg.dec -d TestPkg/TestPkg.dsc

After run StructuredPcdValueGenerator.py, Structure PCD value will output as byte array.

Liming Gao (3):
  BaseTools: Update Makefile to work at absolute path
  BaseTools: Add PcdValueCommon logic into CommonLib
  TestPkg: Show Structure PCD value assignment

 BaseTools/Source/C/Common/GNUmakefile      |   3 +-
 BaseTools/Source/C/Common/Makefile         |   3 +-
 BaseTools/Source/C/Common/PcdValueCommon.c | 601 ++++++++++++++++++++++++  BaseTools/Source/C/Common/PcdValueCommon.h |  78 ++++
 BaseTools/Source/C/Makefiles/app.makefile  |   2 +-
 BaseTools/Source/C/Makefiles/lib.makefile  |   2 +
 BaseTools/Source/C/Makefiles/ms.app        |   4 +-
 TestPkg/Include/Guid/Test.h                |  31 ++
 TestPkg/StructuredPcdValueGenerator.py     | 702 +++++++++++++++++++++++++++++
 TestPkg/TestPkg.dec                        |  44 ++
 TestPkg/TestPkg.dsc                        |  69 +++
 11 files changed, 1534 insertions(+), 5 deletions(-)  create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.c
 create mode 100644 BaseTools/Source/C/Common/PcdValueCommon.h
 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

--
2.8.0.windows.1

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


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-05-05  6:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-04-11 15:16 [RFC 0/3] Structure PCD value assignment in DEC/DSC Liming Gao
2017-04-11 15:16 ` [RFC 1/3] BaseTools: Update Makefile to work at absolute path Liming Gao
2017-04-11 15:16 ` [RFC 2/3] BaseTools: Add PcdValueCommon logic into CommonLib Liming Gao
2017-04-11 15:16 ` [RFC 3/3] TestPkg: Show Structure PCD value assignment Liming Gao
2017-04-11 15:24 ` [RFC 0/3] Structure PCD value assignment in DEC/DSC Laszlo Ersek
2017-04-11 16:46   ` Kinney, Michael D
2017-05-05  6:00 ` Tim Lewis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox