blob: fa9d7fe757856b457a1c338bd95f36f4f7a520ad [file] [log] [blame]
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * UEFI Shell-like command
4 *
5 * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
6 */
7
8#include <charset.h>
9#include <common.h>
10#include <command.h>
11#include <efi_loader.h>
Heinrich Schuchardt50adeff2020-09-27 14:50:25 +020012#include <efi_rng.h>
AKASHI Takahiroe7c08832019-02-25 15:54:38 +090013#include <exports.h>
Heinrich Schuchardt9df002e2019-04-29 13:51:45 +020014#include <hexdump.h>
Simon Glass0f2af882020-05-10 11:40:05 -060015#include <log.h>
AKASHI Takahiroe7c08832019-02-25 15:54:38 +090016#include <malloc.h>
Heinrich Schuchardtfec10a42020-03-14 08:44:07 +010017#include <mapmem.h>
AKASHI Takahiroe7c08832019-02-25 15:54:38 +090018#include <search.h>
19#include <linux/ctype.h>
20
AKASHI Takahiroe32788a2019-02-25 15:54:39 +090021#define BS systab.boottime
AKASHI Takahiro38833c82020-11-17 09:28:01 +090022#define RT systab.runtime
AKASHI Takahiroe7c08832019-02-25 15:54:38 +090023
AKASHI Takahiro38833c82020-11-17 09:28:01 +090024#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
25/**
26 * do_efi_capsule_update() - process a capsule update
27 *
28 * @cmdtp: Command table
29 * @flag: Command flag
30 * @argc: Number of arguments
31 * @argv: Argument array
32 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
33 *
34 * Implement efidebug "capsule update" sub-command.
35 * process a capsule update.
36 *
37 * efidebug capsule update [-v] <capsule address>
38 */
39static int do_efi_capsule_update(struct cmd_tbl *cmdtp, int flag,
40 int argc, char * const argv[])
41{
42 struct efi_capsule_header *capsule;
43 int verbose = 0;
44 char *endp;
45 efi_status_t ret;
46
47 if (argc != 2 && argc != 3)
48 return CMD_RET_USAGE;
49
50 if (argc == 3) {
51 if (strcmp(argv[1], "-v"))
52 return CMD_RET_USAGE;
53
54 verbose = 1;
55 argc--;
56 argv++;
57 }
58
59 capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16);
60 if (endp == argv[1]) {
61 printf("Invalid address: %s", argv[1]);
62 return CMD_RET_FAILURE;
63 }
64
65 if (verbose) {
66 printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
67 printf("Capsule flags: 0x%x\n", capsule->flags);
68 printf("Capsule header size: 0x%x\n", capsule->header_size);
69 printf("Capsule image size: 0x%x\n",
70 capsule->capsule_image_size);
71 }
72
73 ret = EFI_CALL(RT->update_capsule(&capsule, 1, (u64)NULL));
74 if (ret) {
75 printf("Cannot handle a capsule at %p", capsule);
76 return CMD_RET_FAILURE;
77 }
78
79 return CMD_RET_SUCCESS;
80}
81
82/**
83 * do_efi_capsule_show() - show capsule information
84 *
85 * @cmdtp: Command table
86 * @flag: Command flag
87 * @argc: Number of arguments
88 * @argv: Argument array
89 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
90 *
91 * Implement efidebug "capsule show" sub-command.
92 * show capsule information.
93 *
94 * efidebug capsule show <capsule address>
95 */
96static int do_efi_capsule_show(struct cmd_tbl *cmdtp, int flag,
97 int argc, char * const argv[])
98{
99 struct efi_capsule_header *capsule;
100 char *endp;
101
102 if (argc != 2)
103 return CMD_RET_USAGE;
104
105 capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16);
106 if (endp == argv[1]) {
107 printf("Invalid address: %s", argv[1]);
108 return CMD_RET_FAILURE;
109 }
110
111 printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
112 printf("Capsule flags: 0x%x\n", capsule->flags);
113 printf("Capsule header size: 0x%x\n", capsule->header_size);
114 printf("Capsule image size: 0x%x\n",
115 capsule->capsule_image_size);
116
117 return CMD_RET_SUCCESS;
118}
119
120/**
121 * do_efi_capsule_res() - show a capsule update result
122 *
123 * @cmdtp: Command table
124 * @flag: Command flag
125 * @argc: Number of arguments
126 * @argv: Argument array
127 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
128 *
129 * Implement efidebug "capsule result" sub-command.
130 * show a capsule update result.
131 * If result number is not specified, CapsuleLast will be shown.
132 *
133 * efidebug capsule result [<capsule result number>]
134 */
135static int do_efi_capsule_res(struct cmd_tbl *cmdtp, int flag,
136 int argc, char * const argv[])
137{
138 int capsule_id;
139 char *endp;
140 char var_name[12];
141 u16 var_name16[12], *p;
142 efi_guid_t guid;
143 struct efi_capsule_result_variable_header *result = NULL;
144 efi_uintn_t size;
145 efi_status_t ret;
146
147 if (argc != 1 && argc != 2)
148 return CMD_RET_USAGE;
149
150 guid = efi_guid_capsule_report;
151 if (argc == 1) {
152 size = sizeof(var_name16);
153 ret = EFI_CALL(RT->get_variable(L"CapsuleLast", &guid, NULL,
154 &size, var_name16));
155 if (ret != EFI_SUCCESS) {
156 if (ret == EFI_NOT_FOUND)
157 printf("CapsuleLast doesn't exist\n");
158 else
159 printf("Failed to get CapsuleLast\n");
160
161 return CMD_RET_FAILURE;
162 }
163 printf("CapsuleLast is %ls\n", var_name16);
164 } else {
165 argc--;
166 argv++;
167
168 capsule_id = simple_strtoul(argv[0], &endp, 16);
169 if (capsule_id < 0 || capsule_id > 0xffff)
170 return CMD_RET_USAGE;
171
172 sprintf(var_name, "Capsule%04X", capsule_id);
173 p = var_name16;
174 utf8_utf16_strncpy(&p, var_name, 9);
175 }
176
177 size = 0;
178 ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
179 if (ret == EFI_BUFFER_TOO_SMALL) {
180 result = malloc(size);
181 ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
182 result));
183 if (ret != EFI_SUCCESS) {
184 free(result);
185 printf("Failed to get %ls\n", var_name16);
186
187 return CMD_RET_FAILURE;
188 }
189 }
190
191 printf("Result total size: 0x%x\n", result->variable_total_size);
192 printf("Capsule guid: %pUl\n", &result->capsule_guid);
193 printf("Time processed: %04d-%02d-%02d %02d:%02d:%02d\n",
194 result->capsule_processed.year, result->capsule_processed.month,
195 result->capsule_processed.day, result->capsule_processed.hour,
196 result->capsule_processed.minute,
197 result->capsule_processed.second);
198 printf("Capsule status: 0x%lx\n", result->capsule_status);
199
200 free(result);
201
202 return CMD_RET_SUCCESS;
203}
204
205static struct cmd_tbl cmd_efidebug_capsule_sub[] = {
206 U_BOOT_CMD_MKENT(update, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_update,
207 "", ""),
208 U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show,
209 "", ""),
210 U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res,
211 "", ""),
212};
213
214/**
215 * do_efi_capsule() - manage UEFI capsules
216 *
217 * @cmdtp: Command table
218 * @flag: Command flag
219 * @argc: Number of arguments
220 * @argv: Argument array
221 * Return: CMD_RET_SUCCESS on success,
222 * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
223 *
224 * Implement efidebug "capsule" sub-command.
225 */
226static int do_efi_capsule(struct cmd_tbl *cmdtp, int flag,
227 int argc, char * const argv[])
228{
229 struct cmd_tbl *cp;
230
231 if (argc < 2)
232 return CMD_RET_USAGE;
233
234 argc--; argv++;
235
236 cp = find_cmd_tbl(argv[0], cmd_efidebug_capsule_sub,
237 ARRAY_SIZE(cmd_efidebug_capsule_sub));
238 if (!cp)
239 return CMD_RET_USAGE;
240
241 return cp->cmd(cmdtp, flag, argc, argv);
242}
243#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */
244
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900245/**
AKASHI Takahiroe32788a2019-02-25 15:54:39 +0900246 * efi_get_device_handle_info() - get information of UEFI device
247 *
248 * @handle: Handle of UEFI device
249 * @dev_path_text: Pointer to text of device path
250 * Return: 0 on success, -1 on failure
251 *
252 * Currently return a formatted text of device path.
253 */
254static int efi_get_device_handle_info(efi_handle_t handle, u16 **dev_path_text)
255{
256 struct efi_device_path *dp;
257 efi_status_t ret;
258
259 ret = EFI_CALL(BS->open_protocol(handle, &efi_guid_device_path,
260 (void **)&dp, NULL /* FIXME */, NULL,
261 EFI_OPEN_PROTOCOL_GET_PROTOCOL));
262 if (ret == EFI_SUCCESS) {
263 *dev_path_text = efi_dp_str(dp);
264 return 0;
265 } else {
266 return -1;
267 }
268}
269
270#define EFI_HANDLE_WIDTH ((int)sizeof(efi_handle_t) * 2)
271
272static const char spc[] = " ";
273static const char sep[] = "================";
274
275/**
276 * do_efi_show_devices() - show UEFI devices
277 *
278 * @cmdtp: Command table
279 * @flag: Command flag
280 * @argc: Number of arguments
281 * @argv: Argument array
282 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
283 *
284 * Implement efidebug "devices" sub-command.
285 * Show all UEFI devices and their information.
286 */
Simon Glassed38aef2020-05-10 11:40:03 -0600287static int do_efi_show_devices(struct cmd_tbl *cmdtp, int flag,
288 int argc, char *const argv[])
AKASHI Takahiroe32788a2019-02-25 15:54:39 +0900289{
290 efi_handle_t *handles;
291 efi_uintn_t num, i;
292 u16 *dev_path_text;
293 efi_status_t ret;
294
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200295 ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
AKASHI Takahiroe32788a2019-02-25 15:54:39 +0900296 &num, &handles));
297 if (ret != EFI_SUCCESS)
298 return CMD_RET_FAILURE;
299
300 if (!num)
301 return CMD_RET_SUCCESS;
302
303 printf("Device%.*s Device Path\n", EFI_HANDLE_WIDTH - 6, spc);
304 printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
305 for (i = 0; i < num; i++) {
306 if (!efi_get_device_handle_info(handles[i], &dev_path_text)) {
307 printf("%p %ls\n", handles[i], dev_path_text);
308 efi_free_pool(dev_path_text);
309 }
310 }
311
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200312 efi_free_pool(handles);
AKASHI Takahiroe32788a2019-02-25 15:54:39 +0900313
314 return CMD_RET_SUCCESS;
315}
316
317/**
AKASHI Takahiro185716a2019-02-25 15:54:40 +0900318 * efi_get_driver_handle_info() - get information of UEFI driver
319 *
320 * @handle: Handle of UEFI device
321 * @driver_name: Driver name
322 * @image_path: Pointer to text of device path
323 * Return: 0 on success, -1 on failure
324 *
325 * Currently return no useful information as all UEFI drivers are
326 * built-in..
327 */
328static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name,
329 u16 **image_path)
330{
331 struct efi_handler *handler;
332 struct efi_loaded_image *image;
333 efi_status_t ret;
334
335 /*
336 * driver name
337 * TODO: support EFI_COMPONENT_NAME2_PROTOCOL
338 */
339 *driver_name = NULL;
340
341 /* image name */
342 ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
343 if (ret != EFI_SUCCESS) {
344 *image_path = NULL;
345 return 0;
346 }
347
348 image = handler->protocol_interface;
349 *image_path = efi_dp_str(image->file_path);
350
351 return 0;
352}
353
354/**
355 * do_efi_show_drivers() - show UEFI drivers
356 *
357 * @cmdtp: Command table
358 * @flag: Command flag
359 * @argc: Number of arguments
360 * @argv: Argument array
361 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
362 *
363 * Implement efidebug "drivers" sub-command.
364 * Show all UEFI drivers and their information.
365 */
Simon Glassed38aef2020-05-10 11:40:03 -0600366static int do_efi_show_drivers(struct cmd_tbl *cmdtp, int flag,
367 int argc, char *const argv[])
AKASHI Takahiro185716a2019-02-25 15:54:40 +0900368{
369 efi_handle_t *handles;
370 efi_uintn_t num, i;
371 u16 *driver_name, *image_path_text;
372 efi_status_t ret;
373
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200374 ret = EFI_CALL(efi_locate_handle_buffer(
AKASHI Takahiro185716a2019-02-25 15:54:40 +0900375 BY_PROTOCOL, &efi_guid_driver_binding_protocol,
376 NULL, &num, &handles));
377 if (ret != EFI_SUCCESS)
378 return CMD_RET_FAILURE;
379
380 if (!num)
381 return CMD_RET_SUCCESS;
382
383 printf("Driver%.*s Name Image Path\n",
384 EFI_HANDLE_WIDTH - 6, spc);
385 printf("%.*s ==================== ====================\n",
386 EFI_HANDLE_WIDTH, sep);
387 for (i = 0; i < num; i++) {
388 if (!efi_get_driver_handle_info(handles[i], &driver_name,
389 &image_path_text)) {
390 if (image_path_text)
391 printf("%p %-20ls %ls\n", handles[i],
392 driver_name, image_path_text);
393 else
394 printf("%p %-20ls <built-in>\n",
395 handles[i], driver_name);
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200396 efi_free_pool(driver_name);
397 efi_free_pool(image_path_text);
AKASHI Takahiro185716a2019-02-25 15:54:40 +0900398 }
399 }
400
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200401 efi_free_pool(handles);
AKASHI Takahiro185716a2019-02-25 15:54:40 +0900402
403 return CMD_RET_SUCCESS;
404}
405
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900406static const struct {
407 const char *text;
408 const efi_guid_t guid;
409} guid_list[] = {
410 {
411 "Device Path",
Heinrich Schuchardt788ad412019-04-20 07:39:11 +0200412 EFI_DEVICE_PATH_PROTOCOL_GUID,
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900413 },
414 {
415 "Device Path To Text",
416 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID,
417 },
418 {
419 "Device Path Utilities",
420 EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID,
421 },
422 {
423 "Unicode Collation 2",
424 EFI_UNICODE_COLLATION_PROTOCOL2_GUID,
425 },
426 {
427 "Driver Binding",
428 EFI_DRIVER_BINDING_PROTOCOL_GUID,
429 },
430 {
431 "Simple Text Input",
432 EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID,
433 },
434 {
435 "Simple Text Input Ex",
436 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID,
437 },
438 {
439 "Simple Text Output",
440 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID,
441 },
442 {
443 "Block IO",
Heinrich Schuchardt788ad412019-04-20 07:39:11 +0200444 EFI_BLOCK_IO_PROTOCOL_GUID,
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900445 },
446 {
447 "Simple File System",
448 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
449 },
450 {
451 "Loaded Image",
Heinrich Schuchardt788ad412019-04-20 07:39:11 +0200452 EFI_LOADED_IMAGE_PROTOCOL_GUID,
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900453 },
454 {
Heinrich Schuchardt788ad412019-04-20 07:39:11 +0200455 "Graphics Output",
456 EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID,
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900457 },
Heinrich Schuchardtae776902019-04-20 07:57:28 +0200458 {
459 "HII String",
460 EFI_HII_STRING_PROTOCOL_GUID,
461 },
462 {
463 "HII Database",
464 EFI_HII_DATABASE_PROTOCOL_GUID,
465 },
466 {
467 "HII Config Routing",
468 EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID,
469 },
470 {
Ilias Apalodimas3510ba72020-02-21 09:55:45 +0200471 "Load File2",
472 EFI_LOAD_FILE2_PROTOCOL_GUID,
473 },
474 {
Heinrich Schuchardt50adeff2020-09-27 14:50:25 +0200475 "Random Number Generator",
476 EFI_RNG_PROTOCOL_GUID,
477 },
478 {
Heinrich Schuchardtae776902019-04-20 07:57:28 +0200479 "Simple Network",
480 EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
481 },
482 {
483 "PXE Base Code",
484 EFI_PXE_BASE_CODE_PROTOCOL_GUID,
485 },
Heinrich Schuchardt75844e52020-01-07 05:57:47 +0100486 /* Configuration table GUIDs */
487 {
488 "ACPI table",
489 EFI_ACPI_TABLE_GUID,
490 },
491 {
492 "device tree",
493 EFI_FDT_GUID,
494 },
495 {
496 "SMBIOS table",
497 SMBIOS_TABLE_GUID,
498 },
Heinrich Schuchardt956eff32020-02-19 20:48:49 +0100499 {
500 "Runtime properties",
501 EFI_RT_PROPERTIES_TABLE_GUID,
502 },
Ilias Apalodimasa51fb1c2020-11-30 11:47:41 +0200503 {
504 "TCG2 Final Events Table",
505 EFI_TCG2_FINAL_EVENTS_TABLE_GUID,
506 },
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900507};
508
509/**
Heinrich Schuchardtc6fc5022020-01-07 06:02:33 +0100510 * get_guid_text - get string of GUID
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900511 *
Heinrich Schuchardtc6fc5022020-01-07 06:02:33 +0100512 * Return description of GUID.
513 *
514 * @guid: GUID
515 * Return: description of GUID or NULL
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900516 */
Heinrich Schuchardtc6fc5022020-01-07 06:02:33 +0100517static const char *get_guid_text(const void *guid)
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900518{
519 int i;
520
Heinrich Schuchardtc6fc5022020-01-07 06:02:33 +0100521 for (i = 0; i < ARRAY_SIZE(guid_list); i++) {
522 /*
523 * As guidcmp uses memcmp() we can safely accept unaligned
524 * GUIDs.
525 */
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900526 if (!guidcmp(&guid_list[i].guid, guid))
Heinrich Schuchardtc6fc5022020-01-07 06:02:33 +0100527 return guid_list[i].text;
528 }
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900529
Heinrich Schuchardtc6fc5022020-01-07 06:02:33 +0100530 return NULL;
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900531}
532
533/**
534 * do_efi_show_handles() - show UEFI handles
535 *
536 * @cmdtp: Command table
537 * @flag: Command flag
538 * @argc: Number of arguments
539 * @argv: Argument array
540 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
541 *
542 * Implement efidebug "dh" sub-command.
543 * Show all UEFI handles and their information, currently all protocols
544 * added to handle.
545 */
Simon Glassed38aef2020-05-10 11:40:03 -0600546static int do_efi_show_handles(struct cmd_tbl *cmdtp, int flag,
547 int argc, char *const argv[])
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900548{
549 efi_handle_t *handles;
550 efi_guid_t **guid;
551 efi_uintn_t num, count, i, j;
552 const char *guid_text;
553 efi_status_t ret;
554
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200555 ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900556 &num, &handles));
557 if (ret != EFI_SUCCESS)
558 return CMD_RET_FAILURE;
559
560 if (!num)
561 return CMD_RET_SUCCESS;
562
563 printf("Handle%.*s Protocols\n", EFI_HANDLE_WIDTH - 6, spc);
564 printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
565 for (i = 0; i < num; i++) {
566 printf("%p", handles[i]);
567 ret = EFI_CALL(BS->protocols_per_handle(handles[i], &guid,
568 &count));
569 if (ret || !count) {
570 putc('\n');
571 continue;
572 }
573
574 for (j = 0; j < count; j++) {
575 if (j)
576 printf(", ");
577 else
578 putc(' ');
579
580 guid_text = get_guid_text(guid[j]);
581 if (guid_text)
582 puts(guid_text);
583 else
584 printf("%pUl", guid[j]);
585 }
586 putc('\n');
587 }
588
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200589 efi_free_pool(handles);
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +0900590
591 return CMD_RET_SUCCESS;
592}
593
AKASHI Takahiro185716a2019-02-25 15:54:40 +0900594/**
AKASHI Takahiro71ab1bf2019-02-25 15:54:42 +0900595 * do_efi_show_images() - show UEFI images
596 *
597 * @cmdtp: Command table
598 * @flag: Command flag
599 * @argc: Number of arguments
600 * @argv: Argument array
601 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
602 *
603 * Implement efidebug "images" sub-command.
604 * Show all UEFI loaded images and their information.
605 */
Simon Glassed38aef2020-05-10 11:40:03 -0600606static int do_efi_show_images(struct cmd_tbl *cmdtp, int flag,
607 int argc, char *const argv[])
AKASHI Takahiro71ab1bf2019-02-25 15:54:42 +0900608{
609 efi_print_image_infos(NULL);
610
611 return CMD_RET_SUCCESS;
612}
613
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900614static const char * const efi_mem_type_string[] = {
615 [EFI_RESERVED_MEMORY_TYPE] = "RESERVED",
616 [EFI_LOADER_CODE] = "LOADER CODE",
617 [EFI_LOADER_DATA] = "LOADER DATA",
618 [EFI_BOOT_SERVICES_CODE] = "BOOT CODE",
619 [EFI_BOOT_SERVICES_DATA] = "BOOT DATA",
620 [EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE",
621 [EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA",
622 [EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL",
623 [EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM",
624 [EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM",
625 [EFI_ACPI_MEMORY_NVS] = "ACPI NVS",
626 [EFI_MMAP_IO] = "IO",
627 [EFI_MMAP_IO_PORT] = "IO PORT",
628 [EFI_PAL_CODE] = "PAL",
Heinrich Schuchardt45176e82020-04-29 20:21:39 +0200629 [EFI_PERSISTENT_MEMORY_TYPE] = "PERSISTENT",
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900630};
631
632static const struct efi_mem_attrs {
633 const u64 bit;
634 const char *text;
635} efi_mem_attrs[] = {
636 {EFI_MEMORY_UC, "UC"},
637 {EFI_MEMORY_UC, "UC"},
638 {EFI_MEMORY_WC, "WC"},
639 {EFI_MEMORY_WT, "WT"},
640 {EFI_MEMORY_WB, "WB"},
641 {EFI_MEMORY_UCE, "UCE"},
642 {EFI_MEMORY_WP, "WP"},
643 {EFI_MEMORY_RP, "RP"},
644 {EFI_MEMORY_XP, "WP"},
645 {EFI_MEMORY_NV, "NV"},
646 {EFI_MEMORY_MORE_RELIABLE, "REL"},
647 {EFI_MEMORY_RO, "RO"},
Heinrich Schuchardte76f0e42020-05-19 07:20:46 +0200648 {EFI_MEMORY_SP, "SP"},
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900649 {EFI_MEMORY_RUNTIME, "RT"},
650};
651
652/**
653 * print_memory_attributes() - print memory map attributes
Heinrich Schuchardtb1d65432019-07-14 14:00:41 +0200654 *
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900655 * @attributes: Attribute value
656 *
657 * Print memory map attributes
658 */
659static void print_memory_attributes(u64 attributes)
660{
661 int sep, i;
662
663 for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
664 if (attributes & efi_mem_attrs[i].bit) {
665 if (sep) {
666 putc('|');
667 } else {
668 putc(' ');
669 sep = 1;
670 }
671 puts(efi_mem_attrs[i].text);
672 }
673}
674
675#define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
676
677/**
678 * do_efi_show_memmap() - show UEFI memory map
679 *
680 * @cmdtp: Command table
681 * @flag: Command flag
682 * @argc: Number of arguments
683 * @argv: Argument array
684 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
685 *
686 * Implement efidebug "memmap" sub-command.
687 * Show UEFI memory map.
688 */
Simon Glassed38aef2020-05-10 11:40:03 -0600689static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
690 int argc, char *const argv[])
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900691{
692 struct efi_mem_desc *memmap = NULL, *map;
693 efi_uintn_t map_size = 0;
694 const char *type;
695 int i;
696 efi_status_t ret;
697
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200698 ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900699 if (ret == EFI_BUFFER_TOO_SMALL) {
700 map_size += sizeof(struct efi_mem_desc); /* for my own */
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200701 ret = efi_allocate_pool(EFI_LOADER_DATA, map_size,
702 (void *)&memmap);
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900703 if (ret != EFI_SUCCESS)
704 return CMD_RET_FAILURE;
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200705 ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900706 }
707 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200708 efi_free_pool(memmap);
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900709 return CMD_RET_FAILURE;
710 }
711
712 printf("Type Start%.*s End%.*s Attributes\n",
713 EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
714 printf("================ %.*s %.*s ==========\n",
715 EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
AKASHI Takahiroac0abe22020-05-08 14:50:18 +0900716 /*
717 * Coverity check: dereferencing null pointer "map."
718 * This is a false positive as memmap will always be
719 * populated by allocate_pool() above.
720 */
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900721 for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
Heinrich Schuchardt45176e82020-04-29 20:21:39 +0200722 if (map->type < ARRAY_SIZE(efi_mem_type_string))
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900723 type = efi_mem_type_string[map->type];
724 else
725 type = "(unknown)";
726
727 printf("%-16s %.*llx-%.*llx", type,
728 EFI_PHYS_ADDR_WIDTH,
Heinrich Schuchardt9d4c7882020-03-27 04:33:17 +0000729 (u64)map_to_sysmem((void *)(uintptr_t)
730 map->physical_start),
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900731 EFI_PHYS_ADDR_WIDTH,
Heinrich Schuchardt9d4c7882020-03-27 04:33:17 +0000732 (u64)map_to_sysmem((void *)(uintptr_t)
733 (map->physical_start +
734 map->num_pages * EFI_PAGE_SIZE)));
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900735
736 print_memory_attributes(map->attribute);
737 putc('\n');
738 }
739
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200740 efi_free_pool(memmap);
AKASHI Takahiro32979d82019-02-25 15:54:43 +0900741
742 return CMD_RET_SUCCESS;
743}
744
AKASHI Takahiro71ab1bf2019-02-25 15:54:42 +0900745/**
Heinrich Schuchardt75844e52020-01-07 05:57:47 +0100746 * do_efi_show_tables() - show UEFI configuration tables
747 *
748 * @cmdtp: Command table
749 * @flag: Command flag
750 * @argc: Number of arguments
751 * @argv: Argument array
752 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
753 *
754 * Implement efidebug "tables" sub-command.
755 * Show UEFI configuration tables.
756 */
Simon Glassed38aef2020-05-10 11:40:03 -0600757static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
758 int argc, char *const argv[])
Heinrich Schuchardt75844e52020-01-07 05:57:47 +0100759{
760 efi_uintn_t i;
761 const char *guid_str;
762
763 for (i = 0; i < systab.nr_tables; ++i) {
764 guid_str = get_guid_text(&systab.tables[i].guid);
765 if (!guid_str)
766 guid_str = "";
767 printf("%pUl %s\n", &systab.tables[i].guid, guid_str);
768 }
769
770 return CMD_RET_SUCCESS;
771}
772
773/**
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900774 * do_efi_boot_add() - set UEFI load option
775 *
776 * @cmdtp: Command table
777 * @flag: Command flag
778 * @argc: Number of arguments
779 * @argv: Argument array
780 * Return: CMD_RET_SUCCESS on success,
781 * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
782 *
Heinrich Schuchardtb1d65432019-07-14 14:00:41 +0200783 * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
784 *
785 * efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900786 */
Simon Glassed38aef2020-05-10 11:40:03 -0600787static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
788 int argc, char *const argv[])
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900789{
790 int id;
791 char *endp;
792 char var_name[9];
793 u16 var_name16[9], *p;
794 efi_guid_t guid;
795 size_t label_len, label_len16;
796 u16 *label;
797 struct efi_device_path *device_path = NULL, *file_path = NULL;
798 struct efi_load_option lo;
799 void *data = NULL;
800 efi_uintn_t size;
Heinrich Schuchardt8bdd1492019-06-20 12:48:04 +0200801 efi_status_t ret;
Heinrich Schuchardt99a21fc2019-06-20 12:59:45 +0200802 int r = CMD_RET_SUCCESS;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900803
804 if (argc < 6 || argc > 7)
805 return CMD_RET_USAGE;
806
807 id = (int)simple_strtoul(argv[1], &endp, 16);
808 if (*endp != '\0' || id > 0xffff)
Heinrich Schuchardtb2469722019-02-28 20:41:58 +0100809 return CMD_RET_USAGE;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900810
811 sprintf(var_name, "Boot%04X", id);
812 p = var_name16;
813 utf8_utf16_strncpy(&p, var_name, 9);
814
815 guid = efi_global_variable_guid;
816
817 /* attributes */
818 lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
819
820 /* label */
821 label_len = strlen(argv[2]);
822 label_len16 = utf8_utf16_strnlen(argv[2], label_len);
823 label = malloc((label_len16 + 1) * sizeof(u16));
824 if (!label)
825 return CMD_RET_FAILURE;
826 lo.label = label; /* label will be changed below */
827 utf8_utf16_strncpy(&label, argv[2], label_len);
828
829 /* file path */
830 ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
831 &file_path);
832 if (ret != EFI_SUCCESS) {
833 printf("Cannot create device path for \"%s %s\"\n",
834 argv[3], argv[4]);
Heinrich Schuchardt8bdd1492019-06-20 12:48:04 +0200835 r = CMD_RET_FAILURE;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900836 goto out;
837 }
838 lo.file_path = file_path;
839 lo.file_path_length = efi_dp_size(file_path)
840 + sizeof(struct efi_device_path); /* for END */
841
842 /* optional data */
AKASHI Takahiro085372e2020-05-08 14:50:47 +0900843 if (argc == 6)
Heinrich Schuchardt9df002e2019-04-29 13:51:45 +0200844 lo.optional_data = NULL;
845 else
846 lo.optional_data = (const u8 *)argv[6];
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900847
848 size = efi_serialize_load_option(&lo, (u8 **)&data);
849 if (!size) {
Heinrich Schuchardt8bdd1492019-06-20 12:48:04 +0200850 r = CMD_RET_FAILURE;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900851 goto out;
852 }
853
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200854 ret = EFI_CALL(efi_set_variable(var_name16, &guid,
AKASHI Takahiroc1f3ebc2019-06-04 15:52:10 +0900855 EFI_VARIABLE_NON_VOLATILE |
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900856 EFI_VARIABLE_BOOTSERVICE_ACCESS |
857 EFI_VARIABLE_RUNTIME_ACCESS,
858 size, data));
Heinrich Schuchardt99a21fc2019-06-20 12:59:45 +0200859 if (ret != EFI_SUCCESS) {
860 printf("Cannot set %ls\n", var_name16);
861 r = CMD_RET_FAILURE;
862 }
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900863out:
864 free(data);
865 efi_free_pool(device_path);
866 efi_free_pool(file_path);
867 free(lo.label);
868
Heinrich Schuchardt8bdd1492019-06-20 12:48:04 +0200869 return r;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900870}
871
872/**
873 * do_efi_boot_rm() - delete UEFI load options
874 *
875 * @cmdtp: Command table
876 * @flag: Command flag
877 * @argc: Number of arguments
878 * @argv: Argument array
879 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
880 *
881 * Implement efidebug "boot rm" sub-command.
882 * Delete UEFI load options.
Heinrich Schuchardtb1d65432019-07-14 14:00:41 +0200883 *
884 * efidebug boot rm <id> ...
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900885 */
Simon Glassed38aef2020-05-10 11:40:03 -0600886static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
887 int argc, char *const argv[])
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900888{
889 efi_guid_t guid;
890 int id, i;
891 char *endp;
892 char var_name[9];
AKASHI Takahirocfdccd22020-02-28 09:05:04 +0900893 u16 var_name16[9], *p;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900894 efi_status_t ret;
895
896 if (argc == 1)
897 return CMD_RET_USAGE;
898
899 guid = efi_global_variable_guid;
900 for (i = 1; i < argc; i++, argv++) {
901 id = (int)simple_strtoul(argv[1], &endp, 16);
902 if (*endp != '\0' || id > 0xffff)
903 return CMD_RET_FAILURE;
904
905 sprintf(var_name, "Boot%04X", id);
AKASHI Takahirocfdccd22020-02-28 09:05:04 +0900906 p = var_name16;
907 utf8_utf16_strncpy(&p, var_name, 9);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900908
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +0200909 ret = EFI_CALL(efi_set_variable(var_name16, &guid, 0, 0, NULL));
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900910 if (ret) {
Heinrich Schuchardt3be0bda2020-03-02 20:13:10 +0100911 printf("Cannot remove %ls\n", var_name16);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900912 return CMD_RET_FAILURE;
913 }
914 }
915
916 return CMD_RET_SUCCESS;
917}
918
919/**
920 * show_efi_boot_opt_data() - dump UEFI load option
921 *
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +0200922 * @varname16: variable name
Heinrich Schuchardt9df002e2019-04-29 13:51:45 +0200923 * @data: value of UEFI load option variable
924 * @size: size of the boot option
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900925 *
926 * Decode the value of UEFI load option variable and print information.
927 */
Heinrich Schuchardt7ca84f82020-05-31 22:46:09 +0200928static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900929{
930 struct efi_load_option lo;
931 char *label, *p;
932 size_t label_len16, label_len;
933 u16 *dp_str;
Heinrich Schuchardt7ca84f82020-05-31 22:46:09 +0200934 efi_status_t ret;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900935
Heinrich Schuchardt7ca84f82020-05-31 22:46:09 +0200936 ret = efi_deserialize_load_option(&lo, data, size);
937 if (ret != EFI_SUCCESS) {
938 printf("%ls: invalid load option\n", varname16);
939 return;
940 }
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900941
942 label_len16 = u16_strlen(lo.label);
943 label_len = utf16_utf8_strnlen(lo.label, label_len16);
944 label = malloc(label_len + 1);
945 if (!label)
946 return;
947 p = label;
948 utf16_utf8_strncpy(&p, lo.label, label_len16);
949
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +0200950 printf("%ls:\nattributes: %c%c%c (0x%08x)\n",
951 varname16,
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900952 /* ACTIVE */
953 lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
954 /* FORCE RECONNECT */
955 lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
956 /* HIDDEN */
957 lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
958 lo.attributes);
Heinrich Schuchardt9df002e2019-04-29 13:51:45 +0200959 printf(" label: %s\n", label);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900960
961 dp_str = efi_dp_str(lo.file_path);
Heinrich Schuchardt9df002e2019-04-29 13:51:45 +0200962 printf(" file_path: %ls\n", dp_str);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900963 efi_free_pool(dp_str);
964
Heinrich Schuchardt9df002e2019-04-29 13:51:45 +0200965 printf(" data:\n");
966 print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
Heinrich Schuchardt7ca84f82020-05-31 22:46:09 +0200967 lo.optional_data, *size, true);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900968 free(label);
969}
970
971/**
972 * show_efi_boot_opt() - dump UEFI load option
973 *
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +0200974 * @varname16: variable name
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900975 *
976 * Dump information defined by UEFI load option.
977 */
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +0200978static void show_efi_boot_opt(u16 *varname16)
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900979{
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +0200980 void *data;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900981 efi_uintn_t size;
AKASHI Takahirodab93f42019-11-26 10:11:22 +0900982 efi_status_t ret;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900983
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900984 size = 0;
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +0200985 ret = EFI_CALL(efi_get_variable(varname16, &efi_global_variable_guid,
986 NULL, &size, NULL));
AKASHI Takahirodab93f42019-11-26 10:11:22 +0900987 if (ret == EFI_BUFFER_TOO_SMALL) {
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900988 data = malloc(size);
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +0200989 if (!data) {
990 printf("ERROR: Out of memory\n");
991 return;
992 }
993 ret = EFI_CALL(efi_get_variable(varname16,
994 &efi_global_variable_guid,
995 NULL, &size, data));
996 if (ret == EFI_SUCCESS)
Heinrich Schuchardt7ca84f82020-05-31 22:46:09 +0200997 show_efi_boot_opt_data(varname16, data, &size);
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +0200998 free(data);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +0900999 }
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001000}
1001
AKASHI Takahiro016bfcd2019-04-26 09:44:18 +09001002static int u16_tohex(u16 c)
1003{
1004 if (c >= '0' && c <= '9')
1005 return c - '0';
1006 if (c >= 'A' && c <= 'F')
1007 return c - 'A' + 10;
1008
1009 /* not hexadecimal */
1010 return -1;
1011}
1012
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001013/**
1014 * show_efi_boot_dump() - dump all UEFI load options
1015 *
1016 * @cmdtp: Command table
1017 * @flag: Command flag
1018 * @argc: Number of arguments
1019 * @argv: Argument array
1020 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1021 *
1022 * Implement efidebug "boot dump" sub-command.
1023 * Dump information of all UEFI load options defined.
Heinrich Schuchardt21715092019-07-25 20:52:23 +02001024 *
1025 * efidebug boot dump
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001026 */
Simon Glassed38aef2020-05-10 11:40:03 -06001027static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
1028 int argc, char *const argv[])
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001029{
AKASHI Takahiro016bfcd2019-04-26 09:44:18 +09001030 u16 *var_name16, *p;
1031 efi_uintn_t buf_size, size;
1032 efi_guid_t guid;
1033 int id, i, digit;
1034 efi_status_t ret;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001035
1036 if (argc > 1)
1037 return CMD_RET_USAGE;
1038
AKASHI Takahiro016bfcd2019-04-26 09:44:18 +09001039 buf_size = 128;
1040 var_name16 = malloc(buf_size);
1041 if (!var_name16)
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001042 return CMD_RET_FAILURE;
1043
AKASHI Takahiro016bfcd2019-04-26 09:44:18 +09001044 var_name16[0] = 0;
1045 for (;;) {
1046 size = buf_size;
1047 ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
1048 &guid));
1049 if (ret == EFI_NOT_FOUND)
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001050 break;
AKASHI Takahiro016bfcd2019-04-26 09:44:18 +09001051 if (ret == EFI_BUFFER_TOO_SMALL) {
1052 buf_size = size;
1053 p = realloc(var_name16, buf_size);
1054 if (!p) {
1055 free(var_name16);
1056 return CMD_RET_FAILURE;
1057 }
1058 var_name16 = p;
1059 ret = EFI_CALL(efi_get_next_variable_name(&size,
1060 var_name16,
1061 &guid));
1062 }
1063 if (ret != EFI_SUCCESS) {
1064 free(var_name16);
1065 return CMD_RET_FAILURE;
1066 }
1067
1068 if (memcmp(var_name16, L"Boot", 8))
1069 continue;
1070
1071 for (id = 0, i = 0; i < 4; i++) {
1072 digit = u16_tohex(var_name16[4 + i]);
1073 if (digit < 0)
1074 break;
1075 id = (id << 4) + digit;
1076 }
1077 if (i == 4 && !var_name16[8])
Heinrich Schuchardt8d8be692020-04-29 19:20:35 +02001078 show_efi_boot_opt(var_name16);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001079 }
AKASHI Takahiro016bfcd2019-04-26 09:44:18 +09001080
1081 free(var_name16);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001082
1083 return CMD_RET_SUCCESS;
1084}
1085
1086/**
1087 * show_efi_boot_order() - show order of UEFI load options
1088 *
1089 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1090 *
1091 * Show order of UEFI load options defined by BootOrder variable.
1092 */
1093static int show_efi_boot_order(void)
1094{
Heinrich Schuchardt98fc6152020-04-29 21:15:08 +02001095 u16 *bootorder;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001096 efi_uintn_t size;
1097 int num, i;
1098 char var_name[9];
1099 u16 var_name16[9], *p16;
1100 void *data;
1101 struct efi_load_option lo;
1102 char *label, *p;
1103 size_t label_len16, label_len;
1104 efi_status_t ret;
1105
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001106 size = 0;
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +02001107 ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
Heinrich Schuchardt98fc6152020-04-29 21:15:08 +02001108 NULL, &size, NULL));
1109 if (ret != EFI_BUFFER_TOO_SMALL) {
1110 if (ret == EFI_NOT_FOUND) {
1111 printf("BootOrder not defined\n");
1112 return CMD_RET_SUCCESS;
1113 } else {
1114 return CMD_RET_FAILURE;
1115 }
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001116 }
Heinrich Schuchardt98fc6152020-04-29 21:15:08 +02001117 bootorder = malloc(size);
1118 if (!bootorder) {
1119 printf("ERROR: Out of memory\n");
1120 return CMD_RET_FAILURE;
1121 }
1122 ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
1123 NULL, &size, bootorder));
1124 if (ret != EFI_SUCCESS) {
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001125 ret = CMD_RET_FAILURE;
1126 goto out;
1127 }
1128
1129 num = size / sizeof(u16);
1130 for (i = 0; i < num; i++) {
1131 sprintf(var_name, "Boot%04X", bootorder[i]);
1132 p16 = var_name16;
1133 utf8_utf16_strncpy(&p16, var_name, 9);
1134
1135 size = 0;
Heinrich Schuchardt98fc6152020-04-29 21:15:08 +02001136 ret = EFI_CALL(efi_get_variable(var_name16,
1137 &efi_global_variable_guid, NULL,
1138 &size, NULL));
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001139 if (ret != EFI_BUFFER_TOO_SMALL) {
Heinrich Schuchardt98fc6152020-04-29 21:15:08 +02001140 printf("%2d: %s: (not defined)\n", i + 1, var_name);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001141 continue;
1142 }
1143
1144 data = malloc(size);
1145 if (!data) {
1146 ret = CMD_RET_FAILURE;
1147 goto out;
1148 }
Heinrich Schuchardt98fc6152020-04-29 21:15:08 +02001149 ret = EFI_CALL(efi_get_variable(var_name16,
1150 &efi_global_variable_guid, NULL,
1151 &size, data));
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001152 if (ret != EFI_SUCCESS) {
1153 free(data);
1154 ret = CMD_RET_FAILURE;
1155 goto out;
1156 }
1157
Heinrich Schuchardt7ca84f82020-05-31 22:46:09 +02001158 ret = efi_deserialize_load_option(&lo, data, &size);
1159 if (ret != EFI_SUCCESS) {
1160 printf("%ls: invalid load option\n", var_name16);
1161 ret = CMD_RET_FAILURE;
1162 goto out;
1163 }
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001164
1165 label_len16 = u16_strlen(lo.label);
1166 label_len = utf16_utf8_strnlen(lo.label, label_len16);
1167 label = malloc(label_len + 1);
1168 if (!label) {
1169 free(data);
1170 ret = CMD_RET_FAILURE;
1171 goto out;
1172 }
1173 p = label;
1174 utf16_utf8_strncpy(&p, lo.label, label_len16);
Heinrich Schuchardt98fc6152020-04-29 21:15:08 +02001175 printf("%2d: %s: %s\n", i + 1, var_name, label);
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001176 free(label);
1177
1178 free(data);
1179 }
1180out:
1181 free(bootorder);
1182
1183 return ret;
1184}
1185
1186/**
1187 * do_efi_boot_next() - manage UEFI BootNext variable
1188 *
1189 * @cmdtp: Command table
1190 * @flag: Command flag
1191 * @argc: Number of arguments
1192 * @argv: Argument array
1193 * Return: CMD_RET_SUCCESS on success,
1194 * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1195 *
1196 * Implement efidebug "boot next" sub-command.
1197 * Set BootNext variable.
Heinrich Schuchardtb1d65432019-07-14 14:00:41 +02001198 *
1199 * efidebug boot next <id>
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001200 */
Simon Glassed38aef2020-05-10 11:40:03 -06001201static int do_efi_boot_next(struct cmd_tbl *cmdtp, int flag,
1202 int argc, char *const argv[])
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001203{
1204 u16 bootnext;
1205 efi_uintn_t size;
1206 char *endp;
1207 efi_guid_t guid;
1208 efi_status_t ret;
Heinrich Schuchardt99a21fc2019-06-20 12:59:45 +02001209 int r = CMD_RET_SUCCESS;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001210
1211 if (argc != 2)
1212 return CMD_RET_USAGE;
1213
1214 bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
Heinrich Schuchardt90c9d042020-05-09 17:59:19 +02001215 if (*endp) {
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001216 printf("invalid value: %s\n", argv[1]);
Heinrich Schuchardt8bdd1492019-06-20 12:48:04 +02001217 r = CMD_RET_FAILURE;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001218 goto out;
1219 }
1220
1221 guid = efi_global_variable_guid;
1222 size = sizeof(u16);
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +02001223 ret = EFI_CALL(efi_set_variable(L"BootNext", &guid,
AKASHI Takahiroc1f3ebc2019-06-04 15:52:10 +09001224 EFI_VARIABLE_NON_VOLATILE |
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001225 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1226 EFI_VARIABLE_RUNTIME_ACCESS,
1227 size, &bootnext));
Heinrich Schuchardt99a21fc2019-06-20 12:59:45 +02001228 if (ret != EFI_SUCCESS) {
1229 printf("Cannot set BootNext\n");
1230 r = CMD_RET_FAILURE;
1231 }
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001232out:
Heinrich Schuchardt8bdd1492019-06-20 12:48:04 +02001233 return r;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001234}
1235
1236/**
1237 * do_efi_boot_order() - manage UEFI BootOrder variable
1238 *
1239 * @cmdtp: Command table
1240 * @flag: Command flag
1241 * @argc: Number of arguments
1242 * @argv: Argument array
1243 * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
1244 *
1245 * Implement efidebug "boot order" sub-command.
1246 * Show order of UEFI load options, or change it in BootOrder variable.
Heinrich Schuchardtb1d65432019-07-14 14:00:41 +02001247 *
1248 * efidebug boot order [<id> ...]
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001249 */
Simon Glassed38aef2020-05-10 11:40:03 -06001250static int do_efi_boot_order(struct cmd_tbl *cmdtp, int flag,
1251 int argc, char *const argv[])
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001252{
1253 u16 *bootorder = NULL;
1254 efi_uintn_t size;
1255 int id, i;
1256 char *endp;
1257 efi_guid_t guid;
1258 efi_status_t ret;
Heinrich Schuchardt99a21fc2019-06-20 12:59:45 +02001259 int r = CMD_RET_SUCCESS;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001260
1261 if (argc == 1)
1262 return show_efi_boot_order();
1263
1264 argc--;
1265 argv++;
1266
1267 size = argc * sizeof(u16);
1268 bootorder = malloc(size);
1269 if (!bootorder)
1270 return CMD_RET_FAILURE;
1271
1272 for (i = 0; i < argc; i++) {
1273 id = (int)simple_strtoul(argv[i], &endp, 16);
1274 if (*endp != '\0' || id > 0xffff) {
1275 printf("invalid value: %s\n", argv[i]);
Heinrich Schuchardt8bdd1492019-06-20 12:48:04 +02001276 r = CMD_RET_FAILURE;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001277 goto out;
1278 }
1279
1280 bootorder[i] = (u16)id;
1281 }
1282
1283 guid = efi_global_variable_guid;
Heinrich Schuchardt982c7d92020-05-02 16:08:37 +02001284 ret = EFI_CALL(efi_set_variable(L"BootOrder", &guid,
AKASHI Takahiroc1f3ebc2019-06-04 15:52:10 +09001285 EFI_VARIABLE_NON_VOLATILE |
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001286 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1287 EFI_VARIABLE_RUNTIME_ACCESS,
1288 size, bootorder));
Heinrich Schuchardt99a21fc2019-06-20 12:59:45 +02001289 if (ret != EFI_SUCCESS) {
1290 printf("Cannot set BootOrder\n");
1291 r = CMD_RET_FAILURE;
1292 }
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001293out:
1294 free(bootorder);
1295
Heinrich Schuchardt8bdd1492019-06-20 12:48:04 +02001296 return r;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001297}
1298
Simon Glassed38aef2020-05-10 11:40:03 -06001299static struct cmd_tbl cmd_efidebug_boot_sub[] = {
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001300 U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
1301 U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
1302 U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
1303 U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
1304 U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
1305 "", ""),
1306};
1307
1308/**
1309 * do_efi_boot_opt() - manage UEFI load options
1310 *
1311 * @cmdtp: Command table
1312 * @flag: Command flag
1313 * @argc: Number of arguments
1314 * @argv: Argument array
1315 * Return: CMD_RET_SUCCESS on success,
1316 * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1317 *
1318 * Implement efidebug "boot" sub-command.
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001319 */
Simon Glassed38aef2020-05-10 11:40:03 -06001320static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
1321 int argc, char *const argv[])
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001322{
Simon Glassed38aef2020-05-10 11:40:03 -06001323 struct cmd_tbl *cp;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001324
1325 if (argc < 2)
1326 return CMD_RET_USAGE;
1327
1328 argc--; argv++;
1329
1330 cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
1331 ARRAY_SIZE(cmd_efidebug_boot_sub));
1332 if (!cp)
1333 return CMD_RET_USAGE;
1334
1335 return cp->cmd(cmdtp, flag, argc, argv);
1336}
1337
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001338/**
1339 * do_efi_test_bootmgr() - run simple bootmgr for test
1340 *
1341 * @cmdtp: Command table
1342 * @flag: Command flag
1343 * @argc: Number of arguments
1344 * @argv: Argument array
1345 * Return: CMD_RET_SUCCESS on success,
1346 * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1347 *
1348 * Implement efidebug "test bootmgr" sub-command.
1349 * Run simple bootmgr for test.
1350 *
1351 * efidebug test bootmgr
1352 */
Simon Glassed38aef2020-05-10 11:40:03 -06001353static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001354 int argc, char * const argv[])
1355{
1356 efi_handle_t image;
1357 efi_uintn_t exit_data_size = 0;
1358 u16 *exit_data = NULL;
1359 efi_status_t ret;
Heinrich Schuchardte6ed8352020-08-11 18:20:50 +02001360 void *load_options = NULL;
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001361
Heinrich Schuchardta7647a72020-08-07 17:49:39 +02001362 ret = efi_bootmgr_load(&image, &load_options);
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001363 printf("efi_bootmgr_load() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1364
1365 /* We call efi_start_image() even if error for test purpose. */
1366 ret = EFI_CALL(efi_start_image(image, &exit_data_size, &exit_data));
1367 printf("efi_start_image() returned: %ld\n", ret & ~EFI_ERROR_MASK);
1368 if (ret && exit_data)
1369 efi_free_pool(exit_data);
1370
1371 efi_restore_gd();
1372
Heinrich Schuchardta7647a72020-08-07 17:49:39 +02001373 free(load_options);
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001374 return CMD_RET_SUCCESS;
1375}
1376
Simon Glassed38aef2020-05-10 11:40:03 -06001377static struct cmd_tbl cmd_efidebug_test_sub[] = {
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001378 U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
1379 "", ""),
1380};
1381
1382/**
1383 * do_efi_test() - manage UEFI load options
1384 *
1385 * @cmdtp: Command table
1386 * @flag: Command flag
1387 * @argc: Number of arguments
1388 * @argv: Argument array
1389 * Return: CMD_RET_SUCCESS on success,
1390 * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1391 *
1392 * Implement efidebug "test" sub-command.
1393 */
Simon Glassed38aef2020-05-10 11:40:03 -06001394static int do_efi_test(struct cmd_tbl *cmdtp, int flag,
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001395 int argc, char * const argv[])
1396{
Simon Glassed38aef2020-05-10 11:40:03 -06001397 struct cmd_tbl *cp;
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001398
1399 if (argc < 2)
1400 return CMD_RET_USAGE;
1401
1402 argc--; argv++;
1403
1404 cp = find_cmd_tbl(argv[0], cmd_efidebug_test_sub,
1405 ARRAY_SIZE(cmd_efidebug_test_sub));
1406 if (!cp)
1407 return CMD_RET_USAGE;
1408
1409 return cp->cmd(cmdtp, flag, argc, argv);
1410}
1411
Ilias Apalodimasf5009402020-05-17 22:25:45 +03001412/**
1413 * do_efi_query_info() - QueryVariableInfo EFI service
1414 *
1415 * @cmdtp: Command table
1416 * @flag: Command flag
1417 * @argc: Number of arguments
1418 * @argv: Argument array
1419 * Return: CMD_RET_SUCCESS on success,
1420 * CMD_RET_USAGE or CMD_RET_FAILURE on failure
1421 *
1422 * Implement efidebug "test" sub-command.
1423 */
1424
Simon Glassed38aef2020-05-10 11:40:03 -06001425static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag,
Ilias Apalodimasf5009402020-05-17 22:25:45 +03001426 int argc, char * const argv[])
1427{
1428 efi_status_t ret;
1429 u32 attr = 0;
1430 u64 max_variable_storage_size;
1431 u64 remain_variable_storage_size;
1432 u64 max_variable_size;
1433 int i;
1434
1435 for (i = 1; i < argc; i++) {
1436 if (!strcmp(argv[i], "-bs"))
1437 attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
1438 else if (!strcmp(argv[i], "-rt"))
1439 attr |= EFI_VARIABLE_RUNTIME_ACCESS;
1440 else if (!strcmp(argv[i], "-nv"))
1441 attr |= EFI_VARIABLE_NON_VOLATILE;
1442 else if (!strcmp(argv[i], "-at"))
1443 attr |=
1444 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
1445 }
1446
1447 ret = EFI_CALL(efi_query_variable_info(attr,
1448 &max_variable_storage_size,
1449 &remain_variable_storage_size,
1450 &max_variable_size));
1451 if (ret != EFI_SUCCESS) {
1452 printf("Error: Cannot query UEFI variables, r = %lu\n",
1453 ret & ~EFI_ERROR_MASK);
1454 return CMD_RET_FAILURE;
1455 }
1456
1457 printf("Max storage size %llu\n", max_variable_storage_size);
1458 printf("Remaining storage size %llu\n", remain_variable_storage_size);
1459 printf("Max variable size %llu\n", max_variable_size);
1460
1461 return CMD_RET_SUCCESS;
1462}
1463
Simon Glassed38aef2020-05-10 11:40:03 -06001464static struct cmd_tbl cmd_efidebug_sub[] = {
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001465 U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
AKASHI Takahiro38833c82020-11-17 09:28:01 +09001466#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
1467 U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule,
1468 "", ""),
1469#endif
AKASHI Takahiroe32788a2019-02-25 15:54:39 +09001470 U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
1471 "", ""),
AKASHI Takahiro185716a2019-02-25 15:54:40 +09001472 U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
1473 "", ""),
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +09001474 U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
1475 "", ""),
AKASHI Takahiro71ab1bf2019-02-25 15:54:42 +09001476 U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
1477 "", ""),
AKASHI Takahiro32979d82019-02-25 15:54:43 +09001478 U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
1479 "", ""),
Heinrich Schuchardt75844e52020-01-07 05:57:47 +01001480 U_BOOT_CMD_MKENT(tables, CONFIG_SYS_MAXARGS, 1, do_efi_show_tables,
1481 "", ""),
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001482 U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
1483 "", ""),
Ilias Apalodimasf5009402020-05-17 22:25:45 +03001484 U_BOOT_CMD_MKENT(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
1485 "", ""),
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001486};
1487
1488/**
1489 * do_efidebug() - display and configure UEFI environment
1490 *
1491 * @cmdtp: Command table
1492 * @flag: Command flag
1493 * @argc: Number of arguments
1494 * @argv: Argument array
1495 * Return: CMD_RET_SUCCESS on success,
1496 * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
1497 *
1498 * Implement efidebug command which allows us to display and
1499 * configure UEFI environment.
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001500 */
Simon Glassed38aef2020-05-10 11:40:03 -06001501static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
1502 int argc, char *const argv[])
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001503{
Simon Glassed38aef2020-05-10 11:40:03 -06001504 struct cmd_tbl *cp;
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001505 efi_status_t r;
1506
1507 if (argc < 2)
1508 return CMD_RET_USAGE;
1509
1510 argc--; argv++;
1511
1512 /* Initialize UEFI drivers */
1513 r = efi_init_obj_list();
1514 if (r != EFI_SUCCESS) {
1515 printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
1516 r & ~EFI_ERROR_MASK);
1517 return CMD_RET_FAILURE;
1518 }
1519
1520 cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
1521 ARRAY_SIZE(cmd_efidebug_sub));
1522 if (!cp)
1523 return CMD_RET_USAGE;
1524
1525 return cp->cmd(cmdtp, flag, argc, argv);
1526}
1527
1528#ifdef CONFIG_SYS_LONGHELP
1529static char efidebug_help_text[] =
1530 " - UEFI Shell-like interface to configure UEFI environment\n"
1531 "\n"
1532 "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
1533 " - set UEFI BootXXXX variable\n"
1534 " <load options> will be passed to UEFI application\n"
1535 "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
1536 " - delete UEFI BootXXXX variables\n"
1537 "efidebug boot dump\n"
1538 " - dump all UEFI BootXXXX variables\n"
1539 "efidebug boot next <bootid>\n"
1540 " - set UEFI BootNext variable\n"
1541 "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
1542 " - set/show UEFI boot order\n"
AKASHI Takahiroe32788a2019-02-25 15:54:39 +09001543 "\n"
AKASHI Takahiro38833c82020-11-17 09:28:01 +09001544#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
1545 "efidebug capsule update [-v] <capsule address>\n"
1546 " - process a capsule\n"
1547 "efidebug capsule show <capsule address>\n"
1548 " - show capsule information\n"
1549 "efidebug capsule result [<capsule result var>]\n"
1550 " - show a capsule update result\n"
1551 "\n"
1552#endif
AKASHI Takahiroe32788a2019-02-25 15:54:39 +09001553 "efidebug devices\n"
Heinrich Schuchardtc414d882020-01-07 07:48:15 +01001554 " - show UEFI devices\n"
AKASHI Takahiro185716a2019-02-25 15:54:40 +09001555 "efidebug drivers\n"
Heinrich Schuchardtc414d882020-01-07 07:48:15 +01001556 " - show UEFI drivers\n"
AKASHI Takahiro02e8ca62019-02-25 15:54:41 +09001557 "efidebug dh\n"
Heinrich Schuchardtc414d882020-01-07 07:48:15 +01001558 " - show UEFI handles\n"
AKASHI Takahiro71ab1bf2019-02-25 15:54:42 +09001559 "efidebug images\n"
AKASHI Takahiro32979d82019-02-25 15:54:43 +09001560 " - show loaded images\n"
1561 "efidebug memmap\n"
Heinrich Schuchardtc414d882020-01-07 07:48:15 +01001562 " - show UEFI memory map\n"
Heinrich Schuchardt75844e52020-01-07 05:57:47 +01001563 "efidebug tables\n"
AKASHI Takahiro36bba2c2020-04-14 11:51:48 +09001564 " - show UEFI configuration tables\n"
1565 "efidebug test bootmgr\n"
Ilias Apalodimasf5009402020-05-17 22:25:45 +03001566 " - run simple bootmgr for test\n"
1567 "efidebug query [-nv][-bs][-rt][-at]\n"
1568 " - show size of UEFI variables store\n";
AKASHI Takahiroe7c08832019-02-25 15:54:38 +09001569#endif
1570
1571U_BOOT_CMD(
1572 efidebug, 10, 0, do_efidebug,
1573 "Configure UEFI environment",
1574 efidebug_help_text
1575);