efi_selftest_config_table.c 6.6 KB

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