]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StandaloneMmPkg/Core/InstallConfigurationTable.c
StandaloneMmPkg/Core: Implementation of Standalone MM Core Module.
[mirror_edk2.git] / StandaloneMmPkg / Core / InstallConfigurationTable.c
diff --git a/StandaloneMmPkg/Core/InstallConfigurationTable.c b/StandaloneMmPkg/Core/InstallConfigurationTable.c
new file mode 100644 (file)
index 0000000..2392be9
--- /dev/null
@@ -0,0 +1,178 @@
+/** @file\r
+  System Management System Table Services MmInstallConfigurationTable service\r
+\r
+  Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  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 "StandaloneMmCore.h"\r
+\r
+#define CONFIG_TABLE_SIZE_INCREASED 0x10\r
+\r
+UINTN  mMmSystemTableAllocateSize = 0;\r
+\r
+/**\r
+  The MmInstallConfigurationTable() function is used to maintain the list\r
+  of configuration tables that are stored in the System Management System\r
+  Table.  The list is stored as an array of (GUID, Pointer) pairs.  The list\r
+  must be allocated from pool memory with PoolType set to EfiRuntimeServicesData.\r
+\r
+  @param  SystemTable      A pointer to the SMM System Table (SMST).\r
+  @param  Guid             A pointer to the GUID for the entry to add, update, or remove.\r
+  @param  Table            A pointer to the buffer of the table to add.\r
+  @param  TableSize        The size of the table to install.\r
+\r
+  @retval EFI_SUCCESS           The (Guid, Table) pair was added, updated, or removed.\r
+  @retval EFI_INVALID_PARAMETER Guid is not valid.\r
+  @retval EFI_NOT_FOUND         An attempt was made to delete a non-existent entry.\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough memory available to complete the operation.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmInstallConfigurationTable (\r
+  IN  CONST EFI_MM_SYSTEM_TABLE    *SystemTable,\r
+  IN  CONST EFI_GUID               *Guid,\r
+  IN  VOID                         *Table,\r
+  IN  UINTN                        TableSize\r
+  )\r
+{\r
+  UINTN                    Index;\r
+  EFI_CONFIGURATION_TABLE  *ConfigurationTable;\r
+  EFI_CONFIGURATION_TABLE  *OldTable;\r
+\r
+  //\r
+  // If Guid is NULL, then this operation cannot be performed\r
+  //\r
+  if (Guid == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ConfigurationTable = gMmCoreMmst.MmConfigurationTable;\r
+\r
+  //\r
+  // Search all the table for an entry that matches Guid\r
+  //\r
+  for (Index = 0; Index < gMmCoreMmst.NumberOfTableEntries; Index++) {\r
+    if (CompareGuid (Guid, &(ConfigurationTable[Index].VendorGuid))) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index < gMmCoreMmst.NumberOfTableEntries) {\r
+    //\r
+    // A match was found, so this is either a modify or a delete operation\r
+    //\r
+    if (Table != NULL) {\r
+      //\r
+      // If Table is not NULL, then this is a modify operation.\r
+      // Modify the table entry and return.\r
+      //\r
+      ConfigurationTable[Index].VendorTable = Table;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    //\r
+    // A match was found and Table is NULL, so this is a delete operation.\r
+    //\r
+    gMmCoreMmst.NumberOfTableEntries--;\r
+\r
+    //\r
+    // Copy over deleted entry\r
+    //\r
+    CopyMem (\r
+      &(ConfigurationTable[Index]),\r
+      &(ConfigurationTable[Index + 1]),\r
+      (gMmCoreMmst.NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)\r
+      );\r
+\r
+  } else {\r
+    //\r
+    // No matching GUIDs were found, so this is an add operation.\r
+    //\r
+    if (Table == NULL) {\r
+      //\r
+      // If Table is NULL on an add operation, then return an error.\r
+      //\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Assume that Index == gMmCoreMmst.NumberOfTableEntries\r
+    //\r
+    if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mMmSystemTableAllocateSize) {\r
+      //\r
+      // Allocate a table with one additional entry.\r
+      //\r
+      mMmSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));\r
+      ConfigurationTable = AllocatePool (mMmSystemTableAllocateSize);\r
+      if (ConfigurationTable == NULL) {\r
+        //\r
+        // If a new table could not be allocated, then return an error.\r
+        //\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      if (gMmCoreMmst.MmConfigurationTable != NULL) {\r
+        //\r
+        // Copy the old table to the new table.\r
+        //\r
+        CopyMem (\r
+          ConfigurationTable,\r
+          gMmCoreMmst.MmConfigurationTable,\r
+          Index * sizeof (EFI_CONFIGURATION_TABLE)\r
+          );\r
+\r
+        //\r
+        // Record the old table pointer.\r
+        //\r
+        OldTable = gMmCoreMmst.MmConfigurationTable;\r
+\r
+        //\r
+        // As the MmInstallConfigurationTable() may be re-entered by FreePool() in\r
+        // its calling stack, updating System table to the new table pointer must\r
+        // be done before calling FreePool() to free the old table.\r
+        // It can make sure the gMmCoreMmst.MmConfigurationTable point to the new\r
+        // table and avoid the errors of use-after-free to the old table by the\r
+        // reenter of MmInstallConfigurationTable() in FreePool()'s calling stack.\r
+        //\r
+        gMmCoreMmst.MmConfigurationTable = ConfigurationTable;\r
+\r
+        //\r
+        // Free the old table after updating System Table to the new table pointer.\r
+        //\r
+        FreePool (OldTable);\r
+      } else {\r
+        //\r
+        // Update System Table\r
+        //\r
+        gMmCoreMmst.MmConfigurationTable = ConfigurationTable;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Fill in the new entry\r
+    //\r
+    CopyGuid ((VOID *)&ConfigurationTable[Index].VendorGuid, Guid);\r
+    ConfigurationTable[Index].VendorTable = Table;\r
+\r
+    //\r
+    // This is an add operation, so increment the number of table entries\r
+    //\r
+    gMmCoreMmst.NumberOfTableEntries++;\r
+  }\r
+\r
+  //\r
+  // CRC-32 field is ignorable for SMM System Table and should be set to zero\r
+  //\r
+\r
+  return EFI_SUCCESS;\r
+}\r