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