efi_uclass.c 8.9 KB

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