xref: /rk3399_rockchip-uboot/cmd/gpt.c (revision 73d6d18b7147c90d6f8a60acb8dad663a225e63d)
12e192b24SSimon Glass /*
22e192b24SSimon Glass  * cmd_gpt.c -- GPT (GUID Partition Table) handling command
32e192b24SSimon Glass  *
42e192b24SSimon Glass  * Copyright (C) 2015
52e192b24SSimon Glass  * Lukasz Majewski <l.majewski@majess.pl>
62e192b24SSimon Glass  *
72e192b24SSimon Glass  * Copyright (C) 2012 Samsung Electronics
82e192b24SSimon Glass  * author: Lukasz Majewski <l.majewski@samsung.com>
92e192b24SSimon Glass  * author: Piotr Wilczek <p.wilczek@samsung.com>
102e192b24SSimon Glass  *
112e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
122e192b24SSimon Glass  */
132e192b24SSimon Glass 
142e192b24SSimon Glass #include <common.h>
152e192b24SSimon Glass #include <malloc.h>
162e192b24SSimon Glass #include <command.h>
172e192b24SSimon Glass #include <part_efi.h>
182e192b24SSimon Glass #include <exports.h>
192e192b24SSimon Glass #include <linux/ctype.h>
202e192b24SSimon Glass #include <div64.h>
212e192b24SSimon Glass #include <memalign.h>
222e192b24SSimon Glass 
232e192b24SSimon Glass /**
242e192b24SSimon Glass  * extract_env(): Expand env name from string format '&{env_name}'
252e192b24SSimon Glass  *                and return pointer to the env (if the env is set)
262e192b24SSimon Glass  *
272e192b24SSimon Glass  * @param str - pointer to string
282e192b24SSimon Glass  * @param env - pointer to pointer to extracted env
292e192b24SSimon Glass  *
302e192b24SSimon Glass  * @return - zero on successful expand and env is set
312e192b24SSimon Glass  */
322e192b24SSimon Glass static int extract_env(const char *str, char **env)
332e192b24SSimon Glass {
342e192b24SSimon Glass 	int ret = -1;
352e192b24SSimon Glass 	char *e, *s;
362e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
372e192b24SSimon Glass 	char uuid_str[UUID_STR_LEN + 1];
382e192b24SSimon Glass #endif
392e192b24SSimon Glass 
402e192b24SSimon Glass 	if (!str || strlen(str) < 4)
412e192b24SSimon Glass 		return -1;
422e192b24SSimon Glass 
432e192b24SSimon Glass 	if (!((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}')))
442e192b24SSimon Glass 		return -1;
452e192b24SSimon Glass 
462e192b24SSimon Glass 	s = strdup(str);
472e192b24SSimon Glass 	if (s == NULL)
482e192b24SSimon Glass 		return -1;
492e192b24SSimon Glass 
502e192b24SSimon Glass 	memset(s + strlen(s) - 1, '\0', 1);
512e192b24SSimon Glass 	memmove(s, s + 2, strlen(s) - 1);
522e192b24SSimon Glass 
532e192b24SSimon Glass 	e = getenv(s);
542e192b24SSimon Glass 	if (e == NULL) {
552e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
562e192b24SSimon Glass 		debug("%s unset. ", str);
579da52f8fSVincent Tinelli 		gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_GUID);
582e192b24SSimon Glass 		setenv(s, uuid_str);
592e192b24SSimon Glass 
602e192b24SSimon Glass 		e = getenv(s);
612e192b24SSimon Glass 		if (e) {
622e192b24SSimon Glass 			debug("Set to random.\n");
632e192b24SSimon Glass 			ret = 0;
642e192b24SSimon Glass 		} else {
652e192b24SSimon Glass 			debug("Can't get random UUID.\n");
662e192b24SSimon Glass 		}
672e192b24SSimon Glass #else
682e192b24SSimon Glass 		debug("%s unset.\n", str);
692e192b24SSimon Glass #endif
702e192b24SSimon Glass 	} else {
712e192b24SSimon Glass 		debug("%s get from environment.\n", str);
722e192b24SSimon Glass 		ret = 0;
732e192b24SSimon Glass 	}
742e192b24SSimon Glass 
752e192b24SSimon Glass 	*env = e;
762e192b24SSimon Glass 	free(s);
772e192b24SSimon Glass 
782e192b24SSimon Glass 	return ret;
792e192b24SSimon Glass }
802e192b24SSimon Glass 
812e192b24SSimon Glass /**
822e192b24SSimon Glass  * extract_val(): Extract value from a key=value pair list (comma separated).
832e192b24SSimon Glass  *                Only value for the given key is returend.
842e192b24SSimon Glass  *                Function allocates memory for the value, remember to free!
852e192b24SSimon Glass  *
862e192b24SSimon Glass  * @param str - pointer to string with key=values pairs
872e192b24SSimon Glass  * @param key - pointer to the key to search for
882e192b24SSimon Glass  *
892e192b24SSimon Glass  * @return - pointer to allocated string with the value
902e192b24SSimon Glass  */
912e192b24SSimon Glass static char *extract_val(const char *str, const char *key)
922e192b24SSimon Glass {
932e192b24SSimon Glass 	char *v, *k;
942e192b24SSimon Glass 	char *s, *strcopy;
952e192b24SSimon Glass 	char *new = NULL;
962e192b24SSimon Glass 
972e192b24SSimon Glass 	strcopy = strdup(str);
982e192b24SSimon Glass 	if (strcopy == NULL)
992e192b24SSimon Glass 		return NULL;
1002e192b24SSimon Glass 
1012e192b24SSimon Glass 	s = strcopy;
1022e192b24SSimon Glass 	while (s) {
1032e192b24SSimon Glass 		v = strsep(&s, ",");
1042e192b24SSimon Glass 		if (!v)
1052e192b24SSimon Glass 			break;
1062e192b24SSimon Glass 		k = strsep(&v, "=");
1072e192b24SSimon Glass 		if (!k)
1082e192b24SSimon Glass 			break;
1092e192b24SSimon Glass 		if  (strcmp(k, key) == 0) {
1102e192b24SSimon Glass 			new = strdup(v);
1112e192b24SSimon Glass 			break;
1122e192b24SSimon Glass 		}
1132e192b24SSimon Glass 	}
1142e192b24SSimon Glass 
1152e192b24SSimon Glass 	free(strcopy);
1162e192b24SSimon Glass 
1172e192b24SSimon Glass 	return new;
1182e192b24SSimon Glass }
1192e192b24SSimon Glass 
1202e192b24SSimon Glass /**
1212e192b24SSimon Glass  * found_key(): Found key without value in parameter list (comma separated).
1222e192b24SSimon Glass  *
1232e192b24SSimon Glass  * @param str - pointer to string with key
1242e192b24SSimon Glass  * @param key - pointer to the key to search for
1252e192b24SSimon Glass  *
1262e192b24SSimon Glass  * @return - true on found key
1272e192b24SSimon Glass  */
1282e192b24SSimon Glass static bool found_key(const char *str, const char *key)
1292e192b24SSimon Glass {
1302e192b24SSimon Glass 	char *k;
1312e192b24SSimon Glass 	char *s, *strcopy;
1322e192b24SSimon Glass 	bool result = false;
1332e192b24SSimon Glass 
1342e192b24SSimon Glass 	strcopy = strdup(str);
1352e192b24SSimon Glass 	if (!strcopy)
1362e192b24SSimon Glass 		return NULL;
1372e192b24SSimon Glass 
1382e192b24SSimon Glass 	s = strcopy;
1392e192b24SSimon Glass 	while (s) {
1402e192b24SSimon Glass 		k = strsep(&s, ",");
1412e192b24SSimon Glass 		if (!k)
1422e192b24SSimon Glass 			break;
1432e192b24SSimon Glass 		if  (strcmp(k, key) == 0) {
1442e192b24SSimon Glass 			result = true;
1452e192b24SSimon Glass 			break;
1462e192b24SSimon Glass 		}
1472e192b24SSimon Glass 	}
1482e192b24SSimon Glass 
1492e192b24SSimon Glass 	free(strcopy);
1502e192b24SSimon Glass 
1512e192b24SSimon Glass 	return result;
1522e192b24SSimon Glass }
1532e192b24SSimon Glass 
1542e192b24SSimon Glass /**
1552e192b24SSimon Glass  * set_gpt_info(): Fill partition information from string
1562e192b24SSimon Glass  *		function allocates memory, remember to free!
1572e192b24SSimon Glass  *
1582e192b24SSimon Glass  * @param dev_desc - pointer block device descriptor
1592e192b24SSimon Glass  * @param str_part - pointer to string with partition information
1602e192b24SSimon Glass  * @param str_disk_guid - pointer to pointer to allocated string with disk guid
1612e192b24SSimon Glass  * @param partitions - pointer to pointer to allocated partitions array
1622e192b24SSimon Glass  * @param parts_count - number of partitions
1632e192b24SSimon Glass  *
1642e192b24SSimon Glass  * @return - zero on success, otherwise error
1652e192b24SSimon Glass  *
1662e192b24SSimon Glass  */
1674101f687SSimon Glass static int set_gpt_info(struct blk_desc *dev_desc,
1682e192b24SSimon Glass 			const char *str_part,
1692e192b24SSimon Glass 			char **str_disk_guid,
1702e192b24SSimon Glass 			disk_partition_t **partitions,
1712e192b24SSimon Glass 			u8 *parts_count)
1722e192b24SSimon Glass {
1732e192b24SSimon Glass 	char *tok, *str, *s;
1742e192b24SSimon Glass 	int i;
1752e192b24SSimon Glass 	char *val, *p;
1762e192b24SSimon Glass 	int p_count;
1772e192b24SSimon Glass 	disk_partition_t *parts;
1782e192b24SSimon Glass 	int errno = 0;
1792e192b24SSimon Glass 	uint64_t size_ll, start_ll;
18066636235SMichael Trimarchi 	lbaint_t offset = 0;
1812e192b24SSimon Glass 
1822e192b24SSimon Glass 	debug("%s:  lba num: 0x%x %d\n", __func__,
1832e192b24SSimon Glass 	      (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba);
1842e192b24SSimon Glass 
1852e192b24SSimon Glass 	if (str_part == NULL)
1862e192b24SSimon Glass 		return -1;
1872e192b24SSimon Glass 
1882e192b24SSimon Glass 	str = strdup(str_part);
1892e192b24SSimon Glass 
1902e192b24SSimon Glass 	/* extract disk guid */
1912e192b24SSimon Glass 	s = str;
1922e192b24SSimon Glass 	val = extract_val(str, "uuid_disk");
1932e192b24SSimon Glass 	if (!val) {
1942e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
1952e192b24SSimon Glass 		*str_disk_guid = malloc(UUID_STR_LEN + 1);
1962e192b24SSimon Glass 		gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD);
1972e192b24SSimon Glass #else
1982e192b24SSimon Glass 		free(str);
1992e192b24SSimon Glass 		return -2;
2002e192b24SSimon Glass #endif
2012e192b24SSimon Glass 	} else {
2022e192b24SSimon Glass 		val = strsep(&val, ";");
2032e192b24SSimon Glass 		if (extract_env(val, &p))
2042e192b24SSimon Glass 			p = val;
2052e192b24SSimon Glass 		*str_disk_guid = strdup(p);
2062e192b24SSimon Glass 		free(val);
2072e192b24SSimon Glass 		/* Move s to first partition */
2082e192b24SSimon Glass 		strsep(&s, ";");
2092e192b24SSimon Glass 	}
2102e192b24SSimon Glass 	if (strlen(s) == 0)
2112e192b24SSimon Glass 		return -3;
2122e192b24SSimon Glass 
2132e192b24SSimon Glass 	i = strlen(s) - 1;
2142e192b24SSimon Glass 	if (s[i] == ';')
2152e192b24SSimon Glass 		s[i] = '\0';
2162e192b24SSimon Glass 
2172e192b24SSimon Glass 	/* calculate expected number of partitions */
2182e192b24SSimon Glass 	p_count = 1;
2192e192b24SSimon Glass 	p = s;
2202e192b24SSimon Glass 	while (*p) {
2212e192b24SSimon Glass 		if (*p++ == ';')
2222e192b24SSimon Glass 			p_count++;
2232e192b24SSimon Glass 	}
2242e192b24SSimon Glass 
2252e192b24SSimon Glass 	/* allocate memory for partitions */
2262e192b24SSimon Glass 	parts = calloc(sizeof(disk_partition_t), p_count);
2272e192b24SSimon Glass 
2282e192b24SSimon Glass 	/* retrieve partitions data from string */
2292e192b24SSimon Glass 	for (i = 0; i < p_count; i++) {
2302e192b24SSimon Glass 		tok = strsep(&s, ";");
2312e192b24SSimon Glass 
2322e192b24SSimon Glass 		if (tok == NULL)
2332e192b24SSimon Glass 			break;
2342e192b24SSimon Glass 
2352e192b24SSimon Glass 		/* uuid */
2362e192b24SSimon Glass 		val = extract_val(tok, "uuid");
2372e192b24SSimon Glass 		if (!val) {
2382e192b24SSimon Glass 			/* 'uuid' is optional if random uuid's are enabled */
2392e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
2402e192b24SSimon Glass 			gen_rand_uuid_str(parts[i].uuid, UUID_STR_FORMAT_STD);
2412e192b24SSimon Glass #else
2422e192b24SSimon Glass 			errno = -4;
2432e192b24SSimon Glass 			goto err;
2442e192b24SSimon Glass #endif
2452e192b24SSimon Glass 		} else {
2462e192b24SSimon Glass 			if (extract_env(val, &p))
2472e192b24SSimon Glass 				p = val;
2482e192b24SSimon Glass 			if (strlen(p) >= sizeof(parts[i].uuid)) {
2492e192b24SSimon Glass 				printf("Wrong uuid format for partition %d\n", i);
2502e192b24SSimon Glass 				errno = -4;
2512e192b24SSimon Glass 				goto err;
2522e192b24SSimon Glass 			}
2532e192b24SSimon Glass 			strcpy((char *)parts[i].uuid, p);
2542e192b24SSimon Glass 			free(val);
2552e192b24SSimon Glass 		}
2562e192b24SSimon Glass #ifdef CONFIG_PARTITION_TYPE_GUID
2572e192b24SSimon Glass 		/* guid */
2582e192b24SSimon Glass 		val = extract_val(tok, "type");
2592e192b24SSimon Glass 		if (val) {
2602e192b24SSimon Glass 			/* 'type' is optional */
2612e192b24SSimon Glass 			if (extract_env(val, &p))
2622e192b24SSimon Glass 				p = val;
2632e192b24SSimon Glass 			if (strlen(p) >= sizeof(parts[i].type_guid)) {
2642e192b24SSimon Glass 				printf("Wrong type guid format for partition %d\n",
2652e192b24SSimon Glass 				       i);
2662e192b24SSimon Glass 				errno = -4;
2672e192b24SSimon Glass 				goto err;
2682e192b24SSimon Glass 			}
2692e192b24SSimon Glass 			strcpy((char *)parts[i].type_guid, p);
2702e192b24SSimon Glass 			free(val);
2712e192b24SSimon Glass 		}
2722e192b24SSimon Glass #endif
2732e192b24SSimon Glass 		/* name */
2742e192b24SSimon Glass 		val = extract_val(tok, "name");
2752e192b24SSimon Glass 		if (!val) { /* name is mandatory */
2762e192b24SSimon Glass 			errno = -4;
2772e192b24SSimon Glass 			goto err;
2782e192b24SSimon Glass 		}
2792e192b24SSimon Glass 		if (extract_env(val, &p))
2802e192b24SSimon Glass 			p = val;
2812e192b24SSimon Glass 		if (strlen(p) >= sizeof(parts[i].name)) {
2822e192b24SSimon Glass 			errno = -4;
2832e192b24SSimon Glass 			goto err;
2842e192b24SSimon Glass 		}
2852e192b24SSimon Glass 		strcpy((char *)parts[i].name, p);
2862e192b24SSimon Glass 		free(val);
2872e192b24SSimon Glass 
2882e192b24SSimon Glass 		/* size */
2892e192b24SSimon Glass 		val = extract_val(tok, "size");
2902e192b24SSimon Glass 		if (!val) { /* 'size' is mandatory */
2912e192b24SSimon Glass 			errno = -4;
2922e192b24SSimon Glass 			goto err;
2932e192b24SSimon Glass 		}
2942e192b24SSimon Glass 		if (extract_env(val, &p))
2952e192b24SSimon Glass 			p = val;
29666636235SMichael Trimarchi 		if ((strcmp(p, "-") == 0)) {
297c2fdd345SKever Yang 			/* Let part efi module to auto extend the size */
298c2fdd345SKever Yang 			parts[i].size = 0;
29966636235SMichael Trimarchi 		} else {
3002e192b24SSimon Glass 			size_ll = ustrtoull(p, &p, 0);
3012e192b24SSimon Glass 			parts[i].size = lldiv(size_ll, dev_desc->blksz);
30266636235SMichael Trimarchi 		}
30366636235SMichael Trimarchi 
3042e192b24SSimon Glass 		free(val);
3052e192b24SSimon Glass 
3062e192b24SSimon Glass 		/* start address */
3072e192b24SSimon Glass 		val = extract_val(tok, "start");
3082e192b24SSimon Glass 		if (val) { /* start address is optional */
3092e192b24SSimon Glass 			if (extract_env(val, &p))
3102e192b24SSimon Glass 				p = val;
3112e192b24SSimon Glass 			start_ll = ustrtoull(p, &p, 0);
3122e192b24SSimon Glass 			parts[i].start = lldiv(start_ll, dev_desc->blksz);
3132e192b24SSimon Glass 			free(val);
3142e192b24SSimon Glass 		}
3152e192b24SSimon Glass 
31666636235SMichael Trimarchi 		offset += parts[i].size + parts[i].start;
31766636235SMichael Trimarchi 
3182e192b24SSimon Glass 		/* bootable */
3192e192b24SSimon Glass 		if (found_key(tok, "bootable"))
3202e192b24SSimon Glass 			parts[i].bootable = 1;
3212e192b24SSimon Glass 	}
3222e192b24SSimon Glass 
3232e192b24SSimon Glass 	*parts_count = p_count;
3242e192b24SSimon Glass 	*partitions = parts;
3252e192b24SSimon Glass 	free(str);
3262e192b24SSimon Glass 
3272e192b24SSimon Glass 	return 0;
3282e192b24SSimon Glass err:
3292e192b24SSimon Glass 	free(str);
3302e192b24SSimon Glass 	free(*str_disk_guid);
3312e192b24SSimon Glass 	free(parts);
3322e192b24SSimon Glass 
3332e192b24SSimon Glass 	return errno;
3342e192b24SSimon Glass }
3352e192b24SSimon Glass 
3364101f687SSimon Glass static int gpt_default(struct blk_desc *blk_dev_desc, const char *str_part)
3372e192b24SSimon Glass {
3382e192b24SSimon Glass 	int ret;
3392e192b24SSimon Glass 	char *str_disk_guid;
3402e192b24SSimon Glass 	u8 part_count = 0;
3412e192b24SSimon Glass 	disk_partition_t *partitions = NULL;
3422e192b24SSimon Glass 
3432e192b24SSimon Glass 	/* fill partitions */
3442e192b24SSimon Glass 	ret = set_gpt_info(blk_dev_desc, str_part,
3452e192b24SSimon Glass 			&str_disk_guid, &partitions, &part_count);
3462e192b24SSimon Glass 	if (ret) {
3472e192b24SSimon Glass 		if (ret == -1)
3482e192b24SSimon Glass 			printf("No partition list provided\n");
3492e192b24SSimon Glass 		if (ret == -2)
3502e192b24SSimon Glass 			printf("Missing disk guid\n");
3512e192b24SSimon Glass 		if ((ret == -3) || (ret == -4))
3522e192b24SSimon Glass 			printf("Partition list incomplete\n");
3532e192b24SSimon Glass 		return -1;
3542e192b24SSimon Glass 	}
3552e192b24SSimon Glass 
3562e192b24SSimon Glass 	/* save partitions layout to disk */
3572e192b24SSimon Glass 	ret = gpt_restore(blk_dev_desc, str_disk_guid, partitions, part_count);
3582e192b24SSimon Glass 	free(str_disk_guid);
3592e192b24SSimon Glass 	free(partitions);
3602e192b24SSimon Glass 
3612e192b24SSimon Glass 	return ret;
3622e192b24SSimon Glass }
3632e192b24SSimon Glass 
3644101f687SSimon Glass static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)
3652e192b24SSimon Glass {
3662e192b24SSimon Glass 	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1,
3672e192b24SSimon Glass 				     blk_dev_desc->blksz);
3682e192b24SSimon Glass 	disk_partition_t *partitions = NULL;
3692e192b24SSimon Glass 	gpt_entry *gpt_pte = NULL;
3702e192b24SSimon Glass 	char *str_disk_guid;
3712e192b24SSimon Glass 	u8 part_count = 0;
3722e192b24SSimon Glass 	int ret = 0;
3732e192b24SSimon Glass 
3742e192b24SSimon Glass 	/* fill partitions */
3752e192b24SSimon Glass 	ret = set_gpt_info(blk_dev_desc, str_part,
3762e192b24SSimon Glass 			&str_disk_guid, &partitions, &part_count);
3772e192b24SSimon Glass 	if (ret) {
3782e192b24SSimon Glass 		if (ret == -1) {
3792e192b24SSimon Glass 			printf("No partition list provided - only basic check\n");
3802e192b24SSimon Glass 			ret = gpt_verify_headers(blk_dev_desc, gpt_head,
3812e192b24SSimon Glass 						 &gpt_pte);
3822e192b24SSimon Glass 			goto out;
3832e192b24SSimon Glass 		}
3842e192b24SSimon Glass 		if (ret == -2)
3852e192b24SSimon Glass 			printf("Missing disk guid\n");
3862e192b24SSimon Glass 		if ((ret == -3) || (ret == -4))
3872e192b24SSimon Glass 			printf("Partition list incomplete\n");
3882e192b24SSimon Glass 		return -1;
3892e192b24SSimon Glass 	}
3902e192b24SSimon Glass 
3912e192b24SSimon Glass 	/* Check partition layout with provided pattern */
3922e192b24SSimon Glass 	ret = gpt_verify_partitions(blk_dev_desc, partitions, part_count,
3932e192b24SSimon Glass 				    gpt_head, &gpt_pte);
3942e192b24SSimon Glass 	free(str_disk_guid);
3952e192b24SSimon Glass 	free(partitions);
3962e192b24SSimon Glass  out:
3972e192b24SSimon Glass 	free(gpt_pte);
3982e192b24SSimon Glass 	return ret;
3992e192b24SSimon Glass }
4002e192b24SSimon Glass 
401*73d6d18bSAlison Chaiken static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
402*73d6d18bSAlison Chaiken {
403*73d6d18bSAlison Chaiken 	int ret;
404*73d6d18bSAlison Chaiken 	char disk_guid[UUID_STR_LEN + 1];
405*73d6d18bSAlison Chaiken 
406*73d6d18bSAlison Chaiken 	ret = get_disk_guid(dev_desc, disk_guid);
407*73d6d18bSAlison Chaiken 	if (ret < 0)
408*73d6d18bSAlison Chaiken 		return CMD_RET_FAILURE;
409*73d6d18bSAlison Chaiken 
410*73d6d18bSAlison Chaiken 	if (namestr)
411*73d6d18bSAlison Chaiken 		setenv(namestr, disk_guid);
412*73d6d18bSAlison Chaiken 	else
413*73d6d18bSAlison Chaiken 		printf("%s\n", disk_guid);
414*73d6d18bSAlison Chaiken 
415*73d6d18bSAlison Chaiken 	return ret;
416*73d6d18bSAlison Chaiken }
417*73d6d18bSAlison Chaiken 
4182e192b24SSimon Glass /**
4192e192b24SSimon Glass  * do_gpt(): Perform GPT operations
4202e192b24SSimon Glass  *
4212e192b24SSimon Glass  * @param cmdtp - command name
4222e192b24SSimon Glass  * @param flag
4232e192b24SSimon Glass  * @param argc
4242e192b24SSimon Glass  * @param argv
4252e192b24SSimon Glass  *
4262e192b24SSimon Glass  * @return zero on success; otherwise error
4272e192b24SSimon Glass  */
4282e192b24SSimon Glass static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
4292e192b24SSimon Glass {
4302e192b24SSimon Glass 	int ret = CMD_RET_SUCCESS;
4312e192b24SSimon Glass 	int dev = 0;
4322e192b24SSimon Glass 	char *ep;
4334101f687SSimon Glass 	struct blk_desc *blk_dev_desc = NULL;
4342e192b24SSimon Glass 
4352e192b24SSimon Glass 	if (argc < 4 || argc > 5)
4362e192b24SSimon Glass 		return CMD_RET_USAGE;
4372e192b24SSimon Glass 
4382e192b24SSimon Glass 	dev = (int)simple_strtoul(argv[3], &ep, 10);
4392e192b24SSimon Glass 	if (!ep || ep[0] != '\0') {
4402e192b24SSimon Glass 		printf("'%s' is not a number\n", argv[3]);
4412e192b24SSimon Glass 		return CMD_RET_USAGE;
4422e192b24SSimon Glass 	}
443db1d9e78SSimon Glass 	blk_dev_desc = blk_get_dev(argv[2], dev);
4442e192b24SSimon Glass 	if (!blk_dev_desc) {
4452e192b24SSimon Glass 		printf("%s: %s dev %d NOT available\n",
4462e192b24SSimon Glass 		       __func__, argv[2], dev);
4472e192b24SSimon Glass 		return CMD_RET_FAILURE;
4482e192b24SSimon Glass 	}
4492e192b24SSimon Glass 
4502e192b24SSimon Glass 	if ((strcmp(argv[1], "write") == 0) && (argc == 5)) {
4512e192b24SSimon Glass 		printf("Writing GPT: ");
4522e192b24SSimon Glass 		ret = gpt_default(blk_dev_desc, argv[4]);
4532e192b24SSimon Glass 	} else if ((strcmp(argv[1], "verify") == 0)) {
4542e192b24SSimon Glass 		ret = gpt_verify(blk_dev_desc, argv[4]);
4552e192b24SSimon Glass 		printf("Verify GPT: ");
456*73d6d18bSAlison Chaiken 	} else if (strcmp(argv[1], "guid") == 0) {
457*73d6d18bSAlison Chaiken 		ret = do_disk_guid(blk_dev_desc, argv[4]);
4582e192b24SSimon Glass 	} else {
4592e192b24SSimon Glass 		return CMD_RET_USAGE;
4602e192b24SSimon Glass 	}
4612e192b24SSimon Glass 
4622e192b24SSimon Glass 	if (ret) {
4632e192b24SSimon Glass 		printf("error!\n");
4642e192b24SSimon Glass 		return CMD_RET_FAILURE;
4652e192b24SSimon Glass 	}
4662e192b24SSimon Glass 
4672e192b24SSimon Glass 	printf("success!\n");
4682e192b24SSimon Glass 	return CMD_RET_SUCCESS;
4692e192b24SSimon Glass }
4702e192b24SSimon Glass 
4712e192b24SSimon Glass U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
4722e192b24SSimon Glass 	"GUID Partition Table",
4732e192b24SSimon Glass 	"<command> <interface> <dev> <partitions_list>\n"
4742e192b24SSimon Glass 	" - GUID partition table restoration and validity check\n"
4752e192b24SSimon Glass 	" Restore or verify GPT information on a device connected\n"
4762e192b24SSimon Glass 	" to interface\n"
4772e192b24SSimon Glass 	" Example usage:\n"
4782e192b24SSimon Glass 	" gpt write mmc 0 $partitions\n"
4792e192b24SSimon Glass 	" gpt verify mmc 0 $partitions\n"
480*73d6d18bSAlison Chaiken 	" guid <interface> <dev>\n"
481*73d6d18bSAlison Chaiken 	"    - print disk GUID\n"
482*73d6d18bSAlison Chaiken 	" guid <interface> <dev> <varname>\n"
483*73d6d18bSAlison Chaiken 	"    - set environment variable to disk GUID\n"
484*73d6d18bSAlison Chaiken 	" Example usage:\n"
485*73d6d18bSAlison Chaiken 	" gpt guid mmc 0\n"
486*73d6d18bSAlison Chaiken 	" gpt guid mmc 0 varname\n"
4872e192b24SSimon Glass );
488