blob: bd72822c0b72e26052357ad89bad52f2ac189067 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassc7ae3df2016-11-07 08:47:08 -07002/*
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +01003 * Hello world EFI application
Simon Glassc7ae3df2016-11-07 08:47:08 -07004 *
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +01005 * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
Simon Glassc7ae3df2016-11-07 08:47:08 -07006 *
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +01007 * 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.
Simon Glassc7ae3df2016-11-07 08:47:08 -070016 */
17
Simon Glassc7ae3df2016-11-07 08:47:08 -070018#include <efi_api.h>
19
Heinrich Schuchardtdec88e42019-04-20 07:39:11 +020020static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010021static const efi_guid_t device_path_to_text_protocol_guid =
22 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
23static const efi_guid_t device_path_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
Heinrich Schuchardt0aaabbb2018-01-19 20:24:42 +010024static const efi_guid_t fdt_guid = EFI_FDT_GUID;
Bin Meng47cae012018-06-27 20:38:04 -070025static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
Heinrich Schuchardt0aaabbb2018-01-19 20:24:42 +010026static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
27
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010028static struct efi_system_table *systable;
29static struct efi_boot_services *boottime;
30static struct efi_simple_text_output_protocol *con_out;
31
Heinrich Schuchardta641e362022-09-01 22:23:47 +020032/*
33 * Print an unsigned 32bit value as decimal number to an u16 string
34 *
35 * @value: value to be printed
36 * @buf: pointer to buffer address
37 * on return position of terminating zero word
38 */
39static void uint2dec(u32 value, u16 **buf)
40{
41 u16 *pos = *buf;
42 int i;
43 u16 c;
44 u64 f;
45
46 /*
47 * Increment by .5 and multiply with
48 * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
49 * to move the first digit to bit 60-63.
50 */
51 f = 0x225C17D0;
52 f += (0x9B5A52DULL * value) >> 28;
53 f += 0x44B82FA0ULL * value;
54
55 for (i = 0; i < 10; ++i) {
56 /* Write current digit */
57 c = f >> 60;
58 if (c || pos != *buf)
59 *pos++ = c + '0';
60 /* Eliminate current digit */
61 f &= 0xfffffffffffffff;
62 /* Get next digit */
63 f *= 0xaULL;
64 }
65 if (pos == *buf)
66 *pos++ = '0';
67 *pos = 0;
68 *buf = pos;
69}
70
Heinrich Schuchardt87fc2752018-09-24 23:53:51 +020071/**
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010072 * print_uefi_revision() - print UEFI revision number
Heinrich Schuchardtbbf75dd2017-11-26 14:05:20 +010073 */
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010074static void print_uefi_revision(void)
Simon Glassc7ae3df2016-11-07 08:47:08 -070075{
Heinrich Schuchardta641e362022-09-01 22:23:47 +020076 u16 rev[13] = {0};
77 u16 *buf = rev;
78 u16 digit;
Simon Glassc7ae3df2016-11-07 08:47:08 -070079
Heinrich Schuchardta641e362022-09-01 22:23:47 +020080 uint2dec(systable->hdr.revision >> 16, &buf);
81 *buf++ = '.';
82 uint2dec(systable->hdr.revision & 0xffff, &buf);
83
84 /* Minor revision is only to be shown if non-zero */
85 digit = *--buf;
86 if (digit == '0') {
87 *buf = 0;
88 } else {
89 *buf++ = '.';
90 *buf = digit;
Heinrich Schuchardtf7c342f2018-02-05 18:24:26 +010091 }
Heinrich Schuchardtf7c342f2018-02-05 18:24:26 +010092
Simon Glass156ccbc2022-01-23 12:55:12 -070093 con_out->output_string(con_out, u"Running on UEFI ");
Heinrich Schuchardtf7c342f2018-02-05 18:24:26 +010094 con_out->output_string(con_out, rev);
Simon Glass156ccbc2022-01-23 12:55:12 -070095 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010096}
Heinrich Schuchardtf7c342f2018-02-05 18:24:26 +010097
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010098/**
99 * print_config_tables() - print configuration tables
100 */
101static void print_config_tables(void)
102{
103 efi_uintn_t i;
104
Heinrich Schuchardt0aaabbb2018-01-19 20:24:42 +0100105 /* Find configuration tables */
106 for (i = 0; i < systable->nr_tables; ++i) {
Heinrich Schuchardt64463042019-01-20 08:20:32 +0100107 if (!memcmp(&systable->tables[i].guid, &fdt_guid,
108 sizeof(efi_guid_t)))
Heinrich Schuchardt87fc2752018-09-24 23:53:51 +0200109 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700110 (con_out, u"Have device tree\r\n");
Heinrich Schuchardt64463042019-01-20 08:20:32 +0100111 if (!memcmp(&systable->tables[i].guid, &acpi_guid,
112 sizeof(efi_guid_t)))
Heinrich Schuchardt87fc2752018-09-24 23:53:51 +0200113 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700114 (con_out, u"Have ACPI 2.0 table\r\n");
Heinrich Schuchardt64463042019-01-20 08:20:32 +0100115 if (!memcmp(&systable->tables[i].guid, &smbios_guid,
116 sizeof(efi_guid_t)))
Heinrich Schuchardt87fc2752018-09-24 23:53:51 +0200117 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700118 (con_out, u"Have SMBIOS table\r\n");
Heinrich Schuchardt0aaabbb2018-01-19 20:24:42 +0100119 }
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100120}
121
122/**
123 * print_load_options() - print load options
124 *
125 * @systable: system table
126 * @con_out: simple text output protocol
127 */
Heinrich Schuchardt575cfe72023-02-10 08:45:38 +0100128static void print_load_options(struct efi_loaded_image *loaded_image)
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100129{
Heinrich Schuchardtbbf75dd2017-11-26 14:05:20 +0100130 /* Output the load options */
Simon Glass156ccbc2022-01-23 12:55:12 -0700131 con_out->output_string(con_out, u"Load options: ");
Heinrich Schuchardtbbf75dd2017-11-26 14:05:20 +0100132 if (loaded_image->load_options_size && loaded_image->load_options)
133 con_out->output_string(con_out,
134 (u16 *)loaded_image->load_options);
135 else
Simon Glass156ccbc2022-01-23 12:55:12 -0700136 con_out->output_string(con_out, u"<none>");
137 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100138}
139
140/**
141 * print_device_path() - print device path
142 *
143 * @device_path: device path to print
144 * @dp2txt: device path to text protocol
145 */
Heinrich Schuchardt575cfe72023-02-10 08:45:38 +0100146static
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100147efi_status_t print_device_path(struct efi_device_path *device_path,
148 struct efi_device_path_to_text_protocol *dp2txt)
149{
150 u16 *string;
151 efi_status_t ret;
152
153 if (!device_path) {
Simon Glass156ccbc2022-01-23 12:55:12 -0700154 con_out->output_string(con_out, u"<none>\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100155 return EFI_SUCCESS;
156 }
157
158 string = dp2txt->convert_device_path_to_text(device_path, true, false);
159 if (!string) {
160 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700161 (con_out, u"Cannot convert device path to text\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100162 return EFI_OUT_OF_RESOURCES;
163 }
164 con_out->output_string(con_out, string);
Simon Glass156ccbc2022-01-23 12:55:12 -0700165 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100166 ret = boottime->free_pool(string);
167 if (ret != EFI_SUCCESS) {
Simon Glass156ccbc2022-01-23 12:55:12 -0700168 con_out->output_string(con_out, u"Cannot free pool memory\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100169 return ret;
170 }
171 return EFI_SUCCESS;
172}
173
174/**
175 * efi_main() - entry point of the EFI application.
176 *
177 * @handle: handle of the loaded image
178 * @systab: system table
Heinrich Schuchardt3dd719d2022-01-20 19:48:20 +0100179 * Return: status code
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100180 */
181efi_status_t EFIAPI efi_main(efi_handle_t handle,
182 struct efi_system_table *systab)
183{
184 struct efi_loaded_image *loaded_image;
185 struct efi_device_path_to_text_protocol *device_path_to_text;
186 struct efi_device_path *device_path;
187 efi_status_t ret;
188
189 systable = systab;
190 boottime = systable->boottime;
191 con_out = systable->con_out;
192
193 /* UEFI requires CR LF */
Simon Glass156ccbc2022-01-23 12:55:12 -0700194 con_out->output_string(con_out, u"Hello, world!\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100195
196 print_uefi_revision();
197 print_config_tables();
198
199 /* Get the loaded image protocol */
Heinrich Schuchardtff6ce8d2023-04-04 07:17:48 +0200200 ret = boottime->open_protocol(handle, &loaded_image_guid,
201 (void **)&loaded_image, NULL, NULL,
202 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
203
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100204 if (ret != EFI_SUCCESS) {
205 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700206 (con_out, u"Cannot open loaded image protocol\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100207 goto out;
208 }
209 print_load_options(loaded_image);
210
211 /* Get the device path to text protocol */
212 ret = boottime->locate_protocol(&device_path_to_text_protocol_guid,
213 NULL, (void **)&device_path_to_text);
214 if (ret != EFI_SUCCESS) {
215 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700216 (con_out, u"Cannot open device path to text protocol\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100217 goto out;
218 }
Heinrich Schuchardt31eda3f2023-05-12 21:23:15 +0200219 con_out->output_string(con_out, u"File path: ");
220 ret = print_device_path(loaded_image->file_path, device_path_to_text);
221 if (ret != EFI_SUCCESS)
222 goto out;
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100223 if (!loaded_image->device_handle) {
224 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700225 (con_out, u"Missing device handle\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100226 goto out;
227 }
Heinrich Schuchardtff6ce8d2023-04-04 07:17:48 +0200228 ret = boottime->open_protocol(loaded_image->device_handle,
229 &device_path_guid,
230 (void **)&device_path, NULL, NULL,
231 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100232 if (ret != EFI_SUCCESS) {
233 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700234 (con_out, u"Missing device path for device handle\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100235 goto out;
236 }
Simon Glass156ccbc2022-01-23 12:55:12 -0700237 con_out->output_string(con_out, u"Boot device: ");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100238 ret = print_device_path(device_path, device_path_to_text);
239 if (ret != EFI_SUCCESS)
240 goto out;
Heinrich Schuchardtbbf75dd2017-11-26 14:05:20 +0100241
242out:
243 boottime->exit(handle, ret, 0, NULL);
244
245 /* We should never arrive here */
246 return ret;
Simon Glassc7ae3df2016-11-07 08:47:08 -0700247}