cmd: efidebug: add drivers command
[oweals/u-boot.git] / cmd / efidebug.c
1 // 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>
12 #include <environment.h>
13 #include <exports.h>
14 #include <malloc.h>
15 #include <search.h>
16 #include <linux/ctype.h>
17
18 #define BS systab.boottime
19 #define RT systab.runtime
20
21 /**
22  * efi_get_device_handle_info() - get information of UEFI device
23  *
24  * @handle:             Handle of UEFI device
25  * @dev_path_text:      Pointer to text of device path
26  * Return:              0 on success, -1 on failure
27  *
28  * Currently return a formatted text of device path.
29  */
30 static int efi_get_device_handle_info(efi_handle_t handle, u16 **dev_path_text)
31 {
32         struct efi_device_path *dp;
33         efi_status_t ret;
34
35         ret = EFI_CALL(BS->open_protocol(handle, &efi_guid_device_path,
36                                          (void **)&dp, NULL /* FIXME */, NULL,
37                                          EFI_OPEN_PROTOCOL_GET_PROTOCOL));
38         if (ret == EFI_SUCCESS) {
39                 *dev_path_text = efi_dp_str(dp);
40                 return 0;
41         } else {
42                 return -1;
43         }
44 }
45
46 #define EFI_HANDLE_WIDTH ((int)sizeof(efi_handle_t) * 2)
47
48 static const char spc[] = "                ";
49 static const char sep[] = "================";
50
51 /**
52  * do_efi_show_devices() - show UEFI devices
53  *
54  * @cmdtp:      Command table
55  * @flag:       Command flag
56  * @argc:       Number of arguments
57  * @argv:       Argument array
58  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
59  *
60  * Implement efidebug "devices" sub-command.
61  * Show all UEFI devices and their information.
62  */
63 static int do_efi_show_devices(cmd_tbl_t *cmdtp, int flag,
64                                int argc, char * const argv[])
65 {
66         efi_handle_t *handles;
67         efi_uintn_t num, i;
68         u16 *dev_path_text;
69         efi_status_t ret;
70
71         ret = EFI_CALL(BS->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
72                                                 &num, &handles));
73         if (ret != EFI_SUCCESS)
74                 return CMD_RET_FAILURE;
75
76         if (!num)
77                 return CMD_RET_SUCCESS;
78
79         printf("Device%.*s Device Path\n", EFI_HANDLE_WIDTH - 6, spc);
80         printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
81         for (i = 0; i < num; i++) {
82                 if (!efi_get_device_handle_info(handles[i], &dev_path_text)) {
83                         printf("%p %ls\n", handles[i], dev_path_text);
84                         efi_free_pool(dev_path_text);
85                 }
86         }
87
88         EFI_CALL(BS->free_pool(handles));
89
90         return CMD_RET_SUCCESS;
91 }
92
93 /**
94  * efi_get_driver_handle_info() - get information of UEFI driver
95  *
96  * @handle:             Handle of UEFI device
97  * @driver_name:        Driver name
98  * @image_path:         Pointer to text of device path
99  * Return:              0 on success, -1 on failure
100  *
101  * Currently return no useful information as all UEFI drivers are
102  * built-in..
103  */
104 static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name,
105                                       u16 **image_path)
106 {
107         struct efi_handler *handler;
108         struct efi_loaded_image *image;
109         efi_status_t ret;
110
111         /*
112          * driver name
113          * TODO: support EFI_COMPONENT_NAME2_PROTOCOL
114          */
115         *driver_name = NULL;
116
117         /* image name */
118         ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
119         if (ret != EFI_SUCCESS) {
120                 *image_path = NULL;
121                 return 0;
122         }
123
124         image = handler->protocol_interface;
125         *image_path = efi_dp_str(image->file_path);
126
127         return 0;
128 }
129
130 /**
131  * do_efi_show_drivers() - show UEFI drivers
132  *
133  * @cmdtp:      Command table
134  * @flag:       Command flag
135  * @argc:       Number of arguments
136  * @argv:       Argument array
137  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
138  *
139  * Implement efidebug "drivers" sub-command.
140  * Show all UEFI drivers and their information.
141  */
142 static int do_efi_show_drivers(cmd_tbl_t *cmdtp, int flag,
143                                int argc, char * const argv[])
144 {
145         efi_handle_t *handles;
146         efi_uintn_t num, i;
147         u16 *driver_name, *image_path_text;
148         efi_status_t ret;
149
150         ret = EFI_CALL(BS->locate_handle_buffer(
151                                 BY_PROTOCOL, &efi_guid_driver_binding_protocol,
152                                 NULL, &num, &handles));
153         if (ret != EFI_SUCCESS)
154                 return CMD_RET_FAILURE;
155
156         if (!num)
157                 return CMD_RET_SUCCESS;
158
159         printf("Driver%.*s Name                 Image Path\n",
160                EFI_HANDLE_WIDTH - 6, spc);
161         printf("%.*s ==================== ====================\n",
162                EFI_HANDLE_WIDTH, sep);
163         for (i = 0; i < num; i++) {
164                 if (!efi_get_driver_handle_info(handles[i], &driver_name,
165                                                 &image_path_text)) {
166                         if (image_path_text)
167                                 printf("%p %-20ls %ls\n", handles[i],
168                                        driver_name, image_path_text);
169                         else
170                                 printf("%p %-20ls <built-in>\n",
171                                        handles[i], driver_name);
172                         EFI_CALL(BS->free_pool(driver_name));
173                         EFI_CALL(BS->free_pool(image_path_text));
174                 }
175         }
176
177         EFI_CALL(BS->free_pool(handles));
178
179         return CMD_RET_SUCCESS;
180 }
181
182 /**
183  * do_efi_boot_add() - set UEFI load option
184  *
185  * @cmdtp:      Command table
186  * @flag:       Command flag
187  * @argc:       Number of arguments
188  * @argv:       Argument array
189  * Return:      CMD_RET_SUCCESS on success,
190  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
191  *
192  * Implement efidebug "boot add" sub-command.
193  * Create or change UEFI load option.
194  *   - boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
195  */
196 static int do_efi_boot_add(cmd_tbl_t *cmdtp, int flag,
197                            int argc, char * const argv[])
198 {
199         int id;
200         char *endp;
201         char var_name[9];
202         u16 var_name16[9], *p;
203         efi_guid_t guid;
204         size_t label_len, label_len16;
205         u16 *label;
206         struct efi_device_path *device_path = NULL, *file_path = NULL;
207         struct efi_load_option lo;
208         void *data = NULL;
209         efi_uintn_t size;
210         int ret;
211
212         if (argc < 6 || argc > 7)
213                 return CMD_RET_USAGE;
214
215         id = (int)simple_strtoul(argv[1], &endp, 16);
216         if (*endp != '\0' || id > 0xffff)
217                 return CMD_RET_FAILURE;
218
219         sprintf(var_name, "Boot%04X", id);
220         p = var_name16;
221         utf8_utf16_strncpy(&p, var_name, 9);
222
223         guid = efi_global_variable_guid;
224
225         /* attributes */
226         lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
227
228         /* label */
229         label_len = strlen(argv[2]);
230         label_len16 = utf8_utf16_strnlen(argv[2], label_len);
231         label = malloc((label_len16 + 1) * sizeof(u16));
232         if (!label)
233                 return CMD_RET_FAILURE;
234         lo.label = label; /* label will be changed below */
235         utf8_utf16_strncpy(&label, argv[2], label_len);
236
237         /* file path */
238         ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
239                                &file_path);
240         if (ret != EFI_SUCCESS) {
241                 printf("Cannot create device path for \"%s %s\"\n",
242                        argv[3], argv[4]);
243                 ret = CMD_RET_FAILURE;
244                 goto out;
245         }
246         lo.file_path = file_path;
247         lo.file_path_length = efi_dp_size(file_path)
248                                 + sizeof(struct efi_device_path); /* for END */
249
250         /* optional data */
251         lo.optional_data = (u8 *)(argc == 6 ? "" : argv[6]);
252
253         size = efi_serialize_load_option(&lo, (u8 **)&data);
254         if (!size) {
255                 ret = CMD_RET_FAILURE;
256                 goto out;
257         }
258
259         ret = EFI_CALL(RT->set_variable(var_name16, &guid,
260                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
261                                         EFI_VARIABLE_RUNTIME_ACCESS,
262                                         size, data));
263         ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
264 out:
265         free(data);
266         efi_free_pool(device_path);
267         efi_free_pool(file_path);
268         free(lo.label);
269
270         return ret;
271 }
272
273 /**
274  * do_efi_boot_rm() - delete UEFI load options
275  *
276  * @cmdtp:      Command table
277  * @flag:       Command flag
278  * @argc:       Number of arguments
279  * @argv:       Argument array
280  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
281  *
282  * Implement efidebug "boot rm" sub-command.
283  * Delete UEFI load options.
284  *   - boot rm <id> ...
285  */
286 static int do_efi_boot_rm(cmd_tbl_t *cmdtp, int flag,
287                           int argc, char * const argv[])
288 {
289         efi_guid_t guid;
290         int id, i;
291         char *endp;
292         char var_name[9];
293         u16 var_name16[9];
294         efi_status_t ret;
295
296         if (argc == 1)
297                 return CMD_RET_USAGE;
298
299         guid = efi_global_variable_guid;
300         for (i = 1; i < argc; i++, argv++) {
301                 id = (int)simple_strtoul(argv[1], &endp, 16);
302                 if (*endp != '\0' || id > 0xffff)
303                         return CMD_RET_FAILURE;
304
305                 sprintf(var_name, "Boot%04X", id);
306                 utf8_utf16_strncpy((u16 **)&var_name16, var_name, 9);
307
308                 ret = EFI_CALL(RT->set_variable(var_name16, &guid, 0, 0, NULL));
309                 if (ret) {
310                         printf("cannot remove Boot%04X", id);
311                         return CMD_RET_FAILURE;
312                 }
313         }
314
315         return CMD_RET_SUCCESS;
316 }
317
318 /**
319  * show_efi_boot_opt_data() - dump UEFI load option
320  *
321  * @id:         Load option number
322  * @data:       Value of UEFI load option variable
323  *
324  * Decode the value of UEFI load option variable and print information.
325  */
326 static void show_efi_boot_opt_data(int id, void *data)
327 {
328         struct efi_load_option lo;
329         char *label, *p;
330         size_t label_len16, label_len;
331         u16 *dp_str;
332
333         efi_deserialize_load_option(&lo, data);
334
335         label_len16 = u16_strlen(lo.label);
336         label_len = utf16_utf8_strnlen(lo.label, label_len16);
337         label = malloc(label_len + 1);
338         if (!label)
339                 return;
340         p = label;
341         utf16_utf8_strncpy(&p, lo.label, label_len16);
342
343         printf("Boot%04X:\n", id);
344         printf("\tattributes: %c%c%c (0x%08x)\n",
345                /* ACTIVE */
346                lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
347                /* FORCE RECONNECT */
348                lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
349                /* HIDDEN */
350                lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
351                lo.attributes);
352         printf("\tlabel: %s\n", label);
353
354         dp_str = efi_dp_str(lo.file_path);
355         printf("\tfile_path: %ls\n", dp_str);
356         efi_free_pool(dp_str);
357
358         printf("\tdata: %s\n", lo.optional_data);
359
360         free(label);
361 }
362
363 /**
364  * show_efi_boot_opt() - dump UEFI load option
365  *
366  * @id:         Load option number
367  *
368  * Dump information defined by UEFI load option.
369  */
370 static void show_efi_boot_opt(int id)
371 {
372         char var_name[9];
373         u16 var_name16[9], *p;
374         efi_guid_t guid;
375         void *data = NULL;
376         efi_uintn_t size;
377         int ret;
378
379         sprintf(var_name, "Boot%04X", id);
380         p = var_name16;
381         utf8_utf16_strncpy(&p, var_name, 9);
382         guid = efi_global_variable_guid;
383
384         size = 0;
385         ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
386         if (ret == (int)EFI_BUFFER_TOO_SMALL) {
387                 data = malloc(size);
388                 ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
389                                                 data));
390         }
391         if (ret == EFI_SUCCESS)
392                 show_efi_boot_opt_data(id, data);
393         else if (ret == EFI_NOT_FOUND)
394                 printf("Boot%04X: not found\n", id);
395
396         free(data);
397 }
398
399 /**
400  * show_efi_boot_dump() - dump all UEFI load options
401  *
402  * @cmdtp:      Command table
403  * @flag:       Command flag
404  * @argc:       Number of arguments
405  * @argv:       Argument array
406  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
407  *
408  * Implement efidebug "boot dump" sub-command.
409  * Dump information of all UEFI load options defined.
410  *   - boot dump
411  */
412 static int do_efi_boot_dump(cmd_tbl_t *cmdtp, int flag,
413                             int argc, char * const argv[])
414 {
415         char regex[256];
416         char * const regexlist[] = {regex};
417         char *variables = NULL, *boot, *value;
418         int len;
419         int id;
420
421         if (argc > 1)
422                 return CMD_RET_USAGE;
423
424         snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_Boot[0-9A-F]+");
425
426         /* TODO: use GetNextVariableName? */
427         len = hexport_r(&env_htab, '\n', H_MATCH_REGEX | H_MATCH_KEY,
428                         &variables, 0, 1, regexlist);
429
430         if (!len)
431                 return CMD_RET_SUCCESS;
432
433         if (len < 0)
434                 return CMD_RET_FAILURE;
435
436         boot = variables;
437         while (*boot) {
438                 value = strstr(boot, "Boot") + 4;
439                 id = (int)simple_strtoul(value, NULL, 16);
440                 show_efi_boot_opt(id);
441                 boot = strchr(boot, '\n');
442                 if (!*boot)
443                         break;
444                 boot++;
445         }
446         free(variables);
447
448         return CMD_RET_SUCCESS;
449 }
450
451 /**
452  * show_efi_boot_order() - show order of UEFI load options
453  *
454  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
455  *
456  * Show order of UEFI load options defined by BootOrder variable.
457  */
458 static int show_efi_boot_order(void)
459 {
460         efi_guid_t guid;
461         u16 *bootorder = NULL;
462         efi_uintn_t size;
463         int num, i;
464         char var_name[9];
465         u16 var_name16[9], *p16;
466         void *data;
467         struct efi_load_option lo;
468         char *label, *p;
469         size_t label_len16, label_len;
470         efi_status_t ret;
471
472         guid = efi_global_variable_guid;
473         size = 0;
474         ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL, &size,
475                                         NULL));
476         if (ret == EFI_BUFFER_TOO_SMALL) {
477                 bootorder = malloc(size);
478                 ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL,
479                                                 &size, bootorder));
480         }
481         if (ret == EFI_NOT_FOUND) {
482                 printf("BootOrder not defined\n");
483                 ret = CMD_RET_SUCCESS;
484                 goto out;
485         } else if (ret != EFI_SUCCESS) {
486                 ret = CMD_RET_FAILURE;
487                 goto out;
488         }
489
490         num = size / sizeof(u16);
491         for (i = 0; i < num; i++) {
492                 sprintf(var_name, "Boot%04X", bootorder[i]);
493                 p16 = var_name16;
494                 utf8_utf16_strncpy(&p16, var_name, 9);
495
496                 size = 0;
497                 ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
498                                                 NULL));
499                 if (ret != EFI_BUFFER_TOO_SMALL) {
500                         printf("%2d: Boot%04X: (not defined)\n",
501                                i + 1, bootorder[i]);
502                         continue;
503                 }
504
505                 data = malloc(size);
506                 if (!data) {
507                         ret = CMD_RET_FAILURE;
508                         goto out;
509                 }
510                 ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
511                                                 data));
512                 if (ret != EFI_SUCCESS) {
513                         free(data);
514                         ret = CMD_RET_FAILURE;
515                         goto out;
516                 }
517
518                 efi_deserialize_load_option(&lo, data);
519
520                 label_len16 = u16_strlen(lo.label);
521                 label_len = utf16_utf8_strnlen(lo.label, label_len16);
522                 label = malloc(label_len + 1);
523                 if (!label) {
524                         free(data);
525                         ret = CMD_RET_FAILURE;
526                         goto out;
527                 }
528                 p = label;
529                 utf16_utf8_strncpy(&p, lo.label, label_len16);
530                 printf("%2d: Boot%04X: %s\n", i + 1, bootorder[i], label);
531                 free(label);
532
533                 free(data);
534         }
535 out:
536         free(bootorder);
537
538         return ret;
539 }
540
541 /**
542  * do_efi_boot_next() - manage UEFI BootNext variable
543  *
544  * @cmdtp:      Command table
545  * @flag:       Command flag
546  * @argc:       Number of arguments
547  * @argv:       Argument array
548  * Return:      CMD_RET_SUCCESS on success,
549  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
550  *
551  * Implement efidebug "boot next" sub-command.
552  * Set BootNext variable.
553  *   - boot next <id>
554  */
555 static int do_efi_boot_next(cmd_tbl_t *cmdtp, int flag,
556                             int argc, char * const argv[])
557 {
558         u16 bootnext;
559         efi_uintn_t size;
560         char *endp;
561         efi_guid_t guid;
562         efi_status_t ret;
563
564         if (argc != 2)
565                 return CMD_RET_USAGE;
566
567         bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
568         if (*endp != '\0' || bootnext > 0xffff) {
569                 printf("invalid value: %s\n", argv[1]);
570                 ret = CMD_RET_FAILURE;
571                 goto out;
572         }
573
574         guid = efi_global_variable_guid;
575         size = sizeof(u16);
576         ret = EFI_CALL(RT->set_variable(L"BootNext", &guid,
577                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
578                                         EFI_VARIABLE_RUNTIME_ACCESS,
579                                         size, &bootnext));
580         ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
581 out:
582         return ret;
583 }
584
585 /**
586  * do_efi_boot_order() - manage UEFI BootOrder variable
587  *
588  * @cmdtp:      Command table
589  * @flag:       Command flag
590  * @argc:       Number of arguments
591  * @argv:       Argument array
592  * Return:      CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
593  *
594  * Implement efidebug "boot order" sub-command.
595  * Show order of UEFI load options, or change it in BootOrder variable.
596  *   - boot order [<id> ...]
597  */
598 static int do_efi_boot_order(cmd_tbl_t *cmdtp, int flag,
599                              int argc, char * const argv[])
600 {
601         u16 *bootorder = NULL;
602         efi_uintn_t size;
603         int id, i;
604         char *endp;
605         efi_guid_t guid;
606         efi_status_t ret;
607
608         if (argc == 1)
609                 return show_efi_boot_order();
610
611         argc--;
612         argv++;
613
614         size = argc * sizeof(u16);
615         bootorder = malloc(size);
616         if (!bootorder)
617                 return CMD_RET_FAILURE;
618
619         for (i = 0; i < argc; i++) {
620                 id = (int)simple_strtoul(argv[i], &endp, 16);
621                 if (*endp != '\0' || id > 0xffff) {
622                         printf("invalid value: %s\n", argv[i]);
623                         ret = CMD_RET_FAILURE;
624                         goto out;
625                 }
626
627                 bootorder[i] = (u16)id;
628         }
629
630         guid = efi_global_variable_guid;
631         ret = EFI_CALL(RT->set_variable(L"BootOrder", &guid,
632                                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
633                                         EFI_VARIABLE_RUNTIME_ACCESS,
634                                         size, bootorder));
635         ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
636 out:
637         free(bootorder);
638
639         return ret;
640 }
641
642 static cmd_tbl_t cmd_efidebug_boot_sub[] = {
643         U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
644         U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
645         U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
646         U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
647         U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
648                          "", ""),
649 };
650
651 /**
652  * do_efi_boot_opt() - manage UEFI load options
653  *
654  * @cmdtp:      Command table
655  * @flag:       Command flag
656  * @argc:       Number of arguments
657  * @argv:       Argument array
658  * Return:      CMD_RET_SUCCESS on success,
659  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
660  *
661  * Implement efidebug "boot" sub-command.
662  * See above for details of sub-commands.
663  */
664 static int do_efi_boot_opt(cmd_tbl_t *cmdtp, int flag,
665                            int argc, char * const argv[])
666 {
667         cmd_tbl_t *cp;
668
669         if (argc < 2)
670                 return CMD_RET_USAGE;
671
672         argc--; argv++;
673
674         cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
675                           ARRAY_SIZE(cmd_efidebug_boot_sub));
676         if (!cp)
677                 return CMD_RET_USAGE;
678
679         return cp->cmd(cmdtp, flag, argc, argv);
680 }
681
682 static cmd_tbl_t cmd_efidebug_sub[] = {
683         U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
684         U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
685                          "", ""),
686         U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
687                          "", ""),
688 };
689
690 /**
691  * do_efidebug() - display and configure UEFI environment
692  *
693  * @cmdtp:      Command table
694  * @flag:       Command flag
695  * @argc:       Number of arguments
696  * @argv:       Argument array
697  * Return:      CMD_RET_SUCCESS on success,
698  *              CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
699  *
700  * Implement efidebug command which allows us to display and
701  * configure UEFI environment.
702  * See above for details of sub-commands.
703  */
704 static int do_efidebug(cmd_tbl_t *cmdtp, int flag,
705                        int argc, char * const argv[])
706 {
707         cmd_tbl_t *cp;
708         efi_status_t r;
709
710         if (argc < 2)
711                 return CMD_RET_USAGE;
712
713         argc--; argv++;
714
715         /* Initialize UEFI drivers */
716         r = efi_init_obj_list();
717         if (r != EFI_SUCCESS) {
718                 printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
719                        r & ~EFI_ERROR_MASK);
720                 return CMD_RET_FAILURE;
721         }
722
723         cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
724                           ARRAY_SIZE(cmd_efidebug_sub));
725         if (!cp)
726                 return CMD_RET_USAGE;
727
728         return cp->cmd(cmdtp, flag, argc, argv);
729 }
730
731 #ifdef CONFIG_SYS_LONGHELP
732 static char efidebug_help_text[] =
733         "  - UEFI Shell-like interface to configure UEFI environment\n"
734         "\n"
735         "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
736         "  - set UEFI BootXXXX variable\n"
737         "    <load options> will be passed to UEFI application\n"
738         "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
739         "  - delete UEFI BootXXXX variables\n"
740         "efidebug boot dump\n"
741         "  - dump all UEFI BootXXXX variables\n"
742         "efidebug boot next <bootid>\n"
743         "  - set UEFI BootNext variable\n"
744         "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
745         "  - set/show UEFI boot order\n"
746         "\n"
747         "efidebug devices\n"
748         "  - show uefi devices\n"
749         "efidebug drivers\n"
750         "  - show uefi drivers\n";
751 #endif
752
753 U_BOOT_CMD(
754         efidebug, 10, 0, do_efidebug,
755         "Configure UEFI environment",
756         efidebug_help_text
757 );