efi_uclass.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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: ERROR: Cannot free pool\n", __func__);
  217. /* Detach driver from controller */
  218. ret = EFI_CALL(systab.boottime->close_protocol(
  219. controller_handle, guid_controller,
  220. this->driver_binding_handle, controller_handle));
  221. out:
  222. return EFI_EXIT(ret);
  223. }
  224. /**
  225. * efi_add_driver() - add driver
  226. *
  227. * @drv: driver to add
  228. * Return: status code
  229. */
  230. static efi_status_t efi_add_driver(struct driver *drv)
  231. {
  232. efi_status_t ret;
  233. const struct efi_driver_ops *ops = drv->ops;
  234. struct efi_driver_binding_extended_protocol *bp;
  235. debug("EFI: Adding driver '%s'\n", drv->name);
  236. if (!ops->protocol) {
  237. printf("EFI: ERROR: protocol GUID missing for driver '%s'\n",
  238. drv->name);
  239. return EFI_INVALID_PARAMETER;
  240. }
  241. bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol));
  242. if (!bp)
  243. return EFI_OUT_OF_RESOURCES;
  244. bp->bp.supported = efi_uc_supported;
  245. bp->bp.start = efi_uc_start;
  246. bp->bp.stop = efi_uc_stop;
  247. bp->bp.version = 0xffffffff;
  248. bp->ops = drv->ops;
  249. ret = efi_create_handle(&bp->bp.driver_binding_handle);
  250. if (ret != EFI_SUCCESS) {
  251. free(bp);
  252. goto out;
  253. }
  254. bp->bp.image_handle = bp->bp.driver_binding_handle;
  255. ret = efi_add_protocol(bp->bp.driver_binding_handle,
  256. &efi_guid_driver_binding_protocol, bp);
  257. if (ret != EFI_SUCCESS) {
  258. efi_delete_handle(bp->bp.driver_binding_handle);
  259. free(bp);
  260. goto out;
  261. }
  262. out:
  263. return ret;
  264. }
  265. /**
  266. * efi_driver_init() - initialize the EFI drivers
  267. *
  268. * Called by efi_init_obj_list().
  269. *
  270. * Return: 0 = success, any other value will stop further execution
  271. */
  272. efi_status_t efi_driver_init(void)
  273. {
  274. struct driver *drv;
  275. efi_status_t ret = EFI_SUCCESS;
  276. debug("EFI: Initializing EFI driver framework\n");
  277. for (drv = ll_entry_start(struct driver, driver);
  278. drv < ll_entry_end(struct driver, driver); ++drv) {
  279. if (drv->id == UCLASS_EFI) {
  280. ret = efi_add_driver(drv);
  281. if (ret != EFI_SUCCESS) {
  282. printf("EFI: ERROR: failed to add driver %s\n",
  283. drv->name);
  284. break;
  285. }
  286. }
  287. }
  288. return ret;
  289. }
  290. /**
  291. * efi_uc_init() - initialize the EFI uclass
  292. *
  293. * @class: the EFI uclass
  294. * Return: 0 = success
  295. */
  296. static int efi_uc_init(struct uclass *class)
  297. {
  298. printf("EFI: Initializing UCLASS_EFI\n");
  299. return 0;
  300. }
  301. /**
  302. * efi_uc_destroy() - destroy the EFI uclass
  303. *
  304. * @class: the EFI uclass
  305. * Return: 0 = success
  306. */
  307. static int efi_uc_destroy(struct uclass *class)
  308. {
  309. printf("Destroying UCLASS_EFI\n");
  310. return 0;
  311. }
  312. UCLASS_DRIVER(efi) = {
  313. .name = "efi",
  314. .id = UCLASS_EFI,
  315. .init = efi_uc_init,
  316. .destroy = efi_uc_destroy,
  317. };