efi_selftest_config_table.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * efi_selftest_config_tables
  4. *
  5. * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. *
  7. * This test checks the following service:
  8. * InstallConfigurationTable.
  9. */
  10. #include <efi_selftest.h>
  11. static const struct efi_system_table *sys_table;
  12. static struct efi_boot_services *boottime;
  13. static efi_guid_t table_guid =
  14. EFI_GUID(0xff1c3f9e, 0x795b, 0x1529, 0xf1, 0x55,
  15. 0x17, 0x2e, 0x51, 0x6b, 0x49, 0x75);
  16. /*
  17. * Notification function, increments the notfication count if parameter
  18. * context is provided.
  19. *
  20. * @event notified event
  21. * @context pointer to the notification count
  22. */
  23. static void EFIAPI notify(struct efi_event *event, void *context)
  24. {
  25. unsigned int *count = context;
  26. if (count)
  27. ++*count;
  28. }
  29. /*
  30. * Check crc32 of a table.
  31. */
  32. static int check_table(const void *table)
  33. {
  34. efi_status_t ret;
  35. u32 crc32, res;
  36. /* Casting from const to not const */
  37. struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
  38. crc32 = hdr->crc32;
  39. /*
  40. * Setting the crc32 of the 'const' table to zero is easier than
  41. * copying
  42. */
  43. hdr->crc32 = 0;
  44. ret = boottime->calculate_crc32(table, hdr->headersize, &res);
  45. /* Reset table crc32 so it stays constant */
  46. hdr->crc32 = crc32;
  47. if (ret != EFI_ST_SUCCESS) {
  48. efi_st_error("CalculateCrc32 failed\n");
  49. return EFI_ST_FAILURE;
  50. }
  51. if (res != crc32) {
  52. efi_st_error("Incorrect CRC32\n");
  53. return EFI_ST_FAILURE;
  54. }
  55. return EFI_ST_SUCCESS;
  56. }
  57. /*
  58. * Setup unit test.
  59. *
  60. * @handle: handle of the loaded image
  61. * @systable: system table
  62. * @return: EFI_ST_SUCCESS for success
  63. */
  64. static int setup(const efi_handle_t handle,
  65. const struct efi_system_table *systable)
  66. {
  67. sys_table = systable;
  68. boottime = systable->boottime;
  69. return EFI_ST_SUCCESS;
  70. }
  71. /*
  72. * Execute unit test.
  73. *
  74. * A table is installed, updated, removed. The table entry and the
  75. * triggering of events is checked.
  76. *
  77. * @return: EFI_ST_SUCCESS for success
  78. */
  79. static int execute(void)
  80. {
  81. efi_status_t ret;
  82. unsigned int counter = 0;
  83. struct efi_event *event;
  84. void *table;
  85. const unsigned int tables[2];
  86. efi_uintn_t i;
  87. efi_uintn_t tabcnt;
  88. efi_uintn_t table_count = sys_table->nr_tables;
  89. ret = boottime->create_event_ex(0, TPL_NOTIFY,
  90. notify, (void *)&counter,
  91. &table_guid, &event);
  92. if (ret != EFI_SUCCESS) {
  93. efi_st_error("Failed to create event\n");
  94. return EFI_ST_FAILURE;
  95. }
  96. /* Try to delete non-existent table */
  97. ret = boottime->install_configuration_table(&table_guid, NULL);
  98. if (ret != EFI_NOT_FOUND) {
  99. efi_st_error("Failed to detect missing table\n");
  100. return EFI_ST_FAILURE;
  101. }
  102. if (counter) {
  103. efi_st_error("Notification function was called.\n");
  104. return EFI_ST_FAILURE;
  105. }
  106. /* Check if the event was signaled */
  107. ret = boottime->check_event(event);
  108. if (ret == EFI_SUCCESS) {
  109. efi_st_error("Event was signaled on EFI_NOT_FOUND\n");
  110. return EFI_ST_FAILURE;
  111. }
  112. if (counter != 1) {
  113. efi_st_error("Notification function was not called.\n");
  114. return EFI_ST_FAILURE;
  115. }
  116. if (table_count != sys_table->nr_tables) {
  117. efi_st_error("Incorrect table count %u, expected %u\n",
  118. (unsigned int)sys_table->nr_tables,
  119. (unsigned int)table_count);
  120. return EFI_ST_FAILURE;
  121. }
  122. /* Install table */
  123. ret = boottime->install_configuration_table(&table_guid,
  124. (void *)&tables[0]);
  125. if (ret != EFI_SUCCESS) {
  126. efi_st_error("Failed to install table\n");
  127. return EFI_ST_FAILURE;
  128. }
  129. /* Check signaled state */
  130. ret = boottime->check_event(event);
  131. if (ret != EFI_SUCCESS) {
  132. efi_st_error("Event was not signaled on insert\n");
  133. return EFI_ST_FAILURE;
  134. }
  135. if (++table_count != sys_table->nr_tables) {
  136. efi_st_error("Incorrect table count %u, expected %u\n",
  137. (unsigned int)sys_table->nr_tables,
  138. (unsigned int)table_count);
  139. return EFI_ST_FAILURE;
  140. }
  141. table = NULL;
  142. for (i = 0; i < sys_table->nr_tables; ++i) {
  143. if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
  144. sizeof(efi_guid_t)))
  145. table = sys_table->tables[i].table;
  146. }
  147. if (!table) {
  148. efi_st_error("Installed table not found\n");
  149. return EFI_ST_FAILURE;
  150. }
  151. if (table != &tables[0]) {
  152. efi_st_error("Incorrect table address\n");
  153. return EFI_ST_FAILURE;
  154. }
  155. if (check_table(sys_table) != EFI_ST_SUCCESS) {
  156. efi_st_error("Checking system table\n");
  157. return EFI_ST_FAILURE;
  158. }
  159. /* Update table */
  160. ret = boottime->install_configuration_table(&table_guid,
  161. (void *)&tables[1]);
  162. if (ret != EFI_SUCCESS) {
  163. efi_st_error("Failed to update table\n");
  164. return EFI_ST_FAILURE;
  165. }
  166. /* Check signaled state */
  167. ret = boottime->check_event(event);
  168. if (ret != EFI_SUCCESS) {
  169. efi_st_error("Event was not signaled on update\n");
  170. return EFI_ST_FAILURE;
  171. }
  172. if (table_count != sys_table->nr_tables) {
  173. efi_st_error("Incorrect table count %u, expected %u\n",
  174. (unsigned int)sys_table->nr_tables,
  175. (unsigned int)table_count);
  176. return EFI_ST_FAILURE;
  177. }
  178. table = NULL;
  179. tabcnt = 0;
  180. for (i = 0; i < sys_table->nr_tables; ++i) {
  181. if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
  182. sizeof(efi_guid_t))) {
  183. table = sys_table->tables[i].table;
  184. ++tabcnt;
  185. }
  186. }
  187. if (!table) {
  188. efi_st_error("Installed table not found\n");
  189. return EFI_ST_FAILURE;
  190. }
  191. if (tabcnt > 1) {
  192. efi_st_error("Duplicate table guid\n");
  193. return EFI_ST_FAILURE;
  194. }
  195. if (table != &tables[1]) {
  196. efi_st_error("Incorrect table address\n");
  197. return EFI_ST_FAILURE;
  198. }
  199. if (check_table(sys_table) != EFI_ST_SUCCESS) {
  200. efi_st_error("Checking system table\n");
  201. return EFI_ST_FAILURE;
  202. }
  203. /* Delete table */
  204. ret = boottime->install_configuration_table(&table_guid, NULL);
  205. if (ret != EFI_SUCCESS) {
  206. efi_st_error("Failed to delete table\n");
  207. return EFI_ST_FAILURE;
  208. }
  209. /* Check signaled state */
  210. ret = boottime->check_event(event);
  211. if (ret != EFI_SUCCESS) {
  212. efi_st_error("Event was not signaled on delete\n");
  213. return EFI_ST_FAILURE;
  214. }
  215. if (--table_count != sys_table->nr_tables) {
  216. efi_st_error("Incorrect table count %u, expected %u\n",
  217. (unsigned int)sys_table->nr_tables,
  218. (unsigned int)table_count);
  219. return EFI_ST_FAILURE;
  220. }
  221. table = NULL;
  222. for (i = 0; i < sys_table->nr_tables; ++i) {
  223. if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
  224. sizeof(efi_guid_t))) {
  225. table = sys_table->tables[i].table;
  226. }
  227. }
  228. if (table) {
  229. efi_st_error("Wrong table deleted\n");
  230. return EFI_ST_FAILURE;
  231. }
  232. ret = boottime->close_event(event);
  233. if (ret != EFI_SUCCESS) {
  234. efi_st_error("Failed to close event\n");
  235. return EFI_ST_FAILURE;
  236. }
  237. if (check_table(sys_table) != EFI_ST_SUCCESS) {
  238. efi_st_error("Checking system table\n");
  239. return EFI_ST_FAILURE;
  240. }
  241. return EFI_ST_SUCCESS;
  242. }
  243. EFI_UNIT_TEST(configtables) = {
  244. .name = "configuration tables",
  245. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  246. .setup = setup,
  247. .execute = execute,
  248. };