blob: d565f3274577dc2d887f80873f33cf06601051e0 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassfac4ced2016-11-07 08:47:08 -07002/*
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +01003 * Hello world EFI application
Simon Glassfac4ced2016-11-07 08:47:08 -07004 *
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +01005 * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
Simon Glassfac4ced2016-11-07 08:47:08 -07006 *
Heinrich Schuchardtd9b2ff72021-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 Glassfac4ced2016-11-07 08:47:08 -070016 */
17
Simon Glassfac4ced2016-11-07 08:47:08 -070018#include <efi_api.h>
19
Heinrich Schuchardt788ad412019-04-20 07:39:11 +020020static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
Heinrich Schuchardtd9b2ff72021-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 Schuchardt5a771522018-01-19 20:24:42 +010024static const efi_guid_t fdt_guid = EFI_FDT_GUID;
Bin Meng8e943292018-06-27 20:38:04 -070025static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
Heinrich Schuchardt5a771522018-01-19 20:24:42 +010026static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
27
Heinrich Schuchardtd9b2ff72021-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 Schuchardt65071642022-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 Schuchardt5b669d82018-09-24 23:53:51 +020071/**
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +010072 * print_uefi_revision() - print UEFI revision number
Heinrich Schuchardt08645802017-11-26 14:05:20 +010073 */
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +010074static void print_uefi_revision(void)
Simon Glassfac4ced2016-11-07 08:47:08 -070075{
Heinrich Schuchardt65071642022-09-01 22:23:47 +020076 u16 rev[13] = {0};
77 u16 *buf = rev;
78 u16 digit;
Simon Glassfac4ced2016-11-07 08:47:08 -070079
Heinrich Schuchardt65071642022-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 Schuchardta0a61dd2018-02-05 18:24:26 +010091 }
Heinrich Schuchardta0a61dd2018-02-05 18:24:26 +010092
Simon Glass90975372022-01-23 12:55:12 -070093 con_out->output_string(con_out, u"Running on UEFI ");
Heinrich Schuchardta0a61dd2018-02-05 18:24:26 +010094 con_out->output_string(con_out, rev);
Simon Glass90975372022-01-23 12:55:12 -070095 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +010096}
Heinrich Schuchardta0a61dd2018-02-05 18:24:26 +010097
Heinrich Schuchardtd9b2ff72021-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 Schuchardt5a771522018-01-19 20:24:42 +0100105 /* Find configuration tables */
106 for (i = 0; i < systable->nr_tables; ++i) {
Heinrich Schuchardtb2b186c2019-01-20 08:20:32 +0100107 if (!memcmp(&systable->tables[i].guid, &fdt_guid,
108 sizeof(efi_guid_t)))
Heinrich Schuchardt5b669d82018-09-24 23:53:51 +0200109 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700110 (con_out, u"Have device tree\r\n");
Heinrich Schuchardtb2b186c2019-01-20 08:20:32 +0100111 if (!memcmp(&systable->tables[i].guid, &acpi_guid,
112 sizeof(efi_guid_t)))
Heinrich Schuchardt5b669d82018-09-24 23:53:51 +0200113 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700114 (con_out, u"Have ACPI 2.0 table\r\n");
Heinrich Schuchardtb2b186c2019-01-20 08:20:32 +0100115 if (!memcmp(&systable->tables[i].guid, &smbios_guid,
116 sizeof(efi_guid_t)))
Heinrich Schuchardt5b669d82018-09-24 23:53:51 +0200117 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700118 (con_out, u"Have SMBIOS table\r\n");
Heinrich Schuchardt5a771522018-01-19 20:24:42 +0100119 }
Heinrich Schuchardtd9b2ff72021-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 */
128void print_load_options(struct efi_loaded_image *loaded_image)
129{
Heinrich Schuchardt08645802017-11-26 14:05:20 +0100130 /* Output the load options */
Simon Glass90975372022-01-23 12:55:12 -0700131 con_out->output_string(con_out, u"Load options: ");
Heinrich Schuchardt08645802017-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 Glass90975372022-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 Schuchardtd9b2ff72021-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 */
146efi_status_t print_device_path(struct efi_device_path *device_path,
147 struct efi_device_path_to_text_protocol *dp2txt)
148{
149 u16 *string;
150 efi_status_t ret;
151
152 if (!device_path) {
Simon Glass90975372022-01-23 12:55:12 -0700153 con_out->output_string(con_out, u"<none>\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100154 return EFI_SUCCESS;
155 }
156
157 string = dp2txt->convert_device_path_to_text(device_path, true, false);
158 if (!string) {
159 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700160 (con_out, u"Cannot convert device path to text\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100161 return EFI_OUT_OF_RESOURCES;
162 }
163 con_out->output_string(con_out, string);
Simon Glass90975372022-01-23 12:55:12 -0700164 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100165 ret = boottime->free_pool(string);
166 if (ret != EFI_SUCCESS) {
Simon Glass90975372022-01-23 12:55:12 -0700167 con_out->output_string(con_out, u"Cannot free pool memory\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100168 return ret;
169 }
170 return EFI_SUCCESS;
171}
172
173/**
174 * efi_main() - entry point of the EFI application.
175 *
176 * @handle: handle of the loaded image
177 * @systab: system table
Heinrich Schuchardtfbe90212022-01-20 19:48:20 +0100178 * Return: status code
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100179 */
180efi_status_t EFIAPI efi_main(efi_handle_t handle,
181 struct efi_system_table *systab)
182{
183 struct efi_loaded_image *loaded_image;
184 struct efi_device_path_to_text_protocol *device_path_to_text;
185 struct efi_device_path *device_path;
186 efi_status_t ret;
187
188 systable = systab;
189 boottime = systable->boottime;
190 con_out = systable->con_out;
191
192 /* UEFI requires CR LF */
Simon Glass90975372022-01-23 12:55:12 -0700193 con_out->output_string(con_out, u"Hello, world!\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100194
195 print_uefi_revision();
196 print_config_tables();
197
198 /* Get the loaded image protocol */
199 ret = boottime->handle_protocol(handle, &loaded_image_guid,
200 (void **)&loaded_image);
201 if (ret != EFI_SUCCESS) {
202 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700203 (con_out, u"Cannot open loaded image protocol\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100204 goto out;
205 }
206 print_load_options(loaded_image);
207
208 /* Get the device path to text protocol */
209 ret = boottime->locate_protocol(&device_path_to_text_protocol_guid,
210 NULL, (void **)&device_path_to_text);
211 if (ret != EFI_SUCCESS) {
212 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700213 (con_out, u"Cannot open device path to text protocol\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100214 goto out;
215 }
216 if (!loaded_image->device_handle) {
217 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700218 (con_out, u"Missing device handle\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100219 goto out;
220 }
221 ret = boottime->handle_protocol(loaded_image->device_handle,
222 &device_path_guid,
223 (void **)&device_path);
224 if (ret != EFI_SUCCESS) {
225 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700226 (con_out, u"Missing device path for device handle\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100227 goto out;
228 }
Simon Glass90975372022-01-23 12:55:12 -0700229 con_out->output_string(con_out, u"Boot device: ");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100230 ret = print_device_path(device_path, device_path_to_text);
231 if (ret != EFI_SUCCESS)
232 goto out;
Simon Glass90975372022-01-23 12:55:12 -0700233 con_out->output_string(con_out, u"File path: ");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100234 ret = print_device_path(loaded_image->file_path, device_path_to_text);
235 if (ret != EFI_SUCCESS)
236 goto out;
Heinrich Schuchardt08645802017-11-26 14:05:20 +0100237
238out:
239 boottime->exit(handle, ret, 0, NULL);
Simon Glassfac4ced2016-11-07 08:47:08 -0700240
Heinrich Schuchardt08645802017-11-26 14:05:20 +0100241 /* We should never arrive here */
242 return ret;
Simon Glassfac4ced2016-11-07 08:47:08 -0700243}