iPXE
efi_utils.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 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 
20 FILE_LICENCE ( GPL2_OR_LATER );
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ipxe/efi/efi.h>
26 #include <ipxe/efi/efi_pci.h>
27 #include <ipxe/efi/efi_utils.h>
28 
29 /** @file
30  *
31  * EFI utilities
32  *
33  */
34 
35 /**
36  * Locate parent device supporting a given protocol
37  *
38  * @v device EFI device handle
39  * @v protocol Protocol GUID
40  * @v parent Parent EFI device handle to fill in
41  * @ret rc Return status code
42  */
44  EFI_HANDLE *parent ) {
46  union {
48  void *interface;
49  } path;
50  EFI_DEVICE_PATH_PROTOCOL *devpath;
51  EFI_STATUS efirc;
52  int rc;
53 
54  /* Get device path */
55  if ( ( efirc = bs->OpenProtocol ( device,
57  &path.interface,
60  rc = -EEFI ( efirc );
61  DBGC ( device, "EFIDEV %s cannot open device path: %s\n",
62  efi_handle_name ( device ), strerror ( rc ) );
63  goto err_open_device_path;
64  }
65  devpath = path.path;
66 
67  /* Check for presence of specified protocol */
68  if ( ( efirc = bs->LocateDevicePath ( protocol, &devpath,
69  parent ) ) != 0 ) {
70  rc = -EEFI ( efirc );
71  DBGC ( device, "EFIDEV %s has no parent supporting %s: %s\n",
73  efi_guid_ntoa ( protocol ), strerror ( rc ) );
74  goto err_locate_protocol;
75  }
76 
77  /* Success */
78  rc = 0;
79 
80  err_locate_protocol:
83  err_open_device_path:
84  return rc;
85 }
86 
87 /**
88  * Add EFI device as child of another EFI device
89  *
90  * @v parent EFI parent device handle
91  * @v child EFI child device handle
92  * @ret rc Return status code
93  */
94 int efi_child_add ( EFI_HANDLE parent, EFI_HANDLE child ) {
96  void *devpath;
97  EFI_STATUS efirc;
98  int rc;
99 
100  /* Re-open the device path protocol */
101  if ( ( efirc = bs->OpenProtocol ( parent,
103  &devpath,
104  efi_image_handle, child,
106  ) ) != 0 ) {
107  rc = -EEFI ( efirc );
108  DBGC ( parent, "EFIDEV %s could not add child",
109  efi_handle_name ( parent ) );
110  DBGC ( parent, " %s: %s\n",
111  efi_handle_name ( child ), strerror ( rc ) );
112  DBGC_EFI_OPENERS ( parent, parent,
114  return rc;
115  }
116 
117  DBGC2 ( parent, "EFIDEV %s added child", efi_handle_name ( parent ) );
118  DBGC2 ( parent, " %s\n", efi_handle_name ( child ) );
119  return 0;
120 }
121 
122 /**
123  * Remove EFI device as child of another EFI device
124  *
125  * @v parent EFI parent device handle
126  * @v child EFI child device handle
127  */
128 void efi_child_del ( EFI_HANDLE parent, EFI_HANDLE child ) {
130 
132  efi_image_handle, child );
133  DBGC2 ( parent, "EFIDEV %s removed child", efi_handle_name ( parent ) );
134  DBGC2 ( parent, " %s\n", efi_handle_name ( child ) );
135 }
136 
137 /**
138  * Get underlying PCI device information
139  *
140  * @v device EFI device handle
141  * @v prefix Device name prefix
142  * @v dev Generic device to fill in
143  * @ret rc Return status code
144  */
145 static int efi_pci_info ( EFI_HANDLE device, const char *prefix,
146  struct device *dev ) {
148  struct efi_pci_device efipci;
149  int rc;
150 
151  /* Find parent PCI device */
153  &pci_device ) ) != 0 ) {
154  DBGC ( device, "EFIDEV %s is not a PCI device: %s\n",
155  efi_handle_name ( device ), strerror ( rc ) );
156  return rc;
157  }
158 
159  /* Get PCI device information */
160  if ( ( rc = efipci_info ( pci_device, &efipci ) ) != 0 ) {
161  DBGC ( device, "EFIDEV %s could not get PCI information: %s\n",
162  efi_handle_name ( device ), strerror ( rc ) );
163  return rc;
164  }
165 
166  /* Populate device information */
167  memcpy ( &dev->desc, &efipci.pci.dev.desc, sizeof ( dev->desc ) );
168  snprintf ( dev->name, sizeof ( dev->name ), "%s-%s",
169  prefix, efipci.pci.dev.name );
170 
171  return 0;
172 }
173 
174 /**
175  * Get underlying device information
176  *
177  * @v device EFI device handle
178  * @v prefix Device name prefix
179  * @v dev Generic device to fill in
180  */
182  struct device *dev ) {
183  int rc;
184 
185  /* Try getting underlying PCI device information */
186  if ( ( rc = efi_pci_info ( device, prefix, dev ) ) == 0 )
187  return;
188 
189  /* If we cannot get any underlying device information, fall
190  * back to providing information about the EFI handle.
191  */
192  DBGC ( device, "EFIDEV %s could not get underlying device "
193  "information\n", efi_handle_name ( device ) );
194  dev->desc.bus_type = BUS_TYPE_EFI;
195  snprintf ( dev->name, sizeof ( dev->name ), "%s-%p", prefix, device );
196 }
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:162
int efipci_info(EFI_HANDLE device, struct efi_pci_device *efipci)
Get EFI PCI device information.
Definition: efi_pci.c:756
#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
Definition: UefiSpec.h:1273
struct pci_device pci
PCI device.
Definition: efi_pci.h:23
128 bit buffer containing a unique identifier value.
Definition: Base.h:263
Error codes.
EFI_GUID efi_pci_io_protocol_guid
PCI I/O protocol GUID.
Definition: efi_guid.c:216
#define DBGC(...)
Definition: compiler.h:505
char name[40]
Name.
Definition: device.h:75
char prefix[4]
Definition: vmconsole.c:53
#define DBGC_EFI_OPENERS(...)
Definition: efi.h:286
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition: DevicePath.h:51
int efi_child_add(EFI_HANDLE parent, EFI_HANDLE child)
Add EFI device as child of another EFI device.
Definition: efi_utils.c:94
EFI_CLOSE_PROTOCOL CloseProtocol
Definition: UefiSpec.h:1906
struct device dev
Generic device.
Definition: pci.h:193
EFI utilities.
void efi_child_del(EFI_HANDLE parent, EFI_HANDLE child)
Remove EFI device as child of another EFI device.
Definition: efi_utils.c:128
static int efi_pci_info(EFI_HANDLE device, const char *prefix, struct device *dev)
Get underlying PCI device information.
Definition: efi_utils.c:145
FILE_LICENCE(GPL2_OR_LATER)
A hardware device.
Definition: device.h:73
void * memcpy(void *dest, const void *src, size_t len) __nonnull
An object interface.
Definition: interface.h:124
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL
Definition: UefiSpec.h:1271
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition: efi_debug.c:722
const char * efi_guid_ntoa(CONST EFI_GUID *guid)
Convert GUID to a printable string.
Definition: efi_debug.c:192
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
EFI Boot Services Table.
Definition: UefiSpec.h:1836
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:33
A PCI device.
Definition: pci.h:191
EFI_GUID efi_device_path_protocol_guid
Device path protocol GUID.
Definition: efi_guid.c:132
#define BUS_TYPE_EFI
EFI bus type.
Definition: device.h:61
EFI API.
An EFI PCI device.
Definition: efi_pci.h:21
unsigned int bus_type
Bus type.
Definition: device.h:24
#define DBGC2(...)
Definition: compiler.h:522
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
EFI driver interface.
struct device_description desc
Device description.
Definition: device.h:79
int efi_locate_device(EFI_HANDLE device, EFI_GUID *protocol, EFI_HANDLE *parent)
Locate parent device supporting a given protocol.
Definition: efi_utils.c:43
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1905
uint16_t protocol
Protocol ID.
Definition: stp.h:18
String functions.
Definition: efi.h:50
EFI_LOCATE_DEVICE_PATH LocateDevicePath
Definition: UefiSpec.h:1877
void efi_device_info(EFI_HANDLE device, const char *prefix, struct device *dev)
Get underlying device information.
Definition: efi_utils.c:181