]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/PCD/Pei/Pcd.c
MdeModulePkg: Update PCD driver to support the optimized PcdDataBase
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Pei / Pcd.c
index 91eb9d6ccf4c67d319d71d71313ce3eb3e63a4ab..f8213953fa2b4fa7600a72335376a0324533d4cd 100644 (file)
@@ -228,6 +228,103 @@ PcdSetNvStoreDefaultIdCallBack (
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
+/**\r
+  Report Pei PCD database of all SKUs as Guid HOB so that DxePcd can access it.\r
+\r
+  @param PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
+  @param NotifyDescriptor  Address of the notification descriptor data structure.\r
+  @param Ppi               Address of the PPI that was installed.\r
+\r
+  @retval EFI_SUCCESS      Successfully update the Boot records.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EndOfPeiSignalPpiNotifyCallback (\r
+  IN EFI_PEI_SERVICES           **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,\r
+  IN VOID                       *Ppi\r
+  )\r
+{\r
+  PEI_PCD_DATABASE       *Database;\r
+  EFI_BOOT_MODE          BootMode;\r
+  EFI_STATUS             Status;\r
+  UINTN                  Instance;\r
+  EFI_PEI_FV_HANDLE      VolumeHandle;\r
+  EFI_PEI_FILE_HANDLE    FileHandle;\r
+  VOID                   *PcdDb;\r
+  UINT32                 Length;\r
+  PEI_PCD_DATABASE       *PeiPcdDb;\r
+\r
+  Status = PeiServicesGetBootMode(&BootMode);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Don't need to report it on S3 boot.\r
+  //\r
+  if (BootMode == BOOT_ON_S3_RESUME) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  PeiPcdDb = GetPcdDatabase();\r
+  if (PeiPcdDb->SystemSkuId != (SKU_ID) 0) {\r
+    //\r
+    // SkuId has been set. Don't need to report it to DXE phase.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get full PCD database from PcdPeim FileHandle\r
+  //\r
+  Instance    = 0;\r
+  FileHandle  = NULL;\r
+  while (TRUE) {\r
+    //\r
+    // Traverse all firmware volume instances\r
+    //\r
+    Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);\r
+    //\r
+    // Error should not happen\r
+    //\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Find PcdDb file from the beginning in this firmware volume.\r
+    //\r
+    FileHandle = NULL;\r
+    Status = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Find PcdPeim FileHandle in this volume\r
+      //\r
+      break;\r
+    }\r
+    //\r
+    // We cannot find PcdPeim in this firmware volume, then search the next volume.\r
+    //\r
+    Instance++;\r
+  }\r
+\r
+  //\r
+  // Find PEI PcdDb and Build second PcdDB GuidHob\r
+  //\r
+  Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);\r
+  ASSERT_EFI_ERROR (Status);\r
+  Length = PeiPcdDb->LengthForAllSkus;\r
+  Database = BuildGuidHob (&gPcdDataBaseHobGuid, Length);\r
+  CopyMem (Database, PcdDb, Length);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiSignalPpiNotifyList[] = {\r
+  {\r
+    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+    &gEfiEndOfPeiSignalPpiGuid,\r
+    EndOfPeiSignalPpiNotifyCallback\r
+  }\r
+};\r
+\r
 /**\r
   Main entry for PCD PEIM driver.\r
   \r
@@ -262,6 +359,9 @@ PcdPeimInit (
   Status = PeiServicesInstallPpi (&mPpiList2[0]);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  Status = PeiServicesNotifyPpi (&mEndOfPeiSignalPpiNotifyList[0]);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
   Status = PeiRegisterCallBackOnSet (\r
              &gEfiMdeModulePkgTokenSpaceGuid,\r
              PcdToken(PcdSetNvStoreDefaultId),\r
@@ -366,6 +466,14 @@ PeiPcdSetSku (
   PEI_PCD_DATABASE  *PeiPcdDb;\r
   SKU_ID            *SkuIdTable;\r
   UINTN             Index;\r
+  EFI_STATUS            Status;\r
+  UINTN                 Instance;\r
+  EFI_PEI_FV_HANDLE     VolumeHandle;\r
+  EFI_PEI_FILE_HANDLE   FileHandle;\r
+  VOID                  *PcdDb;\r
+  UINT32                Length;\r
+  PCD_DATABASE_SKU_DELTA *SkuDelta;\r
+  PCD_DATA_DELTA         *SkuDeltaData;\r
 \r
   PeiPcdDb = GetPcdDatabase();\r
 \r
@@ -391,8 +499,70 @@ PeiPcdSetSku (
   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
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index < SkuIdTable[0]) {\r
+    //\r
+    // Get full PCD database from PcdPeim FileHandle\r
+    //\r
+    Instance    = 0;\r
+    FileHandle  = NULL;\r
+    while (TRUE) {\r
+      //\r
+      // Traverse all firmware volume instances\r
+      //\r
+      Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);\r
+      //\r
+      // Error should not happen\r
+      //\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      //\r
+      // Find PcdDb file from the beginning in this firmware volume.\r
+      //\r
+      FileHandle = NULL;\r
+      Status = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle);\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Find PcdPeim FileHandle in this volume\r
+        //\r
+        break;\r
+      }\r
+      //\r
+      // We cannot find PcdPeim in this firmware volume, then search the next volume.\r
+      //\r
+      Instance++;\r
+    }\r
+\r
+    //\r
+    // Find the delta data between the different Skus\r
+    //\r
+    Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);\r
+    ASSERT_EFI_ERROR (Status);\r
+    Length = PeiPcdDb->LengthForAllSkus;\r
+    Index  = (PeiPcdDb->Length + 7) & (~7);\r
+    SkuDelta = NULL;\r
+    while (Index < Length) {\r
+      SkuDelta = (PCD_DATABASE_SKU_DELTA *) ((UINT8 *) PcdDb + Index);\r
+      if (SkuDelta->SkuId == SkuId && SkuDelta->SkuIdCompared == 0) {\r
+        break;\r
+      }\r
+      Index = (Index + SkuDelta->Length + 7) & (~7);\r
+    }\r
+\r
+    //\r
+    // Patch the delta data into current PCD database\r
+    //\r
+    if (Index < Length && SkuDelta != NULL) {\r
+      SkuDeltaData = (PCD_DATA_DELTA *) (SkuDelta + 1);\r
+      while ((UINT8 *) SkuDeltaData < (UINT8 *) SkuDelta + SkuDelta->Length) {\r
+        *((UINT8 *) PeiPcdDb + SkuDeltaData->Offset) = (UINT8) SkuDeltaData->Value;\r
+        SkuDeltaData ++;\r
+      }\r
       PeiPcdDb->SystemSkuId = (SKU_ID) SkuId;\r
+      DEBUG ((DEBUG_INFO, "PcdPei - Set current SKU Id to 0x%lx.\n", (SKU_ID) SkuId));\r
       return;\r
     }\r
   }\r
@@ -401,6 +571,7 @@ PeiPcdSetSku (
   // 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 still used.\n"));\r
+\r
   return;\r
 }\r
 \r
@@ -1406,9 +1577,7 @@ GetPtrTypeSize (
 {\r
   INTN        SizeTableIdx;\r
   UINTN       LocalTokenNumber;\r
-  SKU_ID      *SkuIdTable;\r
   SIZE_INFO   *SizeTable;\r
-  UINTN       Index;\r
 \r
   SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);\r
 \r
@@ -1432,27 +1601,12 @@ GetPtrTypeSize (
       //\r
       return *MaxSize;\r
   } else {\r
-    if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
-      //\r
-      // We have only two entry for Non-Sku enabled PCD entry:\r
-      // 1) MAX SIZE\r
-      // 2) Current Size\r
-      //\r
-      return SizeTable[SizeTableIdx + 1];\r
-    } else {\r
-      //\r
-      // We have these entry for SKU enabled PCD entry\r
-      // 1) MAX SIZE\r
-      // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
-      //\r
-      SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, Database);\r
-      for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
-        if (SkuIdTable[1 + Index] == Database->SystemSkuId) {\r
-          return SizeTable[SizeTableIdx + 1 + Index];\r
-        }\r
-      }\r
-      return SizeTable[SizeTableIdx + 1];\r
-    }\r
+    //\r
+    // We have only two entry for Non-Sku enabled PCD entry:\r
+    // 1) MAX SIZE\r
+    // 2) Current Size\r
+    //\r
+    return SizeTable[SizeTableIdx + 1];\r
   }\r
 }\r
 \r
@@ -1479,9 +1633,7 @@ SetPtrTypeSize (
 {\r
   INTN        SizeTableIdx;\r
   UINTN       LocalTokenNumber;\r
-  SKU_ID      *SkuIdTable;\r
   SIZE_INFO   *SizeTable;\r
-  UINTN       Index;\r
   UINTN       MaxSize;\r
   \r
   SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);\r
@@ -1510,30 +1662,13 @@ SetPtrTypeSize (
        return FALSE;\r
     }\r
     \r
-    if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {\r
-      //\r
-      // We have only two entry for Non-Sku enabled PCD entry:\r
-      // 1) MAX SIZE\r
-      // 2) Current Size\r
-      //\r
-      SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
-      return TRUE;\r
-    } else {\r
-      //\r
-      // We have these entry for SKU enabled PCD entry\r
-      // 1) MAX SIZE\r
-      // 2) Current Size for each SKU_ID (It is equal to MaxSku).\r
-      //\r
-      SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, Database);\r
-      for (Index = 0; Index < SkuIdTable[0]; Index++) {\r
-        if (SkuIdTable[1 + Index] == Database->SystemSkuId) {\r
-          SizeTable[SizeTableIdx + 1 + Index] = (SIZE_INFO) *CurrentSize;\r
-          return TRUE;\r
-        }\r
-      }\r
-      SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
-      return TRUE;\r
-    }\r
+    //\r
+    // We have only two entry for Non-Sku enabled PCD entry:\r
+    // 1) MAX SIZE\r
+    // 2) Current Size\r
+    //\r
+    SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;\r
+    return TRUE;\r
   }\r
 \r
 }\r