MdeModulePkg: Add VarCheckPcdLib NULL class library

The check will be based on PcdVarCheck binary that generated
by BaseTools.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18294 6f19259b-4bc3-4df7-8a09-765794883524
diff --git a/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
new file mode 100644
index 0000000..b9d235b
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
@@ -0,0 +1,65 @@
+## @file

+#  NULL class library to register var check PCD handler.

+#

+#  In platform *.fdf, the example build rule for the driver this library linked to.

+#    [Rule.Common.DXE_RUNTIME_DRIVER.VARCHECKPCD]

+#      FILE DRIVER = $(NAMED_GUID) {

+#        RAW          BIN                     $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/PcdVarCheck.bin

+#        DXE_DEPEX    DXE_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex

+#        PE32         PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi

+#        UI           STRING="$(MODULE_NAME)" Optional

+#        VERSION      STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)

+#      }

+#

+#    or

+#

+#    [Rule.Common.DXE_SMM_DRIVER.VARCHECKPCD]

+#      FILE SMM = $(NAMED_GUID) {

+#        RAW          BIN                     $(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/PcdVarCheck.bin

+#        DXE_DEPEX    DXE_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex

+#        PE32         PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi

+#        UI           STRING="$(MODULE_NAME)" Optional

+#        VERSION      STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)

+#      }

+#

+#  In platform *.dsc, also need add one line below to enable PcdVarCheck.bin generation by BaseTools.

+#    PCD_VAR_CHECK_GENERATION            = TRUE

+#

+#  Copyright (c) 2015, 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]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = VarCheckPcdLib

+  MODULE_UNI_FILE                = VarCheckPcdLib.uni

+  FILE_GUID                      = D4FA5311-5F1F-4B1E-9AC3-90C4DFC029F1

+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = NULL|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER

+  CONSTRUCTOR                    = VarCheckPcdLibNullClassConstructor

+

+[Sources]

+  VarCheckPcdLibNullClass.c

+  VarCheckPcdStructure.h

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+

+[LibraryClasses]

+  BaseLib

+  DebugLib

+  BaseMemoryLib

+  DxeServicesLib

+  MemoryAllocationLib

+  VarCheckLib

diff --git a/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.uni b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.uni
new file mode 100644
index 0000000..4a3d932
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.uni
Binary files differ
diff --git a/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLibNullClass.c b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLibNullClass.c
new file mode 100644
index 0000000..72b0363
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLibNullClass.c
@@ -0,0 +1,474 @@
+/** @file

+  Var Check PCD handler.

+

+Copyright (c) 2015, 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.

+

+**/

+

+#include <Library/VarCheckLib.h>

+#include <Library/BaseLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/DxeServicesLib.h>

+

+#include "VarCheckPcdStructure.h"

+

+//#define DUMP_VAR_CHECK_PCD

+

+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckPcdHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

+

+/**

+  Dump some hexadecimal data.

+

+  @param[in] Indent     How many spaces to indent the output.

+  @param[in] Offset     The offset of the dump.

+  @param[in] DataSize   The size in bytes of UserData.

+  @param[in] UserData   The data to dump.

+

+**/

+VOID

+VarCheckPcdInternalDumpHex (

+  IN UINTN        Indent,

+  IN UINTN        Offset,

+  IN UINTN        DataSize,

+  IN VOID         *UserData

+  )

+{

+  UINT8 *Data;

+

+  CHAR8 Val[50];

+

+  CHAR8 Str[20];

+

+  UINT8 TempByte;

+  UINTN Size;

+  UINTN Index;

+

+  Data = UserData;

+  while (DataSize != 0) {

+    Size = 16;

+    if (Size > DataSize) {

+      Size = DataSize;

+    }

+

+    for (Index = 0; Index < Size; Index += 1) {

+      TempByte            = Data[Index];

+      Val[Index * 3 + 0]  = mVarCheckPcdHex[TempByte >> 4];

+      Val[Index * 3 + 1]  = mVarCheckPcdHex[TempByte & 0xF];

+      Val[Index * 3 + 2]  = (CHAR8) ((Index == 7) ? '-' : ' ');

+      Str[Index]          = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);

+    }

+

+    Val[Index * 3]  = 0;

+    Str[Index]      = 0;

+    DEBUG ((EFI_D_INFO, "%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str));

+

+    Data += Size;

+    Offset += Size;

+    DataSize -= Size;

+  }

+}

+

+/**

+  Var Check Pcd ValidData.

+

+  @param[in] PcdValidData   Pointer to Pcd ValidData

+  @param[in] Data           Data pointer.

+  @param[in] DataSize       Size of Data to set.

+

+  @retval TRUE  Check pass

+  @retval FALSE Check fail.

+

+**/

+BOOLEAN

+VarCheckPcdValidData (

+  IN VAR_CHECK_PCD_VALID_DATA_HEADER    *PcdValidData,

+  IN VOID                               *Data,

+  IN UINTN                              DataSize

+  )

+{

+  UINT64   OneData;

+  UINT64   Minimum;

+  UINT64   Maximum;

+  UINT64   OneValue;

+  UINT8    *Ptr;

+

+  OneData = 0;

+  CopyMem (&OneData, (UINT8 *) Data + PcdValidData->VarOffset, PcdValidData->StorageWidth);

+

+  switch (PcdValidData->Type) {

+    case VarCheckPcdValidList:

+      Ptr = (UINT8 *) ((VAR_CHECK_PCD_VALID_LIST *) PcdValidData + 1);

+      while ((UINTN) Ptr < (UINTN) PcdValidData + PcdValidData->Length) {

+        OneValue = 0;

+        CopyMem (&OneValue, Ptr, PcdValidData->StorageWidth);

+        if (OneData == OneValue) {

+          //

+          // Match

+          //

+          break;

+        }

+        Ptr += PcdValidData->StorageWidth;

+      }

+      if ((UINTN) Ptr >= ((UINTN) PcdValidData + PcdValidData->Length)) {

+        //

+        // No match

+        //

+        DEBUG ((EFI_D_INFO, "VarCheckPcdValidData fail: ValidList mismatch (0x%lx)\n", OneData));

+        DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData->Length, (UINT8 *) PcdValidData););

+        return FALSE;

+      }

+      break;

+

+    case VarCheckPcdValidRange:

+      Minimum = 0;

+      Maximum = 0;

+      Ptr = (UINT8 *) ((VAR_CHECK_PCD_VALID_RANGE *) PcdValidData + 1);

+      while ((UINTN) Ptr < (UINTN) PcdValidData + PcdValidData->Length) {

+        CopyMem (&Minimum, Ptr, PcdValidData->StorageWidth);

+        Ptr += PcdValidData->StorageWidth;

+        CopyMem (&Maximum, Ptr, PcdValidData->StorageWidth);

+        Ptr += PcdValidData->StorageWidth;

+

+        if ((OneData >= Minimum) && (OneData <= Maximum)) {

+          return TRUE;

+        }

+      }

+      DEBUG ((EFI_D_INFO, "VarCheckPcdValidData fail: ValidRange mismatch (0x%lx)\n", OneData));

+      DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData->Length, (UINT8 *) PcdValidData););

+      return FALSE;

+      break;

+

+    default:

+      ASSERT (FALSE);

+      break;

+  }

+

+  return TRUE;

+}

+

+VAR_CHECK_PCD_VARIABLE_HEADER   *mVarCheckPcdBin = NULL;

+UINTN                           mVarCheckPcdBinSize = 0;

+

+/**

+  SetVariable check handler PCD.

+

+  @param[in] VariableName       Name of Variable to set.

+  @param[in] VendorGuid         Variable vendor GUID.

+  @param[in] Attributes         Attribute value of the variable.

+  @param[in] DataSize           Size of Data to set.

+  @param[in] Data               Data pointer.

+

+  @retval EFI_SUCCESS               The SetVariable check result was success.

+  @retval EFI_SECURITY_VIOLATION    Check fail.

+

+**/

+EFI_STATUS

+EFIAPI

+SetVariableCheckHandlerPcd (

+  IN CHAR16     *VariableName,

+  IN EFI_GUID   *VendorGuid,

+  IN UINT32     Attributes,

+  IN UINTN      DataSize,

+  IN VOID       *Data

+  )

+{

+  VAR_CHECK_PCD_VARIABLE_HEADER     *PcdVariable;

+  VAR_CHECK_PCD_VALID_DATA_HEADER   *PcdValidData;

+

+  if (mVarCheckPcdBin == NULL) {

+    return EFI_SUCCESS;

+  }

+

+  if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {

+    //

+    // Do not check delete variable.

+    //

+    return EFI_SUCCESS;

+  }

+

+  //

+  // For Pcd Variable header align.

+  //

+  PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (mVarCheckPcdBin);

+  while ((UINTN) PcdVariable < ((UINTN) mVarCheckPcdBin + mVarCheckPcdBinSize)) {

+    if ((StrCmp ((CHAR16 *) (PcdVariable + 1), VariableName) == 0) &&

+        (CompareGuid (&PcdVariable->Guid, VendorGuid))) {

+      //

+      // Found the Pcd Variable that could be used to do check.

+      //

+      DEBUG ((EFI_D_INFO, "VarCheckPcdVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName, VendorGuid, Attributes, DataSize));

+      if ((PcdVariable->Attributes != 0) && PcdVariable->Attributes != Attributes) {

+        DEBUG ((EFI_D_INFO, "VarCheckPcdVariable fail for Attributes - 0x%08x\n", PcdVariable->Attributes));

+        return EFI_SECURITY_VIOLATION;

+      }

+

+      if (DataSize == 0) {

+        DEBUG ((EFI_D_INFO, "VarCheckPcdVariable - CHECK PASS with DataSize == 0 !\n"));

+        return EFI_SUCCESS;

+      }

+

+      //

+      // Do the check.

+      // For Pcd ValidData header align.

+      //

+      PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->HeaderLength));

+      while ((UINTN) PcdValidData < ((UINTN) PcdVariable + PcdVariable->Length)) {

+        if (((UINTN) PcdValidData->VarOffset + PcdValidData->StorageWidth) <= DataSize) {

+          if (!VarCheckPcdValidData (PcdValidData, Data, DataSize)) {

+            return EFI_SECURITY_VIOLATION;

+          }

+        }

+        //

+        // For Pcd ValidData header align.

+        //

+        PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdValidData + PcdValidData->Length));

+      }

+

+      DEBUG ((EFI_D_INFO, "VarCheckPcdVariable - ALL CHECK PASS!\n"));

+      return EFI_SUCCESS;

+    }

+    //

+    // For Pcd Variable header align.

+    //

+    PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->Length));

+  }

+

+  // Not found, so pass.

+  return EFI_SUCCESS;

+}

+

+#ifdef DUMP_VAR_CHECK_PCD

+/**

+  Dump Pcd ValidData.

+

+  @param[in] PcdValidData    Pointer to Pcd ValidData.

+

+**/

+VOID

+DumpPcdValidData (

+  IN VAR_CHECK_PCD_VALID_DATA_HEADER    *PcdValidData

+  )

+{

+  UINT64    Minimum;

+  UINT64    Maximum;

+  UINT64    OneValue;

+  UINT8     *Ptr;

+

+  DEBUG ((EFI_D_INFO, "  VAR_CHECK_PCD_VALID_DATA_HEADER\n"));

+  DEBUG ((EFI_D_INFO, "    Type          - 0x%02x\n", PcdValidData->Type));

+  DEBUG ((EFI_D_INFO, "    Length        - 0x%02x\n", PcdValidData->Length));

+  DEBUG ((EFI_D_INFO, "    VarOffset     - 0x%04x\n", PcdValidData->VarOffset));

+  DEBUG ((EFI_D_INFO, "    StorageWidth  - 0x%02x\n", PcdValidData->StorageWidth));

+

+  switch (PcdValidData->Type) {

+    case VarCheckPcdValidList:

+      Ptr = (UINT8 *) ((VAR_CHECK_PCD_VALID_LIST *) PcdValidData + 1);

+      while ((UINTN) Ptr < ((UINTN) PcdValidData + PcdValidData->Length)) {

+        OneValue = 0;

+        CopyMem (&OneValue, Ptr, PcdValidData->StorageWidth);

+        switch (PcdValidData->StorageWidth) {

+          case sizeof (UINT8):

+            DEBUG ((EFI_D_INFO, "    ValidList   - 0x%02x\n", OneValue));

+            break;

+          case sizeof (UINT16):

+            DEBUG ((EFI_D_INFO, "    ValidList   - 0x%04x\n", OneValue));

+            break;

+          case sizeof (UINT32):

+            DEBUG ((EFI_D_INFO, "    ValidList   - 0x%08x\n", OneValue));

+            break;

+          case sizeof (UINT64):

+            DEBUG ((EFI_D_INFO, "    ValidList   - 0x%016lx\n", OneValue));

+            break;

+          default:

+            ASSERT (FALSE);

+            break;

+        }

+        Ptr += PcdValidData->StorageWidth;

+      }

+      break;

+

+    case VarCheckPcdValidRange:

+      Minimum = 0;

+      Maximum = 0;

+      Ptr = (UINT8 *) ((VAR_CHECK_PCD_VALID_RANGE *) PcdValidData + 1);

+      while ((UINTN) Ptr < (UINTN) PcdValidData + PcdValidData->Length) {

+        CopyMem (&Minimum, Ptr, PcdValidData->StorageWidth);

+        Ptr += PcdValidData->StorageWidth;

+        CopyMem (&Maximum, Ptr, PcdValidData->StorageWidth);

+        Ptr += PcdValidData->StorageWidth;

+

+        switch (PcdValidData->StorageWidth) {

+          case sizeof (UINT8):

+            DEBUG ((EFI_D_INFO, "    Minimum       - 0x%02x\n", Minimum));

+            DEBUG ((EFI_D_INFO, "    Maximum       - 0x%02x\n", Maximum));

+            break;

+          case sizeof (UINT16):

+            DEBUG ((EFI_D_INFO, "    Minimum       - 0x%04x\n", Minimum));

+            DEBUG ((EFI_D_INFO, "    Maximum       - 0x%04x\n", Maximum));

+            break;

+          case sizeof (UINT32):

+            DEBUG ((EFI_D_INFO, "    Minimum       - 0x%08x\n", Minimum));

+            DEBUG ((EFI_D_INFO, "    Maximum       - 0x%08x\n", Maximum));

+            break;

+          case sizeof (UINT64):

+            DEBUG ((EFI_D_INFO, "    Minimum       - 0x%016lx\n", Minimum));

+            DEBUG ((EFI_D_INFO, "    Maximum       - 0x%016lx\n", Maximum));

+            break;

+          default:

+            ASSERT (FALSE);

+            break;

+        }

+      }

+      break;

+

+    default:

+      ASSERT (FALSE);

+      break;

+  }

+}

+

+/**

+  Dump Pcd Variable.

+

+  @param[in] PcdVariable    Pointer to Pcd Variable.

+

+**/

+VOID

+DumpPcdVariable (

+  IN VAR_CHECK_PCD_VARIABLE_HEADER  *PcdVariable

+  )

+{

+  VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData;

+

+  DEBUG ((EFI_D_INFO, "VAR_CHECK_PCD_VARIABLE_HEADER\n"));

+  DEBUG ((EFI_D_INFO, "  Revision        - 0x%04x\n", PcdVariable->Revision));

+  DEBUG ((EFI_D_INFO, "  HeaderLength    - 0x%04x\n", PcdVariable->HeaderLength));

+  DEBUG ((EFI_D_INFO, "  Length          - 0x%08x\n", PcdVariable->Length));

+  DEBUG ((EFI_D_INFO, "  Type            - 0x%02x\n", PcdVariable->Type));

+  DEBUG ((EFI_D_INFO, "  Attributes      - 0x%08x\n", PcdVariable->Attributes));

+  DEBUG ((EFI_D_INFO, "  Guid            - %g\n", &PcdVariable->Guid));

+  DEBUG ((EFI_D_INFO, "  Name            - %s\n", PcdVariable + 1));

+

+  //

+  // For Pcd ValidData header align.

+  //

+  PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->HeaderLength));

+  while ((UINTN) PcdValidData < ((UINTN) PcdVariable + PcdVariable->Length)) {

+    //

+    // Dump Pcd ValidData related to the Pcd Variable.

+    //

+    DumpPcdValidData (PcdValidData);

+    //

+    // For Pcd ValidData header align.

+    //

+    PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdValidData + PcdValidData->Length));

+  }

+}

+

+/**

+  Dump Var Check PCD.

+

+  @param[in] VarCheckPcdBin     Pointer to VarCheckPcdBin.

+  @param[in] VarCheckPcdBinSize VarCheckPcdBin size.

+

+**/

+VOID

+DumpVarCheckPcd (

+  IN VOID   *VarCheckPcdBin,

+  IN UINTN  VarCheckPcdBinSize

+  )

+{

+  VAR_CHECK_PCD_VARIABLE_HEADER     *PcdVariable;

+

+  DEBUG ((EFI_D_INFO, "DumpVarCheckPcd\n"));

+

+  //

+  // For Pcd Variable header align.

+  //

+  PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (VarCheckPcdBin);

+  while ((UINTN) PcdVariable < ((UINTN) VarCheckPcdBin + VarCheckPcdBinSize)) {

+    DumpPcdVariable (PcdVariable);

+    //

+    // For Pcd Variable header align.

+    //

+    PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->Length));

+  }

+}

+#endif

+

+/**

+  Locate VarCheckPcdBin.

+

+**/

+VOID

+EFIAPI

+LocateVarCheckPcdBin (

+  VOID

+  )

+{

+  EFI_STATUS                        Status;

+  VAR_CHECK_PCD_VARIABLE_HEADER     *VarCheckPcdBin;

+  UINTN                             VarCheckPcdBinSize;

+

+  //

+  // Search the VarCheckPcdBin from the first RAW section of current FFS.

+  //

+  Status = GetSectionFromFfs (

+             EFI_SECTION_RAW,

+             0,

+             (VOID **) &VarCheckPcdBin,

+             &VarCheckPcdBinSize

+             );

+  if (!EFI_ERROR (Status)) {

+    //

+    // AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access

+    // in SetVariable check handler.

+    //

+    mVarCheckPcdBin = AllocateRuntimeCopyPool (VarCheckPcdBinSize, VarCheckPcdBin);

+    ASSERT (mVarCheckPcdBin != NULL);

+    mVarCheckPcdBinSize = VarCheckPcdBinSize;

+    FreePool (VarCheckPcdBin);

+

+    DEBUG ((EFI_D_INFO, "VarCheckPcdBin - at 0x%x size = 0x%x\n", mVarCheckPcdBin, mVarCheckPcdBinSize));

+

+#ifdef DUMP_VAR_CHECK_PCD

+    DEBUG_CODE (

+      DumpVarCheckPcd (mVarCheckPcdBin, mVarCheckPcdBinSize);

+    );

+#endif

+  } else {

+    DEBUG ((EFI_D_INFO, "[VarCheckPcd] No VarCheckPcdBin found at the first RAW section\n"));

+  }

+}

+

+/**

+  Constructor function of VarCheckPcdLib to register var check PCD handler.

+

+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.

+  @param[in] SystemTable    A pointer to the EFI System Table.

+

+  @retval EFI_SUCCESS       The constructor executed correctly.

+

+**/

+EFI_STATUS

+EFIAPI

+VarCheckPcdLibNullClassConstructor (

+  IN EFI_HANDLE             ImageHandle,

+  IN EFI_SYSTEM_TABLE       *SystemTable

+  )

+{

+  LocateVarCheckPcdBin ();

+  VarCheckLibRegisterAddressPointer ((VOID **) &mVarCheckPcdBin);

+  VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerPcd);

+

+  return EFI_SUCCESS;

+}

diff --git a/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdStructure.h b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdStructure.h
new file mode 100644
index 0000000..8180bc5
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdStructure.h
@@ -0,0 +1,76 @@
+/** @file

+  Internal structure for Var Check Pcd.

+

+Copyright (c) 2015, 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 _VAR_CHECK_STRUCTURE_H_

+#define _VAR_CHECK_STRUCTURE_H_

+

+//

+// Alignment for PCD Variable and check data header.

+//

+#define HEADER_ALIGNMENT  4

+#define HEADER_ALIGN(Header)  (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1)))

+

+#pragma pack (1)

+

+#define VAR_CHECK_PCD_REVISION  0x0001

+

+typedef enum {

+  VarCheckPcdVariableHeader,

+  VarCheckPcdValidList,

+  VarCheckPcdValidRange,

+  VarCheckPcdCheckTypeMax,

+} VAR_CHECK_PCD_CHECK_TYPE;

+

+typedef struct {

+  UINT16            Revision;

+  UINT16            HeaderLength;

+  UINT32            Length; // Length include this header

+  UINT8             Type;

+  UINT8             Reserved[3];

+  UINT32            Attributes;

+  EFI_GUID          Guid;

+//CHAR16              Name[];

+} VAR_CHECK_PCD_VARIABLE_HEADER;

+

+typedef struct {

+  UINT8             Type;

+  UINT8             Length; // Length include this header

+  UINT16            VarOffset;

+  UINT8             StorageWidth;

+} VAR_CHECK_PCD_VALID_DATA_HEADER;

+

+typedef struct {

+  UINT8             Type;

+  UINT8             Length; // Length include this header

+  UINT16            VarOffset;

+  UINT8             StorageWidth;

+//UINTx               Data[]; // x = UINT8/UINT16/UINT32/UINT64;

+} VAR_CHECK_PCD_VALID_LIST;

+

+//typedef struct {

+//  UINTx             Minimum; // x = UINT8/UINT16/UINT32/UINT64

+//  UINTx             Maximum; // x = UINT8/UINT16/UINT32/UINT64

+//} VAR_CHECK_PCD_VALID_RANGE_DATA;

+

+typedef struct {

+  UINT8             Type;

+  UINT8             Length; // Length include this header

+  UINT16            VarOffset;

+  UINT8             StorageWidth;

+//  VAR_CHECK_PCD_VALID_RANGE_DATA    ValidRange[];

+} VAR_CHECK_PCD_VALID_RANGE;

+

+#pragma pack ()

+

+#endif
\ No newline at end of file
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index c211d7f..9bc8ed5 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -281,6 +281,7 @@
   MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf

   MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf

   MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf

+  MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf

 

   MdeModulePkg/Universal/BdsDxe/BdsDxe.inf

   MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf

@@ -377,6 +378,7 @@
     <LibraryClasses>

       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf

       NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf

+      NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf

   }

   MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf

   

@@ -387,6 +389,7 @@
     <LibraryClasses>

       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf

       NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf

+      NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf

   }

   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf

   MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf