efi_uclass.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Uclass for EFI drivers
  4. *
  5. * Copyright (c) 2017 Heinrich Schuchardt
  6. *
  7. * For each EFI driver the uclass
  8. * - creates a handle
  9. * - installs the driver binding protocol
  10. *
  11. * The uclass provides the bind, start, and stop entry points for the driver
  12. * binding protocol.
  13. *
  14. * In bind() and stop() it checks if the controller implements the protocol
  15. * supported by the EFI driver. In the start() function it calls the bind()
  16. * function of the EFI driver. In the stop() function it destroys the child
  17. * controllers.
  18. */
  19. #include <efi_driver.h>
  20. /**
  21. * check_node_type() - check node type
  22. *
  23. * We do not support partitions as controller handles.
  24. *
  25. * @handle: handle to be checked
  26. * Return: status code
  27. */
  28. static efi_status_t check_node_type(efi_handle_t handle)
  29. {
  30. efi_status_t r, ret = EFI_SUCCESS;
  31. const struct efi_device_path *dp;
  32. /* Open the device path protocol */
  33. r = EFI_CALL(systab.boottime->open_protocol(
  34. handle, &efi_guid_device_path, (void **)&dp,
  35. NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL));
  36. if (r == EFI_SUCCESS && dp) {
  37. /* Get the last node */
  38. const struct efi_device_path *node = efi_dp_last_node(dp);
  39. /* We do not support partitions as controller */
  40. if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE)
  41. ret = EFI_UNSUPPORTED;
  42. }
  43. return ret;
  44. }
  45. /**
  46. * efi_uc_supported() - check if the driver supports the controller
  47. *
  48. * @this: driver binding protocol
  49. * @controller_handle: handle of the controller
  50. * @remaining_device_path: path specifying the child controller
  51. * Return: status code
  52. */
  53. static efi_status_t EFIAPI efi_uc_supported(
  54. struct efi_driver_binding_protocol *this,
  55. efi_handle_t controller_handle,
  56. struct efi_device_path *remaining_device_path)
  57. {
  58. efi_status_t r, ret;
  59. void *interface;
  60. struct efi_driver_binding_extended_protocol *bp =
  61. (struct efi_driver_binding_extended_protocol *)this;
  62. EFI_ENTRY("%p, %p, %ls", this, controller_handle,
  63. efi_dp_str(remaining_device_path));
  64. ret = EFI_CALL(systab.boottime->open_protocol(
  65. controller_handle, bp->ops->protocol,
  66. &interface, this->driver_binding_handle,
  67. controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
  68. switch (ret) {
  69. case EFI_ACCESS_DENIED:
  70. case EFI_ALREADY_STARTED:
  71. goto out;
  72. case EFI_SUCCESS:
  73. break;
  74. default:
  75. ret = EFI_UNSUPPORTED;
  76. goto out;
  77. }
  78. ret = check_node_type(controller_handle);
  79. r = EFI_CALL(systab.boottime->close_protocol(
  80. controller_handle, bp->ops->protocol,
  81. this->driver_binding_handle,
  82. controller_handle));
  83. if (r != EFI_SUCCESS)
  84. ret = EFI_UNSUPPORTED;
  85. out:
  86. return EFI_EXIT(ret);
  87. }
  88. /**
  89. * efi_uc_start() - create child controllers and attach driver
  90. *
  91. * @this: driver binding protocol
  92. * @controller_handle: handle of the controller
  93. * @remaining_device_path: path specifying the child controller
  94. * Return: status code
  95. */
  96. static efi_status_t EFIAPI efi_uc_start(
  97. struct efi_driver_binding_protocol *this,
  98. efi_handle_t controller_handle,
  99. struct efi_device_path *remaining_device_path)
  100. {
  101. efi_status_t r, ret;
  102. void *interface = NULL;
  103. struct efi_driver_binding_extended_protocol *bp =
  104. (struct efi_driver_binding_extended_protocol *)this;
  105. EFI_ENTRY("%p, %pUl, %ls", this, controller_handle,
  106. efi_dp_str(remaining_device_path));
  107. /* Attach driver to controller */
  108. ret = EFI_CALL(systab.boottime->open_protocol(
  109. controller_handle, bp->ops->protocol,
  110. &interface, this->driver_binding_handle,
  111. controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
  112. switch (ret) {
  113. case EFI_ACCESS_DENIED:
  114. case EFI_ALREADY_STARTED:
  115. goto out;
  116. case EFI_SUCCESS:
  117. break;
  118. default:
  119. ret = EFI_UNSUPPORTED;
  120. goto out;
  121. }
  122. ret = check_node_type(controller_handle);
  123. if (ret != EFI_SUCCESS) {
  124. r = EFI_CALL(systab.boottime->close_protocol(
  125. controller_handle, bp->ops->protocol,
  126. this->driver_binding_handle,
  127. controller_handle));
  128. if (r != EFI_SUCCESS)
  129. EFI_PRINT("Failure to close handle\n");
  130. goto out;
  131. }
  132. /* TODO: driver specific stuff */
  133. bp->ops->bind(controller_handle, interface);
  134. out:
  135. return EFI_EXIT(ret);
  136. }
  137. /**
  138. * disconnect_child() - remove a single child controller from the parent
  139. * controller
  140. *
  141. * @controller_handle: parent controller
  142. * @child_handle: child controller
  143. * Return: status code
  144. */
  145. static efi_status_t disconnect_child(efi_handle_t controller_handle,
  146. efi_handle_t child_handle)
  147. {
  148. efi_status_t ret;
  149. efi_guid_t *guid_controller = NULL;
  150. efi_guid_t *guid_child_controller = NULL;
  151. ret = EFI_CALL(systab.boottime->close_protocol(
  152. controller_handle, guid_controller,
  153. child_handle, child_handle));
  154. if (ret != EFI_SUCCESS) {
  155. EFI_PRINT("Cannot close protocol\n");
  156. return ret;
  157. }
  158. ret = EFI_CALL(systab.boottime->uninstall_protocol_interface(
  159. child_handle, guid_child_controller, NULL));
  160. if (ret != EFI_SUCCESS) {
  161. EFI_PRINT("Cannot uninstall protocol interface\n");
  162. return ret;
  163. }
  164. return ret;
  165. }
  166. /**
  167. * efi_uc_stop() - Remove child controllers and disconnect the controller
  168. *
  169. * @this: driver binding protocol
  170. * @controller_handle: handle of the controller
  171. * @number_of_children: number of child controllers to remove
  172. * @child_handle_buffer: handles of the child controllers to remove
  173. * Return: status code
  174. */
  175. static efi_status_t EFIAPI efi_uc_stop(
  176. struct efi_driver_binding_protocol *this,
  177. efi_handle_t controller_handle,
  178. size_t number_of_children,
  179. efi_handle_t *child_handle_buffer)
  180. {
  181. efi_status_t ret;
  182. efi_uintn_t count;
  183. struct efi_open_protocol_info_entry *entry_buffer;
  184. efi_guid_t *guid_controller = NULL;
  185. EFI_ENTRY("%p, %pUl, %zu, %p", this, controller_handle,
  186. number_of_children, child_handle_buffer);
  187. /* Destroy provided child controllers */
  188. if (number_of_children) {
  189. efi_uintn_t i;
  190. for (i = 0; i < number_of_children; ++i) {
  191. ret = disconnect_child(controller_handle,
  192. child_handle_buffer[i]);
  193. if (ret != EFI_SUCCESS)
  194. return ret;
  195. }
  196. return EFI_SUCCESS;
  197. }
  198. /* Destroy all children */
  199. ret = EFI_CALL(systab.boottime->open_protocol_information(
  200. controller_handle, guid_controller,
  201. &entry_buffer, &count));
  202. if (ret != EFI_SUCCESS)
  203. goto out;
  204. while (count) {
  205. if (entry_buffer[--count].attributes &
  206. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
  207. ret = disconnect_child(
  208. controller_handle,
  209. entry_buffer[count].agent_handle);
  210. if (ret != EFI_SUCCESS)
  211. goto out;
  212. }
  213. }
  214. ret = EFI_CALL(systab.boottime->free_pool(entry_buffer));
  215. if (ret != EFI_SUCCESS)
  216. printf("%s(%u) %s: ERROR: Cannot free pool\n",
  217. __FILE__, __LINE__, __func__);
  218. /* Detach driver from controller */
  219. ret = EFI_CALL(systab.boottime->close_protocol(
  220. controller_handle, guid_controller,
  221. this->driver_binding_handle, controller_handle));
  222. out:
  223. return EFI_EXIT(ret);
  224. }
  225. /**
  226. * efi_add_driver() - add driver
  227. *
  228. * @drv: driver to add
  229. * Return: status code
  230. */
  231. static efi_status_t efi_add_driver(struct driver *drv)
  232. {
  233. efi_status_t ret;
  234. const struct efi_driver_ops *ops = drv->ops;
  235. struct efi_driver_binding_extended_protocol *bp;
  236. debug("EFI: Adding driver '%s'\n", drv->name);
  237. if (!ops->protocol) {
  238. printf("EFI: ERROR: protocol GUID missing for driver '%s'\n",
  239. drv->name);
  240. return EFI_INVALID_PARAMETER;
  241. }
  242. bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol));
  243. if (!bp)
  244. return EFI_OUT_OF_RESOURCES;
  245. bp->bp.supported = efi_uc_supported;
  246. bp->bp.start = efi_uc_start;
  247. bp->bp.stop = efi_uc_stop;
  248. bp->bp.version = 0xffffffff;
  249. bp->ops = drv->ops;
  250. ret = efi_create_handle(&bp->bp.driver_binding_handle);
  251. if (ret != EFI_SUCCESS) {
  252. free(bp);
  253. goto out;
  254. }
  255. bp->bp.image_handle = bp->bp.driver_binding_handle;
  256. ret = efi_add_protocol(bp->bp.driver_binding_handle,
  257. &efi_guid_driver_binding_protocol, bp);
  258. if (ret != EFI_SUCCESS) {
  259. efi_delete_handle(bp->bp.driver_binding_handle);
  260. free(bp);
  261. goto out;
  262. }
  263. out:
  264. return ret;
  265. }
  266. /**
  267. * efi_driver_init() - initialize the EFI drivers
  268. *
  269. * Called by efi_init_obj_list().
  270. *
  271. * Return: 0 = success, any other value will stop further execution
  272. */
  273. efi_status_t efi_driver_init(void)
  274. {
  275. struct driver *drv;
  276. efi_status_t ret = EFI_SUCCESS;
  277. /* Save 'gd' pointer */
  278. efi_save_gd();
  279. debug("EFI: Initializing EFI driver framework\n");
  280. for (drv = ll_entry_start(struct driver, driver);
  281. drv < ll_entry_end(struct driver, driver); ++drv) {
  282. if (drv->id == UCLASS_EFI) {
  283. ret = efi_add_driver(drv);
  284. if (ret != EFI_SUCCESS) {
  285. printf("EFI: ERROR: failed to add driver %s\n",
  286. drv->name);
  287. break;
  288. }
  289. }
  290. }
  291. return ret;
  292. }
  293. /**
  294. * efi_uc_init() - initialize the EFI uclass
  295. *
  296. * @class: the EFI uclass
  297. * Return: 0 = success
  298. */
  299. static int efi_uc_init(struct uclass *class)
  300. {
  301. printf("EFI: Initializing UCLASS_EFI\n");
  302. return 0;
  303. }
  304. /**
  305. * efi_uc_destroy() - destroy the EFI uclass
  306. *
  307. * @class: the EFI uclass
  308. * Return: 0 = success
  309. */
  310. static int efi_uc_destroy(struct uclass *class)
  311. {
  312. printf("Destroying UCLASS_EFI\n");
  313. return 0;
  314. }
  315. UCLASS_DRIVER(efi) = {
  316. .name = "efi",
  317. .id = UCLASS_EFI,
  318. .init = efi_uc_init,
  319. .destroy = efi_uc_destroy,
  320. };