efi_selftest_devicepath_util.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * efi_selftest_devicepath_util
  4. *
  5. * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. *
  7. * This unit test checks the device path utilities protocol.
  8. */
  9. #include <efi_selftest.h>
  10. static struct efi_boot_services *boottime;
  11. static efi_guid_t guid_device_path_utilities_protocol =
  12. EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
  13. struct efi_device_path_utilities_protocol *dpu;
  14. /*
  15. * Setup unit test.
  16. *
  17. * Locate the device path utilities protocol.
  18. *
  19. * @handle: handle of the loaded image
  20. * @systable: system table
  21. */
  22. static int setup(const efi_handle_t img_handle,
  23. const struct efi_system_table *systable)
  24. {
  25. int ret;
  26. boottime = systable->boottime;
  27. ret = boottime->locate_protocol(&guid_device_path_utilities_protocol,
  28. NULL, (void **)&dpu);
  29. if (ret != EFI_SUCCESS) {
  30. dpu = NULL;
  31. efi_st_error(
  32. "Device path to text protocol is not available.\n");
  33. return EFI_ST_FAILURE;
  34. }
  35. return EFI_ST_SUCCESS;
  36. }
  37. /*
  38. * Create a device path consisting of a single media device node followed by an
  39. * end node.
  40. *
  41. * @length: length of the media device node
  42. * @dp: device path
  43. * @return: status code
  44. */
  45. static int create_single_node_device_path(unsigned int length,
  46. struct efi_device_path **dp)
  47. {
  48. struct efi_device_path *node;
  49. efi_uintn_t len;
  50. int ret;
  51. node = dpu->create_device_node(DEVICE_PATH_TYPE_MEDIA_DEVICE,
  52. DEVICE_PATH_SUB_TYPE_FILE_PATH, length);
  53. if (!node) {
  54. efi_st_error("CreateDeviceNode failed\n");
  55. return EFI_ST_FAILURE;
  56. }
  57. *dp = dpu->append_device_node(NULL, node);
  58. if (!*dp) {
  59. efi_st_error("AppendDeviceNode failed\n");
  60. return EFI_ST_FAILURE;
  61. }
  62. ret = boottime->free_pool(node);
  63. if (ret != EFI_ST_SUCCESS) {
  64. efi_st_error("FreePool failed\n");
  65. return EFI_ST_FAILURE;
  66. }
  67. len = dpu->get_device_path_size(*dp);
  68. if (len != length + 4) {
  69. efi_st_error("Wrong device path length %u, expected %u\n",
  70. (unsigned int)len, length);
  71. return EFI_ST_FAILURE;
  72. }
  73. return EFI_ST_SUCCESS;
  74. }
  75. /*
  76. * Execute unit test.
  77. *
  78. * In the test device paths are created, copied, and concatenated. The device
  79. * path length is used as a measure of success.
  80. */
  81. static int execute(void)
  82. {
  83. struct efi_device_path *dp1;
  84. struct efi_device_path *dp2;
  85. struct efi_device_path *dp3;
  86. efi_uintn_t len;
  87. int ret;
  88. /* IsDevicePathMultiInstance(NULL) */
  89. if (dpu->is_device_path_multi_instance(NULL)) {
  90. efi_st_error("IsDevicePathMultiInstance(NULL) returned true\n");
  91. return EFI_ST_FAILURE;
  92. }
  93. /* GetDevicePathSize(NULL) */
  94. len = dpu->get_device_path_size(NULL);
  95. if (len) {
  96. efi_st_error("Wrong device path length %u, expected 0\n",
  97. (unsigned int)len);
  98. return EFI_ST_FAILURE;
  99. }
  100. /* DuplicateDevicePath(NULL) */
  101. dp1 = dpu->duplicate_device_path(NULL);
  102. if (dp1) {
  103. efi_st_error("DuplicateDevicePath(NULL) failed\n");
  104. return EFI_ST_FAILURE;
  105. }
  106. /* AppendDevicePath(NULL, NULL) */
  107. dp1 = dpu->append_device_path(NULL, NULL);
  108. if (!dp1) {
  109. efi_st_error("AppendDevicePath(NULL, NULL) failed\n");
  110. return EFI_ST_FAILURE;
  111. }
  112. len = dpu->get_device_path_size(dp1);
  113. if (len != 4) {
  114. efi_st_error("Wrong device path length %u, expected 4\n",
  115. (unsigned int)len);
  116. return EFI_ST_FAILURE;
  117. }
  118. ret = boottime->free_pool(dp1);
  119. if (ret != EFI_ST_SUCCESS) {
  120. efi_st_error("FreePool failed\n");
  121. return EFI_ST_FAILURE;
  122. }
  123. /* CreateDeviceNode */
  124. ret = create_single_node_device_path(21, &dp1);
  125. if (ret != EFI_ST_SUCCESS)
  126. return ret;
  127. ret = create_single_node_device_path(17, &dp2);
  128. if (ret != EFI_ST_SUCCESS)
  129. return ret;
  130. /* AppendDevicePath */
  131. dp3 = dpu->append_device_path(dp1, dp2);
  132. if (!dp3) {
  133. efi_st_error("AppendDevicePath failed\n");
  134. return EFI_ST_FAILURE;
  135. }
  136. if (dp3 == dp1 || dp3 == dp2) {
  137. efi_st_error("AppendDevicePath reused buffer\n");
  138. return EFI_ST_FAILURE;
  139. }
  140. len = dpu->get_device_path_size(dp3);
  141. /* 21 + 17 + 4 */
  142. if (len != 42) {
  143. efi_st_error("Wrong device path length %u, expected 42\n",
  144. (unsigned int)len);
  145. return EFI_ST_FAILURE;
  146. }
  147. ret = boottime->free_pool(dp2);
  148. if (ret != EFI_ST_SUCCESS) {
  149. efi_st_error("FreePool failed\n");
  150. return EFI_ST_FAILURE;
  151. }
  152. /* AppendDeviceNode */
  153. dp2 = dpu->append_device_node(dp1, dp3);
  154. if (!dp2) {
  155. efi_st_error("AppendDevicePath failed\n");
  156. return EFI_ST_FAILURE;
  157. }
  158. len = dpu->get_device_path_size(dp2);
  159. /* 21 + 21 + 4 */
  160. if (len != 46) {
  161. printf("%s(%d) %s\n", __FILE__, __LINE__, __func__);
  162. efi_st_error("Wrong device path length %u, expected 46\n",
  163. (unsigned int)len);
  164. return EFI_ST_FAILURE;
  165. }
  166. ret = boottime->free_pool(dp1);
  167. if (ret != EFI_ST_SUCCESS) {
  168. efi_st_error("FreePool failed\n");
  169. return EFI_ST_FAILURE;
  170. }
  171. /* IsDevicePathMultiInstance */
  172. if (dpu->is_device_path_multi_instance(dp2)) {
  173. printf("%s(%d) %s\n", __FILE__, __LINE__, __func__);
  174. efi_st_error("IsDevicePathMultiInstance returned true\n");
  175. return EFI_ST_FAILURE;
  176. }
  177. /* AppendDevicePathInstance */
  178. dp1 = dpu->append_device_path_instance(dp2, dp3);
  179. if (!dp1) {
  180. efi_st_error("AppendDevicePathInstance failed\n");
  181. return EFI_ST_FAILURE;
  182. }
  183. len = dpu->get_device_path_size(dp1);
  184. /* 46 + 42 */
  185. if (len != 88) {
  186. efi_st_error("Wrong device path length %u, expected 88\n",
  187. (unsigned int)len);
  188. return EFI_ST_FAILURE;
  189. }
  190. /* IsDevicePathMultiInstance */
  191. if (!dpu->is_device_path_multi_instance(dp1)) {
  192. efi_st_error("IsDevicePathMultiInstance returned false\n");
  193. return EFI_ST_FAILURE;
  194. }
  195. ret = boottime->free_pool(dp2);
  196. if (ret != EFI_ST_SUCCESS) {
  197. efi_st_error("FreePool failed\n");
  198. return EFI_ST_FAILURE;
  199. }
  200. ret = boottime->free_pool(dp3);
  201. if (ret != EFI_ST_SUCCESS) {
  202. efi_st_error("FreePool failed\n");
  203. return EFI_ST_FAILURE;
  204. }
  205. /* GetNextDevicePathInstance */
  206. dp3 = dp1;
  207. dp2 = dpu->get_next_device_path_instance(&dp1, &len);
  208. if (!dp2) {
  209. efi_st_error("GetNextDevicePathInstance failed\n");
  210. return EFI_ST_FAILURE;
  211. }
  212. if (!dp1) {
  213. efi_st_error("GetNextDevicePathInstance no 2nd instance\n");
  214. return EFI_ST_FAILURE;
  215. }
  216. if (len != 46) {
  217. efi_st_error("Wrong device path length %u, expected 46\n",
  218. (unsigned int)len);
  219. return EFI_ST_FAILURE;
  220. }
  221. len = dpu->get_device_path_size(dp1);
  222. if (len != 42) {
  223. efi_st_error("Wrong device path length %u, expected 42\n",
  224. (unsigned int)len);
  225. return EFI_ST_FAILURE;
  226. }
  227. ret = boottime->free_pool(dp2);
  228. if (ret != EFI_ST_SUCCESS) {
  229. efi_st_error("FreePool failed\n");
  230. return EFI_ST_FAILURE;
  231. }
  232. dp2 = dpu->get_next_device_path_instance(&dp1, &len);
  233. if (!dp2) {
  234. efi_st_error("GetNextDevicePathInstance failed\n");
  235. return EFI_ST_FAILURE;
  236. }
  237. if (len != 42) {
  238. efi_st_error("Wrong device path length %u, expected 46\n",
  239. (unsigned int)len);
  240. return EFI_ST_FAILURE;
  241. }
  242. if (dp1) {
  243. efi_st_error("GetNextDevicePathInstance did not signal end\n");
  244. return EFI_ST_FAILURE;
  245. }
  246. /* Clean up */
  247. ret = boottime->free_pool(dp2);
  248. if (ret != EFI_ST_SUCCESS) {
  249. efi_st_error("FreePool failed\n");
  250. return EFI_ST_FAILURE;
  251. }
  252. ret = boottime->free_pool(dp3);
  253. if (ret != EFI_ST_SUCCESS) {
  254. efi_st_error("FreePool failed\n");
  255. return EFI_ST_FAILURE;
  256. }
  257. return EFI_ST_SUCCESS;
  258. }
  259. EFI_UNIT_TEST(dputil) = {
  260. .name = "device path utilities protocol",
  261. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  262. .setup = setup,
  263. .execute = execute,
  264. };