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