]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/PCD/Pei/Pcd.c
MdeModulePkg PCD: Enable Firmware to retrieve the default setting
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Pei / Pcd.c
index 7a486b7d1d0503be801f5b948b158e210e6f0735..91eb9d6ccf4c67d319d71d71313ce3eb3e63a4ab 100644 (file)
@@ -1,14 +1,15 @@
 /** @file \r
   All Pcd Ppi services are implemented here.\r
   \r
-Copyright (c) 2006 - 2016, 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
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<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
@@ -128,6 +129,105 @@ EFI_PEI_PPI_DESCRIPTOR  mPpiList2[] = {
   }\r
 };\r
 \r
+/**\r
+  Callback on SET PcdSetNvStoreDefaultId\r
+\r
+  Once PcdSetNvStoreDefaultId is set, the default NV storage will be found from\r
+  PcdNvStoreDefaultValueBuffer, and built into VariableHob.\r
+\r
+  @param[in]      CallBackGuid  The PCD token GUID being set.\r
+  @param[in]      CallBackToken The PCD token number being set.\r
+  @param[in, out] TokenData     A pointer to the token data being set.\r
+  @param[in]      TokenDataSize The size, in bytes, of the data being set.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PcdSetNvStoreDefaultIdCallBack (\r
+  IN CONST EFI_GUID         *CallBackGuid, OPTIONAL\r
+  IN       UINTN            CallBackToken,\r
+  IN OUT   VOID             *TokenData,\r
+  IN       UINTN            TokenDataSize\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINT16     DefaultId;\r
+  SKU_ID     SkuId;\r
+  UINTN      FullSize;\r
+  UINTN      Index;\r
+  UINT8      *DataBuffer;\r
+  UINT8      *VarStoreHobData;\r
+  UINT8      *BufferEnd;\r
+  BOOLEAN    IsFound;\r
+  VARIABLE_STORE_HEADER *NvStoreBuffer;\r
+  PCD_DEFAULT_DATA      *DataHeader;\r
+  PCD_DEFAULT_INFO      *DefaultInfo;\r
+  PCD_DATA_DELTA        *DeltaData;\r
+\r
+  DefaultId = *(UINT16 *) TokenData;\r
+  SkuId     = GetPcdDatabase()->SystemSkuId;\r
+  IsFound   = FALSE;\r
+\r
+  if (PeiPcdGetSizeEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer)) > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {\r
+    DataBuffer = (UINT8 *) PeiPcdGetPtrEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer));\r
+    FullSize   = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *) DataBuffer)->Length;\r
+    DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));\r
+    //\r
+    // The first section data includes NV storage default setting.\r
+    //\r
+    NvStoreBuffer   = (VARIABLE_STORE_HEADER *) ((UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);\r
+    VarStoreHobData = (UINT8 *) BuildGuidHob (&NvStoreBuffer->Signature, NvStoreBuffer->Size);\r
+    ASSERT (VarStoreHobData != NULL);\r
+    CopyMem (VarStoreHobData, NvStoreBuffer, NvStoreBuffer->Size);\r
+    //\r
+    // Find the matched SkuId and DefaultId in the first section\r
+    //\r
+    DefaultInfo    = &(DataHeader->DefaultInfo[0]);\r
+    BufferEnd      = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;\r
+    while ((UINT8 *) DefaultInfo < BufferEnd) {\r
+      if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == SkuId) {\r
+        IsFound = TRUE;\r
+        break;\r
+      }\r
+      DefaultInfo ++;\r
+    }\r
+    //\r
+    // Find the matched SkuId and DefaultId in the remaining section\r
+    //\r
+    Index      = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));\r
+    DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index);\r
+    while (!IsFound && Index < FullSize && DataHeader->DataSize != 0xFFFFFFFF) {\r
+      DefaultInfo = &(DataHeader->DefaultInfo[0]);\r
+      BufferEnd   = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;\r
+      while ((UINT8 *) DefaultInfo < BufferEnd) {\r
+        if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == SkuId) {\r
+          IsFound = TRUE;\r
+          break;\r
+        }\r
+        DefaultInfo ++;\r
+      }\r
+      if (IsFound) {\r
+        DeltaData = (PCD_DATA_DELTA *) BufferEnd;\r
+        BufferEnd = (UINT8 *) DataHeader + DataHeader->DataSize;\r
+        while ((UINT8 *) DeltaData < BufferEnd) {\r
+          *(VarStoreHobData + DeltaData->Offset) = (UINT8) DeltaData->Value;\r
+          DeltaData ++;\r
+        }\r
+        break;\r
+      }\r
+      Index      = (Index + DataHeader->DataSize + 7) & (~7) ;\r
+      DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index);\r
+    }\r
+  }\r
+\r
+  Status = PcdUnRegisterCallBackOnSet (\r
+             &gEfiMdeModulePkgTokenSpaceGuid,\r
+             PcdToken(PcdSetNvStoreDefaultId),\r
+             PcdSetNvStoreDefaultIdCallBack\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
 /**\r
   Main entry for PCD PEIM driver.\r
   \r
@@ -162,6 +262,13 @@ PcdPeimInit (
   Status = PeiServicesInstallPpi (&mPpiList2[0]);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  Status = PeiRegisterCallBackOnSet (\r
+             &gEfiMdeModulePkgTokenSpaceGuid,\r
+             PcdToken(PcdSetNvStoreDefaultId),\r
+             PcdSetNvStoreDefaultIdCallBack\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
   return Status;\r
 }\r
 \r
@@ -261,19 +368,39 @@ PeiPcdSetSku (
   UINTN             Index;\r
 \r
   PeiPcdDb = GetPcdDatabase();\r
+\r
+  if (SkuId == PeiPcdDb->SystemSkuId) {\r
+    //\r
+    // The input SKU Id is equal to current SKU Id, return directly.\r
+    //\r
+    return;\r
+  }\r
+\r
+  if (PeiPcdDb->SystemSkuId != (SKU_ID) 0) {\r
+    DEBUG ((DEBUG_ERROR, "PcdPei - The SKU Id could be changed only once."));\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "PcdPei - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",\r
+      PeiPcdDb->SystemSkuId,\r
+      (SKU_ID) SkuId\r
+      ));\r
+    ASSERT (FALSE);\r
+    return;\r
+  }\r
+\r
   SkuIdTable = (SKU_ID *) ((UINT8 *) PeiPcdDb + PeiPcdDb->SkuIdTableOffset);\r
   for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
     if (SkuId == SkuIdTable[Index + 1]) {\r
+      DEBUG ((EFI_D_INFO, "PcdPei - Set current SKU Id to 0x%lx.\n", (SKU_ID) SkuId));\r
       PeiPcdDb->SystemSkuId = (SKU_ID) SkuId;\r
       return;\r
     }\r
   }\r
 \r
   //\r
-  // Invalid input SkuId, the default SKU Id will be used for the system.\r
+  // Invalid input SkuId, the default SKU Id will be still used for the system.\r
   //\r
-  DEBUG ((EFI_D_INFO, "PcdPei - Invalid input SkuId, the default SKU Id will be used.\n"));\r
-  PeiPcdDb->SystemSkuId = (SKU_ID) 0;\r
+  DEBUG ((EFI_D_INFO, "PcdPei - Invalid input SkuId, the default SKU Id will be still used.\n"));\r
   return;\r
 }\r
 \r
@@ -1116,13 +1243,17 @@ PeiPcdGetNextToken (
     }\r
 \r
     if (Found) {\r
+      //\r
+      // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first\r
+      // token number in found token space.\r
+      //\r
       if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
         *TokenNumber = ExMapTable[Index].ExTokenNumber;\r
          return EFI_SUCCESS;\r
       }\r
 \r
       for ( ; Index < PeiPcdDb->ExTokenCount; Index++) {\r
-        if (ExMapTable[Index].ExTokenNumber == *TokenNumber) {\r
+        if ((ExMapTable[Index].ExTokenNumber == *TokenNumber) && (ExMapTable[Index].ExGuidIndex == GuidTableIdx)) {\r
           break;\r
         }\r
       }\r