You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

efi_blacklist.c 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  20. #include <stddef.h>
  21. #include <string.h>
  22. #include <errno.h>
  23. #include <ipxe/settings.h>
  24. #include <ipxe/efi/efi.h>
  25. #include <ipxe/efi/Protocol/DriverBinding.h>
  26. #include <ipxe/efi/Protocol/LoadedImage.h>
  27. #include <ipxe/efi/Protocol/ComponentName.h>
  28. #include <ipxe/efi/efi_blacklist.h>
  29. /** @file
  30. *
  31. * EFI driver blacklist
  32. *
  33. */
  34. /** A blacklisted driver */
  35. struct efi_blacklist {
  36. /** Name */
  37. const char *name;
  38. /**
  39. * Check if driver is blacklisted
  40. *
  41. * @v binding Driver binding protocol
  42. * @v loaded Loaded image protocol
  43. * @v wtf Component name protocol, if present
  44. * @ret blacklisted Driver is the blacklisted driver
  45. */
  46. int ( * blacklist ) ( EFI_DRIVER_BINDING_PROTOCOL *binding,
  47. EFI_LOADED_IMAGE_PROTOCOL *loaded,
  48. EFI_COMPONENT_NAME_PROTOCOL *wtf );
  49. };
  50. /**
  51. * Blacklist Dell Ip4ConfigDxe driver
  52. *
  53. * @v binding Driver binding protocol
  54. * @v loaded Loaded image protocol
  55. * @v wtf Component name protocol, if present
  56. * @ret blacklisted Driver is the blacklisted driver
  57. */
  58. static int
  59. efi_blacklist_dell_ip4config ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
  60. EFI_LOADED_IMAGE_PROTOCOL *loaded __unused,
  61. EFI_COMPONENT_NAME_PROTOCOL *wtf ) {
  62. static const CHAR16 ip4cfg[] = L"IP4 CONFIG Network Service Driver";
  63. static const char dell[] = "Dell Inc.";
  64. char manufacturer[ sizeof ( dell ) ];
  65. CHAR16 *name;
  66. /* Check driver name */
  67. if ( ! wtf )
  68. return 0;
  69. if ( wtf->GetDriverName ( wtf, "eng", &name ) != 0 )
  70. return 0;
  71. if ( memcmp ( name, ip4cfg, sizeof ( ip4cfg ) ) != 0 )
  72. return 0;
  73. /* Check manufacturer */
  74. fetch_string_setting ( NULL, &manufacturer_setting, manufacturer,
  75. sizeof ( manufacturer ) );
  76. if ( strcmp ( manufacturer, dell ) != 0 )
  77. return 0;
  78. return 1;
  79. }
  80. /** Blacklisted drivers */
  81. static struct efi_blacklist efi_blacklists[] = {
  82. {
  83. .name = "Dell Ip4Config",
  84. .blacklist = efi_blacklist_dell_ip4config,
  85. },
  86. };
  87. /**
  88. * Find driver blacklisting, if any
  89. *
  90. * @v driver Driver binding handle
  91. * @ret blacklist Driver blacklisting, or NULL
  92. * @ret rc Return status code
  93. */
  94. static int efi_blacklist ( EFI_HANDLE driver,
  95. struct efi_blacklist **blacklist ) {
  96. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  97. union {
  98. EFI_DRIVER_BINDING_PROTOCOL *binding;
  99. void *interface;
  100. } binding;
  101. union {
  102. EFI_LOADED_IMAGE_PROTOCOL *loaded;
  103. void *interface;
  104. } loaded;
  105. union {
  106. EFI_COMPONENT_NAME_PROTOCOL *wtf;
  107. void *interface;
  108. } wtf;
  109. unsigned int i;
  110. EFI_HANDLE image;
  111. EFI_STATUS efirc;
  112. int rc;
  113. DBGC2 ( &efi_blacklists, "EFIBL checking %s\n",
  114. efi_handle_name ( driver ) );
  115. /* Mark as not blacklisted */
  116. *blacklist = NULL;
  117. /* Open driver binding protocol */
  118. if ( ( efirc = bs->OpenProtocol (
  119. driver, &efi_driver_binding_protocol_guid,
  120. &binding.interface, efi_image_handle, driver,
  121. EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
  122. rc = -EEFI ( efirc );
  123. DBGC ( driver, "EFIBL %s could not open driver binding "
  124. "protocol: %s\n", efi_handle_name ( driver ),
  125. strerror ( rc ) );
  126. goto err_binding;
  127. }
  128. image = binding.binding->ImageHandle;
  129. /* Open loaded image protocol */
  130. if ( ( efirc = bs->OpenProtocol (
  131. image, &efi_loaded_image_protocol_guid,
  132. &loaded.interface, efi_image_handle, image,
  133. EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
  134. rc = -EEFI ( efirc );
  135. DBGC ( driver, "EFIBL %s could not open",
  136. efi_handle_name ( driver ) );
  137. DBGC ( driver, " %s loaded image protocol: %s\n",
  138. efi_handle_name ( image ), strerror ( rc ) );
  139. goto err_loaded;
  140. }
  141. /* Open component name protocol, if present*/
  142. if ( ( efirc = bs->OpenProtocol (
  143. driver, &efi_component_name_protocol_guid,
  144. &wtf.interface, efi_image_handle, driver,
  145. EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
  146. /* Ignore failure; is not required to be present */
  147. wtf.interface = NULL;
  148. }
  149. /* Check blacklistings */
  150. for ( i = 0 ; i < ( sizeof ( efi_blacklists ) /
  151. sizeof ( efi_blacklists[0] ) ) ; i++ ) {
  152. if ( efi_blacklists[i].blacklist ( binding.binding,
  153. loaded.loaded, wtf.wtf ) ) {
  154. *blacklist = &efi_blacklists[i];
  155. break;
  156. }
  157. }
  158. /* Success */
  159. rc = 0;
  160. /* Close protocols */
  161. if ( wtf.wtf ) {
  162. bs->CloseProtocol ( driver, &efi_component_name_protocol_guid,
  163. efi_image_handle, driver );
  164. }
  165. bs->CloseProtocol ( image, &efi_loaded_image_protocol_guid,
  166. efi_image_handle, image );
  167. err_loaded:
  168. bs->CloseProtocol ( driver, &efi_driver_binding_protocol_guid,
  169. efi_image_handle, driver );
  170. err_binding:
  171. return rc;
  172. }
  173. /**
  174. * Unload any blacklisted drivers
  175. *
  176. */
  177. void efi_unload_blacklist ( void ) {
  178. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  179. struct efi_blacklist *blacklist;
  180. EFI_HANDLE *drivers;
  181. EFI_HANDLE driver;
  182. UINTN num_drivers;
  183. unsigned int i;
  184. EFI_STATUS efirc;
  185. int rc;
  186. /* Locate all driver binding protocol handles */
  187. if ( ( efirc = bs->LocateHandleBuffer (
  188. ByProtocol, &efi_driver_binding_protocol_guid,
  189. NULL, &num_drivers, &drivers ) ) != 0 ) {
  190. rc = -EEFI ( efirc );
  191. DBGC ( &efi_blacklists, "EFIBL could not list all drivers: "
  192. "%s\n", strerror ( rc ) );
  193. return;
  194. }
  195. /* Unload any blacklisted drivers */
  196. for ( i = 0 ; i < num_drivers ; i++ ) {
  197. driver = drivers[i];
  198. if ( ( rc = efi_blacklist ( driver, &blacklist ) ) != 0 ) {
  199. DBGC ( driver, "EFIBL could not determine "
  200. "blacklisting for %s: %s\n",
  201. efi_handle_name ( driver ), strerror ( rc ) );
  202. continue;
  203. }
  204. if ( ! blacklist )
  205. continue;
  206. DBGC ( driver, "EFIBL unloading %s (%s)\n",
  207. efi_handle_name ( driver ), blacklist->name );
  208. if ( ( efirc = bs->UnloadImage ( driver ) ) != 0 ) {
  209. DBGC ( driver, "EFIBL could not unload %s: %s\n",
  210. efi_handle_name ( driver ), strerror ( rc ) );
  211. }
  212. }
  213. /* Free handle list */
  214. bs->FreePool ( drivers );
  215. }