xref: /openbmc/u-boot/cmd/gpt.c (revision db1d9e78)
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 #ifndef CONFIG_PARTITION_UUIDS
242e192b24SSimon Glass #error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled
252e192b24SSimon Glass #endif
262e192b24SSimon Glass 
272e192b24SSimon Glass /**
282e192b24SSimon Glass  * extract_env(): Expand env name from string format '&{env_name}'
292e192b24SSimon Glass  *                and return pointer to the env (if the env is set)
302e192b24SSimon Glass  *
312e192b24SSimon Glass  * @param str - pointer to string
322e192b24SSimon Glass  * @param env - pointer to pointer to extracted env
332e192b24SSimon Glass  *
342e192b24SSimon Glass  * @return - zero on successful expand and env is set
352e192b24SSimon Glass  */
362e192b24SSimon Glass static int extract_env(const char *str, char **env)
372e192b24SSimon Glass {
382e192b24SSimon Glass 	int ret = -1;
392e192b24SSimon Glass 	char *e, *s;
402e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
412e192b24SSimon Glass 	char uuid_str[UUID_STR_LEN + 1];
422e192b24SSimon Glass #endif
432e192b24SSimon Glass 
442e192b24SSimon Glass 	if (!str || strlen(str) < 4)
452e192b24SSimon Glass 		return -1;
462e192b24SSimon Glass 
472e192b24SSimon Glass 	if (!((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}')))
482e192b24SSimon Glass 		return -1;
492e192b24SSimon Glass 
502e192b24SSimon Glass 	s = strdup(str);
512e192b24SSimon Glass 	if (s == NULL)
522e192b24SSimon Glass 		return -1;
532e192b24SSimon Glass 
542e192b24SSimon Glass 	memset(s + strlen(s) - 1, '\0', 1);
552e192b24SSimon Glass 	memmove(s, s + 2, strlen(s) - 1);
562e192b24SSimon Glass 
572e192b24SSimon Glass 	e = getenv(s);
582e192b24SSimon Glass 	if (e == NULL) {
592e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
602e192b24SSimon Glass 		debug("%s unset. ", str);
612e192b24SSimon Glass 		gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_STD);
622e192b24SSimon Glass 		setenv(s, uuid_str);
632e192b24SSimon Glass 
642e192b24SSimon Glass 		e = getenv(s);
652e192b24SSimon Glass 		if (e) {
662e192b24SSimon Glass 			debug("Set to random.\n");
672e192b24SSimon Glass 			ret = 0;
682e192b24SSimon Glass 		} else {
692e192b24SSimon Glass 			debug("Can't get random UUID.\n");
702e192b24SSimon Glass 		}
712e192b24SSimon Glass #else
722e192b24SSimon Glass 		debug("%s unset.\n", str);
732e192b24SSimon Glass #endif
742e192b24SSimon Glass 	} else {
752e192b24SSimon Glass 		debug("%s get from environment.\n", str);
762e192b24SSimon Glass 		ret = 0;
772e192b24SSimon Glass 	}
782e192b24SSimon Glass 
792e192b24SSimon Glass 	*env = e;
802e192b24SSimon Glass 	free(s);
812e192b24SSimon Glass 
822e192b24SSimon Glass 	return ret;
832e192b24SSimon Glass }
842e192b24SSimon Glass 
852e192b24SSimon Glass /**
862e192b24SSimon Glass  * extract_val(): Extract value from a key=value pair list (comma separated).
872e192b24SSimon Glass  *                Only value for the given key is returend.
882e192b24SSimon Glass  *                Function allocates memory for the value, remember to free!
892e192b24SSimon Glass  *
902e192b24SSimon Glass  * @param str - pointer to string with key=values pairs
912e192b24SSimon Glass  * @param key - pointer to the key to search for
922e192b24SSimon Glass  *
932e192b24SSimon Glass  * @return - pointer to allocated string with the value
942e192b24SSimon Glass  */
952e192b24SSimon Glass static char *extract_val(const char *str, const char *key)
962e192b24SSimon Glass {
972e192b24SSimon Glass 	char *v, *k;
982e192b24SSimon Glass 	char *s, *strcopy;
992e192b24SSimon Glass 	char *new = NULL;
1002e192b24SSimon Glass 
1012e192b24SSimon Glass 	strcopy = strdup(str);
1022e192b24SSimon Glass 	if (strcopy == NULL)
1032e192b24SSimon Glass 		return NULL;
1042e192b24SSimon Glass 
1052e192b24SSimon Glass 	s = strcopy;
1062e192b24SSimon Glass 	while (s) {
1072e192b24SSimon Glass 		v = strsep(&s, ",");
1082e192b24SSimon Glass 		if (!v)
1092e192b24SSimon Glass 			break;
1102e192b24SSimon Glass 		k = strsep(&v, "=");
1112e192b24SSimon Glass 		if (!k)
1122e192b24SSimon Glass 			break;
1132e192b24SSimon Glass 		if  (strcmp(k, key) == 0) {
1142e192b24SSimon Glass 			new = strdup(v);
1152e192b24SSimon Glass 			break;
1162e192b24SSimon Glass 		}
1172e192b24SSimon Glass 	}
1182e192b24SSimon Glass 
1192e192b24SSimon Glass 	free(strcopy);
1202e192b24SSimon Glass 
1212e192b24SSimon Glass 	return new;
1222e192b24SSimon Glass }
1232e192b24SSimon Glass 
1242e192b24SSimon Glass /**
1252e192b24SSimon Glass  * found_key(): Found key without value in parameter list (comma separated).
1262e192b24SSimon Glass  *
1272e192b24SSimon Glass  * @param str - pointer to string with key
1282e192b24SSimon Glass  * @param key - pointer to the key to search for
1292e192b24SSimon Glass  *
1302e192b24SSimon Glass  * @return - true on found key
1312e192b24SSimon Glass  */
1322e192b24SSimon Glass static bool found_key(const char *str, const char *key)
1332e192b24SSimon Glass {
1342e192b24SSimon Glass 	char *k;
1352e192b24SSimon Glass 	char *s, *strcopy;
1362e192b24SSimon Glass 	bool result = false;
1372e192b24SSimon Glass 
1382e192b24SSimon Glass 	strcopy = strdup(str);
1392e192b24SSimon Glass 	if (!strcopy)
1402e192b24SSimon Glass 		return NULL;
1412e192b24SSimon Glass 
1422e192b24SSimon Glass 	s = strcopy;
1432e192b24SSimon Glass 	while (s) {
1442e192b24SSimon Glass 		k = strsep(&s, ",");
1452e192b24SSimon Glass 		if (!k)
1462e192b24SSimon Glass 			break;
1472e192b24SSimon Glass 		if  (strcmp(k, key) == 0) {
1482e192b24SSimon Glass 			result = true;
1492e192b24SSimon Glass 			break;
1502e192b24SSimon Glass 		}
1512e192b24SSimon Glass 	}
1522e192b24SSimon Glass 
1532e192b24SSimon Glass 	free(strcopy);
1542e192b24SSimon Glass 
1552e192b24SSimon Glass 	return result;
1562e192b24SSimon Glass }
1572e192b24SSimon Glass 
1582e192b24SSimon Glass /**
1592e192b24SSimon Glass  * set_gpt_info(): Fill partition information from string
1602e192b24SSimon Glass  *		function allocates memory, remember to free!
1612e192b24SSimon Glass  *
1622e192b24SSimon Glass  * @param dev_desc - pointer block device descriptor
1632e192b24SSimon Glass  * @param str_part - pointer to string with partition information
1642e192b24SSimon Glass  * @param str_disk_guid - pointer to pointer to allocated string with disk guid
1652e192b24SSimon Glass  * @param partitions - pointer to pointer to allocated partitions array
1662e192b24SSimon Glass  * @param parts_count - number of partitions
1672e192b24SSimon Glass  *
1682e192b24SSimon Glass  * @return - zero on success, otherwise error
1692e192b24SSimon Glass  *
1702e192b24SSimon Glass  */
1714101f687SSimon Glass static int set_gpt_info(struct blk_desc *dev_desc,
1722e192b24SSimon Glass 			const char *str_part,
1732e192b24SSimon Glass 			char **str_disk_guid,
1742e192b24SSimon Glass 			disk_partition_t **partitions,
1752e192b24SSimon Glass 			u8 *parts_count)
1762e192b24SSimon Glass {
1772e192b24SSimon Glass 	char *tok, *str, *s;
1782e192b24SSimon Glass 	int i;
1792e192b24SSimon Glass 	char *val, *p;
1802e192b24SSimon Glass 	int p_count;
1812e192b24SSimon Glass 	disk_partition_t *parts;
1822e192b24SSimon Glass 	int errno = 0;
1832e192b24SSimon Glass 	uint64_t size_ll, start_ll;
1842e192b24SSimon Glass 
1852e192b24SSimon Glass 	debug("%s:  lba num: 0x%x %d\n", __func__,
1862e192b24SSimon Glass 	      (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba);
1872e192b24SSimon Glass 
1882e192b24SSimon Glass 	if (str_part == NULL)
1892e192b24SSimon Glass 		return -1;
1902e192b24SSimon Glass 
1912e192b24SSimon Glass 	str = strdup(str_part);
1922e192b24SSimon Glass 
1932e192b24SSimon Glass 	/* extract disk guid */
1942e192b24SSimon Glass 	s = str;
1952e192b24SSimon Glass 	val = extract_val(str, "uuid_disk");
1962e192b24SSimon Glass 	if (!val) {
1972e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
1982e192b24SSimon Glass 		*str_disk_guid = malloc(UUID_STR_LEN + 1);
1992e192b24SSimon Glass 		gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD);
2002e192b24SSimon Glass #else
2012e192b24SSimon Glass 		free(str);
2022e192b24SSimon Glass 		return -2;
2032e192b24SSimon Glass #endif
2042e192b24SSimon Glass 	} else {
2052e192b24SSimon Glass 		val = strsep(&val, ";");
2062e192b24SSimon Glass 		if (extract_env(val, &p))
2072e192b24SSimon Glass 			p = val;
2082e192b24SSimon Glass 		*str_disk_guid = strdup(p);
2092e192b24SSimon Glass 		free(val);
2102e192b24SSimon Glass 		/* Move s to first partition */
2112e192b24SSimon Glass 		strsep(&s, ";");
2122e192b24SSimon Glass 	}
2132e192b24SSimon Glass 	if (strlen(s) == 0)
2142e192b24SSimon Glass 		return -3;
2152e192b24SSimon Glass 
2162e192b24SSimon Glass 	i = strlen(s) - 1;
2172e192b24SSimon Glass 	if (s[i] == ';')
2182e192b24SSimon Glass 		s[i] = '\0';
2192e192b24SSimon Glass 
2202e192b24SSimon Glass 	/* calculate expected number of partitions */
2212e192b24SSimon Glass 	p_count = 1;
2222e192b24SSimon Glass 	p = s;
2232e192b24SSimon Glass 	while (*p) {
2242e192b24SSimon Glass 		if (*p++ == ';')
2252e192b24SSimon Glass 			p_count++;
2262e192b24SSimon Glass 	}
2272e192b24SSimon Glass 
2282e192b24SSimon Glass 	/* allocate memory for partitions */
2292e192b24SSimon Glass 	parts = calloc(sizeof(disk_partition_t), p_count);
2302e192b24SSimon Glass 
2312e192b24SSimon Glass 	/* retrieve partitions data from string */
2322e192b24SSimon Glass 	for (i = 0; i < p_count; i++) {
2332e192b24SSimon Glass 		tok = strsep(&s, ";");
2342e192b24SSimon Glass 
2352e192b24SSimon Glass 		if (tok == NULL)
2362e192b24SSimon Glass 			break;
2372e192b24SSimon Glass 
2382e192b24SSimon Glass 		/* uuid */
2392e192b24SSimon Glass 		val = extract_val(tok, "uuid");
2402e192b24SSimon Glass 		if (!val) {
2412e192b24SSimon Glass 			/* 'uuid' is optional if random uuid's are enabled */
2422e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID
2432e192b24SSimon Glass 			gen_rand_uuid_str(parts[i].uuid, UUID_STR_FORMAT_STD);
2442e192b24SSimon Glass #else
2452e192b24SSimon Glass 			errno = -4;
2462e192b24SSimon Glass 			goto err;
2472e192b24SSimon Glass #endif
2482e192b24SSimon Glass 		} else {
2492e192b24SSimon Glass 			if (extract_env(val, &p))
2502e192b24SSimon Glass 				p = val;
2512e192b24SSimon Glass 			if (strlen(p) >= sizeof(parts[i].uuid)) {
2522e192b24SSimon Glass 				printf("Wrong uuid format for partition %d\n", i);
2532e192b24SSimon Glass 				errno = -4;
2542e192b24SSimon Glass 				goto err;
2552e192b24SSimon Glass 			}
2562e192b24SSimon Glass 			strcpy((char *)parts[i].uuid, p);
2572e192b24SSimon Glass 			free(val);
2582e192b24SSimon Glass 		}
2592e192b24SSimon Glass #ifdef CONFIG_PARTITION_TYPE_GUID
2602e192b24SSimon Glass 		/* guid */
2612e192b24SSimon Glass 		val = extract_val(tok, "type");
2622e192b24SSimon Glass 		if (val) {
2632e192b24SSimon Glass 			/* 'type' is optional */
2642e192b24SSimon Glass 			if (extract_env(val, &p))
2652e192b24SSimon Glass 				p = val;
2662e192b24SSimon Glass 			if (strlen(p) >= sizeof(parts[i].type_guid)) {
2672e192b24SSimon Glass 				printf("Wrong type guid format for partition %d\n",
2682e192b24SSimon Glass 				       i);
2692e192b24SSimon Glass 				errno = -4;
2702e192b24SSimon Glass 				goto err;
2712e192b24SSimon Glass 			}
2722e192b24SSimon Glass 			strcpy((char *)parts[i].type_guid, p);
2732e192b24SSimon Glass 			free(val);
2742e192b24SSimon Glass 		}
2752e192b24SSimon Glass #endif
2762e192b24SSimon Glass 		/* name */
2772e192b24SSimon Glass 		val = extract_val(tok, "name");
2782e192b24SSimon Glass 		if (!val) { /* name is mandatory */
2792e192b24SSimon Glass 			errno = -4;
2802e192b24SSimon Glass 			goto err;
2812e192b24SSimon Glass 		}
2822e192b24SSimon Glass 		if (extract_env(val, &p))
2832e192b24SSimon Glass 			p = val;
2842e192b24SSimon Glass 		if (strlen(p) >= sizeof(parts[i].name)) {
2852e192b24SSimon Glass 			errno = -4;
2862e192b24SSimon Glass 			goto err;
2872e192b24SSimon Glass 		}
2882e192b24SSimon Glass 		strcpy((char *)parts[i].name, p);
2892e192b24SSimon Glass 		free(val);
2902e192b24SSimon Glass 
2912e192b24SSimon Glass 		/* size */
2922e192b24SSimon Glass 		val = extract_val(tok, "size");
2932e192b24SSimon Glass 		if (!val) { /* 'size' is mandatory */
2942e192b24SSimon Glass 			errno = -4;
2952e192b24SSimon Glass 			goto err;
2962e192b24SSimon Glass 		}
2972e192b24SSimon Glass 		if (extract_env(val, &p))
2982e192b24SSimon Glass 			p = val;
2992e192b24SSimon Glass 		size_ll = ustrtoull(p, &p, 0);
3002e192b24SSimon Glass 		parts[i].size = lldiv(size_ll, dev_desc->blksz);
3012e192b24SSimon Glass 		free(val);
3022e192b24SSimon Glass 
3032e192b24SSimon Glass 		/* start address */
3042e192b24SSimon Glass 		val = extract_val(tok, "start");
3052e192b24SSimon Glass 		if (val) { /* start address is optional */
3062e192b24SSimon Glass 			if (extract_env(val, &p))
3072e192b24SSimon Glass 				p = val;
3082e192b24SSimon Glass 			start_ll = ustrtoull(p, &p, 0);
3092e192b24SSimon Glass 			parts[i].start = lldiv(start_ll, dev_desc->blksz);
3102e192b24SSimon Glass 			free(val);
3112e192b24SSimon Glass 		}
3122e192b24SSimon Glass 
3132e192b24SSimon Glass 		/* bootable */
3142e192b24SSimon Glass 		if (found_key(tok, "bootable"))
3152e192b24SSimon Glass 			parts[i].bootable = 1;
3162e192b24SSimon Glass 	}
3172e192b24SSimon Glass 
3182e192b24SSimon Glass 	*parts_count = p_count;
3192e192b24SSimon Glass 	*partitions = parts;
3202e192b24SSimon Glass 	free(str);
3212e192b24SSimon Glass 
3222e192b24SSimon Glass 	return 0;
3232e192b24SSimon Glass err:
3242e192b24SSimon Glass 	free(str);
3252e192b24SSimon Glass 	free(*str_disk_guid);
3262e192b24SSimon Glass 	free(parts);
3272e192b24SSimon Glass 
3282e192b24SSimon Glass 	return errno;
3292e192b24SSimon Glass }
3302e192b24SSimon Glass 
3314101f687SSimon Glass static int gpt_default(struct blk_desc *blk_dev_desc, const char *str_part)
3322e192b24SSimon Glass {
3332e192b24SSimon Glass 	int ret;
3342e192b24SSimon Glass 	char *str_disk_guid;
3352e192b24SSimon Glass 	u8 part_count = 0;
3362e192b24SSimon Glass 	disk_partition_t *partitions = NULL;
3372e192b24SSimon Glass 
3382e192b24SSimon Glass 	/* fill partitions */
3392e192b24SSimon Glass 	ret = set_gpt_info(blk_dev_desc, str_part,
3402e192b24SSimon Glass 			&str_disk_guid, &partitions, &part_count);
3412e192b24SSimon Glass 	if (ret) {
3422e192b24SSimon Glass 		if (ret == -1)
3432e192b24SSimon Glass 			printf("No partition list provided\n");
3442e192b24SSimon Glass 		if (ret == -2)
3452e192b24SSimon Glass 			printf("Missing disk guid\n");
3462e192b24SSimon Glass 		if ((ret == -3) || (ret == -4))
3472e192b24SSimon Glass 			printf("Partition list incomplete\n");
3482e192b24SSimon Glass 		return -1;
3492e192b24SSimon Glass 	}
3502e192b24SSimon Glass 
3512e192b24SSimon Glass 	/* save partitions layout to disk */
3522e192b24SSimon Glass 	ret = gpt_restore(blk_dev_desc, str_disk_guid, partitions, part_count);
3532e192b24SSimon Glass 	free(str_disk_guid);
3542e192b24SSimon Glass 	free(partitions);
3552e192b24SSimon Glass 
3562e192b24SSimon Glass 	return ret;
3572e192b24SSimon Glass }
3582e192b24SSimon Glass 
3594101f687SSimon Glass static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)
3602e192b24SSimon Glass {
3612e192b24SSimon Glass 	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1,
3622e192b24SSimon Glass 				     blk_dev_desc->blksz);
3632e192b24SSimon Glass 	disk_partition_t *partitions = NULL;
3642e192b24SSimon Glass 	gpt_entry *gpt_pte = NULL;
3652e192b24SSimon Glass 	char *str_disk_guid;
3662e192b24SSimon Glass 	u8 part_count = 0;
3672e192b24SSimon Glass 	int ret = 0;
3682e192b24SSimon Glass 
3692e192b24SSimon Glass 	/* fill partitions */
3702e192b24SSimon Glass 	ret = set_gpt_info(blk_dev_desc, str_part,
3712e192b24SSimon Glass 			&str_disk_guid, &partitions, &part_count);
3722e192b24SSimon Glass 	if (ret) {
3732e192b24SSimon Glass 		if (ret == -1) {
3742e192b24SSimon Glass 			printf("No partition list provided - only basic check\n");
3752e192b24SSimon Glass 			ret = gpt_verify_headers(blk_dev_desc, gpt_head,
3762e192b24SSimon Glass 						 &gpt_pte);
3772e192b24SSimon Glass 			goto out;
3782e192b24SSimon Glass 		}
3792e192b24SSimon Glass 		if (ret == -2)
3802e192b24SSimon Glass 			printf("Missing disk guid\n");
3812e192b24SSimon Glass 		if ((ret == -3) || (ret == -4))
3822e192b24SSimon Glass 			printf("Partition list incomplete\n");
3832e192b24SSimon Glass 		return -1;
3842e192b24SSimon Glass 	}
3852e192b24SSimon Glass 
3862e192b24SSimon Glass 	/* Check partition layout with provided pattern */
3872e192b24SSimon Glass 	ret = gpt_verify_partitions(blk_dev_desc, partitions, part_count,
3882e192b24SSimon Glass 				    gpt_head, &gpt_pte);
3892e192b24SSimon Glass 	free(str_disk_guid);
3902e192b24SSimon Glass 	free(partitions);
3912e192b24SSimon Glass  out:
3922e192b24SSimon Glass 	free(gpt_pte);
3932e192b24SSimon Glass 	return ret;
3942e192b24SSimon Glass }
3952e192b24SSimon Glass 
3962e192b24SSimon Glass /**
3972e192b24SSimon Glass  * do_gpt(): Perform GPT operations
3982e192b24SSimon Glass  *
3992e192b24SSimon Glass  * @param cmdtp - command name
4002e192b24SSimon Glass  * @param flag
4012e192b24SSimon Glass  * @param argc
4022e192b24SSimon Glass  * @param argv
4032e192b24SSimon Glass  *
4042e192b24SSimon Glass  * @return zero on success; otherwise error
4052e192b24SSimon Glass  */
4062e192b24SSimon Glass static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
4072e192b24SSimon Glass {
4082e192b24SSimon Glass 	int ret = CMD_RET_SUCCESS;
4092e192b24SSimon Glass 	int dev = 0;
4102e192b24SSimon Glass 	char *ep;
4114101f687SSimon Glass 	struct blk_desc *blk_dev_desc = NULL;
4122e192b24SSimon Glass 
4132e192b24SSimon Glass 	if (argc < 4 || argc > 5)
4142e192b24SSimon Glass 		return CMD_RET_USAGE;
4152e192b24SSimon Glass 
4162e192b24SSimon Glass 	dev = (int)simple_strtoul(argv[3], &ep, 10);
4172e192b24SSimon Glass 	if (!ep || ep[0] != '\0') {
4182e192b24SSimon Glass 		printf("'%s' is not a number\n", argv[3]);
4192e192b24SSimon Glass 		return CMD_RET_USAGE;
4202e192b24SSimon Glass 	}
421*db1d9e78SSimon Glass 	blk_dev_desc = blk_get_dev(argv[2], dev);
4222e192b24SSimon Glass 	if (!blk_dev_desc) {
4232e192b24SSimon Glass 		printf("%s: %s dev %d NOT available\n",
4242e192b24SSimon Glass 		       __func__, argv[2], dev);
4252e192b24SSimon Glass 		return CMD_RET_FAILURE;
4262e192b24SSimon Glass 	}
4272e192b24SSimon Glass 
4282e192b24SSimon Glass 	if ((strcmp(argv[1], "write") == 0) && (argc == 5)) {
4292e192b24SSimon Glass 		printf("Writing GPT: ");
4302e192b24SSimon Glass 		ret = gpt_default(blk_dev_desc, argv[4]);
4312e192b24SSimon Glass 	} else if ((strcmp(argv[1], "verify") == 0)) {
4322e192b24SSimon Glass 		ret = gpt_verify(blk_dev_desc, argv[4]);
4332e192b24SSimon Glass 		printf("Verify GPT: ");
4342e192b24SSimon Glass 	} else {
4352e192b24SSimon Glass 		return CMD_RET_USAGE;
4362e192b24SSimon Glass 	}
4372e192b24SSimon Glass 
4382e192b24SSimon Glass 	if (ret) {
4392e192b24SSimon Glass 		printf("error!\n");
4402e192b24SSimon Glass 		return CMD_RET_FAILURE;
4412e192b24SSimon Glass 	}
4422e192b24SSimon Glass 
4432e192b24SSimon Glass 	printf("success!\n");
4442e192b24SSimon Glass 	return CMD_RET_SUCCESS;
4452e192b24SSimon Glass }
4462e192b24SSimon Glass 
4472e192b24SSimon Glass U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
4482e192b24SSimon Glass 	"GUID Partition Table",
4492e192b24SSimon Glass 	"<command> <interface> <dev> <partitions_list>\n"
4502e192b24SSimon Glass 	" - GUID partition table restoration and validity check\n"
4512e192b24SSimon Glass 	" Restore or verify GPT information on a device connected\n"
4522e192b24SSimon Glass 	" to interface\n"
4532e192b24SSimon Glass 	" Example usage:\n"
4542e192b24SSimon Glass 	" gpt write mmc 0 $partitions\n"
4552e192b24SSimon Glass 	" gpt verify mmc 0 $partitions\n"
4562e192b24SSimon Glass );
457