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> 2209a49930SAlison Chaiken #include <linux/compat.h> 23*203f9b48SAlison Chaiken #include <linux/sizes.h> 24*203f9b48SAlison Chaiken #include <stdlib.h> 2509a49930SAlison Chaiken 2609a49930SAlison Chaiken static LIST_HEAD(disk_partitions); 272e192b24SSimon Glass 282e192b24SSimon Glass /** 292e192b24SSimon Glass * extract_env(): Expand env name from string format '&{env_name}' 302e192b24SSimon Glass * and return pointer to the env (if the env is set) 312e192b24SSimon Glass * 322e192b24SSimon Glass * @param str - pointer to string 332e192b24SSimon Glass * @param env - pointer to pointer to extracted env 342e192b24SSimon Glass * 352e192b24SSimon Glass * @return - zero on successful expand and env is set 362e192b24SSimon Glass */ 372e192b24SSimon Glass static int extract_env(const char *str, char **env) 382e192b24SSimon Glass { 392e192b24SSimon Glass int ret = -1; 402e192b24SSimon Glass char *e, *s; 412e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 422e192b24SSimon Glass char uuid_str[UUID_STR_LEN + 1]; 432e192b24SSimon Glass #endif 442e192b24SSimon Glass 452e192b24SSimon Glass if (!str || strlen(str) < 4) 462e192b24SSimon Glass return -1; 472e192b24SSimon Glass 482e192b24SSimon Glass if (!((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}'))) 492e192b24SSimon Glass return -1; 502e192b24SSimon Glass 512e192b24SSimon Glass s = strdup(str); 522e192b24SSimon Glass if (s == NULL) 532e192b24SSimon Glass return -1; 542e192b24SSimon Glass 552e192b24SSimon Glass memset(s + strlen(s) - 1, '\0', 1); 562e192b24SSimon Glass memmove(s, s + 2, strlen(s) - 1); 572e192b24SSimon Glass 582e192b24SSimon Glass e = getenv(s); 592e192b24SSimon Glass if (e == NULL) { 602e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 612e192b24SSimon Glass debug("%s unset. ", str); 629da52f8fSVincent Tinelli gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_GUID); 632e192b24SSimon Glass setenv(s, uuid_str); 642e192b24SSimon Glass 652e192b24SSimon Glass e = getenv(s); 662e192b24SSimon Glass if (e) { 672e192b24SSimon Glass debug("Set to random.\n"); 682e192b24SSimon Glass ret = 0; 692e192b24SSimon Glass } else { 702e192b24SSimon Glass debug("Can't get random UUID.\n"); 712e192b24SSimon Glass } 722e192b24SSimon Glass #else 732e192b24SSimon Glass debug("%s unset.\n", str); 742e192b24SSimon Glass #endif 752e192b24SSimon Glass } else { 762e192b24SSimon Glass debug("%s get from environment.\n", str); 772e192b24SSimon Glass ret = 0; 782e192b24SSimon Glass } 792e192b24SSimon Glass 802e192b24SSimon Glass *env = e; 812e192b24SSimon Glass free(s); 822e192b24SSimon Glass 832e192b24SSimon Glass return ret; 842e192b24SSimon Glass } 852e192b24SSimon Glass 862e192b24SSimon Glass /** 872e192b24SSimon Glass * extract_val(): Extract value from a key=value pair list (comma separated). 882e192b24SSimon Glass * Only value for the given key is returend. 892e192b24SSimon Glass * Function allocates memory for the value, remember to free! 902e192b24SSimon Glass * 912e192b24SSimon Glass * @param str - pointer to string with key=values pairs 922e192b24SSimon Glass * @param key - pointer to the key to search for 932e192b24SSimon Glass * 942e192b24SSimon Glass * @return - pointer to allocated string with the value 952e192b24SSimon Glass */ 962e192b24SSimon Glass static char *extract_val(const char *str, const char *key) 972e192b24SSimon Glass { 982e192b24SSimon Glass char *v, *k; 992e192b24SSimon Glass char *s, *strcopy; 1002e192b24SSimon Glass char *new = NULL; 1012e192b24SSimon Glass 1022e192b24SSimon Glass strcopy = strdup(str); 1032e192b24SSimon Glass if (strcopy == NULL) 1042e192b24SSimon Glass return NULL; 1052e192b24SSimon Glass 1062e192b24SSimon Glass s = strcopy; 1072e192b24SSimon Glass while (s) { 1082e192b24SSimon Glass v = strsep(&s, ","); 1092e192b24SSimon Glass if (!v) 1102e192b24SSimon Glass break; 1112e192b24SSimon Glass k = strsep(&v, "="); 1122e192b24SSimon Glass if (!k) 1132e192b24SSimon Glass break; 1142e192b24SSimon Glass if (strcmp(k, key) == 0) { 1152e192b24SSimon Glass new = strdup(v); 1162e192b24SSimon Glass break; 1172e192b24SSimon Glass } 1182e192b24SSimon Glass } 1192e192b24SSimon Glass 1202e192b24SSimon Glass free(strcopy); 1212e192b24SSimon Glass 1222e192b24SSimon Glass return new; 1232e192b24SSimon Glass } 1242e192b24SSimon Glass 1252e192b24SSimon Glass /** 1262e192b24SSimon Glass * found_key(): Found key without value in parameter list (comma separated). 1272e192b24SSimon Glass * 1282e192b24SSimon Glass * @param str - pointer to string with key 1292e192b24SSimon Glass * @param key - pointer to the key to search for 1302e192b24SSimon Glass * 1312e192b24SSimon Glass * @return - true on found key 1322e192b24SSimon Glass */ 1332e192b24SSimon Glass static bool found_key(const char *str, const char *key) 1342e192b24SSimon Glass { 1352e192b24SSimon Glass char *k; 1362e192b24SSimon Glass char *s, *strcopy; 1372e192b24SSimon Glass bool result = false; 1382e192b24SSimon Glass 1392e192b24SSimon Glass strcopy = strdup(str); 1402e192b24SSimon Glass if (!strcopy) 1412e192b24SSimon Glass return NULL; 1422e192b24SSimon Glass 1432e192b24SSimon Glass s = strcopy; 1442e192b24SSimon Glass while (s) { 1452e192b24SSimon Glass k = strsep(&s, ","); 1462e192b24SSimon Glass if (!k) 1472e192b24SSimon Glass break; 1482e192b24SSimon Glass if (strcmp(k, key) == 0) { 1492e192b24SSimon Glass result = true; 1502e192b24SSimon Glass break; 1512e192b24SSimon Glass } 1522e192b24SSimon Glass } 1532e192b24SSimon Glass 1542e192b24SSimon Glass free(strcopy); 1552e192b24SSimon Glass 1562e192b24SSimon Glass return result; 1572e192b24SSimon Glass } 1582e192b24SSimon Glass 15909a49930SAlison Chaiken #ifdef CONFIG_CMD_GPT_RENAME 16009a49930SAlison Chaiken static void del_gpt_info(void) 16109a49930SAlison Chaiken { 16209a49930SAlison Chaiken struct list_head *pos = &disk_partitions; 16309a49930SAlison Chaiken struct disk_part *curr; 16409a49930SAlison Chaiken while (!list_empty(pos)) { 16509a49930SAlison Chaiken curr = list_entry(pos->next, struct disk_part, list); 16609a49930SAlison Chaiken list_del(pos->next); 16709a49930SAlison Chaiken free(curr); 16809a49930SAlison Chaiken } 16909a49930SAlison Chaiken } 17009a49930SAlison Chaiken 17109a49930SAlison Chaiken static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum) 17209a49930SAlison Chaiken { 17309a49930SAlison Chaiken struct disk_part *newpart; 17409a49930SAlison Chaiken newpart = malloc(sizeof(*newpart)); 17509a49930SAlison Chaiken if (!newpart) 17609a49930SAlison Chaiken return ERR_PTR(-ENOMEM); 17709a49930SAlison Chaiken memset(newpart, '\0', sizeof(newpart)); 17809a49930SAlison Chaiken 17909a49930SAlison Chaiken newpart->gpt_part_info.start = info->start; 18009a49930SAlison Chaiken newpart->gpt_part_info.size = info->size; 18109a49930SAlison Chaiken newpart->gpt_part_info.blksz = info->blksz; 18209a49930SAlison Chaiken strncpy((char *)newpart->gpt_part_info.name, (const char *)info->name, 18309a49930SAlison Chaiken PART_NAME_LEN); 18409a49930SAlison Chaiken newpart->gpt_part_info.name[PART_NAME_LEN - 1] = '\0'; 18509a49930SAlison Chaiken strncpy((char *)newpart->gpt_part_info.type, (const char *)info->type, 18609a49930SAlison Chaiken PART_TYPE_LEN); 18709a49930SAlison Chaiken newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0'; 18809a49930SAlison Chaiken newpart->gpt_part_info.bootable = info->bootable; 18909a49930SAlison Chaiken #ifdef CONFIG_PARTITION_UUIDS 19009a49930SAlison Chaiken strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid, 19109a49930SAlison Chaiken UUID_STR_LEN); 19209a49930SAlison Chaiken /* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */ 19309a49930SAlison Chaiken newpart->gpt_part_info.uuid[UUID_STR_LEN] = '\0'; 19409a49930SAlison Chaiken #endif 19509a49930SAlison Chaiken newpart->partnum = partnum; 19609a49930SAlison Chaiken 19709a49930SAlison Chaiken return newpart; 19809a49930SAlison Chaiken } 19909a49930SAlison Chaiken 200*203f9b48SAlison Chaiken static void prettyprint_part_size(char *sizestr, lbaint_t partsize, 201*203f9b48SAlison Chaiken lbaint_t blksize) 202*203f9b48SAlison Chaiken { 203*203f9b48SAlison Chaiken unsigned long long partbytes, partmegabytes; 204*203f9b48SAlison Chaiken 205*203f9b48SAlison Chaiken partbytes = partsize * blksize; 206*203f9b48SAlison Chaiken partmegabytes = lldiv(partbytes, SZ_1M); 207*203f9b48SAlison Chaiken snprintf(sizestr, 16, "%lluMiB", partmegabytes); 208*203f9b48SAlison Chaiken } 209*203f9b48SAlison Chaiken 21009a49930SAlison Chaiken static void print_gpt_info(void) 21109a49930SAlison Chaiken { 21209a49930SAlison Chaiken struct list_head *pos; 21309a49930SAlison Chaiken struct disk_part *curr; 214*203f9b48SAlison Chaiken char partstartstr[16]; 215*203f9b48SAlison Chaiken char partsizestr[16]; 21609a49930SAlison Chaiken 21709a49930SAlison Chaiken list_for_each(pos, &disk_partitions) { 21809a49930SAlison Chaiken curr = list_entry(pos, struct disk_part, list); 219*203f9b48SAlison Chaiken prettyprint_part_size(partstartstr, curr->gpt_part_info.start, 220*203f9b48SAlison Chaiken curr->gpt_part_info.blksz); 221*203f9b48SAlison Chaiken prettyprint_part_size(partsizestr, curr->gpt_part_info.size, 222*203f9b48SAlison Chaiken curr->gpt_part_info.blksz); 223*203f9b48SAlison Chaiken 22409a49930SAlison Chaiken printf("Partition %d:\n", curr->partnum); 225*203f9b48SAlison Chaiken printf("Start %s, size %s\n", partstartstr, partsizestr); 22609a49930SAlison Chaiken printf("Block size %lu, name %s\n", curr->gpt_part_info.blksz, 22709a49930SAlison Chaiken curr->gpt_part_info.name); 22809a49930SAlison Chaiken printf("Type %s, bootable %d\n", curr->gpt_part_info.type, 22909a49930SAlison Chaiken curr->gpt_part_info.bootable); 23009a49930SAlison Chaiken #ifdef CONFIG_PARTITION_UUIDS 23109a49930SAlison Chaiken printf("UUID %s\n", curr->gpt_part_info.uuid); 23209a49930SAlison Chaiken #endif 23309a49930SAlison Chaiken printf("\n"); 23409a49930SAlison Chaiken } 23509a49930SAlison Chaiken } 23609a49930SAlison Chaiken 237*203f9b48SAlison Chaiken static int calc_parts_list_len(int numparts) 238*203f9b48SAlison Chaiken { 239*203f9b48SAlison Chaiken int partlistlen = UUID_STR_LEN + 1 + strlen("uuid_disk="); 240*203f9b48SAlison Chaiken /* for the comma */ 241*203f9b48SAlison Chaiken partlistlen++; 242*203f9b48SAlison Chaiken 243*203f9b48SAlison Chaiken /* per-partition additions; numparts starts at 1, so this should be correct */ 244*203f9b48SAlison Chaiken partlistlen += numparts * (strlen("name=,") + PART_NAME_LEN + 1); 245*203f9b48SAlison Chaiken /* see part.h for definition of struct disk_partition */ 246*203f9b48SAlison Chaiken partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1); 247*203f9b48SAlison Chaiken partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1); 248*203f9b48SAlison Chaiken partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1); 249*203f9b48SAlison Chaiken /* for the terminating null */ 250*203f9b48SAlison Chaiken partlistlen++; 251*203f9b48SAlison Chaiken debug("Length of partitions_list is %d for %d partitions\n", partlistlen, 252*203f9b48SAlison Chaiken numparts); 253*203f9b48SAlison Chaiken return partlistlen; 254*203f9b48SAlison Chaiken } 255*203f9b48SAlison Chaiken 256*203f9b48SAlison Chaiken /* 257*203f9b48SAlison Chaiken * create the string that upstream 'gpt write' command will accept as an 258*203f9b48SAlison Chaiken * argument 259*203f9b48SAlison Chaiken * 260*203f9b48SAlison Chaiken * From doc/README.gpt, Format of partitions layout: 261*203f9b48SAlison Chaiken * "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; 262*203f9b48SAlison Chaiken * name=kernel,size=60MiB,uuid=...;" 263*203f9b48SAlison Chaiken * The fields 'name' and 'size' are mandatory for every partition. 264*203f9b48SAlison Chaiken * The field 'start' is optional. The fields 'uuid' and 'uuid_disk' 265*203f9b48SAlison Chaiken * are optional if CONFIG_RANDOM_UUID is enabled. 266*203f9b48SAlison Chaiken */ 267*203f9b48SAlison Chaiken static int create_gpt_partitions_list(int numparts, const char *guid, 268*203f9b48SAlison Chaiken char *partitions_list) 269*203f9b48SAlison Chaiken { 270*203f9b48SAlison Chaiken struct list_head *pos; 271*203f9b48SAlison Chaiken struct disk_part *curr; 272*203f9b48SAlison Chaiken char partstr[PART_NAME_LEN + 1]; 273*203f9b48SAlison Chaiken 274*203f9b48SAlison Chaiken if (!partitions_list) 275*203f9b48SAlison Chaiken return -EINVAL; 276*203f9b48SAlison Chaiken 277*203f9b48SAlison Chaiken strcpy(partitions_list, "uuid_disk="); 278*203f9b48SAlison Chaiken strncat(partitions_list, guid, UUID_STR_LEN + 1); 279*203f9b48SAlison Chaiken strcat(partitions_list, ";"); 280*203f9b48SAlison Chaiken 281*203f9b48SAlison Chaiken list_for_each(pos, &disk_partitions) { 282*203f9b48SAlison Chaiken curr = list_entry(pos, struct disk_part, list); 283*203f9b48SAlison Chaiken strcat(partitions_list, "name="); 284*203f9b48SAlison Chaiken strncat(partitions_list, (const char *)curr->gpt_part_info.name, 285*203f9b48SAlison Chaiken PART_NAME_LEN + 1); 286*203f9b48SAlison Chaiken strcat(partitions_list, ",start="); 287*203f9b48SAlison Chaiken prettyprint_part_size(partstr, (unsigned long)curr->gpt_part_info.start, 288*203f9b48SAlison Chaiken (unsigned long) curr->gpt_part_info.blksz); 289*203f9b48SAlison Chaiken /* one extra byte for NULL */ 290*203f9b48SAlison Chaiken strncat(partitions_list, partstr, PART_NAME_LEN + 1); 291*203f9b48SAlison Chaiken strcat(partitions_list, ",size="); 292*203f9b48SAlison Chaiken prettyprint_part_size(partstr, curr->gpt_part_info.size, 293*203f9b48SAlison Chaiken curr->gpt_part_info.blksz); 294*203f9b48SAlison Chaiken strncat(partitions_list, partstr, PART_NAME_LEN + 1); 295*203f9b48SAlison Chaiken 296*203f9b48SAlison Chaiken strcat(partitions_list, ",uuid="); 297*203f9b48SAlison Chaiken strncat(partitions_list, curr->gpt_part_info.uuid, 298*203f9b48SAlison Chaiken UUID_STR_LEN + 1); 299*203f9b48SAlison Chaiken strcat(partitions_list, ";"); 300*203f9b48SAlison Chaiken } 301*203f9b48SAlison Chaiken return 0; 302*203f9b48SAlison Chaiken } 303*203f9b48SAlison Chaiken 30409a49930SAlison Chaiken /* 30509a49930SAlison Chaiken * read partition info into disk_partitions list where 30609a49930SAlison Chaiken * it can be printed or modified 30709a49930SAlison Chaiken */ 30809a49930SAlison Chaiken static int get_gpt_info(struct blk_desc *dev_desc) 30909a49930SAlison Chaiken { 31009a49930SAlison Chaiken /* start partition numbering at 1, as U-Boot does */ 31109a49930SAlison Chaiken int valid_parts = 0, p, ret; 31209a49930SAlison Chaiken disk_partition_t info; 31309a49930SAlison Chaiken struct disk_part *new_disk_part; 31409a49930SAlison Chaiken 315*203f9b48SAlison Chaiken /* 316*203f9b48SAlison Chaiken * Always re-read partition info from device, in case 317*203f9b48SAlison Chaiken * it has changed 318*203f9b48SAlison Chaiken */ 31909a49930SAlison Chaiken INIT_LIST_HEAD(&disk_partitions); 32009a49930SAlison Chaiken 32109a49930SAlison Chaiken for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { 32209a49930SAlison Chaiken ret = part_get_info(dev_desc, p, &info); 32309a49930SAlison Chaiken if (ret) 32409a49930SAlison Chaiken continue; 32509a49930SAlison Chaiken 32609a49930SAlison Chaiken /* Add 1 here because counter is zero-based but p1 is 32709a49930SAlison Chaiken the first partition */ 32809a49930SAlison Chaiken new_disk_part = allocate_disk_part(&info, valid_parts+1); 32909a49930SAlison Chaiken if (IS_ERR(new_disk_part)) 33009a49930SAlison Chaiken goto out; 33109a49930SAlison Chaiken 33209a49930SAlison Chaiken list_add_tail(&new_disk_part->list, &disk_partitions); 33309a49930SAlison Chaiken valid_parts++; 33409a49930SAlison Chaiken } 33509a49930SAlison Chaiken if (valid_parts == 0) { 33609a49930SAlison Chaiken printf("** No valid partitions found **\n"); 33709a49930SAlison Chaiken goto out; 33809a49930SAlison Chaiken } 33909a49930SAlison Chaiken return valid_parts; 34009a49930SAlison Chaiken out: 34109a49930SAlison Chaiken if (valid_parts >= 1) 34209a49930SAlison Chaiken del_gpt_info(); 34309a49930SAlison Chaiken return -ENODEV; 34409a49930SAlison Chaiken } 34509a49930SAlison Chaiken 34609a49930SAlison Chaiken /* a wrapper to test get_gpt_info */ 34709a49930SAlison Chaiken static int do_get_gpt_info(struct blk_desc *dev_desc) 34809a49930SAlison Chaiken { 34909a49930SAlison Chaiken int ret; 35009a49930SAlison Chaiken 35109a49930SAlison Chaiken ret = get_gpt_info(dev_desc); 35209a49930SAlison Chaiken if (ret > 0) { 35309a49930SAlison Chaiken print_gpt_info(); 35409a49930SAlison Chaiken del_gpt_info(); 35509a49930SAlison Chaiken return 0; 35609a49930SAlison Chaiken } 35709a49930SAlison Chaiken return ret; 35809a49930SAlison Chaiken } 35909a49930SAlison Chaiken #endif 36009a49930SAlison Chaiken 3612e192b24SSimon Glass /** 3622e192b24SSimon Glass * set_gpt_info(): Fill partition information from string 3632e192b24SSimon Glass * function allocates memory, remember to free! 3642e192b24SSimon Glass * 3652e192b24SSimon Glass * @param dev_desc - pointer block device descriptor 3662e192b24SSimon Glass * @param str_part - pointer to string with partition information 3672e192b24SSimon Glass * @param str_disk_guid - pointer to pointer to allocated string with disk guid 3682e192b24SSimon Glass * @param partitions - pointer to pointer to allocated partitions array 3692e192b24SSimon Glass * @param parts_count - number of partitions 3702e192b24SSimon Glass * 3712e192b24SSimon Glass * @return - zero on success, otherwise error 3722e192b24SSimon Glass * 3732e192b24SSimon Glass */ 3744101f687SSimon Glass static int set_gpt_info(struct blk_desc *dev_desc, 3752e192b24SSimon Glass const char *str_part, 3762e192b24SSimon Glass char **str_disk_guid, 3772e192b24SSimon Glass disk_partition_t **partitions, 3782e192b24SSimon Glass u8 *parts_count) 3792e192b24SSimon Glass { 3802e192b24SSimon Glass char *tok, *str, *s; 3812e192b24SSimon Glass int i; 3822e192b24SSimon Glass char *val, *p; 3832e192b24SSimon Glass int p_count; 3842e192b24SSimon Glass disk_partition_t *parts; 3852e192b24SSimon Glass int errno = 0; 3862e192b24SSimon Glass uint64_t size_ll, start_ll; 38766636235SMichael Trimarchi lbaint_t offset = 0; 3882e192b24SSimon Glass 3892e192b24SSimon Glass debug("%s: lba num: 0x%x %d\n", __func__, 3902e192b24SSimon Glass (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba); 3912e192b24SSimon Glass 3922e192b24SSimon Glass if (str_part == NULL) 3932e192b24SSimon Glass return -1; 3942e192b24SSimon Glass 3952e192b24SSimon Glass str = strdup(str_part); 396*203f9b48SAlison Chaiken if (str == NULL) 397*203f9b48SAlison Chaiken return -ENOMEM; 3982e192b24SSimon Glass 3992e192b24SSimon Glass /* extract disk guid */ 4002e192b24SSimon Glass s = str; 4012e192b24SSimon Glass val = extract_val(str, "uuid_disk"); 4022e192b24SSimon Glass if (!val) { 4032e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 4042e192b24SSimon Glass *str_disk_guid = malloc(UUID_STR_LEN + 1); 4052e192b24SSimon Glass gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD); 4062e192b24SSimon Glass #else 4072e192b24SSimon Glass free(str); 4082e192b24SSimon Glass return -2; 4092e192b24SSimon Glass #endif 4102e192b24SSimon Glass } else { 4112e192b24SSimon Glass val = strsep(&val, ";"); 4122e192b24SSimon Glass if (extract_env(val, &p)) 4132e192b24SSimon Glass p = val; 4142e192b24SSimon Glass *str_disk_guid = strdup(p); 4152e192b24SSimon Glass free(val); 4162e192b24SSimon Glass /* Move s to first partition */ 4172e192b24SSimon Glass strsep(&s, ";"); 4182e192b24SSimon Glass } 4192e192b24SSimon Glass if (strlen(s) == 0) 4202e192b24SSimon Glass return -3; 4212e192b24SSimon Glass 4222e192b24SSimon Glass i = strlen(s) - 1; 4232e192b24SSimon Glass if (s[i] == ';') 4242e192b24SSimon Glass s[i] = '\0'; 4252e192b24SSimon Glass 4262e192b24SSimon Glass /* calculate expected number of partitions */ 4272e192b24SSimon Glass p_count = 1; 4282e192b24SSimon Glass p = s; 4292e192b24SSimon Glass while (*p) { 4302e192b24SSimon Glass if (*p++ == ';') 4312e192b24SSimon Glass p_count++; 4322e192b24SSimon Glass } 4332e192b24SSimon Glass 4342e192b24SSimon Glass /* allocate memory for partitions */ 4352e192b24SSimon Glass parts = calloc(sizeof(disk_partition_t), p_count); 4362e192b24SSimon Glass 4372e192b24SSimon Glass /* retrieve partitions data from string */ 4382e192b24SSimon Glass for (i = 0; i < p_count; i++) { 4392e192b24SSimon Glass tok = strsep(&s, ";"); 4402e192b24SSimon Glass 4412e192b24SSimon Glass if (tok == NULL) 4422e192b24SSimon Glass break; 4432e192b24SSimon Glass 4442e192b24SSimon Glass /* uuid */ 4452e192b24SSimon Glass val = extract_val(tok, "uuid"); 4462e192b24SSimon Glass if (!val) { 4472e192b24SSimon Glass /* 'uuid' is optional if random uuid's are enabled */ 4482e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 4492e192b24SSimon Glass gen_rand_uuid_str(parts[i].uuid, UUID_STR_FORMAT_STD); 4502e192b24SSimon Glass #else 4512e192b24SSimon Glass errno = -4; 4522e192b24SSimon Glass goto err; 4532e192b24SSimon Glass #endif 4542e192b24SSimon Glass } else { 4552e192b24SSimon Glass if (extract_env(val, &p)) 4562e192b24SSimon Glass p = val; 4572e192b24SSimon Glass if (strlen(p) >= sizeof(parts[i].uuid)) { 4582e192b24SSimon Glass printf("Wrong uuid format for partition %d\n", i); 4592e192b24SSimon Glass errno = -4; 4602e192b24SSimon Glass goto err; 4612e192b24SSimon Glass } 4622e192b24SSimon Glass strcpy((char *)parts[i].uuid, p); 4632e192b24SSimon Glass free(val); 4642e192b24SSimon Glass } 4652e192b24SSimon Glass #ifdef CONFIG_PARTITION_TYPE_GUID 4662e192b24SSimon Glass /* guid */ 4672e192b24SSimon Glass val = extract_val(tok, "type"); 4682e192b24SSimon Glass if (val) { 4692e192b24SSimon Glass /* 'type' is optional */ 4702e192b24SSimon Glass if (extract_env(val, &p)) 4712e192b24SSimon Glass p = val; 4722e192b24SSimon Glass if (strlen(p) >= sizeof(parts[i].type_guid)) { 4732e192b24SSimon Glass printf("Wrong type guid format for partition %d\n", 4742e192b24SSimon Glass i); 4752e192b24SSimon Glass errno = -4; 4762e192b24SSimon Glass goto err; 4772e192b24SSimon Glass } 4782e192b24SSimon Glass strcpy((char *)parts[i].type_guid, p); 4792e192b24SSimon Glass free(val); 4802e192b24SSimon Glass } 4812e192b24SSimon Glass #endif 4822e192b24SSimon Glass /* name */ 4832e192b24SSimon Glass val = extract_val(tok, "name"); 4842e192b24SSimon Glass if (!val) { /* name is mandatory */ 4852e192b24SSimon Glass errno = -4; 4862e192b24SSimon Glass goto err; 4872e192b24SSimon Glass } 4882e192b24SSimon Glass if (extract_env(val, &p)) 4892e192b24SSimon Glass p = val; 4902e192b24SSimon Glass if (strlen(p) >= sizeof(parts[i].name)) { 4912e192b24SSimon Glass errno = -4; 4922e192b24SSimon Glass goto err; 4932e192b24SSimon Glass } 4942e192b24SSimon Glass strcpy((char *)parts[i].name, p); 4952e192b24SSimon Glass free(val); 4962e192b24SSimon Glass 4972e192b24SSimon Glass /* size */ 4982e192b24SSimon Glass val = extract_val(tok, "size"); 4992e192b24SSimon Glass if (!val) { /* 'size' is mandatory */ 5002e192b24SSimon Glass errno = -4; 5012e192b24SSimon Glass goto err; 5022e192b24SSimon Glass } 5032e192b24SSimon Glass if (extract_env(val, &p)) 5042e192b24SSimon Glass p = val; 50566636235SMichael Trimarchi if ((strcmp(p, "-") == 0)) { 506c2fdd345SKever Yang /* Let part efi module to auto extend the size */ 507c2fdd345SKever Yang parts[i].size = 0; 50866636235SMichael Trimarchi } else { 5092e192b24SSimon Glass size_ll = ustrtoull(p, &p, 0); 5102e192b24SSimon Glass parts[i].size = lldiv(size_ll, dev_desc->blksz); 51166636235SMichael Trimarchi } 51266636235SMichael Trimarchi 5132e192b24SSimon Glass free(val); 5142e192b24SSimon Glass 5152e192b24SSimon Glass /* start address */ 5162e192b24SSimon Glass val = extract_val(tok, "start"); 5172e192b24SSimon Glass if (val) { /* start address is optional */ 5182e192b24SSimon Glass if (extract_env(val, &p)) 5192e192b24SSimon Glass p = val; 5202e192b24SSimon Glass start_ll = ustrtoull(p, &p, 0); 5212e192b24SSimon Glass parts[i].start = lldiv(start_ll, dev_desc->blksz); 5222e192b24SSimon Glass free(val); 5232e192b24SSimon Glass } 5242e192b24SSimon Glass 52566636235SMichael Trimarchi offset += parts[i].size + parts[i].start; 52666636235SMichael Trimarchi 5272e192b24SSimon Glass /* bootable */ 5282e192b24SSimon Glass if (found_key(tok, "bootable")) 5292e192b24SSimon Glass parts[i].bootable = 1; 5302e192b24SSimon Glass } 5312e192b24SSimon Glass 5322e192b24SSimon Glass *parts_count = p_count; 5332e192b24SSimon Glass *partitions = parts; 5342e192b24SSimon Glass free(str); 5352e192b24SSimon Glass 5362e192b24SSimon Glass return 0; 5372e192b24SSimon Glass err: 5382e192b24SSimon Glass free(str); 5392e192b24SSimon Glass free(*str_disk_guid); 5402e192b24SSimon Glass free(parts); 5412e192b24SSimon Glass 5422e192b24SSimon Glass return errno; 5432e192b24SSimon Glass } 5442e192b24SSimon Glass 5454101f687SSimon Glass static int gpt_default(struct blk_desc *blk_dev_desc, const char *str_part) 5462e192b24SSimon Glass { 5472e192b24SSimon Glass int ret; 5482e192b24SSimon Glass char *str_disk_guid; 5492e192b24SSimon Glass u8 part_count = 0; 5502e192b24SSimon Glass disk_partition_t *partitions = NULL; 5512e192b24SSimon Glass 5522e192b24SSimon Glass /* fill partitions */ 5532e192b24SSimon Glass ret = set_gpt_info(blk_dev_desc, str_part, 5542e192b24SSimon Glass &str_disk_guid, &partitions, &part_count); 5552e192b24SSimon Glass if (ret) { 5562e192b24SSimon Glass if (ret == -1) 5572e192b24SSimon Glass printf("No partition list provided\n"); 5582e192b24SSimon Glass if (ret == -2) 5592e192b24SSimon Glass printf("Missing disk guid\n"); 5602e192b24SSimon Glass if ((ret == -3) || (ret == -4)) 5612e192b24SSimon Glass printf("Partition list incomplete\n"); 5622e192b24SSimon Glass return -1; 5632e192b24SSimon Glass } 5642e192b24SSimon Glass 5652e192b24SSimon Glass /* save partitions layout to disk */ 5662e192b24SSimon Glass ret = gpt_restore(blk_dev_desc, str_disk_guid, partitions, part_count); 5672e192b24SSimon Glass free(str_disk_guid); 5682e192b24SSimon Glass free(partitions); 5692e192b24SSimon Glass 5702e192b24SSimon Glass return ret; 5712e192b24SSimon Glass } 5722e192b24SSimon Glass 5734101f687SSimon Glass static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part) 5742e192b24SSimon Glass { 5752e192b24SSimon Glass ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, 5762e192b24SSimon Glass blk_dev_desc->blksz); 5772e192b24SSimon Glass disk_partition_t *partitions = NULL; 5782e192b24SSimon Glass gpt_entry *gpt_pte = NULL; 5792e192b24SSimon Glass char *str_disk_guid; 5802e192b24SSimon Glass u8 part_count = 0; 5812e192b24SSimon Glass int ret = 0; 5822e192b24SSimon Glass 5832e192b24SSimon Glass /* fill partitions */ 5842e192b24SSimon Glass ret = set_gpt_info(blk_dev_desc, str_part, 5852e192b24SSimon Glass &str_disk_guid, &partitions, &part_count); 5862e192b24SSimon Glass if (ret) { 5872e192b24SSimon Glass if (ret == -1) { 5882e192b24SSimon Glass printf("No partition list provided - only basic check\n"); 5892e192b24SSimon Glass ret = gpt_verify_headers(blk_dev_desc, gpt_head, 5902e192b24SSimon Glass &gpt_pte); 5912e192b24SSimon Glass goto out; 5922e192b24SSimon Glass } 5932e192b24SSimon Glass if (ret == -2) 5942e192b24SSimon Glass printf("Missing disk guid\n"); 5952e192b24SSimon Glass if ((ret == -3) || (ret == -4)) 5962e192b24SSimon Glass printf("Partition list incomplete\n"); 5972e192b24SSimon Glass return -1; 5982e192b24SSimon Glass } 5992e192b24SSimon Glass 6002e192b24SSimon Glass /* Check partition layout with provided pattern */ 6012e192b24SSimon Glass ret = gpt_verify_partitions(blk_dev_desc, partitions, part_count, 6022e192b24SSimon Glass gpt_head, &gpt_pte); 6032e192b24SSimon Glass free(str_disk_guid); 6042e192b24SSimon Glass free(partitions); 6052e192b24SSimon Glass out: 6062e192b24SSimon Glass free(gpt_pte); 6072e192b24SSimon Glass return ret; 6082e192b24SSimon Glass } 6092e192b24SSimon Glass 61073d6d18bSAlison Chaiken static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) 61173d6d18bSAlison Chaiken { 61273d6d18bSAlison Chaiken int ret; 61373d6d18bSAlison Chaiken char disk_guid[UUID_STR_LEN + 1]; 61473d6d18bSAlison Chaiken 61573d6d18bSAlison Chaiken ret = get_disk_guid(dev_desc, disk_guid); 61673d6d18bSAlison Chaiken if (ret < 0) 61773d6d18bSAlison Chaiken return CMD_RET_FAILURE; 61873d6d18bSAlison Chaiken 61973d6d18bSAlison Chaiken if (namestr) 62073d6d18bSAlison Chaiken setenv(namestr, disk_guid); 62173d6d18bSAlison Chaiken else 62273d6d18bSAlison Chaiken printf("%s\n", disk_guid); 62373d6d18bSAlison Chaiken 62473d6d18bSAlison Chaiken return ret; 62573d6d18bSAlison Chaiken } 62673d6d18bSAlison Chaiken 627*203f9b48SAlison Chaiken #ifdef CONFIG_CMD_GPT_RENAME 628*203f9b48SAlison Chaiken static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm, 629*203f9b48SAlison Chaiken char *name1, char *name2) 630*203f9b48SAlison Chaiken { 631*203f9b48SAlison Chaiken struct list_head *pos; 632*203f9b48SAlison Chaiken struct disk_part *curr; 633*203f9b48SAlison Chaiken disk_partition_t *new_partitions = NULL; 634*203f9b48SAlison Chaiken char disk_guid[UUID_STR_LEN + 1]; 635*203f9b48SAlison Chaiken char *partitions_list, *str_disk_guid; 636*203f9b48SAlison Chaiken u8 part_count = 0; 637*203f9b48SAlison Chaiken int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0; 638*203f9b48SAlison Chaiken 639*203f9b48SAlison Chaiken if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) || 640*203f9b48SAlison Chaiken (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename")))) 641*203f9b48SAlison Chaiken return -EINVAL; 642*203f9b48SAlison Chaiken 643*203f9b48SAlison Chaiken ret = get_disk_guid(dev_desc, disk_guid); 644*203f9b48SAlison Chaiken if (ret < 0) 645*203f9b48SAlison Chaiken return ret; 646*203f9b48SAlison Chaiken numparts = get_gpt_info(dev_desc); 647*203f9b48SAlison Chaiken if (numparts <= 0) 648*203f9b48SAlison Chaiken return numparts ? numparts : -ENODEV; 649*203f9b48SAlison Chaiken 650*203f9b48SAlison Chaiken partlistlen = calc_parts_list_len(numparts); 651*203f9b48SAlison Chaiken partitions_list = malloc(partlistlen); 652*203f9b48SAlison Chaiken if (partitions_list == NULL) 653*203f9b48SAlison Chaiken return -ENOMEM; 654*203f9b48SAlison Chaiken memset(partitions_list, '\0', partlistlen); 655*203f9b48SAlison Chaiken 656*203f9b48SAlison Chaiken ret = create_gpt_partitions_list(numparts, disk_guid, partitions_list); 657*203f9b48SAlison Chaiken if (ret < 0) 658*203f9b48SAlison Chaiken return ret; 659*203f9b48SAlison Chaiken /* 660*203f9b48SAlison Chaiken * Uncomment the following line to print a string that 'gpt write' 661*203f9b48SAlison Chaiken * or 'gpt verify' will accept as input. 662*203f9b48SAlison Chaiken */ 663*203f9b48SAlison Chaiken debug("OLD partitions_list is %s with %u chars\n", partitions_list, 664*203f9b48SAlison Chaiken (unsigned)strlen(partitions_list)); 665*203f9b48SAlison Chaiken 666*203f9b48SAlison Chaiken ret = set_gpt_info(dev_desc, partitions_list, &str_disk_guid, 667*203f9b48SAlison Chaiken &new_partitions, &part_count); 668*203f9b48SAlison Chaiken if (ret < 0) 669*203f9b48SAlison Chaiken return ret; 670*203f9b48SAlison Chaiken 671*203f9b48SAlison Chaiken if (!strcmp(subcomm, "swap")) { 672*203f9b48SAlison Chaiken if ((strlen(name1) > PART_NAME_LEN) || (strlen(name2) > PART_NAME_LEN)) { 673*203f9b48SAlison Chaiken printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN); 674*203f9b48SAlison Chaiken return -EINVAL; 675*203f9b48SAlison Chaiken } 676*203f9b48SAlison Chaiken list_for_each(pos, &disk_partitions) { 677*203f9b48SAlison Chaiken curr = list_entry(pos, struct disk_part, list); 678*203f9b48SAlison Chaiken if (!strcmp((char *)curr->gpt_part_info.name, name1)) { 679*203f9b48SAlison Chaiken strcpy((char *)curr->gpt_part_info.name, name2); 680*203f9b48SAlison Chaiken ctr1++; 681*203f9b48SAlison Chaiken } else if (!strcmp((char *)curr->gpt_part_info.name, name2)) { 682*203f9b48SAlison Chaiken strcpy((char *)curr->gpt_part_info.name, name1); 683*203f9b48SAlison Chaiken ctr2++; 684*203f9b48SAlison Chaiken } 685*203f9b48SAlison Chaiken } 686*203f9b48SAlison Chaiken if ((ctr1 + ctr2 < 2) || (ctr1 != ctr2)) { 687*203f9b48SAlison Chaiken printf("Cannot swap partition names except in pairs.\n"); 688*203f9b48SAlison Chaiken return -EINVAL; 689*203f9b48SAlison Chaiken } 690*203f9b48SAlison Chaiken } else { /* rename */ 691*203f9b48SAlison Chaiken if (strlen(name2) > PART_NAME_LEN) { 692*203f9b48SAlison Chaiken printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN); 693*203f9b48SAlison Chaiken return -EINVAL; 694*203f9b48SAlison Chaiken } 695*203f9b48SAlison Chaiken partnum = (int)simple_strtol(name1, NULL, 10); 696*203f9b48SAlison Chaiken if ((partnum < 0) || (partnum > numparts)) { 697*203f9b48SAlison Chaiken printf("Illegal partition number %s\n", name1); 698*203f9b48SAlison Chaiken return -EINVAL; 699*203f9b48SAlison Chaiken } 700*203f9b48SAlison Chaiken ret = part_get_info(dev_desc, partnum, new_partitions); 701*203f9b48SAlison Chaiken if (ret < 0) 702*203f9b48SAlison Chaiken return ret; 703*203f9b48SAlison Chaiken 704*203f9b48SAlison Chaiken /* U-Boot partition numbering starts at 1 */ 705*203f9b48SAlison Chaiken list_for_each(pos, &disk_partitions) { 706*203f9b48SAlison Chaiken curr = list_entry(pos, struct disk_part, list); 707*203f9b48SAlison Chaiken if (i == partnum) { 708*203f9b48SAlison Chaiken strcpy((char *)curr->gpt_part_info.name, name2); 709*203f9b48SAlison Chaiken break; 710*203f9b48SAlison Chaiken } 711*203f9b48SAlison Chaiken i++; 712*203f9b48SAlison Chaiken } 713*203f9b48SAlison Chaiken } 714*203f9b48SAlison Chaiken 715*203f9b48SAlison Chaiken ret = create_gpt_partitions_list(numparts, disk_guid, partitions_list); 716*203f9b48SAlison Chaiken if (ret < 0) 717*203f9b48SAlison Chaiken return ret; 718*203f9b48SAlison Chaiken debug("NEW partitions_list is %s with %u chars\n", partitions_list, 719*203f9b48SAlison Chaiken (unsigned)strlen(partitions_list)); 720*203f9b48SAlison Chaiken 721*203f9b48SAlison Chaiken ret = set_gpt_info(dev_desc, partitions_list, &str_disk_guid, 722*203f9b48SAlison Chaiken &new_partitions, &part_count); 723*203f9b48SAlison Chaiken if (ret < 0) 724*203f9b48SAlison Chaiken return ret; 725*203f9b48SAlison Chaiken 726*203f9b48SAlison Chaiken debug("Writing new partition table\n"); 727*203f9b48SAlison Chaiken ret = gpt_restore(dev_desc, disk_guid, new_partitions, numparts); 728*203f9b48SAlison Chaiken if (ret < 0) { 729*203f9b48SAlison Chaiken printf("Writing new partition table failed\n"); 730*203f9b48SAlison Chaiken return ret; 731*203f9b48SAlison Chaiken } 732*203f9b48SAlison Chaiken 733*203f9b48SAlison Chaiken debug("Reading back new partition table\n"); 734*203f9b48SAlison Chaiken numparts = get_gpt_info(dev_desc); 735*203f9b48SAlison Chaiken if (numparts <= 0) 736*203f9b48SAlison Chaiken return numparts ? numparts : -ENODEV; 737*203f9b48SAlison Chaiken printf("new partition table with %d partitions is:\n", numparts); 738*203f9b48SAlison Chaiken print_gpt_info(); 739*203f9b48SAlison Chaiken 740*203f9b48SAlison Chaiken del_gpt_info(); 741*203f9b48SAlison Chaiken free(partitions_list); 742*203f9b48SAlison Chaiken free(str_disk_guid); 743*203f9b48SAlison Chaiken free(new_partitions); 744*203f9b48SAlison Chaiken return ret; 745*203f9b48SAlison Chaiken } 746*203f9b48SAlison Chaiken #endif 747*203f9b48SAlison Chaiken 7482e192b24SSimon Glass /** 7492e192b24SSimon Glass * do_gpt(): Perform GPT operations 7502e192b24SSimon Glass * 7512e192b24SSimon Glass * @param cmdtp - command name 7522e192b24SSimon Glass * @param flag 7532e192b24SSimon Glass * @param argc 7542e192b24SSimon Glass * @param argv 7552e192b24SSimon Glass * 7562e192b24SSimon Glass * @return zero on success; otherwise error 7572e192b24SSimon Glass */ 7582e192b24SSimon Glass static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 7592e192b24SSimon Glass { 7602e192b24SSimon Glass int ret = CMD_RET_SUCCESS; 7612e192b24SSimon Glass int dev = 0; 7622e192b24SSimon Glass char *ep; 7634101f687SSimon Glass struct blk_desc *blk_dev_desc = NULL; 7642e192b24SSimon Glass 765*203f9b48SAlison Chaiken #ifndef CONFIG_CMD_GPT_RENAME 7662e192b24SSimon Glass if (argc < 4 || argc > 5) 767*203f9b48SAlison Chaiken #else 768*203f9b48SAlison Chaiken if (argc < 4 || argc > 6) 769*203f9b48SAlison Chaiken #endif 7702e192b24SSimon Glass return CMD_RET_USAGE; 7712e192b24SSimon Glass 7722e192b24SSimon Glass dev = (int)simple_strtoul(argv[3], &ep, 10); 7732e192b24SSimon Glass if (!ep || ep[0] != '\0') { 7742e192b24SSimon Glass printf("'%s' is not a number\n", argv[3]); 7752e192b24SSimon Glass return CMD_RET_USAGE; 7762e192b24SSimon Glass } 777db1d9e78SSimon Glass blk_dev_desc = blk_get_dev(argv[2], dev); 7782e192b24SSimon Glass if (!blk_dev_desc) { 7792e192b24SSimon Glass printf("%s: %s dev %d NOT available\n", 7802e192b24SSimon Glass __func__, argv[2], dev); 7812e192b24SSimon Glass return CMD_RET_FAILURE; 7822e192b24SSimon Glass } 7832e192b24SSimon Glass 7842e192b24SSimon Glass if ((strcmp(argv[1], "write") == 0) && (argc == 5)) { 7852e192b24SSimon Glass printf("Writing GPT: "); 7862e192b24SSimon Glass ret = gpt_default(blk_dev_desc, argv[4]); 7872e192b24SSimon Glass } else if ((strcmp(argv[1], "verify") == 0)) { 7882e192b24SSimon Glass ret = gpt_verify(blk_dev_desc, argv[4]); 7892e192b24SSimon Glass printf("Verify GPT: "); 79073d6d18bSAlison Chaiken } else if (strcmp(argv[1], "guid") == 0) { 79173d6d18bSAlison Chaiken ret = do_disk_guid(blk_dev_desc, argv[4]); 79209a49930SAlison Chaiken #ifdef CONFIG_CMD_GPT_RENAME 79309a49930SAlison Chaiken } else if (strcmp(argv[1], "read") == 0) { 79409a49930SAlison Chaiken ret = do_get_gpt_info(blk_dev_desc); 795*203f9b48SAlison Chaiken } else if ((strcmp(argv[1], "swap") == 0) || 796*203f9b48SAlison Chaiken (strcmp(argv[1], "rename") == 0)) { 797*203f9b48SAlison Chaiken ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]); 79809a49930SAlison Chaiken #endif 7992e192b24SSimon Glass } else { 8002e192b24SSimon Glass return CMD_RET_USAGE; 8012e192b24SSimon Glass } 8022e192b24SSimon Glass 8032e192b24SSimon Glass if (ret) { 8042e192b24SSimon Glass printf("error!\n"); 8052e192b24SSimon Glass return CMD_RET_FAILURE; 8062e192b24SSimon Glass } 8072e192b24SSimon Glass 8082e192b24SSimon Glass printf("success!\n"); 8092e192b24SSimon Glass return CMD_RET_SUCCESS; 8102e192b24SSimon Glass } 8112e192b24SSimon Glass 8122e192b24SSimon Glass U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt, 8132e192b24SSimon Glass "GUID Partition Table", 8142e192b24SSimon Glass "<command> <interface> <dev> <partitions_list>\n" 8152e192b24SSimon Glass " - GUID partition table restoration and validity check\n" 8162e192b24SSimon Glass " Restore or verify GPT information on a device connected\n" 8172e192b24SSimon Glass " to interface\n" 8182e192b24SSimon Glass " Example usage:\n" 8192e192b24SSimon Glass " gpt write mmc 0 $partitions\n" 8202e192b24SSimon Glass " gpt verify mmc 0 $partitions\n" 82109a49930SAlison Chaiken " read <interface> <dev>\n" 82209a49930SAlison Chaiken " - read GPT into a data structure for manipulation\n" 82373d6d18bSAlison Chaiken " guid <interface> <dev>\n" 82473d6d18bSAlison Chaiken " - print disk GUID\n" 82573d6d18bSAlison Chaiken " guid <interface> <dev> <varname>\n" 82673d6d18bSAlison Chaiken " - set environment variable to disk GUID\n" 82773d6d18bSAlison Chaiken " Example usage:\n" 82873d6d18bSAlison Chaiken " gpt guid mmc 0\n" 82973d6d18bSAlison Chaiken " gpt guid mmc 0 varname\n" 830*203f9b48SAlison Chaiken #ifdef CONFIG_CMD_GPT_RENAME 831*203f9b48SAlison Chaiken "gpt partition renaming commands:\n" 832*203f9b48SAlison Chaiken "gpt swap <interface> <dev> <name1> <name2>\n" 833*203f9b48SAlison Chaiken " - change all partitions named name1 to name2\n" 834*203f9b48SAlison Chaiken " and vice-versa\n" 835*203f9b48SAlison Chaiken "gpt rename <interface> <dev> <part> <name>\n" 836*203f9b48SAlison Chaiken " - rename the specified partition\n" 837*203f9b48SAlison Chaiken " Example usage:\n" 838*203f9b48SAlison Chaiken " gpt swap mmc 0 foo bar\n" 839*203f9b48SAlison Chaiken " gpt rename mmc 0 3 foo\n" 840*203f9b48SAlison Chaiken #endif 8412e192b24SSimon Glass ); 842