]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/PciIncompatibleDeviceSupportLib/PciIncompatibleDeviceSupportLib.c
fix Klocwork issues
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / PciIncompatibleDeviceSupportLib / PciIncompatibleDeviceSupportLib.c
CommitLineData
54bd896e 1/** @file\r
2 The implementation of PCI incompatible device support libary.\r
3\r
53bd6e4c 4Copyright (c) 2006 - 2007, Intel Corporation \r
5All rights reserved. This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
54bd896e 12\r
13**/\r
14\r
54bd896e 15#include "IncompatiblePciDeviceList.h"\r
16\r
17/**\r
18 Check whether two PCI devices matched\r
19\r
20 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
21 @param Header A pointer to EFI_PCI_DEVICE_INFO.\r
22\r
23 @retval returns EFI_SUCCESS if two PCI device matched.\r
24**/\r
54bd896e 25EFI_STATUS\r
26DeviceCheck (\r
27 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
28 IN EFI_PCI_DEVICE_INFO *Header\r
29 )\r
30{\r
31 //\r
32 // See if the Header matches the parameters passed in\r
33 //\r
34 if (Header->VendorID != DEVICE_ID_NOCARE) {\r
35 if (PciDeviceInfo->VendorID != Header->VendorID) {\r
36 return EFI_UNSUPPORTED;\r
37 }\r
38 }\r
39\r
40 if (Header->DeviceID != DEVICE_ID_NOCARE) {\r
41 if (PciDeviceInfo->DeviceID != Header->DeviceID) {\r
42 return EFI_UNSUPPORTED;\r
43 }\r
44 }\r
45\r
46 if (Header->RevisionID != DEVICE_ID_NOCARE) {\r
47 if (PciDeviceInfo->RevisionID != Header->RevisionID) {\r
48 return EFI_UNSUPPORTED;\r
49 }\r
50 }\r
51\r
52 if (Header->SubsystemVendorID != DEVICE_ID_NOCARE) {\r
53 if (PciDeviceInfo->SubsystemVendorID != Header->SubsystemVendorID) {\r
54 return EFI_UNSUPPORTED;\r
55 }\r
56 }\r
57\r
58 if (Header->SubsystemID != DEVICE_ID_NOCARE) {\r
59 if (PciDeviceInfo->SubsystemID != Header->SubsystemID) {\r
60 return EFI_UNSUPPORTED;\r
61 }\r
62 }\r
63\r
64 return EFI_SUCCESS;\r
65}\r
66\r
67\r
68/**\r
69 Check the incompatible device list for ACPI resource update and return\r
70 the configuration\r
71\r
72 This function searches the incompatible device list according to request\r
73 information. If the PCI device belongs to the devices list, corresponding\r
74 configuration informtion will be returned, in the meantime return EFI_SUCCESS.\r
75\r
76 @param PciDeviceInfo A pointer to PCI device information.\r
77 @param Configuration Returned information.\r
78\r
79 @retval returns EFI_SUCCESS if check incompatible device ok.\r
80 Otherwise return EFI_UNSUPPORTED.\r
81**/\r
82RETURN_STATUS\r
83EFIAPI\r
84PciResourceUpdateCheck (\r
85 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
86 OUT VOID *Configuration\r
87 )\r
88{\r
89 UINT64 Tag;\r
90 UINT64 *ListPtr;\r
91 UINT64 *TempListPtr;\r
92 EFI_PCI_DEVICE_INFO *Header;\r
93 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AcpiPtr;\r
94 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *OldAcpiPtr;\r
95 EFI_PCI_RESOUCE_DESCRIPTOR *Dsc;\r
96 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
97 UINTN Index;\r
98\r
99 ASSERT (PciDeviceInfo != NULL);\r
100\r
101 //\r
102 // Initialize the return value to NULL\r
103 //\r
104 * (VOID **) Configuration = NULL;\r
105\r
106 ListPtr = IncompatiblePciDeviceListForResource;\r
107 while (*ListPtr != LIST_END_TAG) {\r
108\r
109 Tag = *ListPtr;\r
110\r
111 switch (Tag) {\r
112 case DEVICE_INF_TAG:\r
113 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);\r
114 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);\r
115\r
116 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {\r
117 continue;\r
118 }\r
119\r
120 //\r
121 // Matched an item, so construct the ACPI descriptor for the resource.\r
122 //\r
123 //\r
124 // Count the resource items so that to allocate space\r
125 //\r
126 for (Index = 0, TempListPtr = ListPtr; *TempListPtr == DEVICE_RES_TAG; Index++) {\r
127 TempListPtr = TempListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
128 }\r
129 //\r
130 // If there is at least one type of resource request,\r
131 // allocate a acpi resource node\r
132 //\r
133 if (Index == 0) {\r
134 return EFI_ABORTED;\r
135 }\r
136\r
137 AcpiPtr = AllocateZeroPool (\r
138 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Index + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
139 );\r
261136bc 140 if (AcpiPtr == NULL) {\r
141 return EFI_OUT_OF_RESOURCES;\r
142 }\r
54bd896e 143\r
144 OldAcpiPtr = AcpiPtr;\r
145\r
146 //\r
147 // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure\r
148 // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure\r
149 //\r
150 for (; *ListPtr == DEVICE_RES_TAG;) {\r
151\r
152 Dsc = (EFI_PCI_RESOUCE_DESCRIPTOR *) (ListPtr + 1);\r
153\r
154 AcpiPtr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
155 AcpiPtr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
156 AcpiPtr->ResType = (UINT8) Dsc->ResType;\r
157 AcpiPtr->GenFlag = (UINT8) Dsc->GenFlag;\r
158 AcpiPtr->SpecificFlag = (UINT8) Dsc->SpecificFlag;\r
159 AcpiPtr->AddrSpaceGranularity = Dsc->AddrSpaceGranularity;;\r
160 AcpiPtr->AddrRangeMin = Dsc->AddrRangeMin;\r
161 AcpiPtr->AddrRangeMax = Dsc->AddrRangeMax;\r
162 AcpiPtr->AddrTranslationOffset = Dsc->AddrTranslationOffset;\r
163 AcpiPtr->AddrLen = Dsc->AddrLen;\r
164\r
165 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
166 AcpiPtr++;\r
167 }\r
168 //\r
169 // put the checksum\r
170 //\r
171 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AcpiPtr);\r
172 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
173 PtrEnd->Checksum = 0;\r
174\r
175 *(VOID **) Configuration = OldAcpiPtr;\r
176\r
177 return EFI_SUCCESS;\r
178\r
179 case DEVICE_RES_TAG:\r
180 //\r
181 // Adjust the pointer to the next PCI resource descriptor item\r
182 //\r
183 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
184 break;\r
185\r
186 default:\r
187 return EFI_UNSUPPORTED;\r
188 }\r
189 }\r
190\r
191 return EFI_UNSUPPORTED;\r
192\r
193}\r
194\r
195/**\r
196 Check the incompatible device list and return configuraton register mask values.\r
197\r
198 This function searches the incompatible device list according to request\r
199 information. If the PCI device belongs to the devices list, corresponding\r
200 configuration informtion will be returned, in the meantime return EFI_SUCCESS.\r
201\r
202 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.\r
203 @param AccessType Access Type, READ or WRITE.\r
204 @param Offset The address within the PCI configuration space.\r
205 @param Configuration Returned information.\r
206\r
207 @retval returns EFI_SUCCESS if check incompatible device ok.\r
208 Otherwise return EFI_UNSUPPORTED.\r
209**/\r
210RETURN_STATUS\r
211EFIAPI\r
212PciRegisterUpdateCheck (\r
213 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
214 IN UINT64 AccessType,\r
215 IN UINT64 Offset,\r
216 OUT VOID *Configuration\r
217 )\r
218{\r
219 EFI_PCI_DEVICE_INFO *Header;\r
220 UINT64 Tag;\r
221 UINT64 *ListPtr;\r
222 EFI_PCI_REGISTER_VALUE_DATA *RegisterPtr;\r
223 EFI_PCI_REGISTER_VALUE_DATA *Dsc;\r
224\r
225 ASSERT (PciDeviceInfo != NULL);\r
226\r
227 ListPtr = IncompatiblePciDeviceListForRegister;\r
228\r
229 //\r
230 // Initialize the return value to NULL\r
231 //\r
232 * (VOID **) Configuration = NULL;\r
233\r
234 while (*ListPtr != LIST_END_TAG) {\r
235\r
236 Tag = *ListPtr;\r
237\r
238 switch (Tag) {\r
239 case DEVICE_INF_TAG:\r
240 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);\r
241 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);\r
242\r
243 //\r
244 // Check whether the PCI device matches the device in the incompatible devices list?\r
245 // If not, ship next\r
246 //\r
247 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {\r
248 continue;\r
249 }\r
250\r
251 //\r
252 // Matched an item, check whether access matches?\r
253 //\r
254 for (; *ListPtr == DEVICE_RES_TAG;) {\r
255 ListPtr ++;\r
256 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR *)ListPtr)->Offset == (Offset & 0xfc)) {\r
257 if (((EFI_PCI_REGISTER_VALUE_DESCRIPTOR *)ListPtr)->AccessType == AccessType) {\r
258\r
259 Dsc = (EFI_PCI_REGISTER_VALUE_DATA *) (ListPtr + 2);\r
260 RegisterPtr = AllocateZeroPool (sizeof (EFI_PCI_REGISTER_VALUE_DATA));\r
261136bc 261 if (RegisterPtr == NULL) {\r
262 return EFI_SUCCESS;\r
263 }\r
54bd896e 264\r
265 RegisterPtr->AndValue = Dsc->AndValue;\r
266 RegisterPtr->OrValue = Dsc->OrValue;\r
267\r
268 *(VOID **) Configuration = RegisterPtr;\r
269\r
270 return EFI_SUCCESS;\r
271 }\r
272 }\r
273 ListPtr += sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR) / (sizeof (UINT64));\r
274 }\r
275 return EFI_UNSUPPORTED;\r
276\r
277 case DEVICE_RES_TAG:\r
278 //\r
279 // Adjust the pointer to the next item\r
280 //\r
281 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_REGISTER_VALUE_DESCRIPTOR)) / sizeof (UINT64));\r
282 break;\r
283\r
284 default:\r
285 return EFI_UNSUPPORTED;\r
286 }\r
287 }\r
288\r
289 return EFI_UNSUPPORTED;\r
290}\r
291\r
292/**\r
293 Check the incompatible device list for access width incompatibility and\r
294 return the configuration\r
295\r
296 This function searches the incompatible device list for access width\r
297 incompatibility according to request information. If the PCI device\r
298 belongs to the devices list, corresponding configuration informtion\r
299 will be returned, in the meantime return EFI_SUCCESS.\r
300\r
301 @param PciDeviceInfo A pointer to PCI device information.\r
302 @param AccessType Access type, READ or WRITE.\r
303 @param Offset The address within the PCI configuration space.\r
304 @param AccessWidth Access width needs to check incompatibility.\r
305 @param Configuration Returned information.\r
306\r
307 @retval returns EFI_SUCCESS if check incompatible device ok.\r
308 Otherwise return EFI_UNSUPPORTED.\r
309**/\r
310RETURN_STATUS\r
311EFIAPI\r
312PciRegisterAccessCheck (\r
313 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,\r
314 IN UINT64 AccessType,\r
315 IN UINT64 Offset,\r
316 IN UINT64 AccessWidth,\r
317 OUT VOID *Configuration\r
318 )\r
319{\r
320 EFI_PCI_DEVICE_INFO *Header;\r
321 UINT64 Tag;\r
322 UINT64 *ListPtr;\r
323 EFI_PCI_REGISTER_ACCESS_DATA *RegisterPtr;\r
324 EFI_PCI_REGISTER_ACCESS_DATA *Dsc;\r
325\r
326 ASSERT (PciDeviceInfo != NULL);\r
327\r
328 ListPtr = DeviceListForAccessWidth;\r
329\r
330 //\r
331 // Initialize the return value to NULL\r
332 //\r
333 * (VOID **) Configuration = NULL;\r
334\r
335 while (*ListPtr != LIST_END_TAG) {\r
336\r
337 Tag = *ListPtr;\r
338\r
339 switch (Tag) {\r
340 case DEVICE_INF_TAG:\r
341 Header = (EFI_PCI_DEVICE_INFO *) (ListPtr + 1);\r
342 ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_INFO) / sizeof (UINT64);\r
343\r
344 //\r
345 // Check whether the PCI device matches the device in the incompatible devices list?\r
346 // If not, ship next\r
347 //\r
348 if (DeviceCheck (PciDeviceInfo, Header) != EFI_SUCCESS) {\r
349 continue;\r
350 }\r
351\r
352 //\r
353 // Matched an item, check whether access matches?\r
354 //\r
355 for (; *ListPtr == DEVICE_RES_TAG;) {\r
356 ListPtr ++;\r
357 if (((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR *) ListPtr)->AccessType == AccessType &&\r
358 ((EFI_PCI_REGISTER_ACCESS_DESCRIPTOR *) ListPtr)->AccessWidth == AccessWidth ) {\r
359\r
360 Dsc = (EFI_PCI_REGISTER_ACCESS_DATA *) (ListPtr + 2);\r
361\r
362 if((Dsc->StartOffset <= Offset) && (Dsc->EndOffset > Offset)) {\r
363\r
364 RegisterPtr = AllocateZeroPool (sizeof (EFI_PCI_REGISTER_ACCESS_DATA));\r
261136bc 365 if (RegisterPtr == NULL) {\r
366 return EFI_OUT_OF_RESOURCES;\r
367 }\r
54bd896e 368\r
369 RegisterPtr->StartOffset = Dsc->StartOffset;\r
370 RegisterPtr->EndOffset = Dsc->EndOffset;\r
371 RegisterPtr->Width = Dsc->Width;\r
372\r
373 *(VOID **) Configuration = RegisterPtr;\r
374\r
375 return EFI_SUCCESS;\r
376 }\r
377 }\r
378 ListPtr += sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR) / (sizeof (UINT64));\r
379 }\r
380 return EFI_UNSUPPORTED;\r
381\r
382 case DEVICE_RES_TAG:\r
383 //\r
384 // Adjust the pointer to the next item\r
385 //\r
386 ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_REGISTER_ACCESS_DESCRIPTOR)) / sizeof (UINT64));\r
387 break;\r
388\r
389 default:\r
390 return EFI_UNSUPPORTED;\r
391 }\r
392 }\r
393\r
394 return EFI_UNSUPPORTED;\r
395}\r
396\r