]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / TableHelperLib / TableHelper.c
1 /** @file
2 Table Helper
3
4 Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include <Protocol/AcpiTable.h>
10 #include <Library/BaseLib.h>
11 #include <Library/DebugLib.h>
12 #include <Library/BaseMemoryLib.h>
13
14 // Module specific include files.
15 #include <AcpiTableGenerator.h>
16 #include <ConfigurationManagerObject.h>
17 #include <Library/TableHelperLib.h>
18 #include <Protocol/ConfigurationManagerProtocol.h>
19
20 /** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
21 object from the Configuration Manager.
22
23 @param [in] CfgMgrProtocol Pointer to the Configuration Manager protocol
24 interface.
25 @param [out] CfgMfrInfo Pointer to the Configuration Manager Info
26 object structure.
27
28 @retval EFI_SUCCESS The object is returned.
29 @retval EFI_INVALID_PARAMETER The Object ID is invalid.
30 @retval EFI_NOT_FOUND The requested Object is not found.
31 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
32 Manager is less than the Object size.
33 **/
34 EFI_STATUS
35 EFIAPI
36 GetCgfMgrInfo (
37 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
38 OUT CM_STD_OBJ_CONFIGURATION_MANAGER_INFO **CfgMfrInfo
39 )
40 {
41 EFI_STATUS Status;
42 CM_OBJ_DESCRIPTOR CmObjectDesc;
43
44 ASSERT (CfgMgrProtocol != NULL);
45 ASSERT (CfgMfrInfo != NULL);
46
47 *CfgMfrInfo = NULL;
48 Status = CfgMgrProtocol->GetObject (
49 CfgMgrProtocol,
50 CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
51 CM_NULL_TOKEN,
52 &CmObjectDesc
53 );
54 if (EFI_ERROR (Status)) {
55 DEBUG ((
56 DEBUG_ERROR,
57 "ERROR: Failed to Get Configuration Manager Info. Status = %r\n",
58 Status
59 ));
60 return Status;
61 }
62
63 if (CmObjectDesc.ObjectId != CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo)) {
64 DEBUG ((
65 DEBUG_ERROR,
66 "ERROR: EStdObjCfgMgrInfo: Invalid ObjectId = 0x%x, expected Id = 0x%x\n",
67 CmObjectDesc.ObjectId,
68 CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo)
69 ));
70 ASSERT (FALSE);
71 return EFI_INVALID_PARAMETER;
72 }
73
74 if (CmObjectDesc.Size <
75 (sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO) * CmObjectDesc.Count))
76 {
77 DEBUG ((
78 DEBUG_ERROR,
79 "ERROR: EStdObjCfgMgrInfo: Buffer too small, size = 0x%x\n",
80 CmObjectDesc.Size
81 ));
82 ASSERT (FALSE);
83 return EFI_BAD_BUFFER_SIZE;
84 }
85
86 *CfgMfrInfo = (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO *)CmObjectDesc.Data;
87 return Status;
88 }
89
90 /** The AddAcpiHeader function updates the ACPI header structure pointed by
91 the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
92 Manager protocol to obtain any information required for constructing the
93 header.
94
95 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
96 protocol interface.
97 @param [in] Generator Pointer to the ACPI table Generator.
98 @param [in,out] AcpiHeader Pointer to the ACPI table header to be
99 updated.
100 @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
101 @param [in] Length Length of the ACPI table.
102
103 @retval EFI_SUCCESS The ACPI table is updated successfully.
104 @retval EFI_INVALID_PARAMETER A parameter is invalid.
105 @retval EFI_NOT_FOUND The required object information is not found.
106 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
107 Manager is less than the Object size for the
108 requested object.
109 **/
110 EFI_STATUS
111 EFIAPI
112 AddAcpiHeader (
113 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
114 IN CONST ACPI_TABLE_GENERATOR *CONST Generator,
115 IN OUT EFI_ACPI_DESCRIPTION_HEADER *CONST AcpiHeader,
116 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
117 IN CONST UINT32 Length
118 )
119 {
120 EFI_STATUS Status;
121 CM_STD_OBJ_CONFIGURATION_MANAGER_INFO *CfgMfrInfo;
122
123 ASSERT (CfgMgrProtocol != NULL);
124 ASSERT (Generator != NULL);
125 ASSERT (AcpiHeader != NULL);
126 ASSERT (AcpiTableInfo != NULL);
127 ASSERT (Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
128
129 if ((CfgMgrProtocol == NULL) ||
130 (Generator == NULL) ||
131 (AcpiHeader == NULL) ||
132 (AcpiTableInfo == NULL) ||
133 (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))
134 )
135 {
136 return EFI_INVALID_PARAMETER;
137 }
138
139 Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
140 if (EFI_ERROR (Status)) {
141 DEBUG ((
142 DEBUG_ERROR,
143 "ERROR: Failed to get Configuration Manager info. Status = %r\n",
144 Status
145 ));
146 goto error_handler;
147 }
148
149 // UINT32 Signature
150 AcpiHeader->Signature = Generator->AcpiTableSignature;
151 // UINT32 Length
152 AcpiHeader->Length = Length;
153 // UINT8 Revision
154 AcpiHeader->Revision = AcpiTableInfo->AcpiTableRevision;
155 // UINT8 Checksum
156 AcpiHeader->Checksum = 0;
157
158 // UINT8 OemId[6]
159 CopyMem (AcpiHeader->OemId, CfgMfrInfo->OemId, sizeof (AcpiHeader->OemId));
160
161 // UINT64 OemTableId
162 if (AcpiTableInfo->OemTableId != 0) {
163 AcpiHeader->OemTableId = AcpiTableInfo->OemTableId;
164 } else {
165 AcpiHeader->OemTableId = SIGNATURE_32 (
166 CfgMfrInfo->OemId[0],
167 CfgMfrInfo->OemId[1],
168 CfgMfrInfo->OemId[2],
169 CfgMfrInfo->OemId[3]
170 ) |
171 ((UINT64)Generator->AcpiTableSignature << 32);
172 }
173
174 // UINT32 OemRevision
175 if (AcpiTableInfo->OemRevision != 0) {
176 AcpiHeader->OemRevision = AcpiTableInfo->OemRevision;
177 } else {
178 AcpiHeader->OemRevision = CfgMfrInfo->Revision;
179 }
180
181 // UINT32 CreatorId
182 AcpiHeader->CreatorId = Generator->CreatorId;
183 // UINT32 CreatorRevision
184 AcpiHeader->CreatorRevision = Generator->CreatorRevision;
185
186 error_handler:
187 return Status;
188 }
189
190 /** Build a RootNode containing SSDT ACPI header information using the AmlLib.
191
192 The function utilizes the ACPI table Generator and the Configuration
193 Manager protocol to obtain any information required for constructing the
194 header. It then creates a RootNode. The SSDT ACPI header is part of the
195 RootNode.
196
197 This is essentially a wrapper around AmlCodeGenDefinitionBlock ()
198 from the AmlLib.
199
200 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
201 protocol interface.
202 @param [in] Generator Pointer to the ACPI table Generator.
203 @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
204 @param [out] RootNode If success, contains the created RootNode.
205 The SSDT ACPI header is part of the RootNode.
206
207 @retval EFI_SUCCESS Success.
208 @retval EFI_INVALID_PARAMETER A parameter is invalid.
209 @retval EFI_NOT_FOUND The required object information is not found.
210 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
211 Manager is less than the Object size for the
212 requested object.
213 **/
214 EFI_STATUS
215 EFIAPI
216 AddSsdtAcpiHeader (
217 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
218 IN CONST ACPI_TABLE_GENERATOR *CONST Generator,
219 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
220 OUT AML_ROOT_NODE_HANDLE *RootNode
221 )
222 {
223 EFI_STATUS Status;
224 UINT64 OemTableId;
225 UINT32 OemRevision;
226 CM_STD_OBJ_CONFIGURATION_MANAGER_INFO *CfgMfrInfo;
227
228 ASSERT (CfgMgrProtocol != NULL);
229 ASSERT (Generator != NULL);
230 ASSERT (AcpiTableInfo != NULL);
231
232 if ((CfgMgrProtocol == NULL) ||
233 (Generator == NULL) ||
234 (AcpiTableInfo == NULL))
235 {
236 return EFI_INVALID_PARAMETER;
237 }
238
239 Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
240 if (EFI_ERROR (Status)) {
241 DEBUG ((
242 DEBUG_ERROR,
243 "ERROR: Failed to get Configuration Manager info. Status = %r\n",
244 Status
245 ));
246 return Status;
247 }
248
249 if (AcpiTableInfo->OemTableId != 0) {
250 OemTableId = AcpiTableInfo->OemTableId;
251 } else {
252 OemTableId = SIGNATURE_32 (
253 CfgMfrInfo->OemId[0],
254 CfgMfrInfo->OemId[1],
255 CfgMfrInfo->OemId[2],
256 CfgMfrInfo->OemId[3]
257 ) |
258 ((UINT64)Generator->AcpiTableSignature << 32);
259 }
260
261 if (AcpiTableInfo->OemRevision != 0) {
262 OemRevision = AcpiTableInfo->OemRevision;
263 } else {
264 OemRevision = CfgMfrInfo->Revision;
265 }
266
267 Status = AmlCodeGenDefinitionBlock (
268 "SSDT",
269 (CONST CHAR8 *)&CfgMfrInfo->OemId,
270 (CONST CHAR8 *)&OemTableId,
271 OemRevision,
272 RootNode
273 );
274 ASSERT_EFI_ERROR (Status);
275 return Status;
276 }
277
278 /**
279 Test and report if a duplicate entry exists in the given array of comparable
280 elements.
281
282 @param [in] Array Array of elements to test for duplicates.
283 @param [in] Count Number of elements in Array.
284 @param [in] ElementSize Size of an element in bytes
285 @param [in] EqualTestFunction The function to call to check if any two
286 elements are equal.
287
288 @retval TRUE A duplicate element was found or one of
289 the input arguments is invalid.
290 @retval FALSE Every element in Array is unique.
291 **/
292 BOOLEAN
293 EFIAPI
294 FindDuplicateValue (
295 IN CONST VOID *Array,
296 IN CONST UINTN Count,
297 IN CONST UINTN ElementSize,
298 IN PFN_IS_EQUAL EqualTestFunction
299 )
300 {
301 UINTN Index1;
302 UINTN Index2;
303 UINT8 *Element1;
304 UINT8 *Element2;
305
306 if (Array == NULL) {
307 DEBUG ((DEBUG_ERROR, "ERROR: FindDuplicateValues: Array is NULL.\n"));
308 return TRUE;
309 }
310
311 if (ElementSize == 0) {
312 DEBUG ((DEBUG_ERROR, "ERROR: FindDuplicateValues: ElementSize is 0.\n"));
313 return TRUE;
314 }
315
316 if (EqualTestFunction == NULL) {
317 DEBUG ((
318 DEBUG_ERROR,
319 "ERROR: FindDuplicateValues: EqualTestFunction is NULL.\n"
320 ));
321 return TRUE;
322 }
323
324 if (Count < 2) {
325 return FALSE;
326 }
327
328 for (Index1 = 0; Index1 < Count - 1; Index1++) {
329 for (Index2 = Index1 + 1; Index2 < Count; Index2++) {
330 Element1 = (UINT8 *)Array + (Index1 * ElementSize);
331 Element2 = (UINT8 *)Array + (Index2 * ElementSize);
332
333 if (EqualTestFunction (Element1, Element2, Index1, Index2)) {
334 return TRUE;
335 }
336 }
337 }
338
339 return FALSE;
340 }