efi_uclass.c 8.9 KB

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