Home | History | Annotate | Download | only in Misc
      1 /** @file
      2   UEFI Miscellaneous boot Services InstallConfigurationTable service
      3 
      4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "DxeMain.h"
     16 
     17 #define CONFIG_TABLE_SIZE_INCREASED 0x10
     18 
     19 UINTN mSystemTableAllocateSize = 0;
     20 
     21 /**
     22   Boot Service called to add, modify, or remove a system configuration table from
     23   the EFI System Table.
     24 
     25   @param  Guid           Pointer to the GUID for the entry to add, update, or
     26                          remove
     27   @param  Table          Pointer to the configuration table for the entry to add,
     28                          update, or remove, may be NULL.
     29 
     30   @return EFI_SUCCESS               Guid, Table pair added, updated, or removed.
     31   @return EFI_INVALID_PARAMETER     Input GUID is NULL.
     32   @return EFI_NOT_FOUND             Attempted to delete non-existant entry
     33   @return EFI_OUT_OF_RESOURCES      Not enough memory available
     34 
     35 **/
     36 EFI_STATUS
     37 EFIAPI
     38 CoreInstallConfigurationTable (
     39   IN EFI_GUID *Guid,
     40   IN VOID     *Table
     41   )
     42 {
     43   UINTN                   Index;
     44   EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
     45 
     46   //
     47   // If Guid is NULL, then this operation cannot be performed
     48   //
     49   if (Guid == NULL) {
     50     return EFI_INVALID_PARAMETER;
     51   }
     52 
     53   EfiConfigurationTable = gDxeCoreST->ConfigurationTable;
     54 
     55   //
     56   // Search all the table for an entry that matches Guid
     57   //
     58   for (Index = 0; Index < gDxeCoreST->NumberOfTableEntries; Index++) {
     59     if (CompareGuid (Guid, &(gDxeCoreST->ConfigurationTable[Index].VendorGuid))) {
     60       break;
     61     }
     62   }
     63 
     64   if (Index < gDxeCoreST->NumberOfTableEntries) {
     65     //
     66     // A match was found, so this is either a modify or a delete operation
     67     //
     68     if (Table != NULL) {
     69       //
     70       // If Table is not NULL, then this is a modify operation.
     71       // Modify the table enty and return.
     72       //
     73       gDxeCoreST->ConfigurationTable[Index].VendorTable = Table;
     74 
     75       //
     76       // Signal Configuration Table change
     77       //
     78       CoreNotifySignalList (Guid);
     79 
     80       return EFI_SUCCESS;
     81     }
     82 
     83     //
     84     // A match was found and Table is NULL, so this is a delete operation.
     85     //
     86     gDxeCoreST->NumberOfTableEntries--;
     87 
     88     //
     89     // Copy over deleted entry
     90     //
     91     CopyMem (
     92       &(EfiConfigurationTable[Index]),
     93       &(gDxeCoreST->ConfigurationTable[Index + 1]),
     94       (gDxeCoreST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
     95       );
     96 
     97   } else {
     98 
     99     //
    100     // No matching GUIDs were found, so this is an add operation.
    101     //
    102 
    103     if (Table == NULL) {
    104       //
    105       // If Table is NULL on an add operation, then return an error.
    106       //
    107       return EFI_NOT_FOUND;
    108     }
    109 
    110     //
    111     // Assume that Index == gDxeCoreST->NumberOfTableEntries
    112     //
    113     if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) {
    114       //
    115       // Allocate a table with one additional entry.
    116       //
    117       mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
    118       EfiConfigurationTable = AllocateRuntimePool (mSystemTableAllocateSize);
    119       if (EfiConfigurationTable == NULL) {
    120         //
    121         // If a new table could not be allocated, then return an error.
    122         //
    123         return EFI_OUT_OF_RESOURCES;
    124       }
    125 
    126       if (gDxeCoreST->ConfigurationTable != NULL) {
    127         //
    128         // Copy the old table to the new table.
    129         //
    130         CopyMem (
    131           EfiConfigurationTable,
    132           gDxeCoreST->ConfigurationTable,
    133           Index * sizeof (EFI_CONFIGURATION_TABLE)
    134           );
    135 
    136         //
    137         // Free Old Table
    138         //
    139         CoreFreePool (gDxeCoreST->ConfigurationTable);
    140       }
    141 
    142       //
    143       // Update System Table
    144       //
    145       gDxeCoreST->ConfigurationTable = EfiConfigurationTable;
    146     }
    147 
    148     //
    149     // Fill in the new entry
    150     //
    151     CopyGuid ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid);
    152     EfiConfigurationTable[Index].VendorTable  = Table;
    153 
    154     //
    155     // This is an add operation, so increment the number of table entries
    156     //
    157     gDxeCoreST->NumberOfTableEntries++;
    158   }
    159 
    160   //
    161   // Fix up the CRC-32 in the EFI System Table
    162   //
    163   CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
    164 
    165   //
    166   // Signal Configuration Table change
    167   //
    168   CoreNotifySignalList (Guid);
    169 
    170   return EFI_SUCCESS;
    171 }
    172