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 "nii.h"
36 
37 /** @file
38  *
39  * EFI chainloaded-device-only driver
40  *
41  */
42 
43 /** A chainloaded protocol */
45  /** Protocol GUID */
47  /**
48  * Protocol instance installed on the loaded image's device handle
49  *
50  * We match against the protocol instance (rather than simply
51  * matching against the device handle itself) because some
52  * systems load us via a child of the underlying device, with
53  * a duplicate protocol installed on the child handle.
54  */
55  void *interface;
56 };
57 
58 /** Chainloaded SNP protocol */
59 static struct chained_protocol chained_snp = {
61 };
62 
63 /** Chainloaded NII protocol */
64 static struct chained_protocol chained_nii = {
66 };
67 
68 /**
69  * Locate chainloaded protocol instance
70  *
71  * @v chained Chainloaded protocol
72  * @ret rc Return status code
73  */
74 static int chained_locate ( struct chained_protocol *chained ) {
77  EFI_HANDLE parent;
78  EFI_STATUS efirc;
79  int rc;
80 
81  /* Locate handle supporting this protocol */
82  if ( ( rc = efi_locate_device ( device, chained->protocol,
83  &parent, 0 ) ) != 0 ) {
84  DBGC ( device, "CHAINED %s does not support %s: %s\n",
86  efi_guid_ntoa ( chained->protocol ), strerror ( rc ) );
87  goto err_locate_device;
88  }
89  DBGC ( device, "CHAINED %s found %s on ", efi_handle_name ( device ),
90  efi_guid_ntoa ( chained->protocol ) );
91  DBGC ( device, "%s\n", efi_handle_name ( parent ) );
92 
93  /* Get protocol instance */
94  if ( ( efirc = bs->OpenProtocol ( parent, chained->protocol,
95  &chained->interface, efi_image_handle,
96  device,
98  rc = -EEFI ( efirc );
99  DBGC ( device, "CHAINED %s could not open %s on ",
101  efi_guid_ntoa ( chained->protocol ) );
102  DBGC ( device, "%s: %s\n",
103  efi_handle_name ( parent ), strerror ( rc ) );
104  goto err_open_protocol;
105  }
106 
107  err_locate_device:
108  bs->CloseProtocol ( parent, chained->protocol, efi_image_handle,
109  device );
110  err_open_protocol:
111  return rc;
112 }
113 
114 /**
115  * Check to see if driver supports a device
116  *
117  * @v device EFI device handle
118  * @v chained Chainloaded protocol
119  * @ret rc Return status code
120  */
122  struct chained_protocol *chained ) {
124  EFI_STATUS efirc;
125  void *interface;
126  int rc;
127 
128  /* Get protocol */
129  if ( ( efirc = bs->OpenProtocol ( device, chained->protocol, &interface,
132  rc = -EEFI ( efirc );
133  DBGCP ( device, "CHAINED %s is not a %s device\n",
135  efi_guid_ntoa ( chained->protocol ) );
136  goto err_open_protocol;
137  }
138 
139  /* Test for a match against the chainloading device */
140  if ( interface != chained->interface ) {
141  DBGC ( device, "CHAINED %s %p is not the chainloaded %s\n",
143  efi_guid_ntoa ( chained->protocol ) );
144  rc = -ENOTTY;
145  goto err_no_match;
146  }
147 
148  /* Success */
149  rc = 0;
150  DBGC ( device, "CHAINED %s %p is the chainloaded %s\n",
152  efi_guid_ntoa ( chained->protocol ) );
153 
154  err_no_match:
156  device );
157  err_open_protocol:
158  return rc;
159 }
160 
161 /**
162  * Check to see if driver supports a device
163  *
164  * @v device EFI device handle
165  * @ret rc Return status code
166  */
168 
169  return chained_supported ( device, &chained_snp );
170 }
171 
172 /**
173  * Check to see if driver supports a device
174  *
175  * @v device EFI device handle
176  * @ret rc Return status code
177  */
179 
180  return chained_supported ( device, &chained_nii );
181 }
182 
183 /** EFI SNP chainloading-device-only driver */
184 struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
185  .name = "SNPONLY",
186  .supported = snponly_supported,
187  .start = snpnet_start,
188  .stop = snpnet_stop,
189 };
190 
191 /** EFI NII chainloading-device-only driver */
192 struct efi_driver niionly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
193  .name = "NIIONLY",
194  .supported = niionly_supported,
195  .start = nii_start,
196  .stop = nii_stop,
197 };
198 
199 /**
200  * Initialise EFI chainloaded-device-only driver
201  *
202  */
203 static void chained_init ( void ) {
204 
207 }
208 
209 /** EFI chainloaded-device-only initialisation function */
210 struct init_fn chained_init_fn __init_fn ( INIT_LATE ) = {
212 };
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:121
NII driver.
static int snponly_supported(EFI_HANDLE device)
Check to see if driver supports a device.
Definition: snponly.c:167
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 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:610
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_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:44
EFI utilities.
int snpnet_start(struct efi_device *efidev)
Attach driver to device.
Definition: snpnet.c:493
A hardware device.
Definition: device.h:73
static struct chained_protocol chained_nii
Chainloaded NII protocol.
Definition: snponly.c:64
An initialisation function.
Definition: init.h:14
static struct chained_protocol chained_snp
Chainloaded SNP protocol.
Definition: snponly.c:59
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:178
SNP NIC driver.
static void chained_init(void)
Initialise EFI chainloaded-device-only driver.
Definition: snponly.c:203
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
EFI API.
EFI_GUID * protocol
Protocol GUID.
Definition: snponly.c:46
An EFI driver.
Definition: efi_driver.h:31
#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:33
void * interface
Protocol instance installed on the loaded image's device handle.
Definition: snponly.c:55
#define DBGCP(...)
Definition: compiler.h:539
static int chained_locate(struct chained_protocol *chained)
Locate chainloaded protocol instance.
Definition: snponly.c:74
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1986
#define INIT_LATE
Late initialisation.
Definition: init.h:31
String functions.
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:63