/src/u-boot/lib/efi_loader/efi_setup.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0+ |
2 | | /* |
3 | | * EFI setup code |
4 | | * |
5 | | * Copyright (c) 2016-2018 Alexander Graf et al. |
6 | | */ |
7 | | |
8 | | #define LOG_CATEGORY LOGC_EFI |
9 | | |
10 | | #include <efi_loader.h> |
11 | | #include <efi_variable.h> |
12 | | #include <log.h> |
13 | | #include <asm-generic/unaligned.h> |
14 | | #include <net.h> |
15 | | |
16 | 0 | #define OBJ_LIST_INITIALIZED 0 |
17 | 0 | #define OBJ_LIST_NOT_INITIALIZED 1 |
18 | | |
19 | | efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; |
20 | | |
21 | | const efi_guid_t efi_debug_image_info_table_guid = |
22 | | EFI_DEBUG_IMAGE_INFO_TABLE_GUID; |
23 | | |
24 | | /* |
25 | | * Allow unaligned memory access. |
26 | | * |
27 | | * This routine is overridden by architectures providing this feature. |
28 | | */ |
29 | | void __weak allow_unaligned(void) |
30 | 0 | { |
31 | 0 | } |
32 | | |
33 | | /** |
34 | | * efi_init_platform_lang() - define supported languages |
35 | | * |
36 | | * Set the PlatformLangCodes and PlatformLang variables. |
37 | | * |
38 | | * Return: status code |
39 | | */ |
40 | | static efi_status_t efi_init_platform_lang(void) |
41 | 0 | { |
42 | 0 | efi_status_t ret; |
43 | 0 | efi_uintn_t data_size = 0; |
44 | 0 | char *lang = CONFIG_EFI_PLATFORM_LANG_CODES; |
45 | 0 | char *pos; |
46 | | |
47 | | /* |
48 | | * Variable PlatformLangCodes defines the language codes that the |
49 | | * machine can support. |
50 | | */ |
51 | 0 | ret = efi_set_variable_int(u"PlatformLangCodes", |
52 | 0 | &efi_global_variable_guid, |
53 | 0 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
54 | 0 | EFI_VARIABLE_RUNTIME_ACCESS | |
55 | 0 | EFI_VARIABLE_READ_ONLY, |
56 | 0 | sizeof(CONFIG_EFI_PLATFORM_LANG_CODES), |
57 | 0 | CONFIG_EFI_PLATFORM_LANG_CODES, false); |
58 | 0 | if (ret != EFI_SUCCESS) |
59 | 0 | goto out; |
60 | | |
61 | | /* |
62 | | * Variable PlatformLang defines the language that the machine has been |
63 | | * configured for. |
64 | | */ |
65 | 0 | ret = efi_get_variable_int(u"PlatformLang", |
66 | 0 | &efi_global_variable_guid, |
67 | 0 | NULL, &data_size, &pos, NULL); |
68 | 0 | if (ret == EFI_BUFFER_TOO_SMALL) { |
69 | | /* The variable is already set. Do not change it. */ |
70 | 0 | ret = EFI_SUCCESS; |
71 | 0 | goto out; |
72 | 0 | } |
73 | | |
74 | | /* |
75 | | * The list of supported languages is semicolon separated. Use the first |
76 | | * language to initialize PlatformLang. |
77 | | */ |
78 | 0 | pos = strchr(lang, ';'); |
79 | 0 | if (pos) |
80 | 0 | *pos = 0; |
81 | |
|
82 | 0 | ret = efi_set_variable_int(u"PlatformLang", |
83 | 0 | &efi_global_variable_guid, |
84 | 0 | EFI_VARIABLE_NON_VOLATILE | |
85 | 0 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
86 | 0 | EFI_VARIABLE_RUNTIME_ACCESS, |
87 | 0 | 1 + strlen(lang), lang, false); |
88 | 0 | out: |
89 | 0 | if (ret != EFI_SUCCESS) |
90 | 0 | printf("EFI: cannot initialize platform language settings\n"); |
91 | 0 | return ret; |
92 | 0 | } |
93 | | |
94 | | /** |
95 | | * efi_init_secure_boot - initialize secure boot state |
96 | | * |
97 | | * Return: status code |
98 | | */ |
99 | | static efi_status_t efi_init_secure_boot(void) |
100 | 0 | { |
101 | 0 | efi_guid_t signature_types[] = { |
102 | 0 | EFI_CERT_SHA256_GUID, |
103 | 0 | EFI_CERT_X509_GUID, |
104 | 0 | }; |
105 | 0 | efi_status_t ret; |
106 | |
|
107 | 0 | ret = efi_set_variable_int(u"SignatureSupport", |
108 | 0 | &efi_global_variable_guid, |
109 | 0 | EFI_VARIABLE_READ_ONLY | |
110 | 0 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
111 | 0 | EFI_VARIABLE_RUNTIME_ACCESS, |
112 | 0 | sizeof(signature_types), |
113 | 0 | &signature_types, false); |
114 | 0 | if (ret != EFI_SUCCESS) |
115 | 0 | printf("EFI: cannot initialize SignatureSupport variable\n"); |
116 | |
|
117 | 0 | return ret; |
118 | 0 | } |
119 | | |
120 | | /** |
121 | | * efi_init_capsule - initialize capsule update state |
122 | | * |
123 | | * Return: status code |
124 | | */ |
125 | | static efi_status_t efi_init_capsule(void) |
126 | 0 | { |
127 | 0 | efi_status_t ret = EFI_SUCCESS; |
128 | |
|
129 | 0 | if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) { |
130 | 0 | u16 var_name16[12]; |
131 | |
|
132 | 0 | efi_create_indexed_name(var_name16, sizeof(var_name16), |
133 | 0 | "Capsule", CONFIG_EFI_CAPSULE_MAX); |
134 | |
|
135 | 0 | ret = efi_set_variable_int(u"CapsuleMax", |
136 | 0 | &efi_guid_capsule_report, |
137 | 0 | EFI_VARIABLE_READ_ONLY | |
138 | 0 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
139 | 0 | EFI_VARIABLE_RUNTIME_ACCESS, |
140 | 0 | 22, var_name16, false); |
141 | 0 | if (ret != EFI_SUCCESS) |
142 | 0 | printf("EFI: cannot initialize CapsuleMax variable\n"); |
143 | 0 | } |
144 | |
|
145 | 0 | return ret; |
146 | 0 | } |
147 | | |
148 | | /** |
149 | | * efi_init_os_indications() - indicate supported features for OS requests |
150 | | * |
151 | | * Set the OsIndicationsSupported variable. |
152 | | * |
153 | | * Return: status code |
154 | | */ |
155 | | static efi_status_t efi_init_os_indications(void) |
156 | 0 | { |
157 | 0 | u64 os_indications_supported = 0; |
158 | |
|
159 | 0 | if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) |
160 | 0 | os_indications_supported |= |
161 | 0 | EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED; |
162 | |
|
163 | 0 | if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK)) |
164 | 0 | os_indications_supported |= |
165 | 0 | EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED; |
166 | |
|
167 | 0 | if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT)) |
168 | 0 | os_indications_supported |= |
169 | 0 | EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED; |
170 | |
|
171 | 0 | return efi_set_variable_int(u"OsIndicationsSupported", |
172 | 0 | &efi_global_variable_guid, |
173 | 0 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
174 | 0 | EFI_VARIABLE_RUNTIME_ACCESS | |
175 | 0 | EFI_VARIABLE_READ_ONLY, |
176 | 0 | sizeof(os_indications_supported), |
177 | 0 | &os_indications_supported, false); |
178 | 0 | } |
179 | | |
180 | | /** |
181 | | * efi_init_early() - handle initialization at early stage |
182 | | * |
183 | | * expected to be called in board_init_r(). |
184 | | * |
185 | | * Return: status code |
186 | | */ |
187 | | int efi_init_early(void) |
188 | 0 | { |
189 | 0 | efi_status_t ret; |
190 | | |
191 | | /* Allow unaligned memory access */ |
192 | 0 | allow_unaligned(); |
193 | | |
194 | | /* Initialize root node */ |
195 | 0 | ret = efi_root_node_register(); |
196 | 0 | if (ret != EFI_SUCCESS) |
197 | 0 | goto out; |
198 | | |
199 | 0 | ret = efi_console_register(); |
200 | 0 | if (ret != EFI_SUCCESS) |
201 | 0 | goto out; |
202 | | |
203 | | /* Initialize EFI driver uclass */ |
204 | 0 | ret = efi_driver_init(); |
205 | 0 | if (ret != EFI_SUCCESS) |
206 | 0 | goto out; |
207 | | |
208 | 0 | return 0; |
209 | 0 | out: |
210 | | /* never re-init UEFI subsystem */ |
211 | 0 | efi_obj_list_initialized = ret; |
212 | |
|
213 | 0 | return -1; |
214 | 0 | } |
215 | | |
216 | | /** |
217 | | * efi_start_obj_list() - Start EFI object list |
218 | | * |
219 | | * Return: status code |
220 | | */ |
221 | | static efi_status_t efi_start_obj_list(void) |
222 | 0 | { |
223 | 0 | efi_status_t ret = EFI_SUCCESS; |
224 | |
|
225 | 0 | if (IS_ENABLED(CONFIG_NETDEVICES)) |
226 | 0 | ret = efi_net_do_start(eth_get_dev()); |
227 | |
|
228 | 0 | return ret; |
229 | 0 | } |
230 | | |
231 | | /** |
232 | | * efi_init_obj_list() - Initialize and populate EFI object list |
233 | | * |
234 | | * Return: status code |
235 | | */ |
236 | | efi_status_t efi_init_obj_list(void) |
237 | 0 | { |
238 | 0 | efi_status_t ret = EFI_SUCCESS; |
239 | | |
240 | | /* Initialize only once, but start every time if correctly initialized*/ |
241 | 0 | if (efi_obj_list_initialized == OBJ_LIST_INITIALIZED) |
242 | 0 | return efi_start_obj_list(); |
243 | 0 | if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED) |
244 | 0 | return efi_obj_list_initialized; |
245 | | |
246 | | /* Set up console modes */ |
247 | 0 | efi_setup_console_size(); |
248 | | |
249 | | /* |
250 | | * Probe block devices to find the ESP. |
251 | | * efi_disks_register() must be called before efi_init_variables(). |
252 | | */ |
253 | 0 | ret = efi_disks_register(); |
254 | 0 | if (ret != EFI_SUCCESS) |
255 | 0 | goto out; |
256 | | |
257 | | /* Initialize variable services */ |
258 | 0 | ret = efi_init_variables(); |
259 | 0 | if (ret != EFI_SUCCESS) |
260 | 0 | goto out; |
261 | | |
262 | 0 | if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) { |
263 | | /* update boot option after variable service initialized */ |
264 | 0 | ret = efi_bootmgr_update_media_device_boot_option(); |
265 | 0 | if (ret != EFI_SUCCESS) |
266 | 0 | goto out; |
267 | 0 | } |
268 | | |
269 | | /* Define supported languages */ |
270 | 0 | ret = efi_init_platform_lang(); |
271 | 0 | if (ret != EFI_SUCCESS) |
272 | 0 | goto out; |
273 | | |
274 | | /* Indicate supported features */ |
275 | 0 | ret = efi_init_os_indications(); |
276 | 0 | if (ret != EFI_SUCCESS) |
277 | 0 | goto out; |
278 | | |
279 | | /* Initialize system table */ |
280 | 0 | ret = efi_initialize_system_table(); |
281 | 0 | if (ret != EFI_SUCCESS) |
282 | 0 | goto out; |
283 | | |
284 | | /* Initialize system table pointer */ |
285 | 0 | if (IS_ENABLED(CONFIG_EFI_DEBUG_SUPPORT)) { |
286 | 0 | efi_guid_t debug_image_info_table_guid = |
287 | 0 | efi_debug_image_info_table_guid; |
288 | |
|
289 | 0 | ret = efi_initialize_system_table_pointer(); |
290 | 0 | if (ret != EFI_SUCCESS) |
291 | 0 | goto out; |
292 | | |
293 | 0 | ret = efi_install_configuration_table(&debug_image_info_table_guid, |
294 | 0 | &efi_m_debug_info_table_header); |
295 | 0 | if (ret != EFI_SUCCESS) |
296 | 0 | goto out; |
297 | 0 | } |
298 | | |
299 | 0 | if (IS_ENABLED(CONFIG_EFI_ECPT)) { |
300 | 0 | ret = efi_ecpt_register(); |
301 | 0 | if (ret != EFI_SUCCESS) |
302 | 0 | goto out; |
303 | 0 | } |
304 | | |
305 | 0 | if (IS_ENABLED(CONFIG_EFI_ESRT)) { |
306 | 0 | ret = efi_esrt_register(); |
307 | 0 | if (ret != EFI_SUCCESS) |
308 | 0 | goto out; |
309 | 0 | } |
310 | | |
311 | 0 | if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { |
312 | 0 | ret = efi_tcg2_register(); |
313 | 0 | if (ret != EFI_SUCCESS) |
314 | 0 | goto out; |
315 | | |
316 | 0 | ret = efi_tcg2_do_initial_measurement(); |
317 | 0 | if (ret == EFI_SECURITY_VIOLATION) |
318 | 0 | goto out; |
319 | 0 | } |
320 | | |
321 | | /* Install EFI_RNG_PROTOCOL */ |
322 | 0 | if (IS_ENABLED(CONFIG_EFI_RNG_PROTOCOL)) { |
323 | 0 | ret = efi_rng_register(); |
324 | 0 | if (ret != EFI_SUCCESS) |
325 | 0 | goto out; |
326 | 0 | } |
327 | | |
328 | 0 | if (IS_ENABLED(CONFIG_EFI_RISCV_BOOT_PROTOCOL)) { |
329 | 0 | ret = efi_riscv_register(); |
330 | 0 | if (ret != EFI_SUCCESS) |
331 | 0 | goto out; |
332 | 0 | } |
333 | | |
334 | | /* Secure boot */ |
335 | 0 | if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) { |
336 | 0 | ret = efi_init_secure_boot(); |
337 | 0 | if (ret != EFI_SUCCESS) |
338 | 0 | goto out; |
339 | 0 | } |
340 | | |
341 | | /* Indicate supported runtime services */ |
342 | 0 | ret = efi_init_runtime_supported(); |
343 | 0 | if (ret != EFI_SUCCESS) |
344 | 0 | goto out; |
345 | | |
346 | 0 | if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) { |
347 | 0 | ret = efi_load_capsule_drivers(); |
348 | 0 | if (ret != EFI_SUCCESS) |
349 | 0 | goto out; |
350 | 0 | } |
351 | | |
352 | 0 | if (IS_ENABLED(CONFIG_VIDEO)) { |
353 | 0 | ret = efi_gop_register(); |
354 | 0 | if (ret != EFI_SUCCESS) |
355 | 0 | goto out; |
356 | 0 | } |
357 | 0 | if (IS_ENABLED(CONFIG_NETDEVICES)) { |
358 | 0 | ret = efi_net_register(eth_get_dev()); |
359 | 0 | if (ret != EFI_SUCCESS) |
360 | 0 | goto out; |
361 | 0 | } |
362 | 0 | if (IS_ENABLED(CONFIG_ACPI)) { |
363 | 0 | ret = efi_acpi_register(); |
364 | 0 | if (ret != EFI_SUCCESS) |
365 | 0 | goto out; |
366 | 0 | } |
367 | 0 | if (IS_ENABLED(CONFIG_SMBIOS)) { |
368 | 0 | ret = efi_smbios_register(); |
369 | 0 | if (ret != EFI_SUCCESS) |
370 | 0 | goto out; |
371 | 0 | } |
372 | 0 | ret = efi_watchdog_register(); |
373 | 0 | if (ret != EFI_SUCCESS) |
374 | 0 | goto out; |
375 | | |
376 | 0 | ret = efi_init_capsule(); |
377 | 0 | if (ret != EFI_SUCCESS) |
378 | 0 | goto out; |
379 | | |
380 | | /* Initialize EFI runtime services */ |
381 | 0 | ret = efi_reset_system_init(); |
382 | 0 | if (ret != EFI_SUCCESS) |
383 | 0 | goto out; |
384 | | |
385 | | /* Execute capsules after reboot */ |
386 | 0 | if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK) && |
387 | 0 | !IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY)) |
388 | 0 | ret = efi_launch_capsules(); |
389 | 0 | if (ret != EFI_SUCCESS) |
390 | 0 | goto out; |
391 | | |
392 | 0 | ret = efi_start_obj_list(); |
393 | 0 | out: |
394 | 0 | efi_obj_list_initialized = ret; |
395 | 0 | return ret; |
396 | 0 | } |