efi_uclass.c 8.4 KB

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