efi_selftest_load_initrd.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * efi_selftest_load_initrd
  4. *
  5. * Copyright (c) 2020 Ilias Apalodimas <ilias.apalodimas@linaro.org>
  6. *
  7. * This test checks the FileLoad2 protocol.
  8. * A known file is read from the file system and verified.
  9. *
  10. * An example usage - given a file image with a file system in partition 1
  11. * holding file initrd - is:
  12. *
  13. * * Configure the sandbox with
  14. *
  15. * CONFIG_EFI_SELFTEST=y
  16. * CONFIG_EFI_LOAD_FILE2_INITRD=y
  17. * CONFIG_EFI_INITRD_FILESPEC="host 0:1 initrd"
  18. *
  19. * * Run ./u-boot and execute
  20. *
  21. * host bind 0 image
  22. * setenv efi_selftest load initrd
  23. * bootefi selftest
  24. *
  25. * This would provide a test output like:
  26. *
  27. * Testing EFI API implementation
  28. *
  29. * Selected test: 'load initrd'
  30. *
  31. * Setting up 'load initrd'
  32. * Setting up 'load initrd' succeeded
  33. *
  34. * Executing 'load initrd'
  35. * Loaded 12378613 bytes
  36. * CRC32 2997478465
  37. *
  38. * Now the size and CRC32 can be compared to the provided file.
  39. */
  40. #include <efi_selftest.h>
  41. #include <efi_loader.h>
  42. #include <efi_load_initrd.h>
  43. static struct efi_boot_services *boottime;
  44. static struct efi_initrd_dp dp = {
  45. .vendor = {
  46. {
  47. DEVICE_PATH_TYPE_MEDIA_DEVICE,
  48. DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
  49. sizeof(dp.vendor),
  50. },
  51. EFI_INITRD_MEDIA_GUID,
  52. },
  53. .end = {
  54. DEVICE_PATH_TYPE_END,
  55. DEVICE_PATH_SUB_TYPE_END,
  56. sizeof(dp.end),
  57. }
  58. };
  59. static struct efi_initrd_dp dp_invalid = {
  60. .vendor = {
  61. {
  62. DEVICE_PATH_TYPE_MEDIA_DEVICE,
  63. DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
  64. sizeof(dp.vendor),
  65. },
  66. EFI_INITRD_MEDIA_GUID,
  67. },
  68. .end = {
  69. 0x8f, /* invalid */
  70. 0xfe, /* invalid */
  71. sizeof(dp.end),
  72. }
  73. };
  74. static int setup(const efi_handle_t handle,
  75. const struct efi_system_table *systable)
  76. {
  77. boottime = systable->boottime;
  78. return EFI_ST_SUCCESS;
  79. }
  80. static int execute(void)
  81. {
  82. efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
  83. struct efi_load_file_protocol *lf2;
  84. struct efi_device_path *dp2, *dp2_invalid;
  85. efi_status_t status;
  86. efi_handle_t handle;
  87. char buffer[64];
  88. efi_uintn_t buffer_size;
  89. void *buf;
  90. u32 crc32;
  91. memset(buffer, 0, sizeof(buffer));
  92. dp2 = (struct efi_device_path *)&dp;
  93. status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle);
  94. if (status != EFI_SUCCESS) {
  95. efi_st_error("Unable to locate device path\n");
  96. return EFI_ST_FAILURE;
  97. }
  98. status = boottime->handle_protocol(handle, &lf2_proto_guid,
  99. (void **)&lf2);
  100. if (status != EFI_SUCCESS) {
  101. efi_st_error("Unable to locate protocol\n");
  102. return EFI_ST_FAILURE;
  103. }
  104. /* Case 1:
  105. * buffer_size can't be NULL
  106. * protocol can't be NULL
  107. */
  108. status = lf2->load_file(lf2, dp2, false, NULL, &buffer);
  109. if (status != EFI_INVALID_PARAMETER) {
  110. efi_st_error("Buffer size can't be NULL\n");
  111. return EFI_ST_FAILURE;
  112. }
  113. buffer_size = sizeof(buffer);
  114. status = lf2->load_file(NULL, dp2, false, &buffer_size, &buffer);
  115. if (status != EFI_INVALID_PARAMETER) {
  116. efi_st_error("Protocol can't be NULL\n");
  117. return EFI_ST_FAILURE;
  118. }
  119. /*
  120. * Case 2: Match end node type/sub-type on device path
  121. */
  122. dp2_invalid = (struct efi_device_path *)&dp_invalid;
  123. buffer_size = sizeof(buffer);
  124. status = lf2->load_file(lf2, dp2_invalid, false, &buffer_size, &buffer);
  125. if (status != EFI_INVALID_PARAMETER) {
  126. efi_st_error("Invalid device path type must return EFI_INVALID_PARAMETER\n");
  127. return EFI_ST_FAILURE;
  128. }
  129. status = lf2->load_file(lf2, dp2_invalid, false, &buffer_size, &buffer);
  130. if (status != EFI_INVALID_PARAMETER) {
  131. efi_st_error("Invalid device path sub-type must return EFI_INVALID_PARAMETER\n");
  132. return EFI_ST_FAILURE;
  133. }
  134. /*
  135. * Case 3:
  136. * BootPolicy 'true' must return EFI_UNSUPPORTED
  137. */
  138. buffer_size = sizeof(buffer);
  139. status = lf2->load_file(lf2, dp2, true, &buffer_size, &buffer);
  140. if (status != EFI_UNSUPPORTED) {
  141. efi_st_error("BootPolicy true must return EFI_UNSUPPORTED\n");
  142. return EFI_ST_FAILURE;
  143. }
  144. /*
  145. * Case: Pass buffer size as zero, firmware must return
  146. * EFI_BUFFER_TOO_SMALL and an appropriate size
  147. */
  148. buffer_size = 0;
  149. status = lf2->load_file(lf2, dp2, false, &buffer_size, NULL);
  150. if (status != EFI_BUFFER_TOO_SMALL || !buffer_size) {
  151. efi_st_printf("buffer_size: %u\n", (unsigned int)buffer_size);
  152. efi_st_printf("status: %x\n", (unsigned int)status);
  153. efi_st_error("Buffer size not updated\n");
  154. return EFI_ST_FAILURE;
  155. }
  156. /*
  157. * Case: Pass buffer size as smaller than the file_size,
  158. * firmware must return * EFI_BUFFER_TOO_SMALL and an appropriate size
  159. */
  160. buffer_size = 1;
  161. status = lf2->load_file(lf2, dp2, false, &buffer_size, &buffer);
  162. if (status != EFI_BUFFER_TOO_SMALL || buffer_size <= 1) {
  163. efi_st_error("Buffer size not updated\n");
  164. return EFI_ST_FAILURE;
  165. }
  166. status = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size,
  167. &buf);
  168. if (status != EFI_SUCCESS) {
  169. efi_st_error("Cannot allocate buffer\n");
  170. return EFI_ST_FAILURE;
  171. }
  172. /* Case: Pass correct buffer, load the file and verify checksum*/
  173. status = lf2->load_file(lf2, dp2, false, &buffer_size, buf);
  174. if (status != EFI_SUCCESS) {
  175. efi_st_error("Loading initrd failed\n");
  176. return EFI_ST_FAILURE;
  177. }
  178. efi_st_printf("Loaded %u bytes\n", (unsigned int)buffer_size);
  179. status = boottime->calculate_crc32(buf, buffer_size, &crc32);
  180. if (status != EFI_SUCCESS) {
  181. efi_st_error("Could not determine CRC32\n");
  182. return EFI_ST_FAILURE;
  183. }
  184. efi_st_printf("CRC32 %.8x\n", (unsigned int)crc32);
  185. status = boottime->free_pool(buf);
  186. if (status != EFI_SUCCESS) {
  187. efi_st_error("Cannot free buffer\n");
  188. return EFI_ST_FAILURE;
  189. }
  190. return EFI_ST_SUCCESS;
  191. }
  192. EFI_UNIT_TEST(load_initrd) = {
  193. .name = "load initrd",
  194. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  195. .setup = setup,
  196. .execute = execute,
  197. .on_request = true,
  198. };