iPXE
snponly.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 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 <string.h>
27 #include <errno.h>
28 #include <ipxe/init.h>
29 #include <ipxe/efi/efi.h>
30 #include <ipxe/efi/efi_driver.h>
31 #include <ipxe/efi/efi_utils.h>
34 #include "snpnet.h"
35 #include "mnpnet.h"
36 #include "nii.h"
37 
38 /** @file
39  *
40  * EFI chainloaded-device-only driver
41  *
42  */
43 
44 /** A chainloaded protocol */
46  /** Protocol GUID */
48  /**
49  * Target device handle
50  *
51  * This is the uppermost handle on which the same protocol
52  * instance is installed as we find on the loaded image's
53  * device handle.
54  *
55  * We match against the protocol instance (rather than simply
56  * matching against the device handle itself) because some
57  * systems load us via a child of the underlying device, with
58  * a duplicate protocol installed on the child handle.
59  *
60  * We record the handle rather than the protocol instance
61  * pointer since the calls to DisconnectController() and
62  * ConnectController() may end up uninstalling and
63  * reinstalling the protocol instance.
64  */
66 };
67 
68 /** Chainloaded SNP protocol */
69 static struct chained_protocol chained_snp = {
71 };
72 
73 /** Chainloaded NII protocol */
74 static struct chained_protocol chained_nii = {
76 };
77 
78 /** Chainloaded MNP protocol */
79 static struct chained_protocol chained_mnp = {
81 };
82 
83 /**
84  * Locate chainloaded protocol
85  *
86  * @v chained Chainloaded protocol
87  */
88 static void chained_locate ( struct chained_protocol *chained ) {
92  void *match = NULL;
93  void *interface;
94  unsigned int skip;
95  EFI_STATUS efirc;
96  int rc;
97 
98  /* Identify target device handle */
99  for ( skip = 0 ; ; skip++ ) {
100 
101  /* Locate handle supporting this protocol */
102  if ( ( rc = efi_locate_device ( device, chained->protocol,
103  &handle, skip ) ) != 0 ) {
104  if ( skip == 0 ) {
105  DBGC ( device, "CHAINED %s does not support "
106  "%s: %s\n", efi_handle_name ( device ),
107  efi_guid_ntoa ( chained->protocol ),
108  strerror ( rc ) );
109  }
110  break;
111  }
112 
113  /* Get protocol instance */
114  if ( ( efirc = bs->OpenProtocol (
115  handle, chained->protocol, &interface,
118  rc = -EEFI ( efirc );
119  DBGC ( device, "CHAINED %s could not open %s on ",
121  efi_guid_ntoa ( chained->protocol ) );
122  DBGC ( device, "%s: %s\n",
123  efi_handle_name ( handle ), strerror ( rc ) );
124  break;
125  }
126  bs->CloseProtocol ( handle, chained->protocol,
128 
129  /* Stop if we reach a non-matching protocol instance */
130  if ( match && ( match != interface ) ) {
131  DBGC ( device, "CHAINED %s found non-matching %s on ",
133  efi_guid_ntoa ( chained->protocol ) );
134  DBGC ( device, "%s\n", efi_handle_name ( handle ) );
135  break;
136  }
137 
138  /* Record this handle */
139  chained->device = handle;
140  match = interface;
141  DBGC ( device, "CHAINED %s found %s on ",
143  efi_guid_ntoa ( chained->protocol ) );
144  DBGC ( device, "%s\n", efi_handle_name ( chained->device ) );
145  }
146 }
147 
148 /**
149  * Check to see if driver supports a device
150  *
151  * @v device EFI device handle
152  * @v chained Chainloaded protocol
153  * @ret rc Return status code
154  */
156  struct chained_protocol *chained ) {
158  void *interface;
159  EFI_STATUS efirc;
160  int rc;
161 
162  /* Get protocol */
163  if ( ( efirc = bs->OpenProtocol ( device, chained->protocol, &interface,
166  rc = -EEFI ( efirc );
167  DBGCP ( device, "CHAINED %s is not a %s device\n",
169  efi_guid_ntoa ( chained->protocol ) );
170  goto err_open_protocol;
171  }
172 
173  /* Ignore non-matching handles */
174  if ( device != chained->device ) {
175  DBGC2 ( device, "CHAINED %s is not the chainloaded %s\n",
177  efi_guid_ntoa ( chained->protocol ) );
178  rc = -ENOTTY;
179  goto err_no_match;
180  }
181 
182  /* Success */
183  rc = 0;
184  DBGC ( device, "CHAINED %s is the chainloaded %s\n",
186  efi_guid_ntoa ( chained->protocol ) );
187 
188  err_no_match:
190  device );
191  err_open_protocol:
192  return rc;
193 }
194 
195 /**
196  * Check to see if driver supports a device
197  *
198  * @v device EFI device handle
199  * @ret rc Return status code
200  */
202 
203  return chained_supported ( device, &chained_snp );
204 }
205 
206 /**
207  * Check to see if driver supports a device
208  *
209  * @v device EFI device handle
210  * @ret rc Return status code
211  */
213 
214  return chained_supported ( device, &chained_nii );
215 }
216 
217 /**
218  * Check to see if driver supports a device
219  *
220  * @v device EFI device handle
221  * @ret rc Return status code
222  */
224 
225  return chained_supported ( device, &chained_mnp );
226 }
227 
228 /** EFI SNP chainloading-device-only driver */
229 struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
230  .name = "SNPONLY",
231  .supported = snponly_supported,
232  .start = snpnet_start,
233  .stop = snpnet_stop,
234 };
235 
236 /** EFI NII chainloading-device-only driver */
237 struct efi_driver niionly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
238  .name = "NIIONLY",
239  .supported = niionly_supported,
240  .start = nii_start,
241  .stop = nii_stop,
242 };
243 
244 /** EFI MNP chainloading-device-only driver */
245 struct efi_driver mnponly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
246  .name = "MNPONLY",
247  .supported = mnponly_supported,
248  .start = mnpnet_start,
249  .stop = mnpnet_stop,
250 };
251 
252 /**
253  * Initialise EFI chainloaded-device-only driver
254  *
255  */
256 static void chained_init ( void ) {
257 
261 }
262 
263 /** EFI chainloaded-device-only initialisation function */
264 struct init_fn chained_init_fn __init_fn ( INIT_LATE ) = {
266 };
EFI_GUID efi_nii31_protocol_guid
Network interface identifier protocol GUID (new version)
Definition: efi_guid.c:279
static int chained_supported(EFI_HANDLE device, struct chained_protocol *chained)
Check to see if driver supports a device.
Definition: snponly.c:155
NII driver.
static int snponly_supported(EFI_HANDLE device)
Check to see if driver supports a device.
Definition: snponly.c:201
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2081
EFI_LOADED_IMAGE_PROTOCOL * efi_loaded_image
Loaded image protocol for this image.
Definition: efi_init.c:37
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:171
EFI_HANDLE device
Target device handle.
Definition: snponly.c:65
EFI driver interface.
void(* initialise)(void)
Definition: init.h:15
128 bit buffer containing a unique identifier value.
Definition: Base.h:215
Error codes.
int nii_start(struct efi_device *efidev)
Attach driver to device.
Definition: nii.c:1272
void snpnet_stop(struct efi_device *efidev)
Detach driver from device.
Definition: snpnet.c:658
EFI_GUID efi_simple_network_protocol_guid
Simple network protocol GUID.
Definition: efi_guid.c:307
#define DBGC(...)
Definition: compiler.h:505
EFI Network Interface Identifier Protocol.
void nii_stop(struct efi_device *efidev)
Detach driver from device.
Definition: nii.c:1391
EFI_GUID efi_managed_network_service_binding_protocol_guid
Managed network service binding protocol GUID.
Definition: efi_guid.c:255
EFI_CLOSE_PROTOCOL CloseProtocol
Definition: UefiSpec.h:1987
struct efi_driver snponly_driver __efi_driver(EFI_DRIVER_NORMAL)
EFI SNP chainloading-device-only driver.
A chainloaded protocol.
Definition: snponly.c:45
EFI utilities.
int snpnet_start(struct efi_device *efidev)
Attach driver to device.
Definition: snpnet.c:541
static int mnponly_supported(EFI_HANDLE device)
Check to see if driver supports a device.
Definition: snponly.c:223
A hardware device.
Definition: device.h:73
static struct chained_protocol chained_nii
Chainloaded NII protocol.
Definition: snponly.c:74
An initialisation function.
Definition: init.h:14
static struct chained_protocol chained_snp
Chainloaded SNP protocol.
Definition: snponly.c:69
An object interface.
Definition: interface.h:124
The EFI_SIMPLE_NETWORK_PROTOCOL provides services to initialize a network interface,...
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL
Definition: UefiSpec.h:1344
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition: efi_debug.c:808
const char * efi_guid_ntoa(CONST EFI_GUID *guid)
Convert GUID to a printable string.
Definition: efi_debug.c:254
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
EFI Boot Services Table.
Definition: UefiSpec.h:1917
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:34
static int niionly_supported(EFI_HANDLE device)
Check to see if driver supports a device.
Definition: snponly.c:212
MNP NIC driver.
SNP NIC driver.
static void chained_init(void)
Initialise EFI chainloaded-device-only driver.
Definition: snponly.c:256
int efi_locate_device(EFI_HANDLE device, EFI_GUID *protocol, EFI_HANDLE *parent, unsigned int skip)
Locate parent device supporting a given protocol.
Definition: efi_utils.c:45
void mnpnet_stop(struct efi_device *efidev)
Detach driver from device.
Definition: mnpnet.c:483
EFI API.
EFI_GUID * protocol
Protocol GUID.
Definition: snponly.c:47
An EFI driver.
Definition: efi_driver.h:33
#define DBGC2(...)
Definition: compiler.h:522
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
struct init_fn chained_init_fn __init_fn(INIT_LATE)
EFI chainloaded-device-only initialisation function.
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:31
const char * name
Name.
Definition: efi_driver.h:35
#define DBGCP(...)
Definition: compiler.h:539
static void chained_locate(struct chained_protocol *chained)
Locate chainloaded protocol.
Definition: snponly.c:88
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1986
#define INIT_LATE
Late initialisation.
Definition: init.h:31
uint16_t handle
Handle.
Definition: smbios.h:16
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
int mnpnet_start(struct efi_device *efidev)
Attach driver to device.
Definition: mnpnet.c:368
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
Definition: efi.h:59
EFI_HANDLE DeviceHandle
The device handle that the EFI Image was loaded from.
Definition: LoadedImage.h:55
#define EFI_DRIVER_NORMAL
Normal drivers.
Definition: efi_driver.h:65
static struct chained_protocol chained_mnp
Chainloaded MNP protocol.
Definition: snponly.c:79