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
CoreInstallConfigurationTable(IN EFI_GUID * Guid,IN VOID * Table)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