]> Git Repo - J-u-boot.git/blame - lib/efi_loader/helloworld.c
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / lib / efi_loader / helloworld.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
c7ae3dfd 2/*
dd860b90 3 * Hello world EFI application
c7ae3dfd 4 *
7de51622
SG
5 * Copyright (c) 2016 Google, Inc
6 * Written by Simon Glass <[email protected]>
7 *
dd860b90 8 * Copyright 2020, Heinrich Schuchardt <[email protected]>
c7ae3dfd 9 *
dd860b90
HS
10 * 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.
c7ae3dfd
SG
19 */
20
c7ae3dfd
SG
21#include <efi_api.h>
22
dec88e41 23static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
dd860b90
HS
24static 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;
0aaabbb2 27static const efi_guid_t fdt_guid = EFI_FDT_GUID;
47cae019 28static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
0aaabbb2
HS
29static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
30
dd860b90
HS
31static struct efi_system_table *systable;
32static struct efi_boot_services *boottime;
33static struct efi_simple_text_output_protocol *con_out;
34
a641e36f
HS
35/*
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
3899e3f0
SG
74/**
75 * 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
87fc275c 101/**
dd860b90 102 * print_uefi_revision() - print UEFI revision number
bbf75dd9 103 */
dd860b90 104static void print_uefi_revision(void)
c7ae3dfd 105{
a641e36f
HS
106 u16 rev[13] = {0};
107 u16 *buf = rev;
108 u16 digit;
109
110 uint2dec(systable->hdr.revision >> 16, &buf);
111 *buf++ = '.';
112 uint2dec(systable->hdr.revision & 0xffff, &buf);
c7ae3dfd 113
a641e36f
HS
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;
f7c342f4 121 }
f7c342f4 122
156ccbc3 123 con_out->output_string(con_out, u"Running on UEFI ");
f7c342f4 124 con_out->output_string(con_out, rev);
156ccbc3 125 con_out->output_string(con_out, u"\r\n");
3899e3f0
SG
126
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");
dd860b90
HS
136}
137
138/**
139 * print_config_tables() - print configuration tables
140 */
141static void print_config_tables(void)
142{
143 efi_uintn_t i;
f7c342f4 144
0aaabbb2
HS
145 /* Find configuration tables */
146 for (i = 0; i < systable->nr_tables; ++i) {
64463044
HS
147 if (!memcmp(&systable->tables[i].guid, &fdt_guid,
148 sizeof(efi_guid_t)))
87fc275c 149 con_out->output_string
156ccbc3 150 (con_out, u"Have device tree\r\n");
64463044
HS
151 if (!memcmp(&systable->tables[i].guid, &acpi_guid,
152 sizeof(efi_guid_t)))
87fc275c 153 con_out->output_string
156ccbc3 154 (con_out, u"Have ACPI 2.0 table\r\n");
64463044
HS
155 if (!memcmp(&systable->tables[i].guid, &smbios_guid,
156 sizeof(efi_guid_t)))
87fc275c 157 con_out->output_string
156ccbc3 158 (con_out, u"Have SMBIOS table\r\n");
0aaabbb2 159 }
dd860b90
HS
160}
161
162/**
163 * print_load_options() - print load options
164 *
165 * @systable: system table
166 * @con_out: simple text output protocol
167 */
575cfe7b 168static void print_load_options(struct efi_loaded_image *loaded_image)
dd860b90 169{
bbf75dd9 170 /* Output the load options */
156ccbc3 171 con_out->output_string(con_out, u"Load options: ");
bbf75dd9
HS
172 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
156ccbc3
SG
176 con_out->output_string(con_out, u"<none>");
177 con_out->output_string(con_out, u"\r\n");
dd860b90
HS
178}
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 */
575cfe7b 186static
dd860b90
HS
187efi_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) {
156ccbc3 194 con_out->output_string(con_out, u"<none>\r\n");
dd860b90
HS
195 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
156ccbc3 201 (con_out, u"Cannot convert device path to text\r\n");
dd860b90
HS
202 return EFI_OUT_OF_RESOURCES;
203 }
204 con_out->output_string(con_out, string);
156ccbc3 205 con_out->output_string(con_out, u"\r\n");
dd860b90
HS
206 ret = boottime->free_pool(string);
207 if (ret != EFI_SUCCESS) {
156ccbc3 208 con_out->output_string(con_out, u"Cannot free pool memory\r\n");
dd860b90
HS
209 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
3dd719d4 219 * Return: status code
dd860b90
HS
220 */
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 */
156ccbc3 234 con_out->output_string(con_out, u"Hello, world!\r\n");
dd860b90
HS
235
236 print_uefi_revision();
237 print_config_tables();
238
239 /* Get the loaded image protocol */
ff6ce8da
HS
240 ret = boottime->open_protocol(handle, &loaded_image_guid,
241 (void **)&loaded_image, NULL, NULL,
242 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
243
dd860b90
HS
244 if (ret != EFI_SUCCESS) {
245 con_out->output_string
156ccbc3 246 (con_out, u"Cannot open loaded image protocol\r\n");
dd860b90
HS
247 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
156ccbc3 256 (con_out, u"Cannot open device path to text protocol\r\n");
dd860b90
HS
257 goto out;
258 }
31eda3f5
HS
259 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;
dd860b90
HS
263 if (!loaded_image->device_handle) {
264 con_out->output_string
156ccbc3 265 (con_out, u"Missing device handle\r\n");
dd860b90
HS
266 goto out;
267 }
ff6ce8da
HS
268 ret = boottime->open_protocol(loaded_image->device_handle,
269 &device_path_guid,
270 (void **)&device_path, NULL, NULL,
271 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
dd860b90
HS
272 if (ret != EFI_SUCCESS) {
273 con_out->output_string
156ccbc3 274 (con_out, u"Missing device path for device handle\r\n");
dd860b90
HS
275 goto out;
276 }
156ccbc3 277 con_out->output_string(con_out, u"Boot device: ");
dd860b90
HS
278 ret = print_device_path(device_path, device_path_to_text);
279 if (ret != EFI_SUCCESS)
280 goto out;
bbf75dd9
HS
281
282out:
283 boottime->exit(handle, ret, 0, NULL);
284
285 /* We should never arrive here */
286 return ret;
c7ae3dfd 287}
This page took 0.357159 seconds and 5 git commands to generate.