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