mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 11:13:53 +01:00 
			
		
		
		
	1. Do not use tab characters 2. No trailing white space in one line 3. All files must end with CRLF Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
		
			
				
	
	
		
			178 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   System Management System Table Services SmmInstallConfigurationTable service
 | |
| 
 | |
|   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
|   This program and the accompanying materials are licensed and made available
 | |
|   under the terms and conditions of the BSD License which accompanies this
 | |
|   distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "PiSmmCore.h"
 | |
| 
 | |
| #define CONFIG_TABLE_SIZE_INCREASED 0x10
 | |
| 
 | |
| UINTN  mSmmSystemTableAllocateSize = 0;
 | |
| 
 | |
| /**
 | |
|   The SmmInstallConfigurationTable() function is used to maintain the list
 | |
|   of configuration tables that are stored in the System Management System
 | |
|   Table.  The list is stored as an array of (GUID, Pointer) pairs.  The list
 | |
|   must be allocated from pool memory with PoolType set to EfiRuntimeServicesData.
 | |
| 
 | |
|   @param  SystemTable      A pointer to the SMM System Table (SMST).
 | |
|   @param  Guid             A pointer to the GUID for the entry to add, update, or remove.
 | |
|   @param  Table            A pointer to the buffer of the table to add.
 | |
|   @param  TableSize        The size of the table to install.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The (Guid, Table) pair was added, updated, or removed.
 | |
|   @retval EFI_INVALID_PARAMETER Guid is not valid.
 | |
|   @retval EFI_NOT_FOUND         An attempt was made to delete a non-existent entry.
 | |
|   @retval EFI_OUT_OF_RESOURCES  There is not enough memory available to complete the operation.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmInstallConfigurationTable (
 | |
|   IN  CONST EFI_SMM_SYSTEM_TABLE2  *SystemTable,
 | |
|   IN  CONST EFI_GUID               *Guid,
 | |
|   IN  VOID                         *Table,
 | |
|   IN  UINTN                        TableSize
 | |
|   )
 | |
| {
 | |
|   UINTN                    Index;
 | |
|   EFI_CONFIGURATION_TABLE  *ConfigurationTable;
 | |
|   EFI_CONFIGURATION_TABLE  *OldTable;
 | |
| 
 | |
|   //
 | |
|   // If Guid is NULL, then this operation cannot be performed
 | |
|   //
 | |
|   if (Guid == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   ConfigurationTable = gSmmCoreSmst.SmmConfigurationTable;
 | |
| 
 | |
|   //
 | |
|   // Search all the table for an entry that matches Guid
 | |
|   //
 | |
|   for (Index = 0; Index < gSmmCoreSmst.NumberOfTableEntries; Index++) {
 | |
|     if (CompareGuid (Guid, &(ConfigurationTable[Index].VendorGuid))) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Index < gSmmCoreSmst.NumberOfTableEntries) {
 | |
|     //
 | |
|     // A match was found, so this is either a modify or a delete operation
 | |
|     //
 | |
|     if (Table != NULL) {
 | |
|       //
 | |
|       // If Table is not NULL, then this is a modify operation.
 | |
|       // Modify the table entry and return.
 | |
|       //
 | |
|       ConfigurationTable[Index].VendorTable = Table;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // A match was found and Table is NULL, so this is a delete operation.
 | |
|     //
 | |
|     gSmmCoreSmst.NumberOfTableEntries--;
 | |
| 
 | |
|     //
 | |
|     // Copy over deleted entry
 | |
|     //
 | |
|     CopyMem (
 | |
|       &(ConfigurationTable[Index]),
 | |
|       &(ConfigurationTable[Index + 1]),
 | |
|       (gSmmCoreSmst.NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
 | |
|       );
 | |
| 
 | |
|   } else {
 | |
|     //
 | |
|     // No matching GUIDs were found, so this is an add operation.
 | |
|     //
 | |
|     if (Table == NULL) {
 | |
|       //
 | |
|       // If Table is NULL on an add operation, then return an error.
 | |
|       //
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Assume that Index == gSmmCoreSmst.NumberOfTableEntries
 | |
|     //
 | |
|     if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSmmSystemTableAllocateSize) {
 | |
|       //
 | |
|       // Allocate a table with one additional entry.
 | |
|       //
 | |
|       mSmmSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
 | |
|       ConfigurationTable = AllocatePool (mSmmSystemTableAllocateSize);
 | |
|       if (ConfigurationTable == NULL) {
 | |
|         //
 | |
|         // If a new table could not be allocated, then return an error.
 | |
|         //
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       if (gSmmCoreSmst.SmmConfigurationTable != NULL) {
 | |
|         //
 | |
|         // Copy the old table to the new table.
 | |
|         //
 | |
|         CopyMem (
 | |
|           ConfigurationTable,
 | |
|           gSmmCoreSmst.SmmConfigurationTable,
 | |
|           Index * sizeof (EFI_CONFIGURATION_TABLE)
 | |
|           );
 | |
| 
 | |
|         //
 | |
|         // Record the old table pointer.
 | |
|         //
 | |
|         OldTable = gSmmCoreSmst.SmmConfigurationTable;
 | |
| 
 | |
|         //
 | |
|         // As the SmmInstallConfigurationTable() may be re-entered by FreePool() in
 | |
|         // its calling stack, updating System table to the new table pointer must
 | |
|         // be done before calling FreePool() to free the old table.
 | |
|         // It can make sure the gSmmCoreSmst.SmmConfigurationTable point to the new
 | |
|         // table and avoid the errors of use-after-free to the old table by the
 | |
|         // reenter of SmmInstallConfigurationTable() in FreePool()'s calling stack.
 | |
|         //
 | |
|         gSmmCoreSmst.SmmConfigurationTable = ConfigurationTable;
 | |
| 
 | |
|         //
 | |
|         // Free the old table after updating System Table to the new table pointer.
 | |
|         //
 | |
|         FreePool (OldTable);
 | |
|       } else {
 | |
|         //
 | |
|         // Update System Table
 | |
|         //
 | |
|         gSmmCoreSmst.SmmConfigurationTable = ConfigurationTable;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Fill in the new entry
 | |
|     //
 | |
|     CopyGuid ((VOID *)&ConfigurationTable[Index].VendorGuid, Guid);
 | |
|     ConfigurationTable[Index].VendorTable = Table;
 | |
| 
 | |
|     //
 | |
|     // This is an add operation, so increment the number of table entries
 | |
|     //
 | |
|     gSmmCoreSmst.NumberOfTableEntries++;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // CRC-32 field is ignorable for SMM System Table and should be set to zero
 | |
|   //
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |