/** @file UEFI Miscellaneous boot Services InstallConfigurationTable service Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "DxeMain.h" #define CONFIG_TABLE_SIZE_INCREASED 0x10 UINTN mSystemTableAllocateSize = 0; /** Boot Service called to add, modify, or remove a system configuration table from the EFI System Table. @param Guid Pointer to the GUID for the entry to add, update, or remove @param Table Pointer to the configuration table for the entry to add, update, or remove, may be NULL. @return EFI_SUCCESS Guid, Table pair added, updated, or removed. @return EFI_INVALID_PARAMETER Input GUID is NULL. @return EFI_NOT_FOUND Attempted to delete non-existant entry @return EFI_OUT_OF_RESOURCES Not enough memory available **/ EFI_STATUS EFIAPI CoreInstallConfigurationTable ( IN EFI_GUID *Guid, IN VOID *Table ) { UINTN Index; EFI_CONFIGURATION_TABLE *EfiConfigurationTable; EFI_CONFIGURATION_TABLE *OldTable; // // If Guid is NULL, then this operation cannot be performed // if (Guid == NULL) { return EFI_INVALID_PARAMETER; } EfiConfigurationTable = gDxeCoreST->ConfigurationTable; // // Search all the table for an entry that matches Guid // for (Index = 0; Index < gDxeCoreST->NumberOfTableEntries; Index++) { if (CompareGuid (Guid, &(gDxeCoreST->ConfigurationTable[Index].VendorGuid))) { break; } } if (Index < gDxeCoreST->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. // gDxeCoreST->ConfigurationTable[Index].VendorTable = Table; // // Signal Configuration Table change // CoreNotifySignalList (Guid); return EFI_SUCCESS; } // // A match was found and Table is NULL, so this is a delete operation. // gDxeCoreST->NumberOfTableEntries--; // // Copy over deleted entry // CopyMem( &(EfiConfigurationTable[Index]), &(gDxeCoreST->ConfigurationTable[Index + 1]), (gDxeCoreST->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 == gDxeCoreST->NumberOfTableEntries // if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) { // // Allocate a table with one additional entry. // mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE)); EfiConfigurationTable = AllocateRuntimePool (mSystemTableAllocateSize); if (EfiConfigurationTable == NULL) { // // If a new table could not be allocated, then return an error. // return EFI_OUT_OF_RESOURCES; } if (gDxeCoreST->ConfigurationTable != NULL) { // // Copy the old table to the new table. // CopyMem( EfiConfigurationTable, gDxeCoreST->ConfigurationTable, Index * sizeof (EFI_CONFIGURATION_TABLE) ); // // Record the old table pointer. // OldTable = gDxeCoreST->ConfigurationTable; // // As the CoreInstallConfigurationTable() may be re-entered by CoreFreePool() // in its calling stack, updating System table to the new table pointer must // be done before calling CoreFreePool() to free the old table. // It can make sure the gDxeCoreST->ConfigurationTable point to the new table // and avoid the errors of use-after-free to the old table by the reenter of // CoreInstallConfigurationTable() in CoreFreePool()'s calling stack. // gDxeCoreST->ConfigurationTable = EfiConfigurationTable; // // Free the old table after updating System Table to the new table pointer. // CoreFreePool(OldTable); } else { // // Update System Table // gDxeCoreST->ConfigurationTable = EfiConfigurationTable; } } // // Fill in the new entry // CopyGuid ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid); EfiConfigurationTable[Index].VendorTable = Table; // // This is an add operation, so increment the number of table entries // gDxeCoreST->NumberOfTableEntries++; } // // Fix up the CRC-32 in the EFI System Table // CalculateEfiHdrCrc (&gDxeCoreST->Hdr); // // Signal Configuration Table change // CoreNotifySignalList (Guid); return EFI_SUCCESS; }