xref: /rk3399_rockchip-uboot/cmd/gpt.c (revision 2e192b245ed36a63bab0ef576999a95e23f60ecd)
1*2e192b24SSimon Glass /*
2*2e192b24SSimon Glass  * cmd_gpt.c -- GPT (GUID Partition Table) handling command
3*2e192b24SSimon Glass  *
4*2e192b24SSimon Glass  * Copyright (C) 2015
5*2e192b24SSimon Glass  * Lukasz Majewski <l.majewski@majess.pl>
6*2e192b24SSimon Glass  *
7*2e192b24SSimon Glass  * Copyright (C) 2012 Samsung Electronics
8*2e192b24SSimon Glass  * author: Lukasz Majewski <l.majewski@samsung.com>
9*2e192b24SSimon Glass  * author: Piotr Wilczek <p.wilczek@samsung.com>
10*2e192b24SSimon Glass  *
11*2e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
12*2e192b24SSimon Glass  */
13*2e192b24SSimon Glass 
14*2e192b24SSimon Glass #include <common.h>
15*2e192b24SSimon Glass #include <malloc.h>
16*2e192b24SSimon Glass #include <command.h>
17*2e192b24SSimon Glass #include <part_efi.h>
18*2e192b24SSimon Glass #include <exports.h>
19*2e192b24SSimon Glass #include <linux/ctype.h>
20*2e192b24SSimon Glass #include <div64.h>
21*2e192b24SSimon Glass #include <memalign.h>
22*2e192b24SSimon Glass 
23*2e192b24SSimon Glass #ifndef CONFIG_PARTITION_UUIDS
24*2e192b24SSimon Glass #error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled
25*2e192b24SSimon Glass #endif
26*2e192b24SSimon Glass 
27*2e192b24SSimon Glass /**
28*2e192b24SSimon Glass  * extract_env(): Expand env name from string format '&{env_name}'
29*2e192b24SSimon Glass  *                and return pointer to the env (if the env is set)
30*2e192b24SSimon Glass  *
31*2e192b24SSimon Glass  * @param str - pointer to string
32*2e192b24SSimon Glass  * @param env - pointer to pointer to extracted env
33*2e192b24SSimon Glass  *
34*2e192b24SSimon Glass  * @return - zero on successful expand and env is set
35*2e192b24SSimon Glass  */
36*2e192b24SSimon Glass static int extract_env(const char *str, char **env)
37*2e192b24SSimon Glass {
38*2e192b24SSimon Glass 	int ret = -1;
39*2e192b24SSimon Glass 	char *e, *s;
40*2e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
41*2e192b24SSimon Glass 	char uuid_str[UUID_STR_LEN + 1];
42*2e192b24SSimon Glass #endif
43*2e192b24SSimon Glass 
44*2e192b24SSimon Glass 	if (!str || strlen(str) < 4)
45*2e192b24SSimon Glass 		return -1;
46*2e192b24SSimon Glass 
47*2e192b24SSimon Glass 	if (!((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}')))
48*2e192b24SSimon Glass 		return -1;
49*2e192b24SSimon Glass 
50*2e192b24SSimon Glass 	s = strdup(str);
51*2e192b24SSimon Glass 	if (s == NULL)
52*2e192b24SSimon Glass 		return -1;
53*2e192b24SSimon Glass 
54*2e192b24SSimon Glass 	memset(s + strlen(s) - 1, '\0', 1);
55*2e192b24SSimon Glass 	memmove(s, s + 2, strlen(s) - 1);
56*2e192b24SSimon Glass 
57*2e192b24SSimon Glass 	e = getenv(s);
58*2e192b24SSimon Glass 	if (e == NULL) {
59*2e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
60*2e192b24SSimon Glass 		debug("%s unset. ", str);
61*2e192b24SSimon Glass 		gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_STD);
62*2e192b24SSimon Glass 		setenv(s, uuid_str);
63*2e192b24SSimon Glass 
64*2e192b24SSimon Glass 		e = getenv(s);
65*2e192b24SSimon Glass 		if (e) {
66*2e192b24SSimon Glass 			debug("Set to random.\n");
67*2e192b24SSimon Glass 			ret = 0;
68*2e192b24SSimon Glass 		} else {
69*2e192b24SSimon Glass 			debug("Can't get random UUID.\n");
70*2e192b24SSimon Glass 		}
71*2e192b24SSimon Glass #else
72*2e192b24SSimon Glass 		debug("%s unset.\n", str);
73*2e192b24SSimon Glass #endif
74*2e192b24SSimon Glass 	} else {
75*2e192b24SSimon Glass 		debug("%s get from environment.\n", str);
76*2e192b24SSimon Glass 		ret = 0;
77*2e192b24SSimon Glass 	}
78*2e192b24SSimon Glass 
79*2e192b24SSimon Glass 	*env = e;
80*2e192b24SSimon Glass 	free(s);
81*2e192b24SSimon Glass 
82*2e192b24SSimon Glass 	return ret;
83*2e192b24SSimon Glass }
84*2e192b24SSimon Glass 
85*2e192b24SSimon Glass /**
86*2e192b24SSimon Glass  * extract_val(): Extract value from a key=value pair list (comma separated).
87*2e192b24SSimon Glass  *                Only value for the given key is returend.
88*2e192b24SSimon Glass  *                Function allocates memory for the value, remember to free!
89*2e192b24SSimon Glass  *
90*2e192b24SSimon Glass  * @param str - pointer to string with key=values pairs
91*2e192b24SSimon Glass  * @param key - pointer to the key to search for
92*2e192b24SSimon Glass  *
93*2e192b24SSimon Glass  * @return - pointer to allocated string with the value
94*2e192b24SSimon Glass  */
95*2e192b24SSimon Glass static char *extract_val(const char *str, const char *key)
96*2e192b24SSimon Glass {
97*2e192b24SSimon Glass 	char *v, *k;
98*2e192b24SSimon Glass 	char *s, *strcopy;
99*2e192b24SSimon Glass 	char *new = NULL;
100*2e192b24SSimon Glass 
101*2e192b24SSimon Glass 	strcopy = strdup(str);
102*2e192b24SSimon Glass 	if (strcopy == NULL)
103*2e192b24SSimon Glass 		return NULL;
104*2e192b24SSimon Glass 
105*2e192b24SSimon Glass 	s = strcopy;
106*2e192b24SSimon Glass 	while (s) {
107*2e192b24SSimon Glass 		v = strsep(&s, ",");
108*2e192b24SSimon Glass 		if (!v)
109*2e192b24SSimon Glass 			break;
110*2e192b24SSimon Glass 		k = strsep(&v, "=");
111*2e192b24SSimon Glass 		if (!k)
112*2e192b24SSimon Glass 			break;
113*2e192b24SSimon Glass 		if  (strcmp(k, key) == 0) {
114*2e192b24SSimon Glass 			new = strdup(v);
115*2e192b24SSimon Glass 			break;
116*2e192b24SSimon Glass 		}
117*2e192b24SSimon Glass 	}
118*2e192b24SSimon Glass 
119*2e192b24SSimon Glass 	free(strcopy);
120*2e192b24SSimon Glass 
121*2e192b24SSimon Glass 	return new;
122*2e192b24SSimon Glass }
123*2e192b24SSimon Glass 
124*2e192b24SSimon Glass /**
125*2e192b24SSimon Glass  * found_key(): Found key without value in parameter list (comma separated).
126*2e192b24SSimon Glass  *
127*2e192b24SSimon Glass  * @param str - pointer to string with key
128*2e192b24SSimon Glass  * @param key - pointer to the key to search for
129*2e192b24SSimon Glass  *
130*2e192b24SSimon Glass  * @return - true on found key
131*2e192b24SSimon Glass  */
132*2e192b24SSimon Glass static bool found_key(const char *str, const char *key)
133*2e192b24SSimon Glass {
134*2e192b24SSimon Glass 	char *k;
135*2e192b24SSimon Glass 	char *s, *strcopy;
136*2e192b24SSimon Glass 	bool result = false;
137*2e192b24SSimon Glass 
138*2e192b24SSimon Glass 	strcopy = strdup(str);
139*2e192b24SSimon Glass 	if (!strcopy)
140*2e192b24SSimon Glass 		return NULL;
141*2e192b24SSimon Glass 
142*2e192b24SSimon Glass 	s = strcopy;
143*2e192b24SSimon Glass 	while (s) {
144*2e192b24SSimon Glass 		k = strsep(&s, ",");
145*2e192b24SSimon Glass 		if (!k)
146*2e192b24SSimon Glass 			break;
147*2e192b24SSimon Glass 		if  (strcmp(k, key) == 0) {
148*2e192b24SSimon Glass 			result = true;
149*2e192b24SSimon Glass 			break;
150*2e192b24SSimon Glass 		}
151*2e192b24SSimon Glass 	}
152*2e192b24SSimon Glass 
153*2e192b24SSimon Glass 	free(strcopy);
154*2e192b24SSimon Glass 
155*2e192b24SSimon Glass 	return result;
156*2e192b24SSimon Glass }
157*2e192b24SSimon Glass 
158*2e192b24SSimon Glass /**
159*2e192b24SSimon Glass  * set_gpt_info(): Fill partition information from string
160*2e192b24SSimon Glass  *		function allocates memory, remember to free!
161*2e192b24SSimon Glass  *
162*2e192b24SSimon Glass  * @param dev_desc - pointer block device descriptor
163*2e192b24SSimon Glass  * @param str_part - pointer to string with partition information
164*2e192b24SSimon Glass  * @param str_disk_guid - pointer to pointer to allocated string with disk guid
165*2e192b24SSimon Glass  * @param partitions - pointer to pointer to allocated partitions array
166*2e192b24SSimon Glass  * @param parts_count - number of partitions
167*2e192b24SSimon Glass  *
168*2e192b24SSimon Glass  * @return - zero on success, otherwise error
169*2e192b24SSimon Glass  *
170*2e192b24SSimon Glass  */
171*2e192b24SSimon Glass static int set_gpt_info(block_dev_desc_t *dev_desc,
172*2e192b24SSimon Glass 			const char *str_part,
173*2e192b24SSimon Glass 			char **str_disk_guid,
174*2e192b24SSimon Glass 			disk_partition_t **partitions,
175*2e192b24SSimon Glass 			u8 *parts_count)
176*2e192b24SSimon Glass {
177*2e192b24SSimon Glass 	char *tok, *str, *s;
178*2e192b24SSimon Glass 	int i;
179*2e192b24SSimon Glass 	char *val, *p;
180*2e192b24SSimon Glass 	int p_count;
181*2e192b24SSimon Glass 	disk_partition_t *parts;
182*2e192b24SSimon Glass 	int errno = 0;
183*2e192b24SSimon Glass 	uint64_t size_ll, start_ll;
184*2e192b24SSimon Glass 
185*2e192b24SSimon Glass 	debug("%s:  lba num: 0x%x %d\n", __func__,
186*2e192b24SSimon Glass 	      (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba);
187*2e192b24SSimon Glass 
188*2e192b24SSimon Glass 	if (str_part == NULL)
189*2e192b24SSimon Glass 		return -1;
190*2e192b24SSimon Glass 
191*2e192b24SSimon Glass 	str = strdup(str_part);
192*2e192b24SSimon Glass 
193*2e192b24SSimon Glass 	/* extract disk guid */
194*2e192b24SSimon Glass 	s = str;
195*2e192b24SSimon Glass 	val = extract_val(str, "uuid_disk");
196*2e192b24SSimon Glass 	if (!val) {
197*2e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
198*2e192b24SSimon Glass 		*str_disk_guid = malloc(UUID_STR_LEN + 1);
199*2e192b24SSimon Glass 		gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD);
200*2e192b24SSimon Glass #else
201*2e192b24SSimon Glass 		free(str);
202*2e192b24SSimon Glass 		return -2;
203*2e192b24SSimon Glass #endif
204*2e192b24SSimon Glass 	} else {
205*2e192b24SSimon Glass 		val = strsep(&val, ";");
206*2e192b24SSimon Glass 		if (extract_env(val, &p))
207*2e192b24SSimon Glass 			p = val;
208*2e192b24SSimon Glass 		*str_disk_guid = strdup(p);
209*2e192b24SSimon Glass 		free(val);
210*2e192b24SSimon Glass 		/* Move s to first partition */
211*2e192b24SSimon Glass 		strsep(&s, ";");
212*2e192b24SSimon Glass 	}
213*2e192b24SSimon Glass 	if (strlen(s) == 0)
214*2e192b24SSimon Glass 		return -3;
215*2e192b24SSimon Glass 
216*2e192b24SSimon Glass 	i = strlen(s) - 1;
217*2e192b24SSimon Glass 	if (s[i] == ';')
218*2e192b24SSimon Glass 		s[i] = '\0';
219*2e192b24SSimon Glass 
220*2e192b24SSimon Glass 	/* calculate expected number of partitions */
221*2e192b24SSimon Glass 	p_count = 1;
222*2e192b24SSimon Glass 	p = s;
223*2e192b24SSimon Glass 	while (*p) {
224*2e192b24SSimon Glass 		if (*p++ == ';')
225*2e192b24SSimon Glass 			p_count++;
226*2e192b24SSimon Glass 	}
227*2e192b24SSimon Glass 
228*2e192b24SSimon Glass 	/* allocate memory for partitions */
229*2e192b24SSimon Glass 	parts = calloc(sizeof(disk_partition_t), p_count);
230*2e192b24SSimon Glass 
231*2e192b24SSimon Glass 	/* retrieve partitions data from string */
232*2e192b24SSimon Glass 	for (i = 0; i < p_count; i++) {
233*2e192b24SSimon Glass 		tok = strsep(&s, ";");
234*2e192b24SSimon Glass 
235*2e192b24SSimon Glass 		if (tok == NULL)
236*2e192b24SSimon Glass 			break;
237*2e192b24SSimon Glass 
238*2e192b24SSimon Glass 		/* uuid */
239*2e192b24SSimon Glass 		val = extract_val(tok, "uuid");
240*2e192b24SSimon Glass 		if (!val) {
241*2e192b24SSimon Glass 			/* 'uuid' is optional if random uuid's are enabled */
242*2e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
243*2e192b24SSimon Glass 			gen_rand_uuid_str(parts[i].uuid, UUID_STR_FORMAT_STD);
244*2e192b24SSimon Glass #else
245*2e192b24SSimon Glass 			errno = -4;
246*2e192b24SSimon Glass 			goto err;
247*2e192b24SSimon Glass #endif
248*2e192b24SSimon Glass 		} else {
249*2e192b24SSimon Glass 			if (extract_env(val, &p))
250*2e192b24SSimon Glass 				p = val;
251*2e192b24SSimon Glass 			if (strlen(p) >= sizeof(parts[i].uuid)) {
252*2e192b24SSimon Glass 				printf("Wrong uuid format for partition %d\n", i);
253*2e192b24SSimon Glass 				errno = -4;
254*2e192b24SSimon Glass 				goto err;
255*2e192b24SSimon Glass 			}
256*2e192b24SSimon Glass 			strcpy((char *)parts[i].uuid, p);
257*2e192b24SSimon Glass 			free(val);
258*2e192b24SSimon Glass 		}
259*2e192b24SSimon Glass #ifdef CONFIG_PARTITION_TYPE_GUID
260*2e192b24SSimon Glass 		/* guid */
261*2e192b24SSimon Glass 		val = extract_val(tok, "type");
262*2e192b24SSimon Glass 		if (val) {
263*2e192b24SSimon Glass 			/* 'type' is optional */
264*2e192b24SSimon Glass 			if (extract_env(val, &p))
265*2e192b24SSimon Glass 				p = val;
266*2e192b24SSimon Glass 			if (strlen(p) >= sizeof(parts[i].type_guid)) {
267*2e192b24SSimon Glass 				printf("Wrong type guid format for partition %d\n",
268*2e192b24SSimon Glass 				       i);
269*2e192b24SSimon Glass 				errno = -4;
270*2e192b24SSimon Glass 				goto err;
271*2e192b24SSimon Glass 			}
272*2e192b24SSimon Glass 			strcpy((char *)parts[i].type_guid, p);
273*2e192b24SSimon Glass 			free(val);
274*2e192b24SSimon Glass 		}
275*2e192b24SSimon Glass #endif
276*2e192b24SSimon Glass 		/* name */
277*2e192b24SSimon Glass 		val = extract_val(tok, "name");
278*2e192b24SSimon Glass 		if (!val) { /* name is mandatory */
279*2e192b24SSimon Glass 			errno = -4;
280*2e192b24SSimon Glass 			goto err;
281*2e192b24SSimon Glass 		}
282*2e192b24SSimon Glass 		if (extract_env(val, &p))
283*2e192b24SSimon Glass 			p = val;
284*2e192b24SSimon Glass 		if (strlen(p) >= sizeof(parts[i].name)) {
285*2e192b24SSimon Glass 			errno = -4;
286*2e192b24SSimon Glass 			goto err;
287*2e192b24SSimon Glass 		}
288*2e192b24SSimon Glass 		strcpy((char *)parts[i].name, p);
289*2e192b24SSimon Glass 		free(val);
290*2e192b24SSimon Glass 
291*2e192b24SSimon Glass 		/* size */
292*2e192b24SSimon Glass 		val = extract_val(tok, "size");
293*2e192b24SSimon Glass 		if (!val) { /* 'size' is mandatory */
294*2e192b24SSimon Glass 			errno = -4;
295*2e192b24SSimon Glass 			goto err;
296*2e192b24SSimon Glass 		}
297*2e192b24SSimon Glass 		if (extract_env(val, &p))
298*2e192b24SSimon Glass 			p = val;
299*2e192b24SSimon Glass 		size_ll = ustrtoull(p, &p, 0);
300*2e192b24SSimon Glass 		parts[i].size = lldiv(size_ll, dev_desc->blksz);
301*2e192b24SSimon Glass 		free(val);
302*2e192b24SSimon Glass 
303*2e192b24SSimon Glass 		/* start address */
304*2e192b24SSimon Glass 		val = extract_val(tok, "start");
305*2e192b24SSimon Glass 		if (val) { /* start address is optional */
306*2e192b24SSimon Glass 			if (extract_env(val, &p))
307*2e192b24SSimon Glass 				p = val;
308*2e192b24SSimon Glass 			start_ll = ustrtoull(p, &p, 0);
309*2e192b24SSimon Glass 			parts[i].start = lldiv(start_ll, dev_desc->blksz);
310*2e192b24SSimon Glass 			free(val);
311*2e192b24SSimon Glass 		}
312*2e192b24SSimon Glass 
313*2e192b24SSimon Glass 		/* bootable */
314*2e192b24SSimon Glass 		if (found_key(tok, "bootable"))
315*2e192b24SSimon Glass 			parts[i].bootable = 1;
316*2e192b24SSimon Glass 	}
317*2e192b24SSimon Glass 
318*2e192b24SSimon Glass 	*parts_count = p_count;
319*2e192b24SSimon Glass 	*partitions = parts;
320*2e192b24SSimon Glass 	free(str);
321*2e192b24SSimon Glass 
322*2e192b24SSimon Glass 	return 0;
323*2e192b24SSimon Glass err:
324*2e192b24SSimon Glass 	free(str);
325*2e192b24SSimon Glass 	free(*str_disk_guid);
326*2e192b24SSimon Glass 	free(parts);
327*2e192b24SSimon Glass 
328*2e192b24SSimon Glass 	return errno;
329*2e192b24SSimon Glass }
330*2e192b24SSimon Glass 
331*2e192b24SSimon Glass static int gpt_default(block_dev_desc_t *blk_dev_desc, const char *str_part)
332*2e192b24SSimon Glass {
333*2e192b24SSimon Glass 	int ret;
334*2e192b24SSimon Glass 	char *str_disk_guid;
335*2e192b24SSimon Glass 	u8 part_count = 0;
336*2e192b24SSimon Glass 	disk_partition_t *partitions = NULL;
337*2e192b24SSimon Glass 
338*2e192b24SSimon Glass 	/* fill partitions */
339*2e192b24SSimon Glass 	ret = set_gpt_info(blk_dev_desc, str_part,
340*2e192b24SSimon Glass 			&str_disk_guid, &partitions, &part_count);
341*2e192b24SSimon Glass 	if (ret) {
342*2e192b24SSimon Glass 		if (ret == -1)
343*2e192b24SSimon Glass 			printf("No partition list provided\n");
344*2e192b24SSimon Glass 		if (ret == -2)
345*2e192b24SSimon Glass 			printf("Missing disk guid\n");
346*2e192b24SSimon Glass 		if ((ret == -3) || (ret == -4))
347*2e192b24SSimon Glass 			printf("Partition list incomplete\n");
348*2e192b24SSimon Glass 		return -1;
349*2e192b24SSimon Glass 	}
350*2e192b24SSimon Glass 
351*2e192b24SSimon Glass 	/* save partitions layout to disk */
352*2e192b24SSimon Glass 	ret = gpt_restore(blk_dev_desc, str_disk_guid, partitions, part_count);
353*2e192b24SSimon Glass 	free(str_disk_guid);
354*2e192b24SSimon Glass 	free(partitions);
355*2e192b24SSimon Glass 
356*2e192b24SSimon Glass 	return ret;
357*2e192b24SSimon Glass }
358*2e192b24SSimon Glass 
359*2e192b24SSimon Glass static int gpt_verify(block_dev_desc_t *blk_dev_desc, const char *str_part)
360*2e192b24SSimon Glass {
361*2e192b24SSimon Glass 	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1,
362*2e192b24SSimon Glass 				     blk_dev_desc->blksz);
363*2e192b24SSimon Glass 	disk_partition_t *partitions = NULL;
364*2e192b24SSimon Glass 	gpt_entry *gpt_pte = NULL;
365*2e192b24SSimon Glass 	char *str_disk_guid;
366*2e192b24SSimon Glass 	u8 part_count = 0;
367*2e192b24SSimon Glass 	int ret = 0;
368*2e192b24SSimon Glass 
369*2e192b24SSimon Glass 	/* fill partitions */
370*2e192b24SSimon Glass 	ret = set_gpt_info(blk_dev_desc, str_part,
371*2e192b24SSimon Glass 			&str_disk_guid, &partitions, &part_count);
372*2e192b24SSimon Glass 	if (ret) {
373*2e192b24SSimon Glass 		if (ret == -1) {
374*2e192b24SSimon Glass 			printf("No partition list provided - only basic check\n");
375*2e192b24SSimon Glass 			ret = gpt_verify_headers(blk_dev_desc, gpt_head,
376*2e192b24SSimon Glass 						 &gpt_pte);
377*2e192b24SSimon Glass 			goto out;
378*2e192b24SSimon Glass 		}
379*2e192b24SSimon Glass 		if (ret == -2)
380*2e192b24SSimon Glass 			printf("Missing disk guid\n");
381*2e192b24SSimon Glass 		if ((ret == -3) || (ret == -4))
382*2e192b24SSimon Glass 			printf("Partition list incomplete\n");
383*2e192b24SSimon Glass 		return -1;
384*2e192b24SSimon Glass 	}
385*2e192b24SSimon Glass 
386*2e192b24SSimon Glass 	/* Check partition layout with provided pattern */
387*2e192b24SSimon Glass 	ret = gpt_verify_partitions(blk_dev_desc, partitions, part_count,
388*2e192b24SSimon Glass 				    gpt_head, &gpt_pte);
389*2e192b24SSimon Glass 	free(str_disk_guid);
390*2e192b24SSimon Glass 	free(partitions);
391*2e192b24SSimon Glass  out:
392*2e192b24SSimon Glass 	free(gpt_pte);
393*2e192b24SSimon Glass 	return ret;
394*2e192b24SSimon Glass }
395*2e192b24SSimon Glass 
396*2e192b24SSimon Glass /**
397*2e192b24SSimon Glass  * do_gpt(): Perform GPT operations
398*2e192b24SSimon Glass  *
399*2e192b24SSimon Glass  * @param cmdtp - command name
400*2e192b24SSimon Glass  * @param flag
401*2e192b24SSimon Glass  * @param argc
402*2e192b24SSimon Glass  * @param argv
403*2e192b24SSimon Glass  *
404*2e192b24SSimon Glass  * @return zero on success; otherwise error
405*2e192b24SSimon Glass  */
406*2e192b24SSimon Glass static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
407*2e192b24SSimon Glass {
408*2e192b24SSimon Glass 	int ret = CMD_RET_SUCCESS;
409*2e192b24SSimon Glass 	int dev = 0;
410*2e192b24SSimon Glass 	char *ep;
411*2e192b24SSimon Glass 	block_dev_desc_t *blk_dev_desc = NULL;
412*2e192b24SSimon Glass 
413*2e192b24SSimon Glass 	if (argc < 4 || argc > 5)
414*2e192b24SSimon Glass 		return CMD_RET_USAGE;
415*2e192b24SSimon Glass 
416*2e192b24SSimon Glass 	dev = (int)simple_strtoul(argv[3], &ep, 10);
417*2e192b24SSimon Glass 	if (!ep || ep[0] != '\0') {
418*2e192b24SSimon Glass 		printf("'%s' is not a number\n", argv[3]);
419*2e192b24SSimon Glass 		return CMD_RET_USAGE;
420*2e192b24SSimon Glass 	}
421*2e192b24SSimon Glass 	blk_dev_desc = get_dev(argv[2], dev);
422*2e192b24SSimon Glass 	if (!blk_dev_desc) {
423*2e192b24SSimon Glass 		printf("%s: %s dev %d NOT available\n",
424*2e192b24SSimon Glass 		       __func__, argv[2], dev);
425*2e192b24SSimon Glass 		return CMD_RET_FAILURE;
426*2e192b24SSimon Glass 	}
427*2e192b24SSimon Glass 
428*2e192b24SSimon Glass 	if ((strcmp(argv[1], "write") == 0) && (argc == 5)) {
429*2e192b24SSimon Glass 		printf("Writing GPT: ");
430*2e192b24SSimon Glass 		ret = gpt_default(blk_dev_desc, argv[4]);
431*2e192b24SSimon Glass 	} else if ((strcmp(argv[1], "verify") == 0)) {
432*2e192b24SSimon Glass 		ret = gpt_verify(blk_dev_desc, argv[4]);
433*2e192b24SSimon Glass 		printf("Verify GPT: ");
434*2e192b24SSimon Glass 	} else {
435*2e192b24SSimon Glass 		return CMD_RET_USAGE;
436*2e192b24SSimon Glass 	}
437*2e192b24SSimon Glass 
438*2e192b24SSimon Glass 	if (ret) {
439*2e192b24SSimon Glass 		printf("error!\n");
440*2e192b24SSimon Glass 		return CMD_RET_FAILURE;
441*2e192b24SSimon Glass 	}
442*2e192b24SSimon Glass 
443*2e192b24SSimon Glass 	printf("success!\n");
444*2e192b24SSimon Glass 	return CMD_RET_SUCCESS;
445*2e192b24SSimon Glass }
446*2e192b24SSimon Glass 
447*2e192b24SSimon Glass U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
448*2e192b24SSimon Glass 	"GUID Partition Table",
449*2e192b24SSimon Glass 	"<command> <interface> <dev> <partitions_list>\n"
450*2e192b24SSimon Glass 	" - GUID partition table restoration and validity check\n"
451*2e192b24SSimon Glass 	" Restore or verify GPT information on a device connected\n"
452*2e192b24SSimon Glass 	" to interface\n"
453*2e192b24SSimon Glass 	" Example usage:\n"
454*2e192b24SSimon Glass 	" gpt write mmc 0 $partitions\n"
455*2e192b24SSimon Glass 	" gpt verify mmc 0 $partitions\n"
456*2e192b24SSimon Glass );
457