blob: 586177de0c8933f55c315f1d05a5cb9220bcc8f2 [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 *
Simon Glasscba73782024-09-01 19:18:13 -06005 * Copyright (c) 2016 Google, Inc
6 * Written by Simon Glass <sjg@chromium.org>
7 *
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +01008 * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
Simon Glassfac4ced2016-11-07 08:47:08 -07009 *
Heinrich Schuchardtd9b2ff72021-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 Glassfac4ced2016-11-07 08:47:08 -070019 */
20
Simon Glassfac4ced2016-11-07 08:47:08 -070021#include <efi_api.h>
22
Heinrich Schuchardt788ad412019-04-20 07:39:11 +020023static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
Heinrich Schuchardtd9b2ff72021-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 Schuchardt5a771522018-01-19 20:24:42 +010027static const efi_guid_t fdt_guid = EFI_FDT_GUID;
Bin Meng8e943292018-06-27 20:38:04 -070028static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
Heinrich Schuchardt5a771522018-01-19 20:24:42 +010029static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
30
Heinrich Schuchardtd9b2ff72021-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 Schuchardt65071642022-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 Schuchardt5b669d82018-09-24 23:53:51 +020074/**
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +010075 * print_uefi_revision() - print UEFI revision number
Heinrich Schuchardt08645802017-11-26 14:05:20 +010076 */
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +010077static void print_uefi_revision(void)
Simon Glassfac4ced2016-11-07 08:47:08 -070078{
Heinrich Schuchardt65071642022-09-01 22:23:47 +020079 u16 rev[13] = {0};
80 u16 *buf = rev;
81 u16 digit;
Simon Glassfac4ced2016-11-07 08:47:08 -070082
Heinrich Schuchardt65071642022-09-01 22:23:47 +020083 uint2dec(systable->hdr.revision >> 16, &buf);
84 *buf++ = '.';
85 uint2dec(systable->hdr.revision & 0xffff, &buf);
86
87 /* Minor revision is only to be shown if non-zero */
88 digit = *--buf;
89 if (digit == '0') {
90 *buf = 0;
91 } else {
92 *buf++ = '.';
93 *buf = digit;
Heinrich Schuchardta0a61dd2018-02-05 18:24:26 +010094 }
Heinrich Schuchardta0a61dd2018-02-05 18:24:26 +010095
Simon Glass90975372022-01-23 12:55:12 -070096 con_out->output_string(con_out, u"Running on UEFI ");
Heinrich Schuchardta0a61dd2018-02-05 18:24:26 +010097 con_out->output_string(con_out, rev);
Simon Glass90975372022-01-23 12:55:12 -070098 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +010099}
Heinrich Schuchardta0a61dd2018-02-05 18:24:26 +0100100
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100101/**
102 * print_config_tables() - print configuration tables
103 */
104static void print_config_tables(void)
105{
106 efi_uintn_t i;
107
Heinrich Schuchardt5a771522018-01-19 20:24:42 +0100108 /* Find configuration tables */
109 for (i = 0; i < systable->nr_tables; ++i) {
Heinrich Schuchardtb2b186c2019-01-20 08:20:32 +0100110 if (!memcmp(&systable->tables[i].guid, &fdt_guid,
111 sizeof(efi_guid_t)))
Heinrich Schuchardt5b669d82018-09-24 23:53:51 +0200112 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700113 (con_out, u"Have device tree\r\n");
Heinrich Schuchardtb2b186c2019-01-20 08:20:32 +0100114 if (!memcmp(&systable->tables[i].guid, &acpi_guid,
115 sizeof(efi_guid_t)))
Heinrich Schuchardt5b669d82018-09-24 23:53:51 +0200116 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700117 (con_out, u"Have ACPI 2.0 table\r\n");
Heinrich Schuchardtb2b186c2019-01-20 08:20:32 +0100118 if (!memcmp(&systable->tables[i].guid, &smbios_guid,
119 sizeof(efi_guid_t)))
Heinrich Schuchardt5b669d82018-09-24 23:53:51 +0200120 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700121 (con_out, u"Have SMBIOS table\r\n");
Heinrich Schuchardt5a771522018-01-19 20:24:42 +0100122 }
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100123}
124
125/**
126 * print_load_options() - print load options
127 *
128 * @systable: system table
129 * @con_out: simple text output protocol
130 */
Heinrich Schuchardtfc7d3422023-02-10 08:45:38 +0100131static void print_load_options(struct efi_loaded_image *loaded_image)
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100132{
Heinrich Schuchardt08645802017-11-26 14:05:20 +0100133 /* Output the load options */
Simon Glass90975372022-01-23 12:55:12 -0700134 con_out->output_string(con_out, u"Load options: ");
Heinrich Schuchardt08645802017-11-26 14:05:20 +0100135 if (loaded_image->load_options_size && loaded_image->load_options)
136 con_out->output_string(con_out,
137 (u16 *)loaded_image->load_options);
138 else
Simon Glass90975372022-01-23 12:55:12 -0700139 con_out->output_string(con_out, u"<none>");
140 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100141}
142
143/**
144 * print_device_path() - print device path
145 *
146 * @device_path: device path to print
147 * @dp2txt: device path to text protocol
148 */
Heinrich Schuchardtfc7d3422023-02-10 08:45:38 +0100149static
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100150efi_status_t print_device_path(struct efi_device_path *device_path,
151 struct efi_device_path_to_text_protocol *dp2txt)
152{
153 u16 *string;
154 efi_status_t ret;
155
156 if (!device_path) {
Simon Glass90975372022-01-23 12:55:12 -0700157 con_out->output_string(con_out, u"<none>\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100158 return EFI_SUCCESS;
159 }
160
161 string = dp2txt->convert_device_path_to_text(device_path, true, false);
162 if (!string) {
163 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700164 (con_out, u"Cannot convert device path to text\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100165 return EFI_OUT_OF_RESOURCES;
166 }
167 con_out->output_string(con_out, string);
Simon Glass90975372022-01-23 12:55:12 -0700168 con_out->output_string(con_out, u"\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100169 ret = boottime->free_pool(string);
170 if (ret != EFI_SUCCESS) {
Simon Glass90975372022-01-23 12:55:12 -0700171 con_out->output_string(con_out, u"Cannot free pool memory\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100172 return ret;
173 }
174 return EFI_SUCCESS;
175}
176
177/**
178 * efi_main() - entry point of the EFI application.
179 *
180 * @handle: handle of the loaded image
181 * @systab: system table
Heinrich Schuchardtfbe90212022-01-20 19:48:20 +0100182 * Return: status code
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100183 */
184efi_status_t EFIAPI efi_main(efi_handle_t handle,
185 struct efi_system_table *systab)
186{
187 struct efi_loaded_image *loaded_image;
188 struct efi_device_path_to_text_protocol *device_path_to_text;
189 struct efi_device_path *device_path;
190 efi_status_t ret;
191
192 systable = systab;
193 boottime = systable->boottime;
194 con_out = systable->con_out;
195
196 /* UEFI requires CR LF */
Simon Glass90975372022-01-23 12:55:12 -0700197 con_out->output_string(con_out, u"Hello, world!\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100198
199 print_uefi_revision();
200 print_config_tables();
201
202 /* Get the loaded image protocol */
Heinrich Schuchardt5aaea012023-04-04 07:17:48 +0200203 ret = boottime->open_protocol(handle, &loaded_image_guid,
204 (void **)&loaded_image, NULL, NULL,
205 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
206
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100207 if (ret != EFI_SUCCESS) {
208 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700209 (con_out, u"Cannot open loaded image protocol\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100210 goto out;
211 }
212 print_load_options(loaded_image);
213
214 /* Get the device path to text protocol */
215 ret = boottime->locate_protocol(&device_path_to_text_protocol_guid,
216 NULL, (void **)&device_path_to_text);
217 if (ret != EFI_SUCCESS) {
218 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700219 (con_out, u"Cannot open device path to text protocol\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100220 goto out;
221 }
Heinrich Schuchardtc4ff7c02023-05-12 21:23:15 +0200222 con_out->output_string(con_out, u"File path: ");
223 ret = print_device_path(loaded_image->file_path, device_path_to_text);
224 if (ret != EFI_SUCCESS)
225 goto out;
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100226 if (!loaded_image->device_handle) {
227 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700228 (con_out, u"Missing device handle\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100229 goto out;
230 }
Heinrich Schuchardt5aaea012023-04-04 07:17:48 +0200231 ret = boottime->open_protocol(loaded_image->device_handle,
232 &device_path_guid,
233 (void **)&device_path, NULL, NULL,
234 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100235 if (ret != EFI_SUCCESS) {
236 con_out->output_string
Simon Glass90975372022-01-23 12:55:12 -0700237 (con_out, u"Missing device path for device handle\r\n");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100238 goto out;
239 }
Simon Glass90975372022-01-23 12:55:12 -0700240 con_out->output_string(con_out, u"Boot device: ");
Heinrich Schuchardtd9b2ff72021-01-12 12:40:11 +0100241 ret = print_device_path(device_path, device_path_to_text);
242 if (ret != EFI_SUCCESS)
243 goto out;
Heinrich Schuchardt08645802017-11-26 14:05:20 +0100244
245out:
246 boottime->exit(handle, ret, 0, NULL);
Simon Glassfac4ced2016-11-07 08:47:08 -0700247
Heinrich Schuchardt08645802017-11-26 14:05:20 +0100248 /* We should never arrive here */
249 return ret;
Simon Glassfac4ced2016-11-07 08:47:08 -0700250}