efi_selftest_config_table.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. * Setup unit test.
  31. *
  32. * @handle: handle of the loaded image
  33. * @systable: system table
  34. * @return: EFI_ST_SUCCESS for success
  35. */
  36. static int setup(const efi_handle_t handle,
  37. const struct efi_system_table *systable)
  38. {
  39. sys_table = systable;
  40. boottime = systable->boottime;
  41. return EFI_ST_SUCCESS;
  42. }
  43. /*
  44. * Execute unit test.
  45. *
  46. * A table is installed, updated, removed. The table entry and the
  47. * triggering of events is checked.
  48. *
  49. * @return: EFI_ST_SUCCESS for success
  50. */
  51. static int execute(void)
  52. {
  53. efi_status_t ret;
  54. unsigned int counter = 0;
  55. struct efi_event *event;
  56. void *table;
  57. const unsigned int tables[2];
  58. efi_uintn_t i;
  59. efi_uintn_t tabcnt;
  60. efi_uintn_t table_count = sys_table->nr_tables;
  61. ret = boottime->create_event_ex(0, TPL_NOTIFY,
  62. notify, (void *)&counter,
  63. &table_guid, &event);
  64. if (ret != EFI_SUCCESS) {
  65. efi_st_error("Failed to create event\n");
  66. return EFI_ST_FAILURE;
  67. }
  68. /* Try to delete non-existent table */
  69. ret = boottime->install_configuration_table(&table_guid, NULL);
  70. if (ret != EFI_NOT_FOUND) {
  71. efi_st_error("Failed to detect missing table\n");
  72. return EFI_ST_FAILURE;
  73. }
  74. if (counter) {
  75. efi_st_error("Notification function was called.\n");
  76. return EFI_ST_FAILURE;
  77. }
  78. /* Check if the event was signaled */
  79. ret = boottime->check_event(event);
  80. if (ret == EFI_SUCCESS) {
  81. efi_st_error("Event was signaled on EFI_NOT_FOUND\n");
  82. return EFI_ST_FAILURE;
  83. }
  84. if (counter != 1) {
  85. efi_st_error("Notification function was not called.\n");
  86. return EFI_ST_FAILURE;
  87. }
  88. if (table_count != sys_table->nr_tables) {
  89. efi_st_error("Incorrect table count %u, expected %u\n",
  90. (unsigned int)sys_table->nr_tables,
  91. (unsigned int)table_count);
  92. return EFI_ST_FAILURE;
  93. }
  94. /* Install table */
  95. ret = boottime->install_configuration_table(&table_guid,
  96. (void *)&tables[0]);
  97. if (ret != EFI_SUCCESS) {
  98. efi_st_error("Failed to install table\n");
  99. return EFI_ST_FAILURE;
  100. }
  101. /* Check signaled state */
  102. ret = boottime->check_event(event);
  103. if (ret != EFI_SUCCESS) {
  104. efi_st_error("Event was not signaled on insert\n");
  105. return EFI_ST_FAILURE;
  106. }
  107. if (++table_count != sys_table->nr_tables) {
  108. efi_st_error("Incorrect table count %u, expected %u\n",
  109. (unsigned int)sys_table->nr_tables,
  110. (unsigned int)table_count);
  111. return EFI_ST_FAILURE;
  112. }
  113. table = NULL;
  114. for (i = 0; i < sys_table->nr_tables; ++i) {
  115. if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
  116. sizeof(efi_guid_t)))
  117. table = sys_table->tables[i].table;
  118. }
  119. if (!table) {
  120. efi_st_error("Installed table not found\n");
  121. return EFI_ST_FAILURE;
  122. }
  123. if (table != &tables[0]) {
  124. efi_st_error("Incorrect table address\n");
  125. return EFI_ST_FAILURE;
  126. }
  127. /* Update table */
  128. ret = boottime->install_configuration_table(&table_guid,
  129. (void *)&tables[1]);
  130. if (ret != EFI_SUCCESS) {
  131. efi_st_error("Failed to update table\n");
  132. return EFI_ST_FAILURE;
  133. }
  134. /* Check signaled state */
  135. ret = boottime->check_event(event);
  136. if (ret != EFI_SUCCESS) {
  137. efi_st_error("Event was not signaled on update\n");
  138. return EFI_ST_FAILURE;
  139. }
  140. if (table_count != sys_table->nr_tables) {
  141. efi_st_error("Incorrect table count %u, expected %u\n",
  142. (unsigned int)sys_table->nr_tables,
  143. (unsigned int)table_count);
  144. return EFI_ST_FAILURE;
  145. }
  146. table = NULL;
  147. tabcnt = 0;
  148. for (i = 0; i < sys_table->nr_tables; ++i) {
  149. if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
  150. sizeof(efi_guid_t))) {
  151. table = sys_table->tables[i].table;
  152. ++tabcnt;
  153. }
  154. }
  155. if (!table) {
  156. efi_st_error("Installed table not found\n");
  157. return EFI_ST_FAILURE;
  158. }
  159. if (tabcnt > 1) {
  160. efi_st_error("Duplicate table guid\n");
  161. return EFI_ST_FAILURE;
  162. }
  163. if (table != &tables[1]) {
  164. efi_st_error("Incorrect table address\n");
  165. return EFI_ST_FAILURE;
  166. }
  167. /* Delete table */
  168. ret = boottime->install_configuration_table(&table_guid, NULL);
  169. if (ret != EFI_SUCCESS) {
  170. efi_st_error("Failed to delete table\n");
  171. return EFI_ST_FAILURE;
  172. }
  173. /* Check signaled state */
  174. ret = boottime->check_event(event);
  175. if (ret != EFI_SUCCESS) {
  176. efi_st_error("Event was not signaled on delete\n");
  177. return EFI_ST_FAILURE;
  178. }
  179. if (--table_count != sys_table->nr_tables) {
  180. efi_st_error("Incorrect table count %u, expected %u\n",
  181. (unsigned int)sys_table->nr_tables,
  182. (unsigned int)table_count);
  183. return EFI_ST_FAILURE;
  184. }
  185. table = NULL;
  186. for (i = 0; i < sys_table->nr_tables; ++i) {
  187. if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
  188. sizeof(efi_guid_t))) {
  189. table = sys_table->tables[i].table;
  190. }
  191. }
  192. if (table) {
  193. efi_st_error("Wrong table deleted\n");
  194. return EFI_ST_FAILURE;
  195. }
  196. ret = boottime->close_event(event);
  197. if (ret != EFI_SUCCESS) {
  198. efi_st_error("Failed to close event\n");
  199. return EFI_ST_FAILURE;
  200. }
  201. return EFI_ST_SUCCESS;
  202. }
  203. EFI_UNIT_TEST(configtables) = {
  204. .name = "configuration tables",
  205. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  206. .setup = setup,
  207. .execute = execute,
  208. };