1 | /** @file
|
---|
2 | Library class to work with PCI capabilities in PCI config space.
|
---|
3 |
|
---|
4 | Provides functions to parse capabilities lists, and to locate, describe, read
|
---|
5 | and write capabilities. PCI config space access is abstracted away.
|
---|
6 |
|
---|
7 | Copyright (C) 2018, Red Hat, Inc.
|
---|
8 |
|
---|
9 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
10 | **/
|
---|
11 |
|
---|
12 | #ifndef __PCI_CAP_LIB_H__
|
---|
13 | #define __PCI_CAP_LIB_H__
|
---|
14 |
|
---|
15 | #include <Uefi/UefiBaseType.h>
|
---|
16 |
|
---|
17 | //
|
---|
18 | // Base structure for representing a PCI device -- down to the PCI function
|
---|
19 | // level -- for the purposes of this library class. This is a forward
|
---|
20 | // declaration that is completed below. Concrete implementations are supposed
|
---|
21 | // to inherit and extend this type.
|
---|
22 | //
|
---|
23 | typedef struct PCI_CAP_DEV PCI_CAP_DEV;
|
---|
24 |
|
---|
25 | /**
|
---|
26 | Read the config space of a given PCI device (both normal and extended).
|
---|
27 |
|
---|
28 | PCI_CAP_DEV_READ_CONFIG performs as few config space accesses as possible
|
---|
29 | (without attempting 64-bit wide accesses).
|
---|
30 |
|
---|
31 | PCI_CAP_DEV_READ_CONFIG returns an unspecified error if accessing Size bytes
|
---|
32 | from SourceOffset exceeds the config space limit of the PCI device. Fewer
|
---|
33 | than Size bytes may have been read in this case.
|
---|
34 |
|
---|
35 | @param[in] PciDevice Implementation-specific unique representation
|
---|
36 | of the PCI device in the PCI hierarchy.
|
---|
37 |
|
---|
38 | @param[in] SourceOffset Source offset in the config space of the PCI
|
---|
39 | device to start reading from.
|
---|
40 |
|
---|
41 | @param[out] DestinationBuffer Buffer to store the read data to.
|
---|
42 |
|
---|
43 | @param[in] Size The number of bytes to transfer.
|
---|
44 |
|
---|
45 | @retval RETURN_SUCCESS Size bytes have been transferred from config space to
|
---|
46 | DestinationBuffer.
|
---|
47 |
|
---|
48 | @return Unspecified error codes. Fewer than Size bytes may
|
---|
49 | have been read.
|
---|
50 | **/
|
---|
51 | typedef
|
---|
52 | RETURN_STATUS
|
---|
53 | (EFIAPI *PCI_CAP_DEV_READ_CONFIG) (
|
---|
54 | IN PCI_CAP_DEV *PciDevice,
|
---|
55 | IN UINT16 SourceOffset,
|
---|
56 | OUT VOID *DestinationBuffer,
|
---|
57 | IN UINT16 Size
|
---|
58 | );
|
---|
59 |
|
---|
60 | /**
|
---|
61 | Write the config space of a given PCI device (both normal and extended).
|
---|
62 |
|
---|
63 | PCI_CAP_DEV_WRITE_CONFIG performs as few config space accesses as possible
|
---|
64 | (without attempting 64-bit wide accesses).
|
---|
65 |
|
---|
66 | PCI_CAP_DEV_WRITE_CONFIG returns an unspecified error if accessing Size bytes
|
---|
67 | at DestinationOffset exceeds the config space limit of the PCI device. Fewer
|
---|
68 | than Size bytes may have been written in this case.
|
---|
69 |
|
---|
70 | @param[in] PciDevice Implementation-specific unique representation
|
---|
71 | of the PCI device in the PCI hierarchy.
|
---|
72 |
|
---|
73 | @param[in] DestinationOffset Destination offset in the config space of the
|
---|
74 | PCI device to start writing at.
|
---|
75 |
|
---|
76 | @param[in] SourceBuffer Buffer to read the data to be stored from.
|
---|
77 |
|
---|
78 | @param[in] Size The number of bytes to transfer.
|
---|
79 |
|
---|
80 | @retval RETURN_SUCCESS Size bytes have been transferred from SourceBuffer to
|
---|
81 | config space.
|
---|
82 |
|
---|
83 | @return Unspecified error codes. Fewer than Size bytes may
|
---|
84 | have been written.
|
---|
85 | **/
|
---|
86 | typedef
|
---|
87 | RETURN_STATUS
|
---|
88 | (EFIAPI *PCI_CAP_DEV_WRITE_CONFIG) (
|
---|
89 | IN PCI_CAP_DEV *PciDevice,
|
---|
90 | IN UINT16 DestinationOffset,
|
---|
91 | IN VOID *SourceBuffer,
|
---|
92 | IN UINT16 Size
|
---|
93 | );
|
---|
94 |
|
---|
95 | //
|
---|
96 | // Complete the PCI_CAP_DEV type here. The base abstraction only requires
|
---|
97 | // config space accessors.
|
---|
98 | //
|
---|
99 | struct PCI_CAP_DEV {
|
---|
100 | PCI_CAP_DEV_READ_CONFIG ReadConfig;
|
---|
101 | PCI_CAP_DEV_WRITE_CONFIG WriteConfig;
|
---|
102 | };
|
---|
103 |
|
---|
104 | //
|
---|
105 | // Opaque data structure representing parsed PCI Capabilities Lists.
|
---|
106 | //
|
---|
107 | typedef struct PCI_CAP_LIST PCI_CAP_LIST;
|
---|
108 |
|
---|
109 | //
|
---|
110 | // Opaque data structure representing a PCI Capability in a parsed Capability
|
---|
111 | // List.
|
---|
112 | //
|
---|
113 | typedef struct PCI_CAP PCI_CAP;
|
---|
114 |
|
---|
115 | //
|
---|
116 | // Distinguishes whether a Capability ID is 8-bit wide and interpreted in
|
---|
117 | // normal config space, or 16-bit wide and interpreted in extended config
|
---|
118 | // space. Capability ID definitions are relative to domain.
|
---|
119 | //
|
---|
120 | typedef enum {
|
---|
121 | PciCapNormal,
|
---|
122 | PciCapExtended
|
---|
123 | } PCI_CAP_DOMAIN;
|
---|
124 |
|
---|
125 | //
|
---|
126 | // Public data structure that PciCapGetInfo() fills in about a PCI_CAP object.
|
---|
127 | //
|
---|
128 | typedef struct {
|
---|
129 | PCI_CAP_DOMAIN Domain;
|
---|
130 | UINT16 CapId;
|
---|
131 | //
|
---|
132 | // The capability identified by Domain and CapId may have multiple instances
|
---|
133 | // in config space. NumInstances provides the total count of occurrences of
|
---|
134 | // the capability. It is always positive.
|
---|
135 | //
|
---|
136 | UINT16 NumInstances;
|
---|
137 | //
|
---|
138 | // Instance is the serial number, in capabilities list traversal order (not
|
---|
139 | // necessarily config space offset order), of the one capability instance
|
---|
140 | // that PciCapGetInfo() is reporting about. Instance is always smaller than
|
---|
141 | // NumInstances.
|
---|
142 | //
|
---|
143 | UINT16 Instance;
|
---|
144 | //
|
---|
145 | // The offset in config space at which the capability header of the
|
---|
146 | // capability instance starts.
|
---|
147 | //
|
---|
148 | UINT16 Offset;
|
---|
149 | //
|
---|
150 | // The deduced maximum size of the capability instance, including the
|
---|
151 | // capability header. This hint is an upper bound, calculated -- without
|
---|
152 | // regard to the internal structure of the capability -- from (a) the next
|
---|
153 | // lowest offset in configuration space that is known to be used by another
|
---|
154 | // capability, and (b) from the end of the config space identified by Domain,
|
---|
155 | // whichever is lower.
|
---|
156 | //
|
---|
157 | UINT16 MaxSizeHint;
|
---|
158 | //
|
---|
159 | // The version number of the capability instance. Always zero when Domain is
|
---|
160 | // PciCapNormal.
|
---|
161 | //
|
---|
162 | UINT8 Version;
|
---|
163 | } PCI_CAP_INFO;
|
---|
164 |
|
---|
165 |
|
---|
166 | /**
|
---|
167 | Parse the capabilities lists (both normal and extended, as applicable) of a
|
---|
168 | PCI device.
|
---|
169 |
|
---|
170 | If the PCI device has no capabilities, that per se will not fail
|
---|
171 | PciCapListInit(); an empty capabilities list will be represented.
|
---|
172 |
|
---|
173 | If the PCI device is found to be PCI Express, then an attempt will be made to
|
---|
174 | parse the extended capabilities list as well. If the first extended config
|
---|
175 | space access -- via PciDevice->ReadConfig() with SourceOffset=0x100 and
|
---|
176 | Size=4 -- fails, that per se will not fail PciCapListInit(); the device will
|
---|
177 | be assumed to have no extended capabilities.
|
---|
178 |
|
---|
179 | @param[in] PciDevice Implementation-specific unique representation of the
|
---|
180 | PCI device in the PCI hierarchy.
|
---|
181 |
|
---|
182 | @param[out] CapList Opaque data structure that holds an in-memory
|
---|
183 | representation of the parsed capabilities lists of
|
---|
184 | PciDevice.
|
---|
185 |
|
---|
186 | @retval RETURN_SUCCESS The capabilities lists have been parsed from
|
---|
187 | config space.
|
---|
188 |
|
---|
189 | @retval RETURN_OUT_OF_RESOURCES Memory allocation failed.
|
---|
190 |
|
---|
191 | @retval RETURN_DEVICE_ERROR A loop or some other kind of invalid pointer
|
---|
192 | was detected in the capabilities lists of
|
---|
193 | PciDevice.
|
---|
194 |
|
---|
195 | @return Error codes propagated from
|
---|
196 | PciDevice->ReadConfig().
|
---|
197 | **/
|
---|
198 | RETURN_STATUS
|
---|
199 | EFIAPI
|
---|
200 | PciCapListInit (
|
---|
201 | IN PCI_CAP_DEV *PciDevice,
|
---|
202 | OUT PCI_CAP_LIST **CapList
|
---|
203 | );
|
---|
204 |
|
---|
205 |
|
---|
206 | /**
|
---|
207 | Free the resources used by CapList.
|
---|
208 |
|
---|
209 | @param[in] CapList The PCI_CAP_LIST object to free, originally produced by
|
---|
210 | PciCapListInit().
|
---|
211 | **/
|
---|
212 | VOID
|
---|
213 | EFIAPI
|
---|
214 | PciCapListUninit (
|
---|
215 | IN PCI_CAP_LIST *CapList
|
---|
216 | );
|
---|
217 |
|
---|
218 |
|
---|
219 | /**
|
---|
220 | Locate a capability instance in the parsed capabilities lists.
|
---|
221 |
|
---|
222 | @param[in] CapList The PCI_CAP_LIST object produced by PciCapListInit().
|
---|
223 |
|
---|
224 | @param[in] Domain Distinguishes whether CapId is 8-bit wide and
|
---|
225 | interpreted in normal config space, or 16-bit wide and
|
---|
226 | interpreted in extended config space. Capability ID
|
---|
227 | definitions are relative to domain.
|
---|
228 |
|
---|
229 | @param[in] CapId Capability identifier to look up.
|
---|
230 |
|
---|
231 | @param[in] Instance Domain and CapId may identify a multi-instance
|
---|
232 | capability. When Instance is zero, the first instance of
|
---|
233 | the capability is located (in list traversal order --
|
---|
234 | which may not mean increasing config space offset
|
---|
235 | order). Higher Instance values locate subsequent
|
---|
236 | instances of the same capability (in list traversal
|
---|
237 | order).
|
---|
238 |
|
---|
239 | @param[out] Cap The capability instance that matches the search
|
---|
240 | criteria. Cap is owned by CapList and becomes invalid
|
---|
241 | when CapList is freed with PciCapListUninit().
|
---|
242 | PciCapListFindCap() may be called with Cap set to NULL,
|
---|
243 | in order to test the existence of a specific capability
|
---|
244 | instance.
|
---|
245 |
|
---|
246 | @retval RETURN_SUCCESS The capability instance identified by (Domain,
|
---|
247 | CapId, Instance) has been found.
|
---|
248 |
|
---|
249 | @retval RETURN_NOT_FOUND The requested (Domain, CapId, Instance) capability
|
---|
250 | instance does not exist.
|
---|
251 | **/
|
---|
252 | RETURN_STATUS
|
---|
253 | EFIAPI
|
---|
254 | PciCapListFindCap (
|
---|
255 | IN PCI_CAP_LIST *CapList,
|
---|
256 | IN PCI_CAP_DOMAIN Domain,
|
---|
257 | IN UINT16 CapId,
|
---|
258 | IN UINT16 Instance,
|
---|
259 | OUT PCI_CAP **Cap OPTIONAL
|
---|
260 | );
|
---|
261 |
|
---|
262 |
|
---|
263 | /**
|
---|
264 | Locate the first instance of the capability given by (Domain, CapId) such
|
---|
265 | that the instance's Version is greater than or equal to MinVersion.
|
---|
266 |
|
---|
267 | This is a convenience function that may save client code calls to
|
---|
268 | PciCapListFindCap() and PciCapGetInfo().
|
---|
269 |
|
---|
270 | @param[in] CapList The PCI_CAP_LIST object produced by PciCapListInit().
|
---|
271 |
|
---|
272 | @param[in] Domain Distinguishes whether CapId is 8-bit wide and
|
---|
273 | interpreted in normal config space, or 16-bit wide and
|
---|
274 | interpreted in extended config space. Capability ID
|
---|
275 | definitions are relative to domain.
|
---|
276 |
|
---|
277 | @param[in] CapId Capability identifier to look up.
|
---|
278 |
|
---|
279 | @param[in] MinVersion The minimum version that the capability instance is
|
---|
280 | required to have. Note that all capability instances
|
---|
281 | in Domain=PciCapNormal have Version=0.
|
---|
282 |
|
---|
283 | @param[out] Cap The first capability instance that matches the search
|
---|
284 | criteria. Cap is owned by CapList and becomes invalid
|
---|
285 | when CapList is freed with PciCapListUninit().
|
---|
286 | PciCapListFindCapVersion() may be called with Cap set
|
---|
287 | to NULL, in order just to test whether the search
|
---|
288 | criteria are satisfiable.
|
---|
289 |
|
---|
290 | @retval RETURN_SUCCESS The first capability instance matching (Domain,
|
---|
291 | CapId, MinVersion) has been located.
|
---|
292 |
|
---|
293 | @retval RETURN_NOT_FOUND No capability instance matches (Domain, CapId,
|
---|
294 | MinVersion).
|
---|
295 | **/
|
---|
296 | RETURN_STATUS
|
---|
297 | EFIAPI
|
---|
298 | PciCapListFindCapVersion (
|
---|
299 | IN PCI_CAP_LIST *CapList,
|
---|
300 | IN PCI_CAP_DOMAIN Domain,
|
---|
301 | IN UINT16 CapId,
|
---|
302 | IN UINT8 MinVersion,
|
---|
303 | OUT PCI_CAP **Cap OPTIONAL
|
---|
304 | );
|
---|
305 |
|
---|
306 |
|
---|
307 | /**
|
---|
308 | Get information about a PCI Capability instance.
|
---|
309 |
|
---|
310 | @param[in] Cap The capability instance to get info about, located with
|
---|
311 | PciCapListFindCap*().
|
---|
312 |
|
---|
313 | @param[out] Info A PCI_CAP_INFO structure that describes the properties of
|
---|
314 | Cap.
|
---|
315 |
|
---|
316 | @retval RETURN_SUCCESS Fields of Info have been set.
|
---|
317 |
|
---|
318 | @return Unspecified error codes, if filling in Info failed
|
---|
319 | for some reason.
|
---|
320 | **/
|
---|
321 | RETURN_STATUS
|
---|
322 | EFIAPI
|
---|
323 | PciCapGetInfo (
|
---|
324 | IN PCI_CAP *Cap,
|
---|
325 | OUT PCI_CAP_INFO *Info
|
---|
326 | );
|
---|
327 |
|
---|
328 |
|
---|
329 | /**
|
---|
330 | Read a slice of a capability instance.
|
---|
331 |
|
---|
332 | The function performs as few config space accesses as possible (without
|
---|
333 | attempting 64-bit wide accesses). PciCapRead() performs bounds checking on
|
---|
334 | SourceOffsetInCap and Size, and only invokes PciDevice->ReadConfig() if the
|
---|
335 | requested transfer falls within Cap.
|
---|
336 |
|
---|
337 | @param[in] PciDevice Implementation-specific unique representation
|
---|
338 | of the PCI device in the PCI hierarchy.
|
---|
339 |
|
---|
340 | @param[in] Cap The capability instance to read, located with
|
---|
341 | PciCapListFindCap*().
|
---|
342 |
|
---|
343 | @param[in] SourceOffsetInCap Source offset relative to the capability
|
---|
344 | header to start reading from. A zero value
|
---|
345 | refers to the first byte of the capability
|
---|
346 | header.
|
---|
347 |
|
---|
348 | @param[out] DestinationBuffer Buffer to store the read data to.
|
---|
349 |
|
---|
350 | @param[in] Size The number of bytes to transfer.
|
---|
351 |
|
---|
352 | @retval RETURN_SUCCESS Size bytes have been transferred from Cap to
|
---|
353 | DestinationBuffer.
|
---|
354 |
|
---|
355 | @retval RETURN_BAD_BUFFER_SIZE Reading Size bytes starting from
|
---|
356 | SourceOffsetInCap would not (entirely) be
|
---|
357 | contained within Cap, as suggested by
|
---|
358 | PCI_CAP_INFO.MaxSizeHint. No bytes have been
|
---|
359 | read.
|
---|
360 |
|
---|
361 | @return Error codes propagated from
|
---|
362 | PciDevice->ReadConfig(). Fewer than Size
|
---|
363 | bytes may have been read.
|
---|
364 | **/
|
---|
365 | RETURN_STATUS
|
---|
366 | EFIAPI
|
---|
367 | PciCapRead (
|
---|
368 | IN PCI_CAP_DEV *PciDevice,
|
---|
369 | IN PCI_CAP *Cap,
|
---|
370 | IN UINT16 SourceOffsetInCap,
|
---|
371 | OUT VOID *DestinationBuffer,
|
---|
372 | IN UINT16 Size
|
---|
373 | );
|
---|
374 |
|
---|
375 |
|
---|
376 | /**
|
---|
377 | Write a slice of a capability instance.
|
---|
378 |
|
---|
379 | The function performs as few config space accesses as possible (without
|
---|
380 | attempting 64-bit wide accesses). PciCapWrite() performs bounds checking on
|
---|
381 | DestinationOffsetInCap and Size, and only invokes PciDevice->WriteConfig() if
|
---|
382 | the requested transfer falls within Cap.
|
---|
383 |
|
---|
384 | @param[in] PciDevice Implementation-specific unique
|
---|
385 | representation of the PCI device in the
|
---|
386 | PCI hierarchy.
|
---|
387 |
|
---|
388 | @param[in] Cap The capability instance to write, located
|
---|
389 | with PciCapListFindCap*().
|
---|
390 |
|
---|
391 | @param[in] DestinationOffsetInCap Destination offset relative to the
|
---|
392 | capability header to start writing at. A
|
---|
393 | zero value refers to the first byte of the
|
---|
394 | capability header.
|
---|
395 |
|
---|
396 | @param[in] SourceBuffer Buffer to read the data to be stored from.
|
---|
397 |
|
---|
398 | @param[in] Size The number of bytes to transfer.
|
---|
399 |
|
---|
400 | @retval RETURN_SUCCESS Size bytes have been transferred from
|
---|
401 | SourceBuffer to Cap.
|
---|
402 |
|
---|
403 | @retval RETURN_BAD_BUFFER_SIZE Writing Size bytes starting at
|
---|
404 | DestinationOffsetInCap would not (entirely)
|
---|
405 | be contained within Cap, as suggested by
|
---|
406 | PCI_CAP_INFO.MaxSizeHint. No bytes have been
|
---|
407 | written.
|
---|
408 |
|
---|
409 | @return Error codes propagated from
|
---|
410 | PciDevice->WriteConfig(). Fewer than Size
|
---|
411 | bytes may have been written.
|
---|
412 | **/
|
---|
413 | RETURN_STATUS
|
---|
414 | EFIAPI
|
---|
415 | PciCapWrite (
|
---|
416 | IN PCI_CAP_DEV *PciDevice,
|
---|
417 | IN PCI_CAP *Cap,
|
---|
418 | IN UINT16 DestinationOffsetInCap,
|
---|
419 | IN VOID *SourceBuffer,
|
---|
420 | IN UINT16 Size
|
---|
421 | );
|
---|
422 |
|
---|
423 | #endif // __PCI_CAP_LIB_H__
|
---|