iPXE
efi_pci.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <ipxe/pci.h>
29 #include <ipxe/efi/efi.h>
30 #include <ipxe/efi/efi_pci.h>
31 #include <ipxe/efi/efi_driver.h>
34 
35 /** @file
36  *
37  * iPXE PCI I/O API for EFI
38  *
39  */
40 
41 /* Disambiguate the various error causes */
42 #define EINFO_EEFI_PCI \
43  __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \
44  "Could not open PCI I/O protocol" )
45 #define EINFO_EEFI_PCI_NOT_PCI \
46  __einfo_platformify ( EINFO_EEFI_PCI, EFI_UNSUPPORTED, \
47  "Not a PCI device" )
48 #define EEFI_PCI_NOT_PCI __einfo_error ( EINFO_EEFI_PCI_NOT_PCI )
49 #define EINFO_EEFI_PCI_IN_USE \
50  __einfo_platformify ( EINFO_EEFI_PCI, EFI_ACCESS_DENIED, \
51  "PCI device already has a driver" )
52 #define EEFI_PCI_IN_USE __einfo_error ( EINFO_EEFI_PCI_IN_USE )
53 #define EEFI_PCI( efirc ) \
54  EPLATFORM ( EINFO_EEFI_PCI, efirc, \
55  EEFI_PCI_NOT_PCI, EEFI_PCI_IN_USE )
56 
57 /******************************************************************************
58  *
59  * iPXE PCI API
60  *
61  ******************************************************************************
62  */
63 
64 /**
65  * Locate EFI PCI root bridge I/O protocol
66  *
67  * @v pci PCI device
68  * @ret handle EFI PCI root bridge handle
69  * @ret root EFI PCI root bridge I/O protocol, or NULL if not found
70  * @ret rc Return status code
71  */
72 static int efipci_root ( struct pci_device *pci, EFI_HANDLE *handle,
75  EFI_HANDLE *handles;
76  UINTN num_handles;
77  union {
78  void *interface;
80  } u;
81  EFI_STATUS efirc;
82  UINTN i;
83  int rc;
84 
85  /* Enumerate all handles */
86  if ( ( efirc = bs->LocateHandleBuffer ( ByProtocol,
88  NULL, &num_handles, &handles ) ) != 0 ) {
89  rc = -EEFI ( efirc );
90  DBGC ( pci, "EFIPCI " PCI_FMT " cannot locate root bridges: "
91  "%s\n", PCI_ARGS ( pci ), strerror ( rc ) );
92  goto err_locate;
93  }
94 
95  /* Look for matching root bridge I/O protocol */
96  for ( i = 0 ; i < num_handles ; i++ ) {
97  *handle = handles[i];
98  if ( ( efirc = bs->OpenProtocol ( *handle,
100  &u.interface, efi_image_handle, *handle,
101  EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
102  rc = -EEFI ( efirc );
103  DBGC ( pci, "EFIPCI " PCI_FMT " cannot open %s: %s\n",
104  PCI_ARGS ( pci ), efi_handle_name ( *handle ),
105  strerror ( rc ) );
106  continue;
107  }
108  if ( u.root->SegmentNumber == PCI_SEG ( pci->busdevfn ) ) {
109  *root = u.root;
110  bs->FreePool ( handles );
111  return 0;
112  }
113  bs->CloseProtocol ( *handle,
116  }
117  DBGC ( pci, "EFIPCI " PCI_FMT " found no root bridge\n",
118  PCI_ARGS ( pci ) );
119  rc = -ENOENT;
120 
121  bs->FreePool ( handles );
122  err_locate:
123  return rc;
124 }
125 
126 /**
127  * Calculate EFI PCI configuration space address
128  *
129  * @v pci PCI device
130  * @v location Encoded offset and width
131  * @ret address EFI PCI address
132  */
133 static unsigned long efipci_address ( struct pci_device *pci,
134  unsigned long location ) {
135 
136  return EFI_PCI_ADDRESS ( PCI_BUS ( pci->busdevfn ),
137  PCI_SLOT ( pci->busdevfn ),
138  PCI_FUNC ( pci->busdevfn ),
139  EFIPCI_OFFSET ( location ) );
140 }
141 
142 /**
143  * Read from PCI configuration space
144  *
145  * @v pci PCI device
146  * @v location Encoded offset and width
147  * @ret value Value
148  * @ret rc Return status code
149  */
150 int efipci_read ( struct pci_device *pci, unsigned long location,
151  void *value ) {
155  EFI_STATUS efirc;
156  int rc;
157 
158  /* Identify root bridge */
159  if ( ( rc = efipci_root ( pci, &handle, &root ) ) != 0 )
160  goto err_root;
161 
162  /* Read from configuration space */
163  if ( ( efirc = root->Pci.Read ( root, EFIPCI_WIDTH ( location ),
164  efipci_address ( pci, location ), 1,
165  value ) ) != 0 ) {
166  rc = -EEFI ( efirc );
167  DBGC ( pci, "EFIPCI " PCI_FMT " config read from offset %02lx "
168  "failed: %s\n", PCI_ARGS ( pci ),
169  EFIPCI_OFFSET ( location ), strerror ( rc ) );
170  goto err_read;
171  }
172 
173  err_read:
176  err_root:
177  return rc;
178 }
179 
180 /**
181  * Write to PCI configuration space
182  *
183  * @v pci PCI device
184  * @v location Encoded offset and width
185  * @v value Value
186  * @ret rc Return status code
187  */
188 int efipci_write ( struct pci_device *pci, unsigned long location,
189  unsigned long value ) {
193  EFI_STATUS efirc;
194  int rc;
195 
196  /* Identify root bridge */
197  if ( ( rc = efipci_root ( pci, &handle, &root ) ) != 0 )
198  goto err_root;
199 
200  /* Read from configuration space */
201  if ( ( efirc = root->Pci.Write ( root, EFIPCI_WIDTH ( location ),
202  efipci_address ( pci, location ), 1,
203  &value ) ) != 0 ) {
204  rc = -EEFI ( efirc );
205  DBGC ( pci, "EFIPCI " PCI_FMT " config write to offset %02lx "
206  "failed: %s\n", PCI_ARGS ( pci ),
207  EFIPCI_OFFSET ( location ), strerror ( rc ) );
208  goto err_write;
209  }
210 
211  err_write:
214  err_root:
215  return rc;
216 }
217 
225 
226 /******************************************************************************
227  *
228  * EFI PCI device instantiation
229  *
230  ******************************************************************************
231  */
232 
233 /**
234  * Open EFI PCI device
235  *
236  * @v device EFI device handle
237  * @v attributes Protocol opening attributes
238  * @v pci PCI device to fill in
239  * @ret rc Return status code
240  */
242  struct pci_device *pci ) {
244  union {
245  EFI_PCI_IO_PROTOCOL *pci_io;
246  void *interface;
247  } pci_io;
248  UINTN pci_segment, pci_bus, pci_dev, pci_fn;
249  unsigned int busdevfn;
250  EFI_STATUS efirc;
251  int rc;
252 
253  /* See if device is a PCI device */
254  if ( ( efirc = bs->OpenProtocol ( device, &efi_pci_io_protocol_guid,
255  &pci_io.interface, efi_image_handle,
256  device, attributes ) ) != 0 ) {
257  rc = -EEFI_PCI ( efirc );
258  DBGCP ( device, "EFIPCI %s cannot open PCI protocols: %s\n",
259  efi_handle_name ( device ), strerror ( rc ) );
260  goto err_open_protocol;
261  }
262 
263  /* Get PCI bus:dev.fn address */
264  if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io, &pci_segment,
265  &pci_bus, &pci_dev,
266  &pci_fn ) ) != 0 ) {
267  rc = -EEFI ( efirc );
268  DBGC ( device, "EFIPCI %s could not get PCI location: %s\n",
269  efi_handle_name ( device ), strerror ( rc ) );
270  goto err_get_location;
271  }
272  busdevfn = PCI_BUSDEVFN ( pci_segment, pci_bus, pci_dev, pci_fn );
273  pci_init ( pci, busdevfn );
274  DBGCP ( device, "EFIPCI " PCI_FMT " is %s\n",
275  PCI_ARGS ( pci ), efi_handle_name ( device ) );
276 
277  /* Try to enable I/O cycles, memory cycles, and bus mastering.
278  * Some platforms will 'helpfully' report errors if these bits
279  * can't be enabled (for example, if the card doesn't actually
280  * support I/O cycles). Work around any such platforms by
281  * enabling bits individually and simply ignoring any errors.
282  */
283  pci_io.pci_io->Attributes ( pci_io.pci_io,
286  pci_io.pci_io->Attributes ( pci_io.pci_io,
289  pci_io.pci_io->Attributes ( pci_io.pci_io,
292 
293  /* Populate PCI device */
294  if ( ( rc = pci_read_config ( pci ) ) != 0 ) {
295  DBGC ( device, "EFIPCI " PCI_FMT " cannot read PCI "
296  "configuration: %s\n",
297  PCI_ARGS ( pci ), strerror ( rc ) );
298  goto err_pci_read_config;
299  }
300 
301  return 0;
302 
303  err_pci_read_config:
304  err_get_location:
307  err_open_protocol:
308  return rc;
309 }
310 
311 /**
312  * Close EFI PCI device
313  *
314  * @v device EFI device handle
315  */
318 
321 }
322 
323 /**
324  * Get EFI PCI device information
325  *
326  * @v device EFI device handle
327  * @v pci PCI device to fill in
328  * @ret rc Return status code
329  */
330 int efipci_info ( EFI_HANDLE device, struct pci_device *pci ) {
331  int rc;
332 
333  /* Open PCI device, if possible */
335  pci ) ) != 0 )
336  return rc;
337 
338  /* Close PCI device */
339  efipci_close ( device );
340 
341  return 0;
342 }
343 
344 /******************************************************************************
345  *
346  * EFI PCI driver
347  *
348  ******************************************************************************
349  */
350 
351 /**
352  * Check to see if driver supports a device
353  *
354  * @v device EFI device handle
355  * @ret rc Return status code
356  */
358  struct pci_device pci;
359  int rc;
360 
361  /* Get PCI device information */
362  if ( ( rc = efipci_info ( device, &pci ) ) != 0 )
363  return rc;
364 
365  /* Look for a driver */
366  if ( ( rc = pci_find_driver ( &pci ) ) != 0 ) {
367  DBGC ( device, "EFIPCI " PCI_FMT " (%04x:%04x class %06x) "
368  "has no driver\n", PCI_ARGS ( &pci ), pci.vendor,
369  pci.device, pci.class );
370  return rc;
371  }
372  DBGC ( device, "EFIPCI " PCI_FMT " (%04x:%04x class %06x) has driver "
373  "\"%s\"\n", PCI_ARGS ( &pci ), pci.vendor, pci.device,
374  pci.class, pci.id->name );
375 
376  return 0;
377 }
378 
379 /**
380  * Attach driver to device
381  *
382  * @v efidev EFI device
383  * @ret rc Return status code
384  */
385 static int efipci_start ( struct efi_device *efidev ) {
386  EFI_HANDLE device = efidev->device;
387  struct pci_device *pci;
388  int rc;
389 
390  /* Allocate PCI device */
391  pci = zalloc ( sizeof ( *pci ) );
392  if ( ! pci ) {
393  rc = -ENOMEM;
394  goto err_alloc;
395  }
396 
397  /* Open PCI device */
400  pci ) ) != 0 ) {
401  DBGC ( device, "EFIPCI %s could not open PCI device: %s\n",
402  efi_handle_name ( device ), strerror ( rc ) );
404  goto err_open;
405  }
406 
407  /* Find driver */
408  if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {
409  DBGC ( device, "EFIPCI " PCI_FMT " has no driver\n",
410  PCI_ARGS ( pci ) );
411  goto err_find_driver;
412  }
413 
414  /* Mark PCI device as a child of the EFI device */
415  pci->dev.parent = &efidev->dev;
416  list_add ( &pci->dev.siblings, &efidev->dev.children );
417 
418  /* Probe driver */
419  if ( ( rc = pci_probe ( pci ) ) != 0 ) {
420  DBGC ( device, "EFIPCI " PCI_FMT " could not probe driver "
421  "\"%s\": %s\n", PCI_ARGS ( pci ), pci->id->name,
422  strerror ( rc ) );
423  goto err_probe;
424  }
425  DBGC ( device, "EFIPCI " PCI_FMT " using driver \"%s\"\n",
426  PCI_ARGS ( pci ), pci->id->name );
427 
428  efidev_set_drvdata ( efidev, pci );
429  return 0;
430 
431  pci_remove ( pci );
432  err_probe:
433  list_del ( &pci->dev.siblings );
434  err_find_driver:
435  efipci_close ( device );
436  err_open:
437  free ( pci );
438  err_alloc:
439  return rc;
440 }
441 
442 /**
443  * Detach driver from device
444  *
445  * @v efidev EFI device
446  */
447 static void efipci_stop ( struct efi_device *efidev ) {
448  struct pci_device *pci = efidev_get_drvdata ( efidev );
449  EFI_HANDLE device = efidev->device;
450 
451  pci_remove ( pci );
452  list_del ( &pci->dev.siblings );
453  efipci_close ( device );
454  free ( pci );
455 }
456 
457 /** EFI PCI driver */
458 struct efi_driver efipci_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
459  .name = "PCI",
460  .supported = efipci_supported,
461  .start = efipci_start,
462  .stop = efipci_stop,
463 };
#define PCI_FUNC(busdevfn)
Definition: pci.h:258
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
#define PCI_BUS(busdevfn)
Definition: pci.h:256
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define EFI_PCI_ADDRESS(bus, dev, func, reg)
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:157
int pci_find_driver(struct pci_device *pci)
Find driver for PCI device.
Definition: pci.c:254
EFI driver interface.
struct stp_switch root
Root switch.
Definition: stp.h:26
uint32_t class
Device class.
Definition: pci.h:206
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
Error codes.
EFI_GUID efi_pci_io_protocol_guid
PCI I/O protocol GUID.
Definition: efi_guid.c:216
static int efipci_start(struct efi_device *efidev)
Attach driver to device.
Definition: efi_pci.c:385
int pci_write_config_word(struct pci_device *pci, unsigned int where, uint16_t value)
Write 16-bit word to PCI configuration space.
struct efi_driver efipci_driver __efi_driver(EFI_DRIVER_NORMAL)
EFI PCI driver.
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:514
unsigned int UINT32
Definition: ProcessorBind.h:56
#define EFI_OPEN_PROTOCOL_BY_DRIVER
Definition: UefiSpec.h:1274
int efipci_write(struct pci_device *pci, unsigned long location, unsigned long value)
Write to PCI configuration space.
Definition: efi_pci.c:188
#define PCI_BUSDEVFN(segment, bus, slot, func)
Definition: pci.h:259
#define EFIPCI_OFFSET(_location)
Definition: efi_pci_api.h:25
#define EFI_OPEN_PROTOCOL_EXCLUSIVE
Definition: UefiSpec.h:1275
int pci_read_config_word(struct pci_device *pci, unsigned int where, uint16_t *value)
Read 16-bit word from PCI configuration space.
#define DBGC_EFI_OPENERS(...)
Definition: efi.h:260
EFI_HANDLE device
EFI device handle.
Definition: efi_driver.h:21
PROVIDE_PCIAPI_INLINE(efi, pci_num_bus)
EFI_CLOSE_PROTOCOL CloseProtocol
Definition: UefiSpec.h:1906
struct device * parent
Bus device.
Definition: device.h:85
struct device dev
Generic device.
Definition: pci.h:189
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define ENOMEM
Not enough space.
Definition: errno.h:534
A hardware device.
Definition: device.h:73
#define EFI_PCI_IO_ATTRIBUTE_MEMORY
Enable the Memory decode bit in the PCI Config Header.
Definition: PciIo.h:66
uint16_t device
Device ID.
Definition: pci.h:204
An object interface.
Definition: interface.h:109
int pci_read_config_dword(struct pci_device *pci, unsigned int where, uint32_t *value)
Read 32-bit dword from PCI configuration space.
static int efipci_root(struct pci_device *pci, EFI_HANDLE *handle, EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **root)
Locate EFI PCI root bridge I/O protocol.
Definition: efi_pci.c:72
int efipci_open(EFI_HANDLE device, UINT32 attributes, struct pci_device *pci)
Open EFI PCI device.
Definition: efi_pci.c:241
#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
Enable the DMA bit in the PCI Config Header.
Definition: PciIo.h:67
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static void efipci_stop(struct efi_device *efidev)
Detach driver from device.
Definition: efi_pci.c:447
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL
Definition: UefiSpec.h:1271
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition: efi_debug.c:713
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
int pci_write_config_byte(struct pci_device *pci, unsigned int where, uint8_t value)
Write byte to PCI configuration space.
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
EFI Boot Services Table.
Definition: UefiSpec.h:1836
#define PCI_FMT
PCI device debug message format.
Definition: pci.h:287
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:30
#define PCI_SLOT(busdevfn)
Definition: pci.h:257
PCI bus.
struct list_head siblings
Devices on the same bus.
Definition: device.h:81
A PCI device.
Definition: pci.h:187
static void * efidev_get_drvdata(struct efi_device *efidev)
Get EFI driver-private data.
Definition: efi_driver.h:83
int pci_read_config(struct pci_device *pci)
Read PCI device configuration.
Definition: pci.c:177
void pci_remove(struct pci_device *pci)
Remove a PCI device.
Definition: pci.c:308
static int efipci_supported(EFI_HANDLE device)
Check to see if driver supports a device.
Definition: efi_pci.c:357
UINT64 UINTN
Unsigned value of native width.
Definition: ProcessorBind.h:71
An EFI device.
Definition: efi_driver.h:17
#define EFI_PCI_IO_ATTRIBUTE_IO
Enable the I/O decode bit in the PCI Config Header.
Definition: PciIo.h:65
const char * name
Name.
Definition: pci.h:153
EFI_FREE_POOL FreePool
Definition: UefiSpec.h:1855
uint16_t vendor
Vendor ID.
Definition: pci.h:202
EFI API.
Enable the attributes specified by the bits that are set in Attributes for this PCI controller.
Definition: PciIo.h:119
Provides the basic Memory, I/O, PCI configuration, and DMA interfaces that are used to abstract acces...
An EFI driver.
Definition: efi_driver.h:31
uint32_t busdevfn
Segment, bus, device, and function (bus:dev.fn) number.
Definition: pci.h:210
#define EFIPCI_WIDTH(_location)
Definition: efi_pci_api.h:26
int pci_num_bus(void)
Determine number of PCI buses within system.
#define EEFI_PCI(efirc)
Definition: efi_pci.c:53
void efipci_close(EFI_HANDLE device)
Close EFI PCI device.
Definition: efi_pci.c:316
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
struct list_head children
Devices attached to this device.
Definition: device.h:83
PCI Root Bridge I/O protocol as defined in the UEFI 2.0 specification.
EFI driver interface.
#define PCI_ARGS(pci)
PCI device debug message arguments.
Definition: pci.h:290
struct pci_device_id * id
Driver device ID.
Definition: pci.h:220
EFI_GUID efi_pci_root_bridge_io_protocol_guid
PCI root bridge I/O protocol GUID.
Definition: efi_guid.c:220
int pci_write_config_dword(struct pci_device *pci, unsigned int where, uint32_t value)
Write 32-bit dword to PCI configuration space.
const char * name
Name.
Definition: efi_driver.h:33
#define DBGCP(...)
Definition: compiler.h:539
Retrieve the set of handles from the handle database that support a specified protocol.
Definition: UefiSpec.h:1448
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1905
int efipci_info(EFI_HANDLE device, struct pci_device *pci)
Get EFI PCI device information.
Definition: efi_pci.c:330
union @16 u
static unsigned long efipci_address(struct pci_device *pci, unsigned long location)
Calculate EFI PCI configuration space address.
Definition: efi_pci.c:133
static void pci_init(struct pci_device *pci, unsigned int busdevfn)
Initialise PCI device.
Definition: pci.h:313
EFI PCI I/O Protocol provides the basic Memory, I/O, PCI configuration, and DMA interfaces that a dri...
static void efidev_set_drvdata(struct efi_device *efidev, void *priv)
Set EFI driver-private data.
Definition: efi_driver.h:72
The EFI_PCI_IO_PROTOCOL provides the basic Memory, I/O, PCI configuration, and DMA interfaces used to...
Definition: PciIo.h:525
struct device dev
Generic device.
Definition: efi_driver.h:19
uint16_t handle
Handle.
Definition: smbios.h:16
#define PCI_SEG(busdevfn)
Definition: pci.h:255
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
int pci_probe(struct pci_device *pci)
Probe a PCI device.
Definition: pci.c:286
Definition: efi.h:55
int efipci_read(struct pci_device *pci, unsigned long location, void *value)
Read from PCI configuration space.
Definition: efi_pci.c:150
EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer
Definition: UefiSpec.h:1913
#define EFI_DRIVER_NORMAL
Normal drivers.
Definition: efi_driver.h:63
int pci_read_config_byte(struct pci_device *pci, unsigned int where, uint8_t *value)
Read byte from PCI configuration space.