helloworld.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Hello world EFI application
  4. *
  5. * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. *
  7. * This test program is used to test the invocation of an EFI application.
  8. * It writes
  9. *
  10. * * a greeting
  11. * * the firmware's UEFI version
  12. * * the installed configuration tables
  13. * * the boot device's device path and the file path
  14. *
  15. * to the console.
  16. */
  17. #include <efi_api.h>
  18. static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
  19. static const efi_guid_t device_path_to_text_protocol_guid =
  20. EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
  21. static const efi_guid_t device_path_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
  22. static const efi_guid_t fdt_guid = EFI_FDT_GUID;
  23. static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
  24. static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
  25. static struct efi_system_table *systable;
  26. static struct efi_boot_services *boottime;
  27. static struct efi_simple_text_output_protocol *con_out;
  28. /**
  29. * print_uefi_revision() - print UEFI revision number
  30. */
  31. static void print_uefi_revision(void)
  32. {
  33. u16 rev[] = L"0.0.0";
  34. rev[0] = (systable->hdr.revision >> 16) + '0';
  35. rev[4] = systable->hdr.revision & 0xffff;
  36. for (; rev[4] >= 10;) {
  37. rev[4] -= 10;
  38. ++rev[2];
  39. }
  40. /* Third digit is only to be shown if non-zero */
  41. if (rev[4])
  42. rev[4] += '0';
  43. else
  44. rev[3] = 0;
  45. con_out->output_string(con_out, L"Running on UEFI ");
  46. con_out->output_string(con_out, rev);
  47. con_out->output_string(con_out, L"\r\n");
  48. }
  49. /**
  50. * print_config_tables() - print configuration tables
  51. */
  52. static void print_config_tables(void)
  53. {
  54. efi_uintn_t i;
  55. /* Find configuration tables */
  56. for (i = 0; i < systable->nr_tables; ++i) {
  57. if (!memcmp(&systable->tables[i].guid, &fdt_guid,
  58. sizeof(efi_guid_t)))
  59. con_out->output_string
  60. (con_out, L"Have device tree\r\n");
  61. if (!memcmp(&systable->tables[i].guid, &acpi_guid,
  62. sizeof(efi_guid_t)))
  63. con_out->output_string
  64. (con_out, L"Have ACPI 2.0 table\r\n");
  65. if (!memcmp(&systable->tables[i].guid, &smbios_guid,
  66. sizeof(efi_guid_t)))
  67. con_out->output_string
  68. (con_out, L"Have SMBIOS table\r\n");
  69. }
  70. }
  71. /**
  72. * print_load_options() - print load options
  73. *
  74. * @systable: system table
  75. * @con_out: simple text output protocol
  76. */
  77. void print_load_options(struct efi_loaded_image *loaded_image)
  78. {
  79. /* Output the load options */
  80. con_out->output_string(con_out, L"Load options: ");
  81. if (loaded_image->load_options_size && loaded_image->load_options)
  82. con_out->output_string(con_out,
  83. (u16 *)loaded_image->load_options);
  84. else
  85. con_out->output_string(con_out, L"<none>");
  86. con_out->output_string(con_out, L"\r\n");
  87. }
  88. /**
  89. * print_device_path() - print device path
  90. *
  91. * @device_path: device path to print
  92. * @dp2txt: device path to text protocol
  93. */
  94. efi_status_t print_device_path(struct efi_device_path *device_path,
  95. struct efi_device_path_to_text_protocol *dp2txt)
  96. {
  97. u16 *string;
  98. efi_status_t ret;
  99. if (!device_path) {
  100. con_out->output_string(con_out, L"<none>\r\n");
  101. return EFI_SUCCESS;
  102. }
  103. string = dp2txt->convert_device_path_to_text(device_path, true, false);
  104. if (!string) {
  105. con_out->output_string
  106. (con_out, L"Cannot convert device path to text\r\n");
  107. return EFI_OUT_OF_RESOURCES;
  108. }
  109. con_out->output_string(con_out, string);
  110. con_out->output_string(con_out, L"\r\n");
  111. ret = boottime->free_pool(string);
  112. if (ret != EFI_SUCCESS) {
  113. con_out->output_string(con_out, L"Cannot free pool memory\r\n");
  114. return ret;
  115. }
  116. return EFI_SUCCESS;
  117. }
  118. /**
  119. * efi_main() - entry point of the EFI application.
  120. *
  121. * @handle: handle of the loaded image
  122. * @systab: system table
  123. * @return: status code
  124. */
  125. efi_status_t EFIAPI efi_main(efi_handle_t handle,
  126. struct efi_system_table *systab)
  127. {
  128. struct efi_loaded_image *loaded_image;
  129. struct efi_device_path_to_text_protocol *device_path_to_text;
  130. struct efi_device_path *device_path;
  131. efi_status_t ret;
  132. systable = systab;
  133. boottime = systable->boottime;
  134. con_out = systable->con_out;
  135. /* UEFI requires CR LF */
  136. con_out->output_string(con_out, L"Hello, world!\r\n");
  137. print_uefi_revision();
  138. print_config_tables();
  139. /* Get the loaded image protocol */
  140. ret = boottime->handle_protocol(handle, &loaded_image_guid,
  141. (void **)&loaded_image);
  142. if (ret != EFI_SUCCESS) {
  143. con_out->output_string
  144. (con_out, L"Cannot open loaded image protocol\r\n");
  145. goto out;
  146. }
  147. print_load_options(loaded_image);
  148. /* Get the device path to text protocol */
  149. ret = boottime->locate_protocol(&device_path_to_text_protocol_guid,
  150. NULL, (void **)&device_path_to_text);
  151. if (ret != EFI_SUCCESS) {
  152. con_out->output_string
  153. (con_out, L"Cannot open device path to text protocol\r\n");
  154. goto out;
  155. }
  156. if (!loaded_image->device_handle) {
  157. con_out->output_string
  158. (con_out, L"Missing device handle\r\n");
  159. goto out;
  160. }
  161. ret = boottime->handle_protocol(loaded_image->device_handle,
  162. &device_path_guid,
  163. (void **)&device_path);
  164. if (ret != EFI_SUCCESS) {
  165. con_out->output_string
  166. (con_out, L"Missing device path for device handle\r\n");
  167. goto out;
  168. }
  169. con_out->output_string(con_out, L"Boot device: ");
  170. ret = print_device_path(device_path, device_path_to_text);
  171. if (ret != EFI_SUCCESS)
  172. goto out;
  173. con_out->output_string(con_out, L"File path: ");
  174. ret = print_device_path(loaded_image->file_path, device_path_to_text);
  175. if (ret != EFI_SUCCESS)
  176. goto out;
  177. out:
  178. boottime->exit(handle, ret, 0, NULL);
  179. /* We should never arrive here */
  180. return ret;
  181. }