efi_selftest_startimage_exit.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * efi_selftest_start_image
  4. *
  5. * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. *
  7. * This test checks the StartImage boot service.
  8. * The efi_selftest_miniapp_exit.efi application is loaded into memory
  9. * and started.
  10. */
  11. #include <efi_selftest.h>
  12. /* Include containing the miniapp.efi application */
  13. #include "efi_miniapp_file_image_exit.h"
  14. /* Block size of compressed disk image */
  15. #define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
  16. /* Binary logarithm of the block size */
  17. #define LB_BLOCK_SIZE 9
  18. static efi_handle_t image_handle;
  19. static struct efi_boot_services *boottime;
  20. /* One 8 byte block of the compressed disk image */
  21. struct line {
  22. size_t addr;
  23. char *line;
  24. };
  25. /* Compressed file image */
  26. struct compressed_file_image {
  27. size_t length;
  28. struct line lines[];
  29. };
  30. static struct compressed_file_image img = EFI_ST_DISK_IMG;
  31. /* Decompressed file image */
  32. static u8 *image;
  33. /*
  34. * Decompress the disk image.
  35. *
  36. * @image decompressed disk image
  37. * @return status code
  38. */
  39. static efi_status_t decompress(u8 **image)
  40. {
  41. u8 *buf;
  42. size_t i;
  43. size_t addr;
  44. size_t len;
  45. efi_status_t ret;
  46. ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
  47. (void **)&buf);
  48. if (ret != EFI_SUCCESS) {
  49. efi_st_error("Out of memory\n");
  50. return ret;
  51. }
  52. boottime->set_mem(buf, img.length, 0);
  53. for (i = 0; ; ++i) {
  54. if (!img.lines[i].line)
  55. break;
  56. addr = img.lines[i].addr;
  57. len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
  58. if (addr + len > img.length)
  59. len = img.length - addr;
  60. boottime->copy_mem(buf + addr, img.lines[i].line, len);
  61. }
  62. *image = buf;
  63. return ret;
  64. }
  65. /*
  66. * Setup unit test.
  67. *
  68. * @handle: handle of the loaded image
  69. * @systable: system table
  70. * @return: EFI_ST_SUCCESS for success
  71. */
  72. static int setup(const efi_handle_t handle,
  73. const struct efi_system_table *systable)
  74. {
  75. image_handle = handle;
  76. boottime = systable->boottime;
  77. /* Load the application image into memory */
  78. decompress(&image);
  79. return EFI_ST_SUCCESS;
  80. }
  81. /*
  82. * Tear down unit test.
  83. *
  84. * @return: EFI_ST_SUCCESS for success
  85. */
  86. static int teardown(void)
  87. {
  88. efi_status_t r = EFI_ST_SUCCESS;
  89. if (image) {
  90. r = boottime->free_pool(image);
  91. if (r != EFI_SUCCESS) {
  92. efi_st_error("Failed to free image\n");
  93. return EFI_ST_FAILURE;
  94. }
  95. }
  96. return r;
  97. }
  98. /*
  99. * Execute unit test.
  100. *
  101. * Load and start the application image.
  102. *
  103. * @return: EFI_ST_SUCCESS for success
  104. */
  105. static int execute(void)
  106. {
  107. efi_status_t ret;
  108. efi_handle_t handle;
  109. efi_uintn_t exit_data_size = 0;
  110. u16 *exit_data = NULL;
  111. u16 expected_text[] = EFI_ST_SUCCESS_STR;
  112. ret = boottime->load_image(false, image_handle, NULL, image,
  113. img.length, &handle);
  114. if (ret != EFI_SUCCESS) {
  115. efi_st_error("Failed to load image\n");
  116. return EFI_ST_FAILURE;
  117. }
  118. ret = boottime->start_image(handle, &exit_data_size, &exit_data);
  119. if (ret != EFI_UNSUPPORTED) {
  120. efi_st_error("Wrong return value from application\n");
  121. return EFI_ST_FAILURE;
  122. }
  123. if (!exit_data || exit_data_size != sizeof(expected_text) ||
  124. memcmp(exit_data, expected_text, sizeof(expected_text))) {
  125. efi_st_error("Incorrect exit data\n");
  126. return EFI_ST_FAILURE;
  127. }
  128. ret = boottime->free_pool(exit_data);
  129. if (ret != EFI_SUCCESS) {
  130. efi_st_error("Failed to free exit data\n");
  131. return EFI_ST_FAILURE;
  132. }
  133. return EFI_ST_SUCCESS;
  134. }
  135. EFI_UNIT_TEST(startimage_exit) = {
  136. .name = "start image exit",
  137. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  138. .setup = setup,
  139. .execute = execute,
  140. .teardown = teardown,
  141. };