blob: d10a5229f740f1e5089f1370d578886cb0d035f8 [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 *
Simon Glass7de51622024-09-01 19:18:13 -06005 * Copyright (c) 2016 Google, Inc
6 * Written by Simon Glass <sjg@chromium.org>
7 *
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +01008 * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
Simon Glassc7ae3df2016-11-07 08:47:08 -07009 *
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010010 * This test program is used to test the invocation of an EFI application.
11 * It writes
12 *
13 * * a greeting
14 * * the firmware's UEFI version
15 * * the installed configuration tables
16 * * the boot device's device path and the file path
17 *
18 * to the console.
Simon Glassc7ae3df2016-11-07 08:47:08 -070019 */
20
Simon Glassc7ae3df2016-11-07 08:47:08 -070021#include <efi_api.h>
22
Heinrich Schuchardtdec88e42019-04-20 07:39:11 +020023static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010024static const efi_guid_t device_path_to_text_protocol_guid =
25 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
26static const efi_guid_t device_path_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
Heinrich Schuchardt0aaabbb2018-01-19 20:24:42 +010027static const efi_guid_t fdt_guid = EFI_FDT_GUID;
Bin Meng47cae012018-06-27 20:38:04 -070028static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
Heinrich Schuchardt0aaabbb2018-01-19 20:24:42 +010029static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
30
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +010031static struct efi_system_table *systable;
32static struct efi_boot_services *boottime;
33static struct efi_simple_text_output_protocol *con_out;
34
Heinrich Schuchardta641e362022-09-01 22:23:47 +020035/*
36 * Print an unsigned 32bit value as decimal number to an u16 string
37 *
38 * @value: value to be printed
39 * @buf: pointer to buffer address
40 * on return position of terminating zero word
41 */
42static void uint2dec(u32 value, u16 **buf)
43{
44 u16 *pos = *buf;
45 int i;
46 u16 c;
47 u64 f;
48
49 /*
50 * Increment by .5 and multiply with
51 * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
52 * to move the first digit to bit 60-63.
53 */
54 f = 0x225C17D0;
55 f += (0x9B5A52DULL * value) >> 28;
56 f += 0x44B82FA0ULL * value;
57
58 for (i = 0; i < 10; ++i) {
59 /* Write current digit */
60 c = f >> 60;
61 if (c || pos != *buf)
62 *pos++ = c + '0';
63 /* Eliminate current digit */
64 f &= 0xfffffffffffffff;
65 /* Get next digit */
66 f *= 0xaULL;
67 }
68 if (pos == *buf)
69 *pos++ = '0';
70 *pos = 0;
71 *buf = pos;
72}
73
Heinrich Schuchardt87fc2752018-09-24 23:53:51 +020074/**
Simon Glass3899e3f2024-09-26 23:59:35 +020075 * Print an unsigned 32bit value as hexadecimal number to an u16 string
76 *
77 * @value: value to be printed
78 * @buf: pointer to buffer address
79 * on return position of terminating zero word
80 */
81static void uint2hex(u32 value, u16 **buf)
82{
83 u16 *pos = *buf;
84 int i;
85 u16 c;
86
87 for (i = 0; i < 8; ++i) {
88 /* Write current digit */
89 c = value >> 28;
90 value <<= 4;
91 if (c < 10)
92 c += '0';
93 else
94 c += 'a' - 10;
95 *pos++ = c;
96 }
97 *pos = 0;
98 *buf = pos;
99}
100
101/**
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100102 * print_uefi_revision() - print UEFI revision number
Heinrich Schuchardtbbf75dd2017-11-26 14:05:20 +0100103 */
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100104static void print_uefi_revision(void)
Simon Glassc7ae3df2016-11-07 08:47:08 -0700105{
Heinrich Schuchardta641e362022-09-01 22:23:47 +0200106 u16 rev[13] = {0};
107 u16 *buf = rev;
108 u16 digit;
Simon Glassc7ae3df2016-11-07 08:47:08 -0700109
Heinrich Schuchardta641e362022-09-01 22:23:47 +0200110 uint2dec(systable->hdr.revision >> 16, &buf);
111 *buf++ = '.';
112 uint2dec(systable->hdr.revision & 0xffff, &buf);
113
114 /* Minor revision is only to be shown if non-zero */
115 digit = *--buf;
116 if (digit == '0') {
117 *buf = 0;
118 } else {
119 *buf++ = '.';
120 *buf = digit;
Heinrich Schuchardtf7c342f2018-02-05 18:24:26 +0100121 }
Heinrich Schuchardtf7c342f2018-02-05 18:24:26 +0100122
Simon Glass156ccbc2022-01-23 12:55:12 -0700123 con_out->output_string(con_out, u"Running on UEFI ");
Heinrich Schuchardtf7c342f2018-02-05 18:24:26 +0100124 con_out->output_string(con_out, rev);
Simon Glass156ccbc2022-01-23 12:55:12 -0700125 con_out->output_string(con_out, u"\r\n");
Simon Glass3899e3f2024-09-26 23:59:35 +0200126
127 con_out->output_string(con_out, u"Firmware vendor: ");
128 con_out->output_string(con_out, systable->fw_vendor);
129 con_out->output_string(con_out, u"\r\n");
130
131 buf = rev;
132 uint2hex(systable->fw_revision, &buf);
133 con_out->output_string(con_out, u"Firmware revision: ");
134 con_out->output_string(con_out, rev);
135 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100136}
Heinrich Schuchardtf7c342f2018-02-05 18:24:26 +0100137
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100138/**
139 * print_config_tables() - print configuration tables
140 */
141static void print_config_tables(void)
142{
143 efi_uintn_t i;
144
Heinrich Schuchardt0aaabbb2018-01-19 20:24:42 +0100145 /* Find configuration tables */
146 for (i = 0; i < systable->nr_tables; ++i) {
Heinrich Schuchardt64463042019-01-20 08:20:32 +0100147 if (!memcmp(&systable->tables[i].guid, &fdt_guid,
148 sizeof(efi_guid_t)))
Heinrich Schuchardt87fc2752018-09-24 23:53:51 +0200149 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700150 (con_out, u"Have device tree\r\n");
Heinrich Schuchardt64463042019-01-20 08:20:32 +0100151 if (!memcmp(&systable->tables[i].guid, &acpi_guid,
152 sizeof(efi_guid_t)))
Heinrich Schuchardt87fc2752018-09-24 23:53:51 +0200153 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700154 (con_out, u"Have ACPI 2.0 table\r\n");
Heinrich Schuchardt64463042019-01-20 08:20:32 +0100155 if (!memcmp(&systable->tables[i].guid, &smbios_guid,
156 sizeof(efi_guid_t)))
Heinrich Schuchardt87fc2752018-09-24 23:53:51 +0200157 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700158 (con_out, u"Have SMBIOS table\r\n");
Heinrich Schuchardt0aaabbb2018-01-19 20:24:42 +0100159 }
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100160}
161
162/**
163 * print_load_options() - print load options
164 *
165 * @systable: system table
166 * @con_out: simple text output protocol
167 */
Heinrich Schuchardt575cfe72023-02-10 08:45:38 +0100168static void print_load_options(struct efi_loaded_image *loaded_image)
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100169{
Heinrich Schuchardtbbf75dd2017-11-26 14:05:20 +0100170 /* Output the load options */
Simon Glass156ccbc2022-01-23 12:55:12 -0700171 con_out->output_string(con_out, u"Load options: ");
Heinrich Schuchardtbbf75dd2017-11-26 14:05:20 +0100172 if (loaded_image->load_options_size && loaded_image->load_options)
173 con_out->output_string(con_out,
174 (u16 *)loaded_image->load_options);
175 else
Simon Glass156ccbc2022-01-23 12:55:12 -0700176 con_out->output_string(con_out, u"<none>");
177 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100178}
179
180/**
181 * print_device_path() - print device path
182 *
183 * @device_path: device path to print
184 * @dp2txt: device path to text protocol
185 */
Heinrich Schuchardt575cfe72023-02-10 08:45:38 +0100186static
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100187efi_status_t print_device_path(struct efi_device_path *device_path,
188 struct efi_device_path_to_text_protocol *dp2txt)
189{
190 u16 *string;
191 efi_status_t ret;
192
193 if (!device_path) {
Simon Glass156ccbc2022-01-23 12:55:12 -0700194 con_out->output_string(con_out, u"<none>\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100195 return EFI_SUCCESS;
196 }
197
198 string = dp2txt->convert_device_path_to_text(device_path, true, false);
199 if (!string) {
200 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700201 (con_out, u"Cannot convert device path to text\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100202 return EFI_OUT_OF_RESOURCES;
203 }
204 con_out->output_string(con_out, string);
Simon Glass156ccbc2022-01-23 12:55:12 -0700205 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100206 ret = boottime->free_pool(string);
207 if (ret != EFI_SUCCESS) {
Simon Glass156ccbc2022-01-23 12:55:12 -0700208 con_out->output_string(con_out, u"Cannot free pool memory\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100209 return ret;
210 }
211 return EFI_SUCCESS;
212}
213
214/**
215 * efi_main() - entry point of the EFI application.
216 *
217 * @handle: handle of the loaded image
218 * @systab: system table
Heinrich Schuchardt3dd719d2022-01-20 19:48:20 +0100219 * Return: status code
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100220 */
221efi_status_t EFIAPI efi_main(efi_handle_t handle,
222 struct efi_system_table *systab)
223{
224 struct efi_loaded_image *loaded_image;
225 struct efi_device_path_to_text_protocol *device_path_to_text;
226 struct efi_device_path *device_path;
227 efi_status_t ret;
228
229 systable = systab;
230 boottime = systable->boottime;
231 con_out = systable->con_out;
232
233 /* UEFI requires CR LF */
Simon Glass156ccbc2022-01-23 12:55:12 -0700234 con_out->output_string(con_out, u"Hello, world!\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100235
236 print_uefi_revision();
237 print_config_tables();
238
239 /* Get the loaded image protocol */
Heinrich Schuchardtff6ce8d2023-04-04 07:17:48 +0200240 ret = boottime->open_protocol(handle, &loaded_image_guid,
241 (void **)&loaded_image, NULL, NULL,
242 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
243
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100244 if (ret != EFI_SUCCESS) {
245 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700246 (con_out, u"Cannot open loaded image protocol\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100247 goto out;
248 }
249 print_load_options(loaded_image);
250
251 /* Get the device path to text protocol */
252 ret = boottime->locate_protocol(&device_path_to_text_protocol_guid,
253 NULL, (void **)&device_path_to_text);
254 if (ret != EFI_SUCCESS) {
255 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700256 (con_out, u"Cannot open device path to text protocol\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100257 goto out;
258 }
Heinrich Schuchardt31eda3f2023-05-12 21:23:15 +0200259 con_out->output_string(con_out, u"File path: ");
260 ret = print_device_path(loaded_image->file_path, device_path_to_text);
261 if (ret != EFI_SUCCESS)
262 goto out;
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100263 if (!loaded_image->device_handle) {
264 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700265 (con_out, u"Missing device handle\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100266 goto out;
267 }
Heinrich Schuchardtff6ce8d2023-04-04 07:17:48 +0200268 ret = boottime->open_protocol(loaded_image->device_handle,
269 &device_path_guid,
270 (void **)&device_path, NULL, NULL,
271 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100272 if (ret != EFI_SUCCESS) {
273 con_out->output_string
Simon Glass156ccbc2022-01-23 12:55:12 -0700274 (con_out, u"Missing device path for device handle\r\n");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100275 goto out;
276 }
Simon Glass156ccbc2022-01-23 12:55:12 -0700277 con_out->output_string(con_out, u"Boot device: ");
Heinrich Schuchardtdd860b92021-01-12 12:40:11 +0100278 ret = print_device_path(device_path, device_path_to_text);
279 if (ret != EFI_SUCCESS)
280 goto out;
Heinrich Schuchardtbbf75dd2017-11-26 14:05:20 +0100281
282out:
283 boottime->exit(handle, ret, 0, NULL);
284
285 /* We should never arrive here */
286 return ret;
Simon Glassc7ae3df2016-11-07 08:47:08 -0700287}