]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLibNullClass.c
MdeModulePkg: Add VarCheckPcdLib NULL class library
[mirror_edk2.git] / MdeModulePkg / Library / VarCheckPcdLib / VarCheckPcdLibNullClass.c
diff --git a/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLibNullClass.c b/MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLibNullClass.c
new file mode 100644 (file)
index 0000000..72b0363
--- /dev/null
@@ -0,0 +1,474 @@
+/** @file\r
+  Var Check PCD handler.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/VarCheckLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+\r
+#include "VarCheckPcdStructure.h"\r
+\r
+//#define DUMP_VAR_CHECK_PCD\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckPcdHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};\r
+\r
+/**\r
+  Dump some hexadecimal data.\r
+\r
+  @param[in] Indent     How many spaces to indent the output.\r
+  @param[in] Offset     The offset of the dump.\r
+  @param[in] DataSize   The size in bytes of UserData.\r
+  @param[in] UserData   The data to dump.\r
+\r
+**/\r
+VOID\r
+VarCheckPcdInternalDumpHex (\r
+  IN UINTN        Indent,\r
+  IN UINTN        Offset,\r
+  IN UINTN        DataSize,\r
+  IN VOID         *UserData\r
+  )\r
+{\r
+  UINT8 *Data;\r
+\r
+  CHAR8 Val[50];\r
+\r
+  CHAR8 Str[20];\r
+\r
+  UINT8 TempByte;\r
+  UINTN Size;\r
+  UINTN Index;\r
+\r
+  Data = UserData;\r
+  while (DataSize != 0) {\r
+    Size = 16;\r
+    if (Size > DataSize) {\r
+      Size = DataSize;\r
+    }\r
+\r
+    for (Index = 0; Index < Size; Index += 1) {\r
+      TempByte            = Data[Index];\r
+      Val[Index * 3 + 0]  = mVarCheckPcdHex[TempByte >> 4];\r
+      Val[Index * 3 + 1]  = mVarCheckPcdHex[TempByte & 0xF];\r
+      Val[Index * 3 + 2]  = (CHAR8) ((Index == 7) ? '-' : ' ');\r
+      Str[Index]          = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);\r
+    }\r
+\r
+    Val[Index * 3]  = 0;\r
+    Str[Index]      = 0;\r
+    DEBUG ((EFI_D_INFO, "%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str));\r
+\r
+    Data += Size;\r
+    Offset += Size;\r
+    DataSize -= Size;\r
+  }\r
+}\r
+\r
+/**\r
+  Var Check Pcd ValidData.\r
+\r
+  @param[in] PcdValidData   Pointer to Pcd ValidData\r
+  @param[in] Data           Data pointer.\r
+  @param[in] DataSize       Size of Data to set.\r
+\r
+  @retval TRUE  Check pass\r
+  @retval FALSE Check fail.\r
+\r
+**/\r
+BOOLEAN\r
+VarCheckPcdValidData (\r
+  IN VAR_CHECK_PCD_VALID_DATA_HEADER    *PcdValidData,\r
+  IN VOID                               *Data,\r
+  IN UINTN                              DataSize\r
+  )\r
+{\r
+  UINT64   OneData;\r
+  UINT64   Minimum;\r
+  UINT64   Maximum;\r
+  UINT64   OneValue;\r
+  UINT8    *Ptr;\r
+\r
+  OneData = 0;\r
+  CopyMem (&OneData, (UINT8 *) Data + PcdValidData->VarOffset, PcdValidData->StorageWidth);\r
+\r
+  switch (PcdValidData->Type) {\r
+    case VarCheckPcdValidList:\r
+      Ptr = (UINT8 *) ((VAR_CHECK_PCD_VALID_LIST *) PcdValidData + 1);\r
+      while ((UINTN) Ptr < (UINTN) PcdValidData + PcdValidData->Length) {\r
+        OneValue = 0;\r
+        CopyMem (&OneValue, Ptr, PcdValidData->StorageWidth);\r
+        if (OneData == OneValue) {\r
+          //\r
+          // Match\r
+          //\r
+          break;\r
+        }\r
+        Ptr += PcdValidData->StorageWidth;\r
+      }\r
+      if ((UINTN) Ptr >= ((UINTN) PcdValidData + PcdValidData->Length)) {\r
+        //\r
+        // No match\r
+        //\r
+        DEBUG ((EFI_D_INFO, "VarCheckPcdValidData fail: ValidList mismatch (0x%lx)\n", OneData));\r
+        DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData->Length, (UINT8 *) PcdValidData););\r
+        return FALSE;\r
+      }\r
+      break;\r
+\r
+    case VarCheckPcdValidRange:\r
+      Minimum = 0;\r
+      Maximum = 0;\r
+      Ptr = (UINT8 *) ((VAR_CHECK_PCD_VALID_RANGE *) PcdValidData + 1);\r
+      while ((UINTN) Ptr < (UINTN) PcdValidData + PcdValidData->Length) {\r
+        CopyMem (&Minimum, Ptr, PcdValidData->StorageWidth);\r
+        Ptr += PcdValidData->StorageWidth;\r
+        CopyMem (&Maximum, Ptr, PcdValidData->StorageWidth);\r
+        Ptr += PcdValidData->StorageWidth;\r
+\r
+        if ((OneData >= Minimum) && (OneData <= Maximum)) {\r
+          return TRUE;\r
+        }\r
+      }\r
+      DEBUG ((EFI_D_INFO, "VarCheckPcdValidData fail: ValidRange mismatch (0x%lx)\n", OneData));\r
+      DEBUG_CODE (VarCheckPcdInternalDumpHex (2, 0, PcdValidData->Length, (UINT8 *) PcdValidData););\r
+      return FALSE;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+VAR_CHECK_PCD_VARIABLE_HEADER   *mVarCheckPcdBin = NULL;\r
+UINTN                           mVarCheckPcdBinSize = 0;\r
+\r
+/**\r
+  SetVariable check handler PCD.\r
+\r
+  @param[in] VariableName       Name of Variable to set.\r
+  @param[in] VendorGuid         Variable vendor GUID.\r
+  @param[in] Attributes         Attribute value of the variable.\r
+  @param[in] DataSize           Size of Data to set.\r
+  @param[in] Data               Data pointer.\r
+\r
+  @retval EFI_SUCCESS               The SetVariable check result was success.\r
+  @retval EFI_SECURITY_VIOLATION    Check fail.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetVariableCheckHandlerPcd (\r
+  IN CHAR16     *VariableName,\r
+  IN EFI_GUID   *VendorGuid,\r
+  IN UINT32     Attributes,\r
+  IN UINTN      DataSize,\r
+  IN VOID       *Data\r
+  )\r
+{\r
+  VAR_CHECK_PCD_VARIABLE_HEADER     *PcdVariable;\r
+  VAR_CHECK_PCD_VALID_DATA_HEADER   *PcdValidData;\r
+\r
+  if (mVarCheckPcdBin == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {\r
+    //\r
+    // Do not check delete variable.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // For Pcd Variable header align.\r
+  //\r
+  PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (mVarCheckPcdBin);\r
+  while ((UINTN) PcdVariable < ((UINTN) mVarCheckPcdBin + mVarCheckPcdBinSize)) {\r
+    if ((StrCmp ((CHAR16 *) (PcdVariable + 1), VariableName) == 0) &&\r
+        (CompareGuid (&PcdVariable->Guid, VendorGuid))) {\r
+      //\r
+      // Found the Pcd Variable that could be used to do check.\r
+      //\r
+      DEBUG ((EFI_D_INFO, "VarCheckPcdVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName, VendorGuid, Attributes, DataSize));\r
+      if ((PcdVariable->Attributes != 0) && PcdVariable->Attributes != Attributes) {\r
+        DEBUG ((EFI_D_INFO, "VarCheckPcdVariable fail for Attributes - 0x%08x\n", PcdVariable->Attributes));\r
+        return EFI_SECURITY_VIOLATION;\r
+      }\r
+\r
+      if (DataSize == 0) {\r
+        DEBUG ((EFI_D_INFO, "VarCheckPcdVariable - CHECK PASS with DataSize == 0 !\n"));\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      //\r
+      // Do the check.\r
+      // For Pcd ValidData header align.\r
+      //\r
+      PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->HeaderLength));\r
+      while ((UINTN) PcdValidData < ((UINTN) PcdVariable + PcdVariable->Length)) {\r
+        if (((UINTN) PcdValidData->VarOffset + PcdValidData->StorageWidth) <= DataSize) {\r
+          if (!VarCheckPcdValidData (PcdValidData, Data, DataSize)) {\r
+            return EFI_SECURITY_VIOLATION;\r
+          }\r
+        }\r
+        //\r
+        // For Pcd ValidData header align.\r
+        //\r
+        PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdValidData + PcdValidData->Length));\r
+      }\r
+\r
+      DEBUG ((EFI_D_INFO, "VarCheckPcdVariable - ALL CHECK PASS!\n"));\r
+      return EFI_SUCCESS;\r
+    }\r
+    //\r
+    // For Pcd Variable header align.\r
+    //\r
+    PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->Length));\r
+  }\r
+\r
+  // Not found, so pass.\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+#ifdef DUMP_VAR_CHECK_PCD\r
+/**\r
+  Dump Pcd ValidData.\r
+\r
+  @param[in] PcdValidData    Pointer to Pcd ValidData.\r
+\r
+**/\r
+VOID\r
+DumpPcdValidData (\r
+  IN VAR_CHECK_PCD_VALID_DATA_HEADER    *PcdValidData\r
+  )\r
+{\r
+  UINT64    Minimum;\r
+  UINT64    Maximum;\r
+  UINT64    OneValue;\r
+  UINT8     *Ptr;\r
+\r
+  DEBUG ((EFI_D_INFO, "  VAR_CHECK_PCD_VALID_DATA_HEADER\n"));\r
+  DEBUG ((EFI_D_INFO, "    Type          - 0x%02x\n", PcdValidData->Type));\r
+  DEBUG ((EFI_D_INFO, "    Length        - 0x%02x\n", PcdValidData->Length));\r
+  DEBUG ((EFI_D_INFO, "    VarOffset     - 0x%04x\n", PcdValidData->VarOffset));\r
+  DEBUG ((EFI_D_INFO, "    StorageWidth  - 0x%02x\n", PcdValidData->StorageWidth));\r
+\r
+  switch (PcdValidData->Type) {\r
+    case VarCheckPcdValidList:\r
+      Ptr = (UINT8 *) ((VAR_CHECK_PCD_VALID_LIST *) PcdValidData + 1);\r
+      while ((UINTN) Ptr < ((UINTN) PcdValidData + PcdValidData->Length)) {\r
+        OneValue = 0;\r
+        CopyMem (&OneValue, Ptr, PcdValidData->StorageWidth);\r
+        switch (PcdValidData->StorageWidth) {\r
+          case sizeof (UINT8):\r
+            DEBUG ((EFI_D_INFO, "    ValidList   - 0x%02x\n", OneValue));\r
+            break;\r
+          case sizeof (UINT16):\r
+            DEBUG ((EFI_D_INFO, "    ValidList   - 0x%04x\n", OneValue));\r
+            break;\r
+          case sizeof (UINT32):\r
+            DEBUG ((EFI_D_INFO, "    ValidList   - 0x%08x\n", OneValue));\r
+            break;\r
+          case sizeof (UINT64):\r
+            DEBUG ((EFI_D_INFO, "    ValidList   - 0x%016lx\n", OneValue));\r
+            break;\r
+          default:\r
+            ASSERT (FALSE);\r
+            break;\r
+        }\r
+        Ptr += PcdValidData->StorageWidth;\r
+      }\r
+      break;\r
+\r
+    case VarCheckPcdValidRange:\r
+      Minimum = 0;\r
+      Maximum = 0;\r
+      Ptr = (UINT8 *) ((VAR_CHECK_PCD_VALID_RANGE *) PcdValidData + 1);\r
+      while ((UINTN) Ptr < (UINTN) PcdValidData + PcdValidData->Length) {\r
+        CopyMem (&Minimum, Ptr, PcdValidData->StorageWidth);\r
+        Ptr += PcdValidData->StorageWidth;\r
+        CopyMem (&Maximum, Ptr, PcdValidData->StorageWidth);\r
+        Ptr += PcdValidData->StorageWidth;\r
+\r
+        switch (PcdValidData->StorageWidth) {\r
+          case sizeof (UINT8):\r
+            DEBUG ((EFI_D_INFO, "    Minimum       - 0x%02x\n", Minimum));\r
+            DEBUG ((EFI_D_INFO, "    Maximum       - 0x%02x\n", Maximum));\r
+            break;\r
+          case sizeof (UINT16):\r
+            DEBUG ((EFI_D_INFO, "    Minimum       - 0x%04x\n", Minimum));\r
+            DEBUG ((EFI_D_INFO, "    Maximum       - 0x%04x\n", Maximum));\r
+            break;\r
+          case sizeof (UINT32):\r
+            DEBUG ((EFI_D_INFO, "    Minimum       - 0x%08x\n", Minimum));\r
+            DEBUG ((EFI_D_INFO, "    Maximum       - 0x%08x\n", Maximum));\r
+            break;\r
+          case sizeof (UINT64):\r
+            DEBUG ((EFI_D_INFO, "    Minimum       - 0x%016lx\n", Minimum));\r
+            DEBUG ((EFI_D_INFO, "    Maximum       - 0x%016lx\n", Maximum));\r
+            break;\r
+          default:\r
+            ASSERT (FALSE);\r
+            break;\r
+        }\r
+      }\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+  }\r
+}\r
+\r
+/**\r
+  Dump Pcd Variable.\r
+\r
+  @param[in] PcdVariable    Pointer to Pcd Variable.\r
+\r
+**/\r
+VOID\r
+DumpPcdVariable (\r
+  IN VAR_CHECK_PCD_VARIABLE_HEADER  *PcdVariable\r
+  )\r
+{\r
+  VAR_CHECK_PCD_VALID_DATA_HEADER *PcdValidData;\r
+\r
+  DEBUG ((EFI_D_INFO, "VAR_CHECK_PCD_VARIABLE_HEADER\n"));\r
+  DEBUG ((EFI_D_INFO, "  Revision        - 0x%04x\n", PcdVariable->Revision));\r
+  DEBUG ((EFI_D_INFO, "  HeaderLength    - 0x%04x\n", PcdVariable->HeaderLength));\r
+  DEBUG ((EFI_D_INFO, "  Length          - 0x%08x\n", PcdVariable->Length));\r
+  DEBUG ((EFI_D_INFO, "  Type            - 0x%02x\n", PcdVariable->Type));\r
+  DEBUG ((EFI_D_INFO, "  Attributes      - 0x%08x\n", PcdVariable->Attributes));\r
+  DEBUG ((EFI_D_INFO, "  Guid            - %g\n", &PcdVariable->Guid));\r
+  DEBUG ((EFI_D_INFO, "  Name            - %s\n", PcdVariable + 1));\r
+\r
+  //\r
+  // For Pcd ValidData header align.\r
+  //\r
+  PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->HeaderLength));\r
+  while ((UINTN) PcdValidData < ((UINTN) PcdVariable + PcdVariable->Length)) {\r
+    //\r
+    // Dump Pcd ValidData related to the Pcd Variable.\r
+    //\r
+    DumpPcdValidData (PcdValidData);\r
+    //\r
+    // For Pcd ValidData header align.\r
+    //\r
+    PcdValidData = (VAR_CHECK_PCD_VALID_DATA_HEADER *) HEADER_ALIGN (((UINTN) PcdValidData + PcdValidData->Length));\r
+  }\r
+}\r
+\r
+/**\r
+  Dump Var Check PCD.\r
+\r
+  @param[in] VarCheckPcdBin     Pointer to VarCheckPcdBin.\r
+  @param[in] VarCheckPcdBinSize VarCheckPcdBin size.\r
+\r
+**/\r
+VOID\r
+DumpVarCheckPcd (\r
+  IN VOID   *VarCheckPcdBin,\r
+  IN UINTN  VarCheckPcdBinSize\r
+  )\r
+{\r
+  VAR_CHECK_PCD_VARIABLE_HEADER     *PcdVariable;\r
+\r
+  DEBUG ((EFI_D_INFO, "DumpVarCheckPcd\n"));\r
+\r
+  //\r
+  // For Pcd Variable header align.\r
+  //\r
+  PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (VarCheckPcdBin);\r
+  while ((UINTN) PcdVariable < ((UINTN) VarCheckPcdBin + VarCheckPcdBinSize)) {\r
+    DumpPcdVariable (PcdVariable);\r
+    //\r
+    // For Pcd Variable header align.\r
+    //\r
+    PcdVariable = (VAR_CHECK_PCD_VARIABLE_HEADER *) HEADER_ALIGN (((UINTN) PcdVariable + PcdVariable->Length));\r
+  }\r
+}\r
+#endif\r
+\r
+/**\r
+  Locate VarCheckPcdBin.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+LocateVarCheckPcdBin (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  VAR_CHECK_PCD_VARIABLE_HEADER     *VarCheckPcdBin;\r
+  UINTN                             VarCheckPcdBinSize;\r
+\r
+  //\r
+  // Search the VarCheckPcdBin from the first RAW section of current FFS.\r
+  //\r
+  Status = GetSectionFromFfs (\r
+             EFI_SECTION_RAW,\r
+             0,\r
+             (VOID **) &VarCheckPcdBin,\r
+             &VarCheckPcdBinSize\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // AllocateRuntimeZeroPool () from MemoryAllocateLib is used for runtime access\r
+    // in SetVariable check handler.\r
+    //\r
+    mVarCheckPcdBin = AllocateRuntimeCopyPool (VarCheckPcdBinSize, VarCheckPcdBin);\r
+    ASSERT (mVarCheckPcdBin != NULL);\r
+    mVarCheckPcdBinSize = VarCheckPcdBinSize;\r
+    FreePool (VarCheckPcdBin);\r
+\r
+    DEBUG ((EFI_D_INFO, "VarCheckPcdBin - at 0x%x size = 0x%x\n", mVarCheckPcdBin, mVarCheckPcdBinSize));\r
+\r
+#ifdef DUMP_VAR_CHECK_PCD\r
+    DEBUG_CODE (\r
+      DumpVarCheckPcd (mVarCheckPcdBin, mVarCheckPcdBinSize);\r
+    );\r
+#endif\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "[VarCheckPcd] No VarCheckPcdBin found at the first RAW section\n"));\r
+  }\r
+}\r
+\r
+/**\r
+  Constructor function of VarCheckPcdLib to register var check PCD handler.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS       The constructor executed correctly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VarCheckPcdLibNullClassConstructor (\r
+  IN EFI_HANDLE             ImageHandle,\r
+  IN EFI_SYSTEM_TABLE       *SystemTable\r
+  )\r
+{\r
+  LocateVarCheckPcdBin ();\r
+  VarCheckLibRegisterAddressPointer ((VOID **) &mVarCheckPcdBin);\r
+  VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerPcd);\r
+\r
+  return EFI_SUCCESS;\r
+}\r