]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
DynamicTablesPkg: Extract AcpiHelperLib from TableHelperLib
[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
125 ASSERT (Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
126\r
127 if ((CfgMgrProtocol == NULL) ||\r
128 (Generator == NULL) ||\r
129 (AcpiHeader == NULL) ||\r
130 (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))\r
131 ) {\r
132 return EFI_INVALID_PARAMETER;\r
133 }\r
134\r
135 Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);\r
136 if (EFI_ERROR (Status)) {\r
137 DEBUG ((\r
138 DEBUG_ERROR,\r
139 "ERROR: Failed to get Configuration Manager info. Status = %r\n",\r
140 Status\r
141 ));\r
142 goto error_handler;\r
143 }\r
144\r
145 // UINT32 Signature\r
146 AcpiHeader->Signature = Generator->AcpiTableSignature;\r
147 // UINT32 Length\r
148 AcpiHeader->Length = Length;\r
149 // UINT8 Revision\r
e12bdeb1 150 AcpiHeader->Revision = AcpiTableInfo->AcpiTableRevision;\r
7130bcef
SM
151 // UINT8 Checksum\r
152 AcpiHeader->Checksum = 0;\r
153\r
154 // UINT8 OemId[6]\r
155 CopyMem (AcpiHeader->OemId, CfgMfrInfo->OemId, sizeof (AcpiHeader->OemId));\r
156\r
157 // UINT64 OemTableId\r
e12bdeb1
SM
158 if (AcpiTableInfo->OemTableId != 0) {\r
159 AcpiHeader->OemTableId = AcpiTableInfo->OemTableId;\r
160 } else {\r
161 AcpiHeader->OemTableId = SIGNATURE_32 (\r
162 CfgMfrInfo->OemId[0],\r
163 CfgMfrInfo->OemId[1],\r
164 CfgMfrInfo->OemId[2],\r
165 CfgMfrInfo->OemId[3]\r
166 ) |\r
167 ((UINT64)Generator->AcpiTableSignature << 32);\r
168 }\r
7130bcef
SM
169\r
170 // UINT32 OemRevision\r
e12bdeb1
SM
171 if (AcpiTableInfo->OemRevision != 0) {\r
172 AcpiHeader->OemRevision = AcpiTableInfo->OemRevision;\r
173 } else {\r
174 AcpiHeader->OemRevision = CfgMfrInfo->Revision;\r
175 }\r
7130bcef
SM
176\r
177 // UINT32 CreatorId\r
178 AcpiHeader->CreatorId = Generator->CreatorId;\r
179 // UINT32 CreatorRevision\r
180 AcpiHeader->CreatorRevision = Generator->CreatorRevision;\r
181\r
182error_handler:\r
183 return Status;\r
184}\r
c1b53091
KK
185\r
186/**\r
187 Test and report if a duplicate entry exists in the given array of comparable\r
188 elements.\r
189\r
190 @param [in] Array Array of elements to test for duplicates.\r
191 @param [in] Count Number of elements in Array.\r
192 @param [in] ElementSize Size of an element in bytes\r
193 @param [in] EqualTestFunction The function to call to check if any two\r
194 elements are equal.\r
195\r
196 @retval TRUE A duplicate element was found or one of\r
197 the input arguments is invalid.\r
198 @retval FALSE Every element in Array is unique.\r
199**/\r
200BOOLEAN\r
201EFIAPI\r
202FindDuplicateValue (\r
203 IN CONST VOID * Array,\r
204 IN CONST UINTN Count,\r
205 IN CONST UINTN ElementSize,\r
206 IN PFN_IS_EQUAL EqualTestFunction\r
207 )\r
208{\r
209 UINTN Index1;\r
210 UINTN Index2;\r
211 UINT8 * Element1;\r
212 UINT8 * Element2;\r
213\r
214 if (Array == NULL) {\r
215 DEBUG ((DEBUG_ERROR, "ERROR: FindDuplicateValues: Array is NULL.\n"));\r
216 return TRUE;\r
217 }\r
218\r
219 if (ElementSize == 0) {\r
220 DEBUG ((DEBUG_ERROR, "ERROR: FindDuplicateValues: ElementSize is 0.\n"));\r
221 return TRUE;\r
222 }\r
223\r
224 if (EqualTestFunction == NULL) {\r
225 DEBUG ((\r
226 DEBUG_ERROR,\r
227 "ERROR: FindDuplicateValues: EqualTestFunction is NULL.\n"\r
228 ));\r
229 return TRUE;\r
230 }\r
231\r
232 if (Count < 2) {\r
233 return FALSE;\r
234 }\r
235\r
236 for (Index1 = 0; Index1 < Count - 1; Index1++) {\r
237 for (Index2 = Index1 + 1; Index2 < Count; Index2++) {\r
238 Element1 = (UINT8*)Array + (Index1 * ElementSize);\r
239 Element2 = (UINT8*)Array + (Index2 * ElementSize);\r
240\r
241 if (EqualTestFunction (Element1, Element2, Index1, Index2)) {\r
242 return TRUE;\r
243 }\r
244 }\r
245 }\r
246 return FALSE;\r
247}\r