efi_selftest_startimage_exit.c 3.0 KB

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