efi_uclass.c 8.4 KB

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