1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
4  *
5  * made from cmd_ext2, which was:
6  *
7  * (C) Copyright 2004
8  * esd gmbh <www.esd-electronics.com>
9  * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
10  *
11  * made from cmd_reiserfs by
12  *
13  * (C) Copyright 2003 - 2004
14  * Sysgo Real-Time Solutions, AG <www.elinos.com>
15  * Pavel Bartusek <pba@sysgo.com>
16  */
17 
18 #include <common.h>
19 #include <config.h>
20 #include <command.h>
21 #include <env.h>
22 #include <part.h>
23 #include <vsprintf.h>
24 
25 enum cmd_part_info {
26 	CMD_PART_INFO_START = 0,
27 	CMD_PART_INFO_SIZE,
28 	CMD_PART_INFO_NUMBER
29 };
30 
do_part_uuid(int argc,char * const argv[])31 static int do_part_uuid(int argc, char *const argv[])
32 {
33 	int part;
34 	struct blk_desc *dev_desc;
35 	struct disk_partition info;
36 
37 	if (argc < 2)
38 		return CMD_RET_USAGE;
39 	if (argc > 3)
40 		return CMD_RET_USAGE;
41 
42 	part = blk_get_device_part_str(argv[0], argv[1], &dev_desc, &info, 0);
43 	if (part < 0)
44 		return 1;
45 
46 	if (argc > 2)
47 		env_set(argv[2], info.uuid);
48 	else
49 		printf("%s\n", info.uuid);
50 
51 	return 0;
52 }
53 
do_part_list(int argc,char * const argv[])54 static int do_part_list(int argc, char *const argv[])
55 {
56 	int ret;
57 	struct blk_desc *desc;
58 	char *var = NULL;
59 	bool bootable = false;
60 	int i;
61 
62 	if (argc < 2)
63 		return CMD_RET_USAGE;
64 
65 	if (argc > 2) {
66 		for (i = 2; i < argc ; i++) {
67 			if (argv[i][0] == '-') {
68 				if (!strcmp(argv[i], "-bootable")) {
69 					bootable = true;
70 				} else {
71 					printf("Unknown option %s\n", argv[i]);
72 					return CMD_RET_USAGE;
73 				}
74 			} else {
75 				var = argv[i];
76 				break;
77 			}
78 		}
79 
80 		/* Loops should have been exited at the last argument, which
81 		 * as it contained the variable */
82 		if (argc != i + 1)
83 			return CMD_RET_USAGE;
84 	}
85 
86 	ret = blk_get_device_by_str(argv[0], argv[1], &desc);
87 	if (ret < 0)
88 		return 1;
89 
90 	if (var != NULL) {
91 		int p;
92 		char str[512] = { '\0', };
93 		struct disk_partition info;
94 
95 		for (p = 1; p < MAX_SEARCH_PARTITIONS; p++) {
96 			char t[5];
97 			int r = part_get_info(desc, p, &info);
98 
99 			if (r != 0)
100 				continue;
101 
102 			if (bootable && !info.bootable)
103 				continue;
104 
105 			sprintf(t, "%s%x", str[0] ? " " : "", p);
106 			strcat(str, t);
107 		}
108 		env_set(var, str);
109 		return 0;
110 	}
111 
112 	part_print(desc);
113 
114 	return 0;
115 }
116 
do_part_info(int argc,char * const argv[],enum cmd_part_info param)117 static int do_part_info(int argc, char *const argv[], enum cmd_part_info param)
118 {
119 	struct blk_desc *desc;
120 	struct disk_partition info;
121 	char buf[512] = { 0 };
122 	char *endp;
123 	int part;
124 	int err;
125 	int ret;
126 
127 	if (argc < 3)
128 		return CMD_RET_USAGE;
129 	if (argc > 4)
130 		return CMD_RET_USAGE;
131 
132 	ret = blk_get_device_by_str(argv[0], argv[1], &desc);
133 	if (ret < 0)
134 		return 1;
135 
136 	part = simple_strtoul(argv[2], &endp, 0);
137 	if (*endp == '\0') {
138 		err = part_get_info(desc, part, &info);
139 		if (err)
140 			return 1;
141 	} else {
142 		part = part_get_info_by_name(desc, argv[2], &info);
143 		if (part == -1)
144 			return 1;
145 	}
146 
147 	switch (param) {
148 	case CMD_PART_INFO_START:
149 		snprintf(buf, sizeof(buf), LBAF, info.start);
150 		break;
151 	case CMD_PART_INFO_SIZE:
152 		snprintf(buf, sizeof(buf), LBAF, info.size);
153 		break;
154 	case CMD_PART_INFO_NUMBER:
155 		snprintf(buf, sizeof(buf), "0x%x", part);
156 		break;
157 	default:
158 		printf("** Unknown cmd_part_info value: %d\n", param);
159 		return 1;
160 	}
161 
162 	if (argc > 3)
163 		env_set(argv[3], buf);
164 	else
165 		printf("%s\n", buf);
166 
167 	return 0;
168 }
169 
do_part_start(int argc,char * const argv[])170 static int do_part_start(int argc, char *const argv[])
171 {
172 	return do_part_info(argc, argv, CMD_PART_INFO_START);
173 }
174 
do_part_size(int argc,char * const argv[])175 static int do_part_size(int argc, char *const argv[])
176 {
177 	return do_part_info(argc, argv, CMD_PART_INFO_SIZE);
178 }
179 
do_part_number(int argc,char * const argv[])180 static int do_part_number(int argc, char *const argv[])
181 {
182 	return do_part_info(argc, argv, CMD_PART_INFO_NUMBER);
183 }
184 
do_part_types(int argc,char * const argv[])185 static int do_part_types(int argc, char * const argv[])
186 {
187 	struct part_driver *drv = ll_entry_start(struct part_driver,
188 						 part_driver);
189 	const int n_ents = ll_entry_count(struct part_driver, part_driver);
190 	struct part_driver *entry;
191 	int i = 0;
192 
193 	puts("Supported partition tables");
194 
195 	for (entry = drv; entry != drv + n_ents; entry++) {
196 		printf("%c %s", i ? ',' : ':', entry->name);
197 		i++;
198 	}
199 	if (!i)
200 		puts(": <none>");
201 	puts("\n");
202 	return CMD_RET_SUCCESS;
203 }
204 
do_part(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])205 static int do_part(struct cmd_tbl *cmdtp, int flag, int argc,
206 		   char *const argv[])
207 {
208 	if (argc < 2)
209 		return CMD_RET_USAGE;
210 
211 	if (!strcmp(argv[1], "uuid"))
212 		return do_part_uuid(argc - 2, argv + 2);
213 	else if (!strcmp(argv[1], "list"))
214 		return do_part_list(argc - 2, argv + 2);
215 	else if (!strcmp(argv[1], "start"))
216 		return do_part_start(argc - 2, argv + 2);
217 	else if (!strcmp(argv[1], "size"))
218 		return do_part_size(argc - 2, argv + 2);
219 	else if (!strcmp(argv[1], "number"))
220 		return do_part_number(argc - 2, argv + 2);
221 	else if (!strcmp(argv[1], "types"))
222 		return do_part_types(argc - 2, argv + 2);
223 	return CMD_RET_USAGE;
224 }
225 
226 U_BOOT_CMD(
227 	part,	CONFIG_SYS_MAXARGS,	1,	do_part,
228 	"disk partition related commands",
229 	"uuid <interface> <dev>:<part>\n"
230 	"    - print partition UUID\n"
231 	"part uuid <interface> <dev>:<part> <varname>\n"
232 	"    - set environment variable to partition UUID\n"
233 	"part list <interface> <dev>\n"
234 	"    - print a device's partition table\n"
235 	"part list <interface> <dev> [flags] <varname>\n"
236 	"    - set environment variable to the list of partitions\n"
237 	"      flags can be -bootable (list only bootable partitions)\n"
238 	"part start <interface> <dev> <part> <varname>\n"
239 	"    - set environment variable to the start of the partition (in blocks)\n"
240 	"      part can be either partition number or partition name\n"
241 	"part size <interface> <dev> <part> <varname>\n"
242 	"    - set environment variable to the size of the partition (in blocks)\n"
243 	"      part can be either partition number or partition name\n"
244 	"part number <interface> <dev> <part> <varname>\n"
245 	"    - set environment variable to the partition number using the partition name\n"
246 	"      part must be specified as partition name\n"
247 	"part types\n"
248 	"    - list supported partition table types"
249 );
250