]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/PCD/Pei/Service.c
MdePkg and MdeModulePkg Pcd: Add the new EFI_GET_PCD_INFO_PROTOCOL and EFI_GET_PCD_IN...
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Pei / Service.c
index 47e87d3bcddba3265c67458da167a7a3a2ced783..04ae874a21c05a1c9d2f48e7bdbe0f8796d515a1 100644 (file)
@@ -15,6 +15,284 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "Service.h"\r
 \r
+/**\r
+  Get Local Token Number by Token Number.\r
+\r
+  @param[in]    Database    PCD database.\r
+  @param[in]    TokenNumber The PCD token number.\r
+\r
+  @return       Local Token Number.\r
+**/\r
+UINT32\r
+GetLocalTokenNumber (\r
+  IN PEI_PCD_DATABASE   *Database,\r
+  IN UINTN              TokenNumber\r
+  )\r
+{\r
+  UINT32                LocalTokenNumber;\r
+  UINTN                 Size;\r
+  UINTN                 MaxSize;\r
+\r
+  //\r
+  // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
+  // We have to decrement TokenNumber by 1 to make it usable\r
+  // as the array index.\r
+  //\r
+  TokenNumber--;\r
+\r
+  LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + TokenNumber);\r
+\r
+  Size = (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;\r
+\r
+  if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
+    if (Size == 0) {\r
+      GetPtrTypeSize (TokenNumber, &MaxSize, Database);\r
+    } else {\r
+      MaxSize = Size;\r
+    }\r
+    LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
+  }\r
+\r
+  return LocalTokenNumber;\r
+}\r
+\r
+/**\r
+  Get PCD type by Local Token Number.\r
+\r
+  @param[in]    LocalTokenNumber The PCD local token number.\r
+\r
+  @return       PCD type.\r
+**/\r
+EFI_PCD_TYPE\r
+GetPcdType (\r
+  IN UINT32             LocalTokenNumber\r
+  )\r
+{\r
+  switch (LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) {\r
+    case PCD_DATUM_TYPE_POINTER:\r
+      return EFI_PCD_TYPE_PTR;\r
+    case PCD_DATUM_TYPE_UINT8:\r
+      if (LocalTokenNumber & PCD_DATUM_TYPE_UINT8_BOOLEAN) {\r
+        return EFI_PCD_TYPE_BOOL;\r
+      } else {\r
+        return EFI_PCD_TYPE_8;\r
+      }\r
+    case PCD_DATUM_TYPE_UINT16:\r
+      return EFI_PCD_TYPE_16;\r
+    case PCD_DATUM_TYPE_UINT32:\r
+      return EFI_PCD_TYPE_32;\r
+    case PCD_DATUM_TYPE_UINT64:\r
+      return EFI_PCD_TYPE_64;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_PCD_TYPE_8;\r
+  }\r
+}\r
+\r
+/**\r
+  Get PCD name.\r
+\r
+  @param[in]    OnlyTokenSpaceName  If TRUE, only need to get the TokenSpaceCName.\r
+                                    If FALSE, need to get the full PCD name.\r
+  @param[in]    Database            PCD database.\r
+  @param[in]    TokenNumber         The PCD token number.\r
+\r
+  @return       The TokenSpaceCName or full PCD name.\r
+**/\r
+CHAR8 *\r
+GetPcdName (\r
+  IN BOOLEAN            OnlyTokenSpaceName,\r
+  IN PEI_PCD_DATABASE   *Database,\r
+  IN UINTN              TokenNumber\r
+  )\r
+{\r
+  UINT8             *StringTable;\r
+  PCD_NAME_INDEX    *PcdNameIndex;\r
+  CHAR8             *TokenSpaceName;\r
+  CHAR8             *PcdName;\r
+  CHAR8             *Name;\r
+\r
+  //\r
+  // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.\r
+  // We have to decrement TokenNumber by 1 to make it usable\r
+  // as the array index.\r
+  //\r
+  TokenNumber--;\r
+\r
+  StringTable = (UINT8 *) Database + Database->StringTableOffset;\r
+\r
+  //\r
+  // Get the PCD name index.\r
+  //\r
+  PcdNameIndex = (PCD_NAME_INDEX *)((UINT8 *) Database + Database->PcdNameTableOffset) + TokenNumber;\r
+  TokenSpaceName = (CHAR8 *)&StringTable[PcdNameIndex->TokenSpaceCNameIndex];\r
+  PcdName = (CHAR8 *)&StringTable[PcdNameIndex->PcdCNameIndex];\r
+\r
+  if (OnlyTokenSpaceName) {\r
+    //\r
+    // Only need to get the TokenSpaceCName.\r
+    //\r
+    Name = AllocateCopyPool (AsciiStrSize (TokenSpaceName), TokenSpaceName);\r
+  } else {\r
+    //\r
+    // Need to get the full PCD name.\r
+    //\r
+    Name = AllocateZeroPool (AsciiStrSize (TokenSpaceName) + AsciiStrSize (PcdName));\r
+    //\r
+    // Catenate TokenSpaceCName and PcdCName with a '.' to form the full PCD name.\r
+    //\r
+    AsciiStrCat (Name, TokenSpaceName);\r
+    Name[AsciiStrSize (TokenSpaceName) - sizeof (CHAR8)] = '.';\r
+    AsciiStrCat (Name, PcdName);  \r
+  }\r
+\r
+  return Name;\r
+}\r
+\r
+/**\r
+  Retrieve additional information associated with a PCD token.\r
+\r
+  This includes information such as the type of value the TokenNumber is associated with as well as possible\r
+  human readable name that is associated with the token.\r
+\r
+  @param[in]    Database    PCD database.\r
+  @param[in]    Guid        The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]    TokenNumber The PCD token number.\r
+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.\r
+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. \r
+\r
+  @retval  EFI_SUCCESS      The PCD information was returned successfully\r
+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.\r
+**/\r
+EFI_STATUS\r
+ExGetPcdInfo (\r
+  IN        PEI_PCD_DATABASE    *Database,\r
+  IN CONST  EFI_GUID            *Guid,\r
+  IN        UINTN               TokenNumber,\r
+  OUT       EFI_PCD_INFO        *PcdInfo\r
+  )\r
+{\r
+  UINTN                 GuidTableIdx;\r
+  EFI_GUID              *MatchGuid;\r
+  EFI_GUID              *GuidTable;\r
+  DYNAMICEX_MAPPING     *ExMapTable;\r
+  UINTN                 Index;\r
+  UINT32                LocalTokenNumber;\r
+\r
+  GuidTable = (EFI_GUID *)((UINT8 *)Database + Database->GuidTableOffset);\r
+  MatchGuid = ScanGuid (GuidTable, Database->GuidTableCount * sizeof(EFI_GUID), Guid);\r
+\r
+  if (MatchGuid == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  GuidTableIdx = MatchGuid - GuidTable;\r
+\r
+  ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)Database + Database->ExMapTableOffset);\r
+\r
+  //\r
+  // Find the PCD by GuidTableIdx and ExTokenNumber in ExMapTable.\r
+  //\r
+  for (Index = 0; Index < Database->ExTokenCount; Index++) {\r
+    if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {\r
+      if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
+        //\r
+        // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,\r
+        // PcdSize to 0 and PcdName to the null-terminated ASCII string\r
+        // associated with the token's namespace Guid.\r
+        //\r
+        PcdInfo->PcdType = EFI_PCD_TYPE_8;\r
+        PcdInfo->PcdSize = 0;\r
+        //\r
+        // Here use one representative in the token space to get the TokenSpaceCName.\r
+        // \r
+        PcdInfo->PcdName = GetPcdName (TRUE, Database, ExMapTable[Index].TokenNumber);\r
+        return EFI_SUCCESS;\r
+      } else if (ExMapTable[Index].ExTokenNumber == TokenNumber) {\r
+        PcdInfo->PcdSize = PeiPcdGetSize (ExMapTable[Index].TokenNumber);\r
+        LocalTokenNumber = GetLocalTokenNumber (Database, ExMapTable[Index].TokenNumber);\r
+        PcdInfo->PcdType = GetPcdType (LocalTokenNumber);\r
+        PcdInfo->PcdName = GetPcdName (FALSE, Database, ExMapTable[Index].TokenNumber);\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Retrieve additional information associated with a PCD token.\r
+\r
+  This includes information such as the type of value the TokenNumber is associated with as well as possible\r
+  human readable name that is associated with the token.\r
+\r
+  @param[in]    Guid        The 128-bit unique value that designates the namespace from which to extract the value.\r
+  @param[in]    TokenNumber The PCD token number.\r
+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.\r
+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.\r
+\r
+  @retval  EFI_SUCCESS      The PCD information was returned successfully.\r
+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.\r
+**/\r
+EFI_STATUS\r
+PeiGetPcdInfo (\r
+  IN CONST  EFI_GUID        *Guid,\r
+  IN        UINTN           TokenNumber,\r
+  OUT       EFI_PCD_INFO    *PcdInfo\r
+  )\r
+{\r
+  PEI_PCD_DATABASE      *PeiPcdDb;\r
+  BOOLEAN               PeiExMapTableEmpty;\r
+  UINTN                 PeiNexTokenNumber;\r
+  UINT32                LocalTokenNumber;\r
+\r
+  if (!FeaturePcdGet (PcdPcdInfoGeneration)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  ASSERT (PcdInfo != NULL);\r
+\r
+  PeiPcdDb          = GetPcdDatabase ();\r
+  PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;\r
+\r
+  if (PeiPcdDb->ExTokenCount == 0) {\r
+    PeiExMapTableEmpty = TRUE;\r
+  } else {\r
+    PeiExMapTableEmpty = FALSE;\r
+  }\r
+\r
+  if (Guid == NULL) {\r
+    if (TokenNumber > PeiNexTokenNumber) {\r
+      return EFI_NOT_FOUND;\r
+    } else if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {\r
+      //\r
+      // TokenNumber is 0, follow spec to set PcdType to EFI_PCD_TYPE_8,\r
+      // PcdSize to 0 and PcdName to NULL for default Token Space.\r
+      //\r
+      PcdInfo->PcdType = EFI_PCD_TYPE_8;\r
+      PcdInfo->PcdSize = 0;\r
+      PcdInfo->PcdName = NULL;\r
+    } else {\r
+      PcdInfo->PcdSize = PeiPcdGetSize (TokenNumber);\r
+      LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber);\r
+      PcdInfo->PcdType = GetPcdType (LocalTokenNumber);\r
+      PcdInfo->PcdName = GetPcdName (FALSE, PeiPcdDb, TokenNumber);\r
+    }\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    if (PeiExMapTableEmpty) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+    return ExGetPcdInfo (\r
+             PeiPcdDb,\r
+             Guid,\r
+             TokenNumber,\r
+             PcdInfo\r
+             );\r
+  }\r
+}\r
+\r
 /**\r
   The function registers the CallBackOnSet fucntion\r
   according to TokenNumber and EFI_GUID space.\r
@@ -150,8 +428,9 @@ LocateExPcdBinary (
 \r
   @param  FileHandle  Handle of the file the external PCD database binary located.\r
 \r
+  @return Pointer to PCD database.\r
 **/\r
-VOID\r
+PEI_PCD_DATABASE *\r
 BuildPcdDatabase (\r
   IN EFI_PEI_FILE_HANDLE    FileHandle\r
   )\r
@@ -182,6 +461,8 @@ BuildPcdDatabase (
   CallbackFnTable = BuildGuidHob (&gEfiCallerIdGuid, SizeOfCallbackFnTable);\r
   \r
   ZeroMem (CallbackFnTable, SizeOfCallbackFnTable);\r
+\r
+  return Database;\r
 }\r
 \r
 /**\r
@@ -462,8 +743,6 @@ SetWorker (
   // comparison.\r
   ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));\r
 \r
-  LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber);\r
-\r
   if (PtrType) {\r
     //\r
     // Get MaxSize first, then check new size with max buffer size.\r
@@ -489,14 +768,7 @@ SetWorker (
     InvokeCallbackOnSet (0, NULL, TokenNumber + 1, Data, *Size);\r
   }\r
 \r
-  if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
-    if (PtrType) {\r
-      GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
-    } else {\r
-      MaxSize = *Size;\r
-    }\r
-    LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
-  }\r
+  LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber + 1);\r
 \r
   Offset          = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
   InternalData    = (VOID *) ((UINT8 *) PeiPcdDb + Offset);\r
@@ -677,7 +949,6 @@ GetWorker (
   STRING_HEAD         StringTableIdx;\r
   PEI_PCD_DATABASE    *PeiPcdDb;\r
   UINT32              LocalTokenNumber;\r
-  UINTN               MaxSize;\r
   UINT32              LocalTokenCount;\r
 \r
   //\r
@@ -697,16 +968,7 @@ GetWorker (
 \r
   ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));\r
 \r
-  LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber);\r
-\r
-  if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == PCD_TYPE_SKU_ENABLED) {\r
-    if (GetSize == 0) {\r
-      GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);\r
-    } else {\r
-      MaxSize = GetSize;\r
-    }\r
-    LocalTokenNumber = GetSkuEnabledTokenNumber (LocalTokenNumber & ~PCD_TYPE_SKU_ENABLED, MaxSize);\r
-  }\r
+  LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber + 1);\r
 \r
   Offset      = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
   StringTable = (UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset;\r