xref: /openbmc/u-boot/cmd/efidebug.c (revision 66eaf566)
159df7e7eSAKASHI Takahiro // SPDX-License-Identifier: GPL-2.0+
259df7e7eSAKASHI Takahiro /*
359df7e7eSAKASHI Takahiro  *  UEFI Shell-like command
459df7e7eSAKASHI Takahiro  *
559df7e7eSAKASHI Takahiro  *  Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
659df7e7eSAKASHI Takahiro  */
759df7e7eSAKASHI Takahiro 
859df7e7eSAKASHI Takahiro #include <charset.h>
959df7e7eSAKASHI Takahiro #include <common.h>
1059df7e7eSAKASHI Takahiro #include <command.h>
1159df7e7eSAKASHI Takahiro #include <efi_loader.h>
1259df7e7eSAKASHI Takahiro #include <environment.h>
1359df7e7eSAKASHI Takahiro #include <exports.h>
1459df7e7eSAKASHI Takahiro #include <malloc.h>
1559df7e7eSAKASHI Takahiro #include <search.h>
1659df7e7eSAKASHI Takahiro #include <linux/ctype.h>
1759df7e7eSAKASHI Takahiro 
18355cdb5aSAKASHI Takahiro #define BS systab.boottime
1959df7e7eSAKASHI Takahiro #define RT systab.runtime
2059df7e7eSAKASHI Takahiro 
2159df7e7eSAKASHI Takahiro /**
22355cdb5aSAKASHI Takahiro  * efi_get_device_handle_info() - get information of UEFI device
23355cdb5aSAKASHI Takahiro  *
24355cdb5aSAKASHI Takahiro  * @handle:		Handle of UEFI device
25355cdb5aSAKASHI Takahiro  * @dev_path_text:	Pointer to text of device path
26355cdb5aSAKASHI Takahiro  * Return:		0 on success, -1 on failure
27355cdb5aSAKASHI Takahiro  *
28355cdb5aSAKASHI Takahiro  * Currently return a formatted text of device path.
29355cdb5aSAKASHI Takahiro  */
30355cdb5aSAKASHI Takahiro static int efi_get_device_handle_info(efi_handle_t handle, u16 **dev_path_text)
31355cdb5aSAKASHI Takahiro {
32355cdb5aSAKASHI Takahiro 	struct efi_device_path *dp;
33355cdb5aSAKASHI Takahiro 	efi_status_t ret;
34355cdb5aSAKASHI Takahiro 
35355cdb5aSAKASHI Takahiro 	ret = EFI_CALL(BS->open_protocol(handle, &efi_guid_device_path,
36355cdb5aSAKASHI Takahiro 					 (void **)&dp, NULL /* FIXME */, NULL,
37355cdb5aSAKASHI Takahiro 					 EFI_OPEN_PROTOCOL_GET_PROTOCOL));
38355cdb5aSAKASHI Takahiro 	if (ret == EFI_SUCCESS) {
39355cdb5aSAKASHI Takahiro 		*dev_path_text = efi_dp_str(dp);
40355cdb5aSAKASHI Takahiro 		return 0;
41355cdb5aSAKASHI Takahiro 	} else {
42355cdb5aSAKASHI Takahiro 		return -1;
43355cdb5aSAKASHI Takahiro 	}
44355cdb5aSAKASHI Takahiro }
45355cdb5aSAKASHI Takahiro 
46355cdb5aSAKASHI Takahiro #define EFI_HANDLE_WIDTH ((int)sizeof(efi_handle_t) * 2)
47355cdb5aSAKASHI Takahiro 
48355cdb5aSAKASHI Takahiro static const char spc[] = "                ";
49355cdb5aSAKASHI Takahiro static const char sep[] = "================";
50355cdb5aSAKASHI Takahiro 
51355cdb5aSAKASHI Takahiro /**
52355cdb5aSAKASHI Takahiro  * do_efi_show_devices() - show UEFI devices
53355cdb5aSAKASHI Takahiro  *
54355cdb5aSAKASHI Takahiro  * @cmdtp:	Command table
55355cdb5aSAKASHI Takahiro  * @flag:	Command flag
56355cdb5aSAKASHI Takahiro  * @argc:	Number of arguments
57355cdb5aSAKASHI Takahiro  * @argv:	Argument array
58355cdb5aSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
59355cdb5aSAKASHI Takahiro  *
60355cdb5aSAKASHI Takahiro  * Implement efidebug "devices" sub-command.
61355cdb5aSAKASHI Takahiro  * Show all UEFI devices and their information.
62355cdb5aSAKASHI Takahiro  */
63355cdb5aSAKASHI Takahiro static int do_efi_show_devices(cmd_tbl_t *cmdtp, int flag,
64355cdb5aSAKASHI Takahiro 			       int argc, char * const argv[])
65355cdb5aSAKASHI Takahiro {
66355cdb5aSAKASHI Takahiro 	efi_handle_t *handles;
67355cdb5aSAKASHI Takahiro 	efi_uintn_t num, i;
68355cdb5aSAKASHI Takahiro 	u16 *dev_path_text;
69355cdb5aSAKASHI Takahiro 	efi_status_t ret;
70355cdb5aSAKASHI Takahiro 
71355cdb5aSAKASHI Takahiro 	ret = EFI_CALL(BS->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
72355cdb5aSAKASHI Takahiro 						&num, &handles));
73355cdb5aSAKASHI Takahiro 	if (ret != EFI_SUCCESS)
74355cdb5aSAKASHI Takahiro 		return CMD_RET_FAILURE;
75355cdb5aSAKASHI Takahiro 
76355cdb5aSAKASHI Takahiro 	if (!num)
77355cdb5aSAKASHI Takahiro 		return CMD_RET_SUCCESS;
78355cdb5aSAKASHI Takahiro 
79355cdb5aSAKASHI Takahiro 	printf("Device%.*s Device Path\n", EFI_HANDLE_WIDTH - 6, spc);
80355cdb5aSAKASHI Takahiro 	printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
81355cdb5aSAKASHI Takahiro 	for (i = 0; i < num; i++) {
82355cdb5aSAKASHI Takahiro 		if (!efi_get_device_handle_info(handles[i], &dev_path_text)) {
83355cdb5aSAKASHI Takahiro 			printf("%p %ls\n", handles[i], dev_path_text);
84355cdb5aSAKASHI Takahiro 			efi_free_pool(dev_path_text);
85355cdb5aSAKASHI Takahiro 		}
86355cdb5aSAKASHI Takahiro 	}
87355cdb5aSAKASHI Takahiro 
88355cdb5aSAKASHI Takahiro 	EFI_CALL(BS->free_pool(handles));
89355cdb5aSAKASHI Takahiro 
90355cdb5aSAKASHI Takahiro 	return CMD_RET_SUCCESS;
91355cdb5aSAKASHI Takahiro }
92355cdb5aSAKASHI Takahiro 
93355cdb5aSAKASHI Takahiro /**
94*66eaf566SAKASHI Takahiro  * efi_get_driver_handle_info() - get information of UEFI driver
95*66eaf566SAKASHI Takahiro  *
96*66eaf566SAKASHI Takahiro  * @handle:		Handle of UEFI device
97*66eaf566SAKASHI Takahiro  * @driver_name:	Driver name
98*66eaf566SAKASHI Takahiro  * @image_path:		Pointer to text of device path
99*66eaf566SAKASHI Takahiro  * Return:		0 on success, -1 on failure
100*66eaf566SAKASHI Takahiro  *
101*66eaf566SAKASHI Takahiro  * Currently return no useful information as all UEFI drivers are
102*66eaf566SAKASHI Takahiro  * built-in..
103*66eaf566SAKASHI Takahiro  */
104*66eaf566SAKASHI Takahiro static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name,
105*66eaf566SAKASHI Takahiro 				      u16 **image_path)
106*66eaf566SAKASHI Takahiro {
107*66eaf566SAKASHI Takahiro 	struct efi_handler *handler;
108*66eaf566SAKASHI Takahiro 	struct efi_loaded_image *image;
109*66eaf566SAKASHI Takahiro 	efi_status_t ret;
110*66eaf566SAKASHI Takahiro 
111*66eaf566SAKASHI Takahiro 	/*
112*66eaf566SAKASHI Takahiro 	 * driver name
113*66eaf566SAKASHI Takahiro 	 * TODO: support EFI_COMPONENT_NAME2_PROTOCOL
114*66eaf566SAKASHI Takahiro 	 */
115*66eaf566SAKASHI Takahiro 	*driver_name = NULL;
116*66eaf566SAKASHI Takahiro 
117*66eaf566SAKASHI Takahiro 	/* image name */
118*66eaf566SAKASHI Takahiro 	ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
119*66eaf566SAKASHI Takahiro 	if (ret != EFI_SUCCESS) {
120*66eaf566SAKASHI Takahiro 		*image_path = NULL;
121*66eaf566SAKASHI Takahiro 		return 0;
122*66eaf566SAKASHI Takahiro 	}
123*66eaf566SAKASHI Takahiro 
124*66eaf566SAKASHI Takahiro 	image = handler->protocol_interface;
125*66eaf566SAKASHI Takahiro 	*image_path = efi_dp_str(image->file_path);
126*66eaf566SAKASHI Takahiro 
127*66eaf566SAKASHI Takahiro 	return 0;
128*66eaf566SAKASHI Takahiro }
129*66eaf566SAKASHI Takahiro 
130*66eaf566SAKASHI Takahiro /**
131*66eaf566SAKASHI Takahiro  * do_efi_show_drivers() - show UEFI drivers
132*66eaf566SAKASHI Takahiro  *
133*66eaf566SAKASHI Takahiro  * @cmdtp:	Command table
134*66eaf566SAKASHI Takahiro  * @flag:	Command flag
135*66eaf566SAKASHI Takahiro  * @argc:	Number of arguments
136*66eaf566SAKASHI Takahiro  * @argv:	Argument array
137*66eaf566SAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
138*66eaf566SAKASHI Takahiro  *
139*66eaf566SAKASHI Takahiro  * Implement efidebug "drivers" sub-command.
140*66eaf566SAKASHI Takahiro  * Show all UEFI drivers and their information.
141*66eaf566SAKASHI Takahiro  */
142*66eaf566SAKASHI Takahiro static int do_efi_show_drivers(cmd_tbl_t *cmdtp, int flag,
143*66eaf566SAKASHI Takahiro 			       int argc, char * const argv[])
144*66eaf566SAKASHI Takahiro {
145*66eaf566SAKASHI Takahiro 	efi_handle_t *handles;
146*66eaf566SAKASHI Takahiro 	efi_uintn_t num, i;
147*66eaf566SAKASHI Takahiro 	u16 *driver_name, *image_path_text;
148*66eaf566SAKASHI Takahiro 	efi_status_t ret;
149*66eaf566SAKASHI Takahiro 
150*66eaf566SAKASHI Takahiro 	ret = EFI_CALL(BS->locate_handle_buffer(
151*66eaf566SAKASHI Takahiro 				BY_PROTOCOL, &efi_guid_driver_binding_protocol,
152*66eaf566SAKASHI Takahiro 				NULL, &num, &handles));
153*66eaf566SAKASHI Takahiro 	if (ret != EFI_SUCCESS)
154*66eaf566SAKASHI Takahiro 		return CMD_RET_FAILURE;
155*66eaf566SAKASHI Takahiro 
156*66eaf566SAKASHI Takahiro 	if (!num)
157*66eaf566SAKASHI Takahiro 		return CMD_RET_SUCCESS;
158*66eaf566SAKASHI Takahiro 
159*66eaf566SAKASHI Takahiro 	printf("Driver%.*s Name                 Image Path\n",
160*66eaf566SAKASHI Takahiro 	       EFI_HANDLE_WIDTH - 6, spc);
161*66eaf566SAKASHI Takahiro 	printf("%.*s ==================== ====================\n",
162*66eaf566SAKASHI Takahiro 	       EFI_HANDLE_WIDTH, sep);
163*66eaf566SAKASHI Takahiro 	for (i = 0; i < num; i++) {
164*66eaf566SAKASHI Takahiro 		if (!efi_get_driver_handle_info(handles[i], &driver_name,
165*66eaf566SAKASHI Takahiro 						&image_path_text)) {
166*66eaf566SAKASHI Takahiro 			if (image_path_text)
167*66eaf566SAKASHI Takahiro 				printf("%p %-20ls %ls\n", handles[i],
168*66eaf566SAKASHI Takahiro 				       driver_name, image_path_text);
169*66eaf566SAKASHI Takahiro 			else
170*66eaf566SAKASHI Takahiro 				printf("%p %-20ls <built-in>\n",
171*66eaf566SAKASHI Takahiro 				       handles[i], driver_name);
172*66eaf566SAKASHI Takahiro 			EFI_CALL(BS->free_pool(driver_name));
173*66eaf566SAKASHI Takahiro 			EFI_CALL(BS->free_pool(image_path_text));
174*66eaf566SAKASHI Takahiro 		}
175*66eaf566SAKASHI Takahiro 	}
176*66eaf566SAKASHI Takahiro 
177*66eaf566SAKASHI Takahiro 	EFI_CALL(BS->free_pool(handles));
178*66eaf566SAKASHI Takahiro 
179*66eaf566SAKASHI Takahiro 	return CMD_RET_SUCCESS;
180*66eaf566SAKASHI Takahiro }
181*66eaf566SAKASHI Takahiro 
182*66eaf566SAKASHI Takahiro /**
18359df7e7eSAKASHI Takahiro  * do_efi_boot_add() - set UEFI load option
18459df7e7eSAKASHI Takahiro  *
18559df7e7eSAKASHI Takahiro  * @cmdtp:	Command table
18659df7e7eSAKASHI Takahiro  * @flag:	Command flag
18759df7e7eSAKASHI Takahiro  * @argc:	Number of arguments
18859df7e7eSAKASHI Takahiro  * @argv:	Argument array
18959df7e7eSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success,
19059df7e7eSAKASHI Takahiro  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
19159df7e7eSAKASHI Takahiro  *
19259df7e7eSAKASHI Takahiro  * Implement efidebug "boot add" sub-command.
19359df7e7eSAKASHI Takahiro  * Create or change UEFI load option.
19459df7e7eSAKASHI Takahiro  *   - boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
19559df7e7eSAKASHI Takahiro  */
19659df7e7eSAKASHI Takahiro static int do_efi_boot_add(cmd_tbl_t *cmdtp, int flag,
19759df7e7eSAKASHI Takahiro 			   int argc, char * const argv[])
19859df7e7eSAKASHI Takahiro {
19959df7e7eSAKASHI Takahiro 	int id;
20059df7e7eSAKASHI Takahiro 	char *endp;
20159df7e7eSAKASHI Takahiro 	char var_name[9];
20259df7e7eSAKASHI Takahiro 	u16 var_name16[9], *p;
20359df7e7eSAKASHI Takahiro 	efi_guid_t guid;
20459df7e7eSAKASHI Takahiro 	size_t label_len, label_len16;
20559df7e7eSAKASHI Takahiro 	u16 *label;
20659df7e7eSAKASHI Takahiro 	struct efi_device_path *device_path = NULL, *file_path = NULL;
20759df7e7eSAKASHI Takahiro 	struct efi_load_option lo;
20859df7e7eSAKASHI Takahiro 	void *data = NULL;
20959df7e7eSAKASHI Takahiro 	efi_uintn_t size;
21059df7e7eSAKASHI Takahiro 	int ret;
21159df7e7eSAKASHI Takahiro 
21259df7e7eSAKASHI Takahiro 	if (argc < 6 || argc > 7)
21359df7e7eSAKASHI Takahiro 		return CMD_RET_USAGE;
21459df7e7eSAKASHI Takahiro 
21559df7e7eSAKASHI Takahiro 	id = (int)simple_strtoul(argv[1], &endp, 16);
21659df7e7eSAKASHI Takahiro 	if (*endp != '\0' || id > 0xffff)
21759df7e7eSAKASHI Takahiro 		return CMD_RET_FAILURE;
21859df7e7eSAKASHI Takahiro 
21959df7e7eSAKASHI Takahiro 	sprintf(var_name, "Boot%04X", id);
22059df7e7eSAKASHI Takahiro 	p = var_name16;
22159df7e7eSAKASHI Takahiro 	utf8_utf16_strncpy(&p, var_name, 9);
22259df7e7eSAKASHI Takahiro 
22359df7e7eSAKASHI Takahiro 	guid = efi_global_variable_guid;
22459df7e7eSAKASHI Takahiro 
22559df7e7eSAKASHI Takahiro 	/* attributes */
22659df7e7eSAKASHI Takahiro 	lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
22759df7e7eSAKASHI Takahiro 
22859df7e7eSAKASHI Takahiro 	/* label */
22959df7e7eSAKASHI Takahiro 	label_len = strlen(argv[2]);
23059df7e7eSAKASHI Takahiro 	label_len16 = utf8_utf16_strnlen(argv[2], label_len);
23159df7e7eSAKASHI Takahiro 	label = malloc((label_len16 + 1) * sizeof(u16));
23259df7e7eSAKASHI Takahiro 	if (!label)
23359df7e7eSAKASHI Takahiro 		return CMD_RET_FAILURE;
23459df7e7eSAKASHI Takahiro 	lo.label = label; /* label will be changed below */
23559df7e7eSAKASHI Takahiro 	utf8_utf16_strncpy(&label, argv[2], label_len);
23659df7e7eSAKASHI Takahiro 
23759df7e7eSAKASHI Takahiro 	/* file path */
23859df7e7eSAKASHI Takahiro 	ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
23959df7e7eSAKASHI Takahiro 			       &file_path);
24059df7e7eSAKASHI Takahiro 	if (ret != EFI_SUCCESS) {
24159df7e7eSAKASHI Takahiro 		printf("Cannot create device path for \"%s %s\"\n",
24259df7e7eSAKASHI Takahiro 		       argv[3], argv[4]);
24359df7e7eSAKASHI Takahiro 		ret = CMD_RET_FAILURE;
24459df7e7eSAKASHI Takahiro 		goto out;
24559df7e7eSAKASHI Takahiro 	}
24659df7e7eSAKASHI Takahiro 	lo.file_path = file_path;
24759df7e7eSAKASHI Takahiro 	lo.file_path_length = efi_dp_size(file_path)
24859df7e7eSAKASHI Takahiro 				+ sizeof(struct efi_device_path); /* for END */
24959df7e7eSAKASHI Takahiro 
25059df7e7eSAKASHI Takahiro 	/* optional data */
25159df7e7eSAKASHI Takahiro 	lo.optional_data = (u8 *)(argc == 6 ? "" : argv[6]);
25259df7e7eSAKASHI Takahiro 
25359df7e7eSAKASHI Takahiro 	size = efi_serialize_load_option(&lo, (u8 **)&data);
25459df7e7eSAKASHI Takahiro 	if (!size) {
25559df7e7eSAKASHI Takahiro 		ret = CMD_RET_FAILURE;
25659df7e7eSAKASHI Takahiro 		goto out;
25759df7e7eSAKASHI Takahiro 	}
25859df7e7eSAKASHI Takahiro 
25959df7e7eSAKASHI Takahiro 	ret = EFI_CALL(RT->set_variable(var_name16, &guid,
26059df7e7eSAKASHI Takahiro 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
26159df7e7eSAKASHI Takahiro 					EFI_VARIABLE_RUNTIME_ACCESS,
26259df7e7eSAKASHI Takahiro 					size, data));
26359df7e7eSAKASHI Takahiro 	ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
26459df7e7eSAKASHI Takahiro out:
26559df7e7eSAKASHI Takahiro 	free(data);
26659df7e7eSAKASHI Takahiro 	efi_free_pool(device_path);
26759df7e7eSAKASHI Takahiro 	efi_free_pool(file_path);
26859df7e7eSAKASHI Takahiro 	free(lo.label);
26959df7e7eSAKASHI Takahiro 
27059df7e7eSAKASHI Takahiro 	return ret;
27159df7e7eSAKASHI Takahiro }
27259df7e7eSAKASHI Takahiro 
27359df7e7eSAKASHI Takahiro /**
27459df7e7eSAKASHI Takahiro  * do_efi_boot_rm() - delete UEFI load options
27559df7e7eSAKASHI Takahiro  *
27659df7e7eSAKASHI Takahiro  * @cmdtp:	Command table
27759df7e7eSAKASHI Takahiro  * @flag:	Command flag
27859df7e7eSAKASHI Takahiro  * @argc:	Number of arguments
27959df7e7eSAKASHI Takahiro  * @argv:	Argument array
28059df7e7eSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
28159df7e7eSAKASHI Takahiro  *
28259df7e7eSAKASHI Takahiro  * Implement efidebug "boot rm" sub-command.
28359df7e7eSAKASHI Takahiro  * Delete UEFI load options.
28459df7e7eSAKASHI Takahiro  *   - boot rm <id> ...
28559df7e7eSAKASHI Takahiro  */
28659df7e7eSAKASHI Takahiro static int do_efi_boot_rm(cmd_tbl_t *cmdtp, int flag,
28759df7e7eSAKASHI Takahiro 			  int argc, char * const argv[])
28859df7e7eSAKASHI Takahiro {
28959df7e7eSAKASHI Takahiro 	efi_guid_t guid;
29059df7e7eSAKASHI Takahiro 	int id, i;
29159df7e7eSAKASHI Takahiro 	char *endp;
29259df7e7eSAKASHI Takahiro 	char var_name[9];
29359df7e7eSAKASHI Takahiro 	u16 var_name16[9];
29459df7e7eSAKASHI Takahiro 	efi_status_t ret;
29559df7e7eSAKASHI Takahiro 
29659df7e7eSAKASHI Takahiro 	if (argc == 1)
29759df7e7eSAKASHI Takahiro 		return CMD_RET_USAGE;
29859df7e7eSAKASHI Takahiro 
29959df7e7eSAKASHI Takahiro 	guid = efi_global_variable_guid;
30059df7e7eSAKASHI Takahiro 	for (i = 1; i < argc; i++, argv++) {
30159df7e7eSAKASHI Takahiro 		id = (int)simple_strtoul(argv[1], &endp, 16);
30259df7e7eSAKASHI Takahiro 		if (*endp != '\0' || id > 0xffff)
30359df7e7eSAKASHI Takahiro 			return CMD_RET_FAILURE;
30459df7e7eSAKASHI Takahiro 
30559df7e7eSAKASHI Takahiro 		sprintf(var_name, "Boot%04X", id);
30659df7e7eSAKASHI Takahiro 		utf8_utf16_strncpy((u16 **)&var_name16, var_name, 9);
30759df7e7eSAKASHI Takahiro 
30859df7e7eSAKASHI Takahiro 		ret = EFI_CALL(RT->set_variable(var_name16, &guid, 0, 0, NULL));
30959df7e7eSAKASHI Takahiro 		if (ret) {
31059df7e7eSAKASHI Takahiro 			printf("cannot remove Boot%04X", id);
31159df7e7eSAKASHI Takahiro 			return CMD_RET_FAILURE;
31259df7e7eSAKASHI Takahiro 		}
31359df7e7eSAKASHI Takahiro 	}
31459df7e7eSAKASHI Takahiro 
31559df7e7eSAKASHI Takahiro 	return CMD_RET_SUCCESS;
31659df7e7eSAKASHI Takahiro }
31759df7e7eSAKASHI Takahiro 
31859df7e7eSAKASHI Takahiro /**
31959df7e7eSAKASHI Takahiro  * show_efi_boot_opt_data() - dump UEFI load option
32059df7e7eSAKASHI Takahiro  *
32159df7e7eSAKASHI Takahiro  * @id:		Load option number
32259df7e7eSAKASHI Takahiro  * @data:	Value of UEFI load option variable
32359df7e7eSAKASHI Takahiro  *
32459df7e7eSAKASHI Takahiro  * Decode the value of UEFI load option variable and print information.
32559df7e7eSAKASHI Takahiro  */
32659df7e7eSAKASHI Takahiro static void show_efi_boot_opt_data(int id, void *data)
32759df7e7eSAKASHI Takahiro {
32859df7e7eSAKASHI Takahiro 	struct efi_load_option lo;
32959df7e7eSAKASHI Takahiro 	char *label, *p;
33059df7e7eSAKASHI Takahiro 	size_t label_len16, label_len;
33159df7e7eSAKASHI Takahiro 	u16 *dp_str;
33259df7e7eSAKASHI Takahiro 
33359df7e7eSAKASHI Takahiro 	efi_deserialize_load_option(&lo, data);
33459df7e7eSAKASHI Takahiro 
33559df7e7eSAKASHI Takahiro 	label_len16 = u16_strlen(lo.label);
33659df7e7eSAKASHI Takahiro 	label_len = utf16_utf8_strnlen(lo.label, label_len16);
33759df7e7eSAKASHI Takahiro 	label = malloc(label_len + 1);
33859df7e7eSAKASHI Takahiro 	if (!label)
33959df7e7eSAKASHI Takahiro 		return;
34059df7e7eSAKASHI Takahiro 	p = label;
34159df7e7eSAKASHI Takahiro 	utf16_utf8_strncpy(&p, lo.label, label_len16);
34259df7e7eSAKASHI Takahiro 
34359df7e7eSAKASHI Takahiro 	printf("Boot%04X:\n", id);
34459df7e7eSAKASHI Takahiro 	printf("\tattributes: %c%c%c (0x%08x)\n",
34559df7e7eSAKASHI Takahiro 	       /* ACTIVE */
34659df7e7eSAKASHI Takahiro 	       lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
34759df7e7eSAKASHI Takahiro 	       /* FORCE RECONNECT */
34859df7e7eSAKASHI Takahiro 	       lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
34959df7e7eSAKASHI Takahiro 	       /* HIDDEN */
35059df7e7eSAKASHI Takahiro 	       lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
35159df7e7eSAKASHI Takahiro 	       lo.attributes);
35259df7e7eSAKASHI Takahiro 	printf("\tlabel: %s\n", label);
35359df7e7eSAKASHI Takahiro 
35459df7e7eSAKASHI Takahiro 	dp_str = efi_dp_str(lo.file_path);
35559df7e7eSAKASHI Takahiro 	printf("\tfile_path: %ls\n", dp_str);
35659df7e7eSAKASHI Takahiro 	efi_free_pool(dp_str);
35759df7e7eSAKASHI Takahiro 
35859df7e7eSAKASHI Takahiro 	printf("\tdata: %s\n", lo.optional_data);
35959df7e7eSAKASHI Takahiro 
36059df7e7eSAKASHI Takahiro 	free(label);
36159df7e7eSAKASHI Takahiro }
36259df7e7eSAKASHI Takahiro 
36359df7e7eSAKASHI Takahiro /**
36459df7e7eSAKASHI Takahiro  * show_efi_boot_opt() - dump UEFI load option
36559df7e7eSAKASHI Takahiro  *
36659df7e7eSAKASHI Takahiro  * @id:		Load option number
36759df7e7eSAKASHI Takahiro  *
36859df7e7eSAKASHI Takahiro  * Dump information defined by UEFI load option.
36959df7e7eSAKASHI Takahiro  */
37059df7e7eSAKASHI Takahiro static void show_efi_boot_opt(int id)
37159df7e7eSAKASHI Takahiro {
37259df7e7eSAKASHI Takahiro 	char var_name[9];
37359df7e7eSAKASHI Takahiro 	u16 var_name16[9], *p;
37459df7e7eSAKASHI Takahiro 	efi_guid_t guid;
37559df7e7eSAKASHI Takahiro 	void *data = NULL;
37659df7e7eSAKASHI Takahiro 	efi_uintn_t size;
37759df7e7eSAKASHI Takahiro 	int ret;
37859df7e7eSAKASHI Takahiro 
37959df7e7eSAKASHI Takahiro 	sprintf(var_name, "Boot%04X", id);
38059df7e7eSAKASHI Takahiro 	p = var_name16;
38159df7e7eSAKASHI Takahiro 	utf8_utf16_strncpy(&p, var_name, 9);
38259df7e7eSAKASHI Takahiro 	guid = efi_global_variable_guid;
38359df7e7eSAKASHI Takahiro 
38459df7e7eSAKASHI Takahiro 	size = 0;
38559df7e7eSAKASHI Takahiro 	ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL));
38659df7e7eSAKASHI Takahiro 	if (ret == (int)EFI_BUFFER_TOO_SMALL) {
38759df7e7eSAKASHI Takahiro 		data = malloc(size);
38859df7e7eSAKASHI Takahiro 		ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
38959df7e7eSAKASHI Takahiro 						data));
39059df7e7eSAKASHI Takahiro 	}
39159df7e7eSAKASHI Takahiro 	if (ret == EFI_SUCCESS)
39259df7e7eSAKASHI Takahiro 		show_efi_boot_opt_data(id, data);
39359df7e7eSAKASHI Takahiro 	else if (ret == EFI_NOT_FOUND)
39459df7e7eSAKASHI Takahiro 		printf("Boot%04X: not found\n", id);
39559df7e7eSAKASHI Takahiro 
39659df7e7eSAKASHI Takahiro 	free(data);
39759df7e7eSAKASHI Takahiro }
39859df7e7eSAKASHI Takahiro 
39959df7e7eSAKASHI Takahiro /**
40059df7e7eSAKASHI Takahiro  * show_efi_boot_dump() - dump all UEFI load options
40159df7e7eSAKASHI Takahiro  *
40259df7e7eSAKASHI Takahiro  * @cmdtp:	Command table
40359df7e7eSAKASHI Takahiro  * @flag:	Command flag
40459df7e7eSAKASHI Takahiro  * @argc:	Number of arguments
40559df7e7eSAKASHI Takahiro  * @argv:	Argument array
40659df7e7eSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
40759df7e7eSAKASHI Takahiro  *
40859df7e7eSAKASHI Takahiro  * Implement efidebug "boot dump" sub-command.
40959df7e7eSAKASHI Takahiro  * Dump information of all UEFI load options defined.
41059df7e7eSAKASHI Takahiro  *   - boot dump
41159df7e7eSAKASHI Takahiro  */
41259df7e7eSAKASHI Takahiro static int do_efi_boot_dump(cmd_tbl_t *cmdtp, int flag,
41359df7e7eSAKASHI Takahiro 			    int argc, char * const argv[])
41459df7e7eSAKASHI Takahiro {
41559df7e7eSAKASHI Takahiro 	char regex[256];
41659df7e7eSAKASHI Takahiro 	char * const regexlist[] = {regex};
41759df7e7eSAKASHI Takahiro 	char *variables = NULL, *boot, *value;
41859df7e7eSAKASHI Takahiro 	int len;
41959df7e7eSAKASHI Takahiro 	int id;
42059df7e7eSAKASHI Takahiro 
42159df7e7eSAKASHI Takahiro 	if (argc > 1)
42259df7e7eSAKASHI Takahiro 		return CMD_RET_USAGE;
42359df7e7eSAKASHI Takahiro 
42459df7e7eSAKASHI Takahiro 	snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_Boot[0-9A-F]+");
42559df7e7eSAKASHI Takahiro 
42659df7e7eSAKASHI Takahiro 	/* TODO: use GetNextVariableName? */
42759df7e7eSAKASHI Takahiro 	len = hexport_r(&env_htab, '\n', H_MATCH_REGEX | H_MATCH_KEY,
42859df7e7eSAKASHI Takahiro 			&variables, 0, 1, regexlist);
42959df7e7eSAKASHI Takahiro 
43059df7e7eSAKASHI Takahiro 	if (!len)
43159df7e7eSAKASHI Takahiro 		return CMD_RET_SUCCESS;
43259df7e7eSAKASHI Takahiro 
43359df7e7eSAKASHI Takahiro 	if (len < 0)
43459df7e7eSAKASHI Takahiro 		return CMD_RET_FAILURE;
43559df7e7eSAKASHI Takahiro 
43659df7e7eSAKASHI Takahiro 	boot = variables;
43759df7e7eSAKASHI Takahiro 	while (*boot) {
43859df7e7eSAKASHI Takahiro 		value = strstr(boot, "Boot") + 4;
43959df7e7eSAKASHI Takahiro 		id = (int)simple_strtoul(value, NULL, 16);
44059df7e7eSAKASHI Takahiro 		show_efi_boot_opt(id);
44159df7e7eSAKASHI Takahiro 		boot = strchr(boot, '\n');
44259df7e7eSAKASHI Takahiro 		if (!*boot)
44359df7e7eSAKASHI Takahiro 			break;
44459df7e7eSAKASHI Takahiro 		boot++;
44559df7e7eSAKASHI Takahiro 	}
44659df7e7eSAKASHI Takahiro 	free(variables);
44759df7e7eSAKASHI Takahiro 
44859df7e7eSAKASHI Takahiro 	return CMD_RET_SUCCESS;
44959df7e7eSAKASHI Takahiro }
45059df7e7eSAKASHI Takahiro 
45159df7e7eSAKASHI Takahiro /**
45259df7e7eSAKASHI Takahiro  * show_efi_boot_order() - show order of UEFI load options
45359df7e7eSAKASHI Takahiro  *
45459df7e7eSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
45559df7e7eSAKASHI Takahiro  *
45659df7e7eSAKASHI Takahiro  * Show order of UEFI load options defined by BootOrder variable.
45759df7e7eSAKASHI Takahiro  */
45859df7e7eSAKASHI Takahiro static int show_efi_boot_order(void)
45959df7e7eSAKASHI Takahiro {
46059df7e7eSAKASHI Takahiro 	efi_guid_t guid;
46159df7e7eSAKASHI Takahiro 	u16 *bootorder = NULL;
46259df7e7eSAKASHI Takahiro 	efi_uintn_t size;
46359df7e7eSAKASHI Takahiro 	int num, i;
46459df7e7eSAKASHI Takahiro 	char var_name[9];
46559df7e7eSAKASHI Takahiro 	u16 var_name16[9], *p16;
46659df7e7eSAKASHI Takahiro 	void *data;
46759df7e7eSAKASHI Takahiro 	struct efi_load_option lo;
46859df7e7eSAKASHI Takahiro 	char *label, *p;
46959df7e7eSAKASHI Takahiro 	size_t label_len16, label_len;
47059df7e7eSAKASHI Takahiro 	efi_status_t ret;
47159df7e7eSAKASHI Takahiro 
47259df7e7eSAKASHI Takahiro 	guid = efi_global_variable_guid;
47359df7e7eSAKASHI Takahiro 	size = 0;
47459df7e7eSAKASHI Takahiro 	ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL, &size,
47559df7e7eSAKASHI Takahiro 					NULL));
47659df7e7eSAKASHI Takahiro 	if (ret == EFI_BUFFER_TOO_SMALL) {
47759df7e7eSAKASHI Takahiro 		bootorder = malloc(size);
47859df7e7eSAKASHI Takahiro 		ret = EFI_CALL(RT->get_variable(L"BootOrder", &guid, NULL,
47959df7e7eSAKASHI Takahiro 						&size, bootorder));
48059df7e7eSAKASHI Takahiro 	}
48159df7e7eSAKASHI Takahiro 	if (ret == EFI_NOT_FOUND) {
48259df7e7eSAKASHI Takahiro 		printf("BootOrder not defined\n");
48359df7e7eSAKASHI Takahiro 		ret = CMD_RET_SUCCESS;
48459df7e7eSAKASHI Takahiro 		goto out;
48559df7e7eSAKASHI Takahiro 	} else if (ret != EFI_SUCCESS) {
48659df7e7eSAKASHI Takahiro 		ret = CMD_RET_FAILURE;
48759df7e7eSAKASHI Takahiro 		goto out;
48859df7e7eSAKASHI Takahiro 	}
48959df7e7eSAKASHI Takahiro 
49059df7e7eSAKASHI Takahiro 	num = size / sizeof(u16);
49159df7e7eSAKASHI Takahiro 	for (i = 0; i < num; i++) {
49259df7e7eSAKASHI Takahiro 		sprintf(var_name, "Boot%04X", bootorder[i]);
49359df7e7eSAKASHI Takahiro 		p16 = var_name16;
49459df7e7eSAKASHI Takahiro 		utf8_utf16_strncpy(&p16, var_name, 9);
49559df7e7eSAKASHI Takahiro 
49659df7e7eSAKASHI Takahiro 		size = 0;
49759df7e7eSAKASHI Takahiro 		ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
49859df7e7eSAKASHI Takahiro 						NULL));
49959df7e7eSAKASHI Takahiro 		if (ret != EFI_BUFFER_TOO_SMALL) {
50059df7e7eSAKASHI Takahiro 			printf("%2d: Boot%04X: (not defined)\n",
50159df7e7eSAKASHI Takahiro 			       i + 1, bootorder[i]);
50259df7e7eSAKASHI Takahiro 			continue;
50359df7e7eSAKASHI Takahiro 		}
50459df7e7eSAKASHI Takahiro 
50559df7e7eSAKASHI Takahiro 		data = malloc(size);
50659df7e7eSAKASHI Takahiro 		if (!data) {
50759df7e7eSAKASHI Takahiro 			ret = CMD_RET_FAILURE;
50859df7e7eSAKASHI Takahiro 			goto out;
50959df7e7eSAKASHI Takahiro 		}
51059df7e7eSAKASHI Takahiro 		ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size,
51159df7e7eSAKASHI Takahiro 						data));
51259df7e7eSAKASHI Takahiro 		if (ret != EFI_SUCCESS) {
51359df7e7eSAKASHI Takahiro 			free(data);
51459df7e7eSAKASHI Takahiro 			ret = CMD_RET_FAILURE;
51559df7e7eSAKASHI Takahiro 			goto out;
51659df7e7eSAKASHI Takahiro 		}
51759df7e7eSAKASHI Takahiro 
51859df7e7eSAKASHI Takahiro 		efi_deserialize_load_option(&lo, data);
51959df7e7eSAKASHI Takahiro 
52059df7e7eSAKASHI Takahiro 		label_len16 = u16_strlen(lo.label);
52159df7e7eSAKASHI Takahiro 		label_len = utf16_utf8_strnlen(lo.label, label_len16);
52259df7e7eSAKASHI Takahiro 		label = malloc(label_len + 1);
52359df7e7eSAKASHI Takahiro 		if (!label) {
52459df7e7eSAKASHI Takahiro 			free(data);
52559df7e7eSAKASHI Takahiro 			ret = CMD_RET_FAILURE;
52659df7e7eSAKASHI Takahiro 			goto out;
52759df7e7eSAKASHI Takahiro 		}
52859df7e7eSAKASHI Takahiro 		p = label;
52959df7e7eSAKASHI Takahiro 		utf16_utf8_strncpy(&p, lo.label, label_len16);
53059df7e7eSAKASHI Takahiro 		printf("%2d: Boot%04X: %s\n", i + 1, bootorder[i], label);
53159df7e7eSAKASHI Takahiro 		free(label);
53259df7e7eSAKASHI Takahiro 
53359df7e7eSAKASHI Takahiro 		free(data);
53459df7e7eSAKASHI Takahiro 	}
53559df7e7eSAKASHI Takahiro out:
53659df7e7eSAKASHI Takahiro 	free(bootorder);
53759df7e7eSAKASHI Takahiro 
53859df7e7eSAKASHI Takahiro 	return ret;
53959df7e7eSAKASHI Takahiro }
54059df7e7eSAKASHI Takahiro 
54159df7e7eSAKASHI Takahiro /**
54259df7e7eSAKASHI Takahiro  * do_efi_boot_next() - manage UEFI BootNext variable
54359df7e7eSAKASHI Takahiro  *
54459df7e7eSAKASHI Takahiro  * @cmdtp:	Command table
54559df7e7eSAKASHI Takahiro  * @flag:	Command flag
54659df7e7eSAKASHI Takahiro  * @argc:	Number of arguments
54759df7e7eSAKASHI Takahiro  * @argv:	Argument array
54859df7e7eSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success,
54959df7e7eSAKASHI Takahiro  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
55059df7e7eSAKASHI Takahiro  *
55159df7e7eSAKASHI Takahiro  * Implement efidebug "boot next" sub-command.
55259df7e7eSAKASHI Takahiro  * Set BootNext variable.
55359df7e7eSAKASHI Takahiro  *   - boot next <id>
55459df7e7eSAKASHI Takahiro  */
55559df7e7eSAKASHI Takahiro static int do_efi_boot_next(cmd_tbl_t *cmdtp, int flag,
55659df7e7eSAKASHI Takahiro 			    int argc, char * const argv[])
55759df7e7eSAKASHI Takahiro {
55859df7e7eSAKASHI Takahiro 	u16 bootnext;
55959df7e7eSAKASHI Takahiro 	efi_uintn_t size;
56059df7e7eSAKASHI Takahiro 	char *endp;
56159df7e7eSAKASHI Takahiro 	efi_guid_t guid;
56259df7e7eSAKASHI Takahiro 	efi_status_t ret;
56359df7e7eSAKASHI Takahiro 
56459df7e7eSAKASHI Takahiro 	if (argc != 2)
56559df7e7eSAKASHI Takahiro 		return CMD_RET_USAGE;
56659df7e7eSAKASHI Takahiro 
56759df7e7eSAKASHI Takahiro 	bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
56859df7e7eSAKASHI Takahiro 	if (*endp != '\0' || bootnext > 0xffff) {
56959df7e7eSAKASHI Takahiro 		printf("invalid value: %s\n", argv[1]);
57059df7e7eSAKASHI Takahiro 		ret = CMD_RET_FAILURE;
57159df7e7eSAKASHI Takahiro 		goto out;
57259df7e7eSAKASHI Takahiro 	}
57359df7e7eSAKASHI Takahiro 
57459df7e7eSAKASHI Takahiro 	guid = efi_global_variable_guid;
57559df7e7eSAKASHI Takahiro 	size = sizeof(u16);
57659df7e7eSAKASHI Takahiro 	ret = EFI_CALL(RT->set_variable(L"BootNext", &guid,
57759df7e7eSAKASHI Takahiro 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
57859df7e7eSAKASHI Takahiro 					EFI_VARIABLE_RUNTIME_ACCESS,
57959df7e7eSAKASHI Takahiro 					size, &bootnext));
58059df7e7eSAKASHI Takahiro 	ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
58159df7e7eSAKASHI Takahiro out:
58259df7e7eSAKASHI Takahiro 	return ret;
58359df7e7eSAKASHI Takahiro }
58459df7e7eSAKASHI Takahiro 
58559df7e7eSAKASHI Takahiro /**
58659df7e7eSAKASHI Takahiro  * do_efi_boot_order() - manage UEFI BootOrder variable
58759df7e7eSAKASHI Takahiro  *
58859df7e7eSAKASHI Takahiro  * @cmdtp:	Command table
58959df7e7eSAKASHI Takahiro  * @flag:	Command flag
59059df7e7eSAKASHI Takahiro  * @argc:	Number of arguments
59159df7e7eSAKASHI Takahiro  * @argv:	Argument array
59259df7e7eSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
59359df7e7eSAKASHI Takahiro  *
59459df7e7eSAKASHI Takahiro  * Implement efidebug "boot order" sub-command.
59559df7e7eSAKASHI Takahiro  * Show order of UEFI load options, or change it in BootOrder variable.
59659df7e7eSAKASHI Takahiro  *   - boot order [<id> ...]
59759df7e7eSAKASHI Takahiro  */
59859df7e7eSAKASHI Takahiro static int do_efi_boot_order(cmd_tbl_t *cmdtp, int flag,
59959df7e7eSAKASHI Takahiro 			     int argc, char * const argv[])
60059df7e7eSAKASHI Takahiro {
60159df7e7eSAKASHI Takahiro 	u16 *bootorder = NULL;
60259df7e7eSAKASHI Takahiro 	efi_uintn_t size;
60359df7e7eSAKASHI Takahiro 	int id, i;
60459df7e7eSAKASHI Takahiro 	char *endp;
60559df7e7eSAKASHI Takahiro 	efi_guid_t guid;
60659df7e7eSAKASHI Takahiro 	efi_status_t ret;
60759df7e7eSAKASHI Takahiro 
60859df7e7eSAKASHI Takahiro 	if (argc == 1)
60959df7e7eSAKASHI Takahiro 		return show_efi_boot_order();
61059df7e7eSAKASHI Takahiro 
61159df7e7eSAKASHI Takahiro 	argc--;
61259df7e7eSAKASHI Takahiro 	argv++;
61359df7e7eSAKASHI Takahiro 
61459df7e7eSAKASHI Takahiro 	size = argc * sizeof(u16);
61559df7e7eSAKASHI Takahiro 	bootorder = malloc(size);
61659df7e7eSAKASHI Takahiro 	if (!bootorder)
61759df7e7eSAKASHI Takahiro 		return CMD_RET_FAILURE;
61859df7e7eSAKASHI Takahiro 
61959df7e7eSAKASHI Takahiro 	for (i = 0; i < argc; i++) {
62059df7e7eSAKASHI Takahiro 		id = (int)simple_strtoul(argv[i], &endp, 16);
62159df7e7eSAKASHI Takahiro 		if (*endp != '\0' || id > 0xffff) {
62259df7e7eSAKASHI Takahiro 			printf("invalid value: %s\n", argv[i]);
62359df7e7eSAKASHI Takahiro 			ret = CMD_RET_FAILURE;
62459df7e7eSAKASHI Takahiro 			goto out;
62559df7e7eSAKASHI Takahiro 		}
62659df7e7eSAKASHI Takahiro 
62759df7e7eSAKASHI Takahiro 		bootorder[i] = (u16)id;
62859df7e7eSAKASHI Takahiro 	}
62959df7e7eSAKASHI Takahiro 
63059df7e7eSAKASHI Takahiro 	guid = efi_global_variable_guid;
63159df7e7eSAKASHI Takahiro 	ret = EFI_CALL(RT->set_variable(L"BootOrder", &guid,
63259df7e7eSAKASHI Takahiro 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
63359df7e7eSAKASHI Takahiro 					EFI_VARIABLE_RUNTIME_ACCESS,
63459df7e7eSAKASHI Takahiro 					size, bootorder));
63559df7e7eSAKASHI Takahiro 	ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
63659df7e7eSAKASHI Takahiro out:
63759df7e7eSAKASHI Takahiro 	free(bootorder);
63859df7e7eSAKASHI Takahiro 
63959df7e7eSAKASHI Takahiro 	return ret;
64059df7e7eSAKASHI Takahiro }
64159df7e7eSAKASHI Takahiro 
64259df7e7eSAKASHI Takahiro static cmd_tbl_t cmd_efidebug_boot_sub[] = {
64359df7e7eSAKASHI Takahiro 	U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
64459df7e7eSAKASHI Takahiro 	U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
64559df7e7eSAKASHI Takahiro 	U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
64659df7e7eSAKASHI Takahiro 	U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
64759df7e7eSAKASHI Takahiro 	U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
64859df7e7eSAKASHI Takahiro 			 "", ""),
64959df7e7eSAKASHI Takahiro };
65059df7e7eSAKASHI Takahiro 
65159df7e7eSAKASHI Takahiro /**
65259df7e7eSAKASHI Takahiro  * do_efi_boot_opt() - manage UEFI load options
65359df7e7eSAKASHI Takahiro  *
65459df7e7eSAKASHI Takahiro  * @cmdtp:	Command table
65559df7e7eSAKASHI Takahiro  * @flag:	Command flag
65659df7e7eSAKASHI Takahiro  * @argc:	Number of arguments
65759df7e7eSAKASHI Takahiro  * @argv:	Argument array
65859df7e7eSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success,
65959df7e7eSAKASHI Takahiro  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
66059df7e7eSAKASHI Takahiro  *
66159df7e7eSAKASHI Takahiro  * Implement efidebug "boot" sub-command.
66259df7e7eSAKASHI Takahiro  * See above for details of sub-commands.
66359df7e7eSAKASHI Takahiro  */
66459df7e7eSAKASHI Takahiro static int do_efi_boot_opt(cmd_tbl_t *cmdtp, int flag,
66559df7e7eSAKASHI Takahiro 			   int argc, char * const argv[])
66659df7e7eSAKASHI Takahiro {
66759df7e7eSAKASHI Takahiro 	cmd_tbl_t *cp;
66859df7e7eSAKASHI Takahiro 
66959df7e7eSAKASHI Takahiro 	if (argc < 2)
67059df7e7eSAKASHI Takahiro 		return CMD_RET_USAGE;
67159df7e7eSAKASHI Takahiro 
67259df7e7eSAKASHI Takahiro 	argc--; argv++;
67359df7e7eSAKASHI Takahiro 
67459df7e7eSAKASHI Takahiro 	cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
67559df7e7eSAKASHI Takahiro 			  ARRAY_SIZE(cmd_efidebug_boot_sub));
67659df7e7eSAKASHI Takahiro 	if (!cp)
67759df7e7eSAKASHI Takahiro 		return CMD_RET_USAGE;
67859df7e7eSAKASHI Takahiro 
67959df7e7eSAKASHI Takahiro 	return cp->cmd(cmdtp, flag, argc, argv);
68059df7e7eSAKASHI Takahiro }
68159df7e7eSAKASHI Takahiro 
68259df7e7eSAKASHI Takahiro static cmd_tbl_t cmd_efidebug_sub[] = {
68359df7e7eSAKASHI Takahiro 	U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
684355cdb5aSAKASHI Takahiro 	U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
685355cdb5aSAKASHI Takahiro 			 "", ""),
686*66eaf566SAKASHI Takahiro 	U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
687*66eaf566SAKASHI Takahiro 			 "", ""),
68859df7e7eSAKASHI Takahiro };
68959df7e7eSAKASHI Takahiro 
69059df7e7eSAKASHI Takahiro /**
69159df7e7eSAKASHI Takahiro  * do_efidebug() - display and configure UEFI environment
69259df7e7eSAKASHI Takahiro  *
69359df7e7eSAKASHI Takahiro  * @cmdtp:	Command table
69459df7e7eSAKASHI Takahiro  * @flag:	Command flag
69559df7e7eSAKASHI Takahiro  * @argc:	Number of arguments
69659df7e7eSAKASHI Takahiro  * @argv:	Argument array
69759df7e7eSAKASHI Takahiro  * Return:	CMD_RET_SUCCESS on success,
69859df7e7eSAKASHI Takahiro  *		CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
69959df7e7eSAKASHI Takahiro  *
70059df7e7eSAKASHI Takahiro  * Implement efidebug command which allows us to display and
70159df7e7eSAKASHI Takahiro  * configure UEFI environment.
70259df7e7eSAKASHI Takahiro  * See above for details of sub-commands.
70359df7e7eSAKASHI Takahiro  */
70459df7e7eSAKASHI Takahiro static int do_efidebug(cmd_tbl_t *cmdtp, int flag,
70559df7e7eSAKASHI Takahiro 		       int argc, char * const argv[])
70659df7e7eSAKASHI Takahiro {
70759df7e7eSAKASHI Takahiro 	cmd_tbl_t *cp;
70859df7e7eSAKASHI Takahiro 	efi_status_t r;
70959df7e7eSAKASHI Takahiro 
71059df7e7eSAKASHI Takahiro 	if (argc < 2)
71159df7e7eSAKASHI Takahiro 		return CMD_RET_USAGE;
71259df7e7eSAKASHI Takahiro 
71359df7e7eSAKASHI Takahiro 	argc--; argv++;
71459df7e7eSAKASHI Takahiro 
71559df7e7eSAKASHI Takahiro 	/* Initialize UEFI drivers */
71659df7e7eSAKASHI Takahiro 	r = efi_init_obj_list();
71759df7e7eSAKASHI Takahiro 	if (r != EFI_SUCCESS) {
71859df7e7eSAKASHI Takahiro 		printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
71959df7e7eSAKASHI Takahiro 		       r & ~EFI_ERROR_MASK);
72059df7e7eSAKASHI Takahiro 		return CMD_RET_FAILURE;
72159df7e7eSAKASHI Takahiro 	}
72259df7e7eSAKASHI Takahiro 
72359df7e7eSAKASHI Takahiro 	cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
72459df7e7eSAKASHI Takahiro 			  ARRAY_SIZE(cmd_efidebug_sub));
72559df7e7eSAKASHI Takahiro 	if (!cp)
72659df7e7eSAKASHI Takahiro 		return CMD_RET_USAGE;
72759df7e7eSAKASHI Takahiro 
72859df7e7eSAKASHI Takahiro 	return cp->cmd(cmdtp, flag, argc, argv);
72959df7e7eSAKASHI Takahiro }
73059df7e7eSAKASHI Takahiro 
73159df7e7eSAKASHI Takahiro #ifdef CONFIG_SYS_LONGHELP
73259df7e7eSAKASHI Takahiro static char efidebug_help_text[] =
73359df7e7eSAKASHI Takahiro 	"  - UEFI Shell-like interface to configure UEFI environment\n"
73459df7e7eSAKASHI Takahiro 	"\n"
73559df7e7eSAKASHI Takahiro 	"efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
73659df7e7eSAKASHI Takahiro 	"  - set UEFI BootXXXX variable\n"
73759df7e7eSAKASHI Takahiro 	"    <load options> will be passed to UEFI application\n"
73859df7e7eSAKASHI Takahiro 	"efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
73959df7e7eSAKASHI Takahiro 	"  - delete UEFI BootXXXX variables\n"
74059df7e7eSAKASHI Takahiro 	"efidebug boot dump\n"
74159df7e7eSAKASHI Takahiro 	"  - dump all UEFI BootXXXX variables\n"
74259df7e7eSAKASHI Takahiro 	"efidebug boot next <bootid>\n"
74359df7e7eSAKASHI Takahiro 	"  - set UEFI BootNext variable\n"
74459df7e7eSAKASHI Takahiro 	"efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
74559df7e7eSAKASHI Takahiro 	"  - set/show UEFI boot order\n"
746355cdb5aSAKASHI Takahiro 	"\n"
747355cdb5aSAKASHI Takahiro 	"efidebug devices\n"
748*66eaf566SAKASHI Takahiro 	"  - show uefi devices\n"
749*66eaf566SAKASHI Takahiro 	"efidebug drivers\n"
750*66eaf566SAKASHI Takahiro 	"  - show uefi drivers\n";
75159df7e7eSAKASHI Takahiro #endif
75259df7e7eSAKASHI Takahiro 
75359df7e7eSAKASHI Takahiro U_BOOT_CMD(
75459df7e7eSAKASHI Takahiro 	efidebug, 10, 0, do_efidebug,
75559df7e7eSAKASHI Takahiro 	"Configure UEFI environment",
75659df7e7eSAKASHI Takahiro 	efidebug_help_text
75759df7e7eSAKASHI Takahiro );
758