iPXE
efi_blacklist.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 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_OR_UBDL );
21 
22 #include <stddef.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ipxe/settings.h>
26 #include <ipxe/efi/efi.h>
30 #include <ipxe/efi/efi_blacklist.h>
31 
32 /** @file
33  *
34  * EFI driver blacklist
35  *
36  */
37 
38 /** A blacklisted driver */
39 struct efi_blacklist {
40  /** Name */
41  const char *name;
42  /**
43  * Check if driver is blacklisted
44  *
45  * @v binding Driver binding protocol
46  * @v loaded Loaded image protocol
47  * @v wtf Component name protocol, if present
48  * @ret blacklisted Driver is the blacklisted driver
49  */
50  int ( * blacklist ) ( EFI_DRIVER_BINDING_PROTOCOL *binding,
53 };
54 
55 /**
56  * Blacklist Dell Ip4ConfigDxe driver
57  *
58  * @v binding Driver binding protocol
59  * @v loaded Loaded image protocol
60  * @v wtf Component name protocol, if present
61  * @ret blacklisted Driver is the blacklisted driver
62  */
63 static int
67  static const CHAR16 ip4cfg[] = L"IP4 CONFIG Network Service Driver";
68  static const char dell[] = "Dell Inc.";
69  char manufacturer[ sizeof ( dell ) ];
70  CHAR16 *name;
71 
72  /* Check driver name */
73  if ( ! wtf )
74  return 0;
75  if ( wtf->GetDriverName ( wtf, "eng", &name ) != 0 )
76  return 0;
77  if ( memcmp ( name, ip4cfg, sizeof ( ip4cfg ) ) != 0 )
78  return 0;
79 
80  /* Check manufacturer */
81  fetch_string_setting ( NULL, &manufacturer_setting, manufacturer,
82  sizeof ( manufacturer ) );
83  if ( strcmp ( manufacturer, dell ) != 0 )
84  return 0;
85 
86  return 1;
87 }
88 
89 /** Blacklisted drivers */
90 static struct efi_blacklist efi_blacklists[] = {
91  {
92  .name = "Dell Ip4Config",
93  .blacklist = efi_blacklist_dell_ip4config,
94  },
95 };
96 
97 /**
98  * Find driver blacklisting, if any
99  *
100  * @v driver Driver binding handle
101  * @ret blacklist Driver blacklisting, or NULL
102  * @ret rc Return status code
103  */
104 static int efi_blacklist ( EFI_HANDLE driver,
105  struct efi_blacklist **blacklist ) {
107  union {
109  void *interface;
110  } binding;
111  union {
113  void *interface;
114  } loaded;
115  union {
117  void *interface;
118  } wtf;
119  unsigned int i;
121  EFI_STATUS efirc;
122  int rc;
123 
124  DBGC2 ( &efi_blacklists, "EFIBL checking %s\n",
125  efi_handle_name ( driver ) );
126 
127  /* Mark as not blacklisted */
128  *blacklist = NULL;
129 
130  /* Open driver binding protocol */
131  if ( ( efirc = bs->OpenProtocol (
133  &binding.interface, efi_image_handle, driver,
134  EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
135  rc = -EEFI ( efirc );
136  DBGC ( driver, "EFIBL %s could not open driver binding "
137  "protocol: %s\n", efi_handle_name ( driver ),
138  strerror ( rc ) );
139  goto err_binding;
140  }
141  image = binding.binding->ImageHandle;
142 
143  /* Open loaded image protocol */
144  if ( ( efirc = bs->OpenProtocol (
146  &loaded.interface, efi_image_handle, image,
147  EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
148  rc = -EEFI ( efirc );
149  DBGC ( driver, "EFIBL %s could not open",
150  efi_handle_name ( driver ) );
151  DBGC ( driver, " %s loaded image protocol: %s\n",
152  efi_handle_name ( image ), strerror ( rc ) );
153  goto err_loaded;
154  }
155 
156  /* Open component name protocol, if present*/
157  if ( ( efirc = bs->OpenProtocol (
159  &wtf.interface, efi_image_handle, driver,
160  EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
161  /* Ignore failure; is not required to be present */
162  wtf.interface = NULL;
163  }
164 
165  /* Check blacklistings */
166  for ( i = 0 ; i < ( sizeof ( efi_blacklists ) /
167  sizeof ( efi_blacklists[0] ) ) ; i++ ) {
168  if ( efi_blacklists[i].blacklist ( binding.binding,
169  loaded.loaded, wtf.wtf ) ) {
170  *blacklist = &efi_blacklists[i];
171  break;
172  }
173  }
174 
175  /* Success */
176  rc = 0;
177 
178  /* Close protocols */
179  if ( wtf.wtf ) {
181  efi_image_handle, driver );
182  }
185  err_loaded:
187  efi_image_handle, driver );
188  err_binding:
189  return rc;
190 }
191 
192 /**
193  * Unload any blacklisted drivers
194  *
195  */
196 void efi_unload_blacklist ( void ) {
198  struct efi_blacklist *blacklist;
199  EFI_HANDLE *drivers;
200  EFI_HANDLE driver;
201  UINTN num_drivers;
202  unsigned int i;
203  EFI_STATUS efirc;
204  int rc;
205 
206  /* Locate all driver binding protocol handles */
207  if ( ( efirc = bs->LocateHandleBuffer (
209  NULL, &num_drivers, &drivers ) ) != 0 ) {
210  rc = -EEFI ( efirc );
211  DBGC ( &efi_blacklists, "EFIBL could not list all drivers: "
212  "%s\n", strerror ( rc ) );
213  return;
214  }
215 
216  /* Unload any blacklisted drivers */
217  for ( i = 0 ; i < num_drivers ; i++ ) {
218  driver = drivers[i];
219  if ( ( rc = efi_blacklist ( driver, &blacklist ) ) != 0 ) {
220  DBGC ( driver, "EFIBL could not determine "
221  "blacklisting for %s: %s\n",
222  efi_handle_name ( driver ), strerror ( rc ) );
223  continue;
224  }
225  if ( ! blacklist )
226  continue;
227  DBGC ( driver, "EFIBL unloading %s (%s)\n",
228  efi_handle_name ( driver ), blacklist->name );
229  if ( ( efirc = bs->UnloadImage ( driver ) ) != 0 ) {
230  DBGC ( driver, "EFIBL could not unload %s: %s\n",
231  efi_handle_name ( driver ), strerror ( rc ) );
232  }
233  }
234 
235  /* Free handle list */
236  bs->FreePool ( drivers );
237 }
UEFI DriverBinding Protocol is defined in UEFI specification.
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
const char * name
Definition: ath9k_hw.c:1984
This protocol is used to retrieve user readable names of drivers and controllers managed by UEFI Driv...
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:157
static int efi_blacklist(EFI_HANDLE driver, struct efi_blacklist **blacklist)
Find driver blacklisting, if any.
Error codes.
#define DBGC(...)
Definition: compiler.h:505
EFI_GUID efi_loaded_image_protocol_guid
Loaded image protocol GUID.
Definition: efi_guid.c:184
EFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName
unsigned short CHAR16
Definition: ProcessorBind.h:59
EFI_IMAGE_UNLOAD UnloadImage
Definition: UefiSpec.h:1886
An executable image.
Definition: image.h:24
EFI Component Name Protocol as defined in the EFI 1.1 specification.
EFI_CLOSE_PROTOCOL CloseProtocol
Definition: UefiSpec.h:1906
UEFI 2.0 Loaded image protocol definition.
static int efi_blacklist_dell_ip4config(EFI_DRIVER_BINDING_PROTOCOL *binding __unused, EFI_LOADED_IMAGE_PROTOCOL *loaded __unused, EFI_COMPONENT_NAME_PROTOCOL *wtf)
Blacklist Dell Ip4ConfigDxe driver.
Definition: efi_blacklist.c:64
Can be used on any image handle to obtain information about the loaded image.
Definition: LoadedImage.h:51
const char * name
Name.
Definition: efi_blacklist.c:41
EFI driver blacklist.
An object interface.
Definition: interface.h:109
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
A blacklisted driver.
Definition: efi_blacklist.c:39
int fetch_string_setting(struct settings *settings, const struct setting *setting, char *data, size_t len)
Fetch value of string setting.
Definition: settings.c:845
static struct efi_blacklist efi_blacklists[]
Blacklisted drivers.
Definition: efi_blacklist.c:90
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL
Definition: UefiSpec.h:1271
Configuration settings.
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
int(* blacklist)(EFI_DRIVER_BINDING_PROTOCOL *binding, EFI_LOADED_IMAGE_PROTOCOL *loaded, EFI_COMPONENT_NAME_PROTOCOL *wtf)
Check if driver is blacklisted.
Definition: efi_blacklist.c:50
EFI Boot Services Table.
Definition: UefiSpec.h:1836
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:30
UINT64 UINTN
Unsigned value of native width.
Definition: ProcessorBind.h:71
This protocol provides the services required to determine if a driver supports a given controller.
EFI_FREE_POOL FreePool
Definition: UefiSpec.h:1855
uint8_t manufacturer
Manufacturer string.
Definition: smbios.h:14
EFI API.
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
#define DBGC2(...)
Definition: compiler.h:522
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:157
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
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
EFI_GUID efi_component_name_protocol_guid
Component name protocol GUID.
Definition: efi_guid.c:120
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
EFI_GUID efi_driver_binding_protocol_guid
Driver binding protocol GUID.
Definition: efi_guid.c:148
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
String functions.
Definition: efi.h:55
EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer
Definition: UefiSpec.h:1913
void efi_unload_blacklist(void)
Unload any blacklisted drivers.