]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
DynamicTablesPkg: Add code for finding duplicate values in arrays
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / TableHelperLib / TableHelper.c
1 /** @file
2 Table Helper
3
4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 **/
7
8 #include <Protocol/AcpiTable.h>
9 #include <Library/BaseLib.h>
10 #include <Library/DebugLib.h>
11 #include <Library/BaseMemoryLib.h>
12
13 // Module specific include files.
14 #include <AcpiTableGenerator.h>
15 #include <ConfigurationManagerObject.h>
16 #include <Library/TableHelperLib.h>
17 #include <Protocol/ConfigurationManagerProtocol.h>
18
19 /** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
20 object from the Configuration Manager.
21
22 @param [in] CfgMgrProtocol Pointer to the Configuration Manager protocol
23 interface.
24 @param [out] CfgMfrInfo Pointer to the Configuration Manager Info
25 object structure.
26
27 @retval EFI_SUCCESS The object is returned.
28 @retval EFI_INVALID_PARAMETER The Object ID is invalid.
29 @retval EFI_NOT_FOUND The requested Object is not found.
30 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
31 Manager is less than the Object size.
32 **/
33 EFI_STATUS
34 EFIAPI
35 GetCgfMgrInfo (
36 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
37 OUT CM_STD_OBJ_CONFIGURATION_MANAGER_INFO ** CfgMfrInfo
38 )
39 {
40 EFI_STATUS Status;
41 CM_OBJ_DESCRIPTOR CmObjectDesc;
42
43 ASSERT (CfgMgrProtocol != NULL);
44 ASSERT (CfgMfrInfo != NULL);
45
46 *CfgMfrInfo = NULL;
47 Status = CfgMgrProtocol->GetObject (
48 CfgMgrProtocol,
49 CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
50 CM_NULL_TOKEN,
51 &CmObjectDesc
52 );
53 if (EFI_ERROR (Status)) {
54 DEBUG ((
55 DEBUG_ERROR,
56 "ERROR: Failed to Get Configuration Manager Info. Status = %r\n",
57 Status
58 ));
59 return Status;
60 }
61
62 if (CmObjectDesc.ObjectId != CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo)) {
63 DEBUG ((
64 DEBUG_ERROR,
65 "ERROR: EStdObjCfgMgrInfo: Invalid ObjectId = 0x%x, expected Id = 0x%x\n",
66 CmObjectDesc.ObjectId,
67 CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo)
68 ));
69 ASSERT (FALSE);
70 return EFI_INVALID_PARAMETER;
71 }
72
73 if (CmObjectDesc.Size <
74 (sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO) * CmObjectDesc.Count)) {
75 DEBUG ((
76 DEBUG_ERROR,
77 "ERROR: EStdObjCfgMgrInfo: Buffer too small, size = 0x%x\n",
78 CmObjectDesc.Size
79 ));
80 ASSERT (FALSE);
81 return EFI_BAD_BUFFER_SIZE;
82 }
83
84 *CfgMfrInfo = (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO*)CmObjectDesc.Data;
85 return Status;
86 }
87
88 /** The AddAcpiHeader function updates the ACPI header structure pointed by
89 the AcpiHeader. It utilizes the ACPI table Generator and the Configuration
90 Manager protocol to obtain any information required for constructing the
91 header.
92
93 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
94 protocol interface.
95 @param [in] Generator Pointer to the ACPI table Generator.
96 @param [in,out] AcpiHeader Pointer to the ACPI table header to be
97 updated.
98 @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
99 @param [in] Length Length of the ACPI table.
100
101 @retval EFI_SUCCESS The ACPI table is updated successfully.
102 @retval EFI_INVALID_PARAMETER A parameter is invalid.
103 @retval EFI_NOT_FOUND The required object information is not found.
104 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
105 Manager is less than the Object size for the
106 requested object.
107 **/
108 EFI_STATUS
109 EFIAPI
110 AddAcpiHeader (
111 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
112 IN CONST ACPI_TABLE_GENERATOR * CONST Generator,
113 IN OUT EFI_ACPI_DESCRIPTION_HEADER * CONST AcpiHeader,
114 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
115 IN CONST UINT32 Length
116 )
117 {
118 EFI_STATUS Status;
119 CM_STD_OBJ_CONFIGURATION_MANAGER_INFO * CfgMfrInfo;
120
121 ASSERT (CfgMgrProtocol != NULL);
122 ASSERT (Generator != NULL);
123 ASSERT (AcpiHeader != NULL);
124 ASSERT (Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
125
126 if ((CfgMgrProtocol == NULL) ||
127 (Generator == NULL) ||
128 (AcpiHeader == NULL) ||
129 (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))
130 ) {
131 return EFI_INVALID_PARAMETER;
132 }
133
134 Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo);
135 if (EFI_ERROR (Status)) {
136 DEBUG ((
137 DEBUG_ERROR,
138 "ERROR: Failed to get Configuration Manager info. Status = %r\n",
139 Status
140 ));
141 goto error_handler;
142 }
143
144 // UINT32 Signature
145 AcpiHeader->Signature = Generator->AcpiTableSignature;
146 // UINT32 Length
147 AcpiHeader->Length = Length;
148 // UINT8 Revision
149 AcpiHeader->Revision = AcpiTableInfo->AcpiTableRevision;
150 // UINT8 Checksum
151 AcpiHeader->Checksum = 0;
152
153 // UINT8 OemId[6]
154 CopyMem (AcpiHeader->OemId, CfgMfrInfo->OemId, sizeof (AcpiHeader->OemId));
155
156 // UINT64 OemTableId
157 if (AcpiTableInfo->OemTableId != 0) {
158 AcpiHeader->OemTableId = AcpiTableInfo->OemTableId;
159 } else {
160 AcpiHeader->OemTableId = SIGNATURE_32 (
161 CfgMfrInfo->OemId[0],
162 CfgMfrInfo->OemId[1],
163 CfgMfrInfo->OemId[2],
164 CfgMfrInfo->OemId[3]
165 ) |
166 ((UINT64)Generator->AcpiTableSignature << 32);
167 }
168
169 // UINT32 OemRevision
170 if (AcpiTableInfo->OemRevision != 0) {
171 AcpiHeader->OemRevision = AcpiTableInfo->OemRevision;
172 } else {
173 AcpiHeader->OemRevision = CfgMfrInfo->Revision;
174 }
175
176 // UINT32 CreatorId
177 AcpiHeader->CreatorId = Generator->CreatorId;
178 // UINT32 CreatorRevision
179 AcpiHeader->CreatorRevision = Generator->CreatorRevision;
180
181 error_handler:
182 return Status;
183 }
184
185 /**
186 Test and report if a duplicate entry exists in the given array of comparable
187 elements.
188
189 @param [in] Array Array of elements to test for duplicates.
190 @param [in] Count Number of elements in Array.
191 @param [in] ElementSize Size of an element in bytes
192 @param [in] EqualTestFunction The function to call to check if any two
193 elements are equal.
194
195 @retval TRUE A duplicate element was found or one of
196 the input arguments is invalid.
197 @retval FALSE Every element in Array is unique.
198 **/
199 BOOLEAN
200 EFIAPI
201 FindDuplicateValue (
202 IN CONST VOID * Array,
203 IN CONST UINTN Count,
204 IN CONST UINTN ElementSize,
205 IN PFN_IS_EQUAL EqualTestFunction
206 )
207 {
208 UINTN Index1;
209 UINTN Index2;
210 UINT8 * Element1;
211 UINT8 * Element2;
212
213 if (Array == NULL) {
214 DEBUG ((DEBUG_ERROR, "ERROR: FindDuplicateValues: Array is NULL.\n"));
215 return TRUE;
216 }
217
218 if (ElementSize == 0) {
219 DEBUG ((DEBUG_ERROR, "ERROR: FindDuplicateValues: ElementSize is 0.\n"));
220 return TRUE;
221 }
222
223 if (EqualTestFunction == NULL) {
224 DEBUG ((
225 DEBUG_ERROR,
226 "ERROR: FindDuplicateValues: EqualTestFunction is NULL.\n"
227 ));
228 return TRUE;
229 }
230
231 if (Count < 2) {
232 return FALSE;
233 }
234
235 for (Index1 = 0; Index1 < Count - 1; Index1++) {
236 for (Index2 = Index1 + 1; Index2 < Count; Index2++) {
237 Element1 = (UINT8*)Array + (Index1 * ElementSize);
238 Element2 = (UINT8*)Array + (Index2 * ElementSize);
239
240 if (EqualTestFunction (Element1, Element2, Index1, Index2)) {
241 return TRUE;
242 }
243 }
244 }
245 return FALSE;
246 }