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> 23203f9b48SAlison Chaiken #include <linux/sizes.h> 24203f9b48SAlison 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 159*2fcaa413SAlison Chaiken static int calc_parts_list_len(int numparts) 160*2fcaa413SAlison Chaiken { 161*2fcaa413SAlison Chaiken int partlistlen = UUID_STR_LEN + 1 + strlen("uuid_disk="); 162*2fcaa413SAlison Chaiken /* for the comma */ 163*2fcaa413SAlison Chaiken partlistlen++; 164*2fcaa413SAlison Chaiken 165*2fcaa413SAlison Chaiken /* per-partition additions; numparts starts at 1, so this should be correct */ 166*2fcaa413SAlison Chaiken partlistlen += numparts * (strlen("name=,") + PART_NAME_LEN + 1); 167*2fcaa413SAlison Chaiken /* see part.h for definition of struct disk_partition */ 168*2fcaa413SAlison Chaiken partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1); 169*2fcaa413SAlison Chaiken partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1); 170*2fcaa413SAlison Chaiken partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1); 171*2fcaa413SAlison Chaiken /* for the terminating null */ 172*2fcaa413SAlison Chaiken partlistlen++; 173*2fcaa413SAlison Chaiken debug("Length of partitions_list is %d for %d partitions\n", partlistlen, 174*2fcaa413SAlison Chaiken numparts); 175*2fcaa413SAlison Chaiken return partlistlen; 176*2fcaa413SAlison Chaiken } 177*2fcaa413SAlison Chaiken 17809a49930SAlison Chaiken #ifdef CONFIG_CMD_GPT_RENAME 17909a49930SAlison Chaiken static void del_gpt_info(void) 18009a49930SAlison Chaiken { 18109a49930SAlison Chaiken struct list_head *pos = &disk_partitions; 18209a49930SAlison Chaiken struct disk_part *curr; 18309a49930SAlison Chaiken while (!list_empty(pos)) { 18409a49930SAlison Chaiken curr = list_entry(pos->next, struct disk_part, list); 18509a49930SAlison Chaiken list_del(pos->next); 18609a49930SAlison Chaiken free(curr); 18709a49930SAlison Chaiken } 18809a49930SAlison Chaiken } 18909a49930SAlison Chaiken 19009a49930SAlison Chaiken static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum) 19109a49930SAlison Chaiken { 19209a49930SAlison Chaiken struct disk_part *newpart; 19309a49930SAlison Chaiken newpart = malloc(sizeof(*newpart)); 19409a49930SAlison Chaiken if (!newpart) 19509a49930SAlison Chaiken return ERR_PTR(-ENOMEM); 19609a49930SAlison Chaiken memset(newpart, '\0', sizeof(newpart)); 19709a49930SAlison Chaiken 19809a49930SAlison Chaiken newpart->gpt_part_info.start = info->start; 19909a49930SAlison Chaiken newpart->gpt_part_info.size = info->size; 20009a49930SAlison Chaiken newpart->gpt_part_info.blksz = info->blksz; 20109a49930SAlison Chaiken strncpy((char *)newpart->gpt_part_info.name, (const char *)info->name, 20209a49930SAlison Chaiken PART_NAME_LEN); 20309a49930SAlison Chaiken newpart->gpt_part_info.name[PART_NAME_LEN - 1] = '\0'; 20409a49930SAlison Chaiken strncpy((char *)newpart->gpt_part_info.type, (const char *)info->type, 20509a49930SAlison Chaiken PART_TYPE_LEN); 20609a49930SAlison Chaiken newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0'; 20709a49930SAlison Chaiken newpart->gpt_part_info.bootable = info->bootable; 20809a49930SAlison Chaiken #ifdef CONFIG_PARTITION_UUIDS 20909a49930SAlison Chaiken strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid, 21009a49930SAlison Chaiken UUID_STR_LEN); 21109a49930SAlison Chaiken /* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */ 21209a49930SAlison Chaiken newpart->gpt_part_info.uuid[UUID_STR_LEN] = '\0'; 21309a49930SAlison Chaiken #endif 21409a49930SAlison Chaiken newpart->partnum = partnum; 21509a49930SAlison Chaiken 21609a49930SAlison Chaiken return newpart; 21709a49930SAlison Chaiken } 21809a49930SAlison Chaiken 219203f9b48SAlison Chaiken static void prettyprint_part_size(char *sizestr, lbaint_t partsize, 220203f9b48SAlison Chaiken lbaint_t blksize) 221203f9b48SAlison Chaiken { 222203f9b48SAlison Chaiken unsigned long long partbytes, partmegabytes; 223203f9b48SAlison Chaiken 224203f9b48SAlison Chaiken partbytes = partsize * blksize; 225203f9b48SAlison Chaiken partmegabytes = lldiv(partbytes, SZ_1M); 226203f9b48SAlison Chaiken snprintf(sizestr, 16, "%lluMiB", partmegabytes); 227203f9b48SAlison Chaiken } 228203f9b48SAlison Chaiken 22909a49930SAlison Chaiken static void print_gpt_info(void) 23009a49930SAlison Chaiken { 23109a49930SAlison Chaiken struct list_head *pos; 23209a49930SAlison Chaiken struct disk_part *curr; 233203f9b48SAlison Chaiken char partstartstr[16]; 234203f9b48SAlison Chaiken char partsizestr[16]; 23509a49930SAlison Chaiken 23609a49930SAlison Chaiken list_for_each(pos, &disk_partitions) { 23709a49930SAlison Chaiken curr = list_entry(pos, struct disk_part, list); 238203f9b48SAlison Chaiken prettyprint_part_size(partstartstr, curr->gpt_part_info.start, 239203f9b48SAlison Chaiken curr->gpt_part_info.blksz); 240203f9b48SAlison Chaiken prettyprint_part_size(partsizestr, curr->gpt_part_info.size, 241203f9b48SAlison Chaiken curr->gpt_part_info.blksz); 242203f9b48SAlison Chaiken 24309a49930SAlison Chaiken printf("Partition %d:\n", curr->partnum); 244203f9b48SAlison Chaiken printf("Start %s, size %s\n", partstartstr, partsizestr); 24509a49930SAlison Chaiken printf("Block size %lu, name %s\n", curr->gpt_part_info.blksz, 24609a49930SAlison Chaiken curr->gpt_part_info.name); 24709a49930SAlison Chaiken printf("Type %s, bootable %d\n", curr->gpt_part_info.type, 24809a49930SAlison Chaiken curr->gpt_part_info.bootable); 24909a49930SAlison Chaiken #ifdef CONFIG_PARTITION_UUIDS 25009a49930SAlison Chaiken printf("UUID %s\n", curr->gpt_part_info.uuid); 25109a49930SAlison Chaiken #endif 25209a49930SAlison Chaiken printf("\n"); 25309a49930SAlison Chaiken } 25409a49930SAlison Chaiken } 25509a49930SAlison Chaiken 256203f9b48SAlison Chaiken /* 257203f9b48SAlison Chaiken * create the string that upstream 'gpt write' command will accept as an 258203f9b48SAlison Chaiken * argument 259203f9b48SAlison Chaiken * 260203f9b48SAlison Chaiken * From doc/README.gpt, Format of partitions layout: 261203f9b48SAlison Chaiken * "uuid_disk=...;name=u-boot,size=60MiB,uuid=...; 262203f9b48SAlison Chaiken * name=kernel,size=60MiB,uuid=...;" 263203f9b48SAlison Chaiken * The fields 'name' and 'size' are mandatory for every partition. 264203f9b48SAlison Chaiken * The field 'start' is optional. The fields 'uuid' and 'uuid_disk' 265203f9b48SAlison Chaiken * are optional if CONFIG_RANDOM_UUID is enabled. 266203f9b48SAlison Chaiken */ 267203f9b48SAlison Chaiken static int create_gpt_partitions_list(int numparts, const char *guid, 268203f9b48SAlison Chaiken char *partitions_list) 269203f9b48SAlison Chaiken { 270203f9b48SAlison Chaiken struct list_head *pos; 271203f9b48SAlison Chaiken struct disk_part *curr; 272203f9b48SAlison Chaiken char partstr[PART_NAME_LEN + 1]; 273203f9b48SAlison Chaiken 274203f9b48SAlison Chaiken if (!partitions_list) 275203f9b48SAlison Chaiken return -EINVAL; 276203f9b48SAlison Chaiken 277203f9b48SAlison Chaiken strcpy(partitions_list, "uuid_disk="); 278203f9b48SAlison Chaiken strncat(partitions_list, guid, UUID_STR_LEN + 1); 279203f9b48SAlison Chaiken strcat(partitions_list, ";"); 280203f9b48SAlison Chaiken 281203f9b48SAlison Chaiken list_for_each(pos, &disk_partitions) { 282203f9b48SAlison Chaiken curr = list_entry(pos, struct disk_part, list); 283203f9b48SAlison Chaiken strcat(partitions_list, "name="); 284203f9b48SAlison Chaiken strncat(partitions_list, (const char *)curr->gpt_part_info.name, 285203f9b48SAlison Chaiken PART_NAME_LEN + 1); 286203f9b48SAlison Chaiken strcat(partitions_list, ",start="); 287203f9b48SAlison Chaiken prettyprint_part_size(partstr, (unsigned long)curr->gpt_part_info.start, 288203f9b48SAlison Chaiken (unsigned long) curr->gpt_part_info.blksz); 289203f9b48SAlison Chaiken /* one extra byte for NULL */ 290203f9b48SAlison Chaiken strncat(partitions_list, partstr, PART_NAME_LEN + 1); 291203f9b48SAlison Chaiken strcat(partitions_list, ",size="); 292203f9b48SAlison Chaiken prettyprint_part_size(partstr, curr->gpt_part_info.size, 293203f9b48SAlison Chaiken curr->gpt_part_info.blksz); 294203f9b48SAlison Chaiken strncat(partitions_list, partstr, PART_NAME_LEN + 1); 295203f9b48SAlison Chaiken 296203f9b48SAlison Chaiken strcat(partitions_list, ",uuid="); 297203f9b48SAlison Chaiken strncat(partitions_list, curr->gpt_part_info.uuid, 298203f9b48SAlison Chaiken UUID_STR_LEN + 1); 299203f9b48SAlison Chaiken strcat(partitions_list, ";"); 300203f9b48SAlison Chaiken } 301203f9b48SAlison Chaiken return 0; 302203f9b48SAlison Chaiken } 303203f9b48SAlison 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 315203f9b48SAlison Chaiken /* 316203f9b48SAlison Chaiken * Always re-read partition info from device, in case 317203f9b48SAlison Chaiken * it has changed 318203f9b48SAlison 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; 388*2fcaa413SAlison Chaiken int max_str_part = calc_parts_list_len(MAX_SEARCH_PARTITIONS); 3892e192b24SSimon Glass 3902e192b24SSimon Glass debug("%s: lba num: 0x%x %d\n", __func__, 3912e192b24SSimon Glass (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba); 3922e192b24SSimon Glass 3932e192b24SSimon Glass if (str_part == NULL) 3942e192b24SSimon Glass return -1; 3952e192b24SSimon Glass 3962e192b24SSimon Glass str = strdup(str_part); 397203f9b48SAlison Chaiken if (str == NULL) 398203f9b48SAlison Chaiken return -ENOMEM; 3992e192b24SSimon Glass 4002e192b24SSimon Glass /* extract disk guid */ 4012e192b24SSimon Glass s = str; 4022e192b24SSimon Glass val = extract_val(str, "uuid_disk"); 4032e192b24SSimon Glass if (!val) { 4042e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 4052e192b24SSimon Glass *str_disk_guid = malloc(UUID_STR_LEN + 1); 406*2fcaa413SAlison Chaiken if (str_disk_guid == NULL) 407*2fcaa413SAlison Chaiken return -ENOMEM; 4082e192b24SSimon Glass gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD); 4092e192b24SSimon Glass #else 4102e192b24SSimon Glass free(str); 4112e192b24SSimon Glass return -2; 4122e192b24SSimon Glass #endif 4132e192b24SSimon Glass } else { 4142e192b24SSimon Glass val = strsep(&val, ";"); 4152e192b24SSimon Glass if (extract_env(val, &p)) 4162e192b24SSimon Glass p = val; 4172e192b24SSimon Glass *str_disk_guid = strdup(p); 4182e192b24SSimon Glass free(val); 4192e192b24SSimon Glass /* Move s to first partition */ 4202e192b24SSimon Glass strsep(&s, ";"); 4212e192b24SSimon Glass } 422*2fcaa413SAlison Chaiken if (s == NULL) { 423*2fcaa413SAlison Chaiken printf("Error: is the partitions string NULL-terminated?\n"); 424*2fcaa413SAlison Chaiken return -EINVAL; 425*2fcaa413SAlison Chaiken } 426*2fcaa413SAlison Chaiken if (strnlen(s, max_str_part) == 0) 4272e192b24SSimon Glass return -3; 4282e192b24SSimon Glass 429*2fcaa413SAlison Chaiken i = strnlen(s, max_str_part) - 1; 4302e192b24SSimon Glass if (s[i] == ';') 4312e192b24SSimon Glass s[i] = '\0'; 4322e192b24SSimon Glass 4332e192b24SSimon Glass /* calculate expected number of partitions */ 4342e192b24SSimon Glass p_count = 1; 4352e192b24SSimon Glass p = s; 4362e192b24SSimon Glass while (*p) { 4372e192b24SSimon Glass if (*p++ == ';') 4382e192b24SSimon Glass p_count++; 4392e192b24SSimon Glass } 4402e192b24SSimon Glass 4412e192b24SSimon Glass /* allocate memory for partitions */ 4422e192b24SSimon Glass parts = calloc(sizeof(disk_partition_t), p_count); 443*2fcaa413SAlison Chaiken if (parts == NULL) 444*2fcaa413SAlison Chaiken return -ENOMEM; 4452e192b24SSimon Glass 4462e192b24SSimon Glass /* retrieve partitions data from string */ 4472e192b24SSimon Glass for (i = 0; i < p_count; i++) { 4482e192b24SSimon Glass tok = strsep(&s, ";"); 4492e192b24SSimon Glass 4502e192b24SSimon Glass if (tok == NULL) 4512e192b24SSimon Glass break; 4522e192b24SSimon Glass 4532e192b24SSimon Glass /* uuid */ 4542e192b24SSimon Glass val = extract_val(tok, "uuid"); 4552e192b24SSimon Glass if (!val) { 4562e192b24SSimon Glass /* 'uuid' is optional if random uuid's are enabled */ 4572e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 4582e192b24SSimon Glass gen_rand_uuid_str(parts[i].uuid, UUID_STR_FORMAT_STD); 4592e192b24SSimon Glass #else 4602e192b24SSimon Glass errno = -4; 4612e192b24SSimon Glass goto err; 4622e192b24SSimon Glass #endif 4632e192b24SSimon Glass } else { 4642e192b24SSimon Glass if (extract_env(val, &p)) 4652e192b24SSimon Glass p = val; 466*2fcaa413SAlison Chaiken if (strnlen(p, max_str_part) >= sizeof(parts[i].uuid)) { 4672e192b24SSimon Glass printf("Wrong uuid format for partition %d\n", i); 4682e192b24SSimon Glass errno = -4; 4692e192b24SSimon Glass goto err; 4702e192b24SSimon Glass } 471*2fcaa413SAlison Chaiken strncpy((char *)parts[i].uuid, p, max_str_part); 4722e192b24SSimon Glass free(val); 4732e192b24SSimon Glass } 4742e192b24SSimon Glass #ifdef CONFIG_PARTITION_TYPE_GUID 4752e192b24SSimon Glass /* guid */ 4762e192b24SSimon Glass val = extract_val(tok, "type"); 4772e192b24SSimon Glass if (val) { 4782e192b24SSimon Glass /* 'type' is optional */ 4792e192b24SSimon Glass if (extract_env(val, &p)) 4802e192b24SSimon Glass p = val; 481*2fcaa413SAlison Chaiken if (strnlen(p, max_str_part) >= sizeof(parts[i].type_guid)) { 4822e192b24SSimon Glass printf("Wrong type guid format for partition %d\n", 4832e192b24SSimon Glass i); 4842e192b24SSimon Glass errno = -4; 4852e192b24SSimon Glass goto err; 4862e192b24SSimon Glass } 487*2fcaa413SAlison Chaiken strncpy((char *)parts[i].type_guid, p, max_str_part); 4882e192b24SSimon Glass free(val); 4892e192b24SSimon Glass } 4902e192b24SSimon Glass #endif 4912e192b24SSimon Glass /* name */ 4922e192b24SSimon Glass val = extract_val(tok, "name"); 4932e192b24SSimon Glass if (!val) { /* name is mandatory */ 4942e192b24SSimon Glass errno = -4; 4952e192b24SSimon Glass goto err; 4962e192b24SSimon Glass } 4972e192b24SSimon Glass if (extract_env(val, &p)) 4982e192b24SSimon Glass p = val; 499*2fcaa413SAlison Chaiken if (strnlen(p, max_str_part) >= sizeof(parts[i].name)) { 5002e192b24SSimon Glass errno = -4; 5012e192b24SSimon Glass goto err; 5022e192b24SSimon Glass } 503*2fcaa413SAlison Chaiken strncpy((char *)parts[i].name, p, max_str_part); 5042e192b24SSimon Glass free(val); 5052e192b24SSimon Glass 5062e192b24SSimon Glass /* size */ 5072e192b24SSimon Glass val = extract_val(tok, "size"); 5082e192b24SSimon Glass if (!val) { /* 'size' is mandatory */ 5092e192b24SSimon Glass errno = -4; 5102e192b24SSimon Glass goto err; 5112e192b24SSimon Glass } 5122e192b24SSimon Glass if (extract_env(val, &p)) 5132e192b24SSimon Glass p = val; 51466636235SMichael Trimarchi if ((strcmp(p, "-") == 0)) { 515c2fdd345SKever Yang /* Let part efi module to auto extend the size */ 516c2fdd345SKever Yang parts[i].size = 0; 51766636235SMichael Trimarchi } else { 5182e192b24SSimon Glass size_ll = ustrtoull(p, &p, 0); 5192e192b24SSimon Glass parts[i].size = lldiv(size_ll, dev_desc->blksz); 52066636235SMichael Trimarchi } 52166636235SMichael Trimarchi 5222e192b24SSimon Glass free(val); 5232e192b24SSimon Glass 5242e192b24SSimon Glass /* start address */ 5252e192b24SSimon Glass val = extract_val(tok, "start"); 5262e192b24SSimon Glass if (val) { /* start address is optional */ 5272e192b24SSimon Glass if (extract_env(val, &p)) 5282e192b24SSimon Glass p = val; 5292e192b24SSimon Glass start_ll = ustrtoull(p, &p, 0); 5302e192b24SSimon Glass parts[i].start = lldiv(start_ll, dev_desc->blksz); 5312e192b24SSimon Glass free(val); 5322e192b24SSimon Glass } 5332e192b24SSimon Glass 53466636235SMichael Trimarchi offset += parts[i].size + parts[i].start; 53566636235SMichael Trimarchi 5362e192b24SSimon Glass /* bootable */ 5372e192b24SSimon Glass if (found_key(tok, "bootable")) 5382e192b24SSimon Glass parts[i].bootable = 1; 5392e192b24SSimon Glass } 5402e192b24SSimon Glass 5412e192b24SSimon Glass *parts_count = p_count; 5422e192b24SSimon Glass *partitions = parts; 5432e192b24SSimon Glass free(str); 5442e192b24SSimon Glass 5452e192b24SSimon Glass return 0; 5462e192b24SSimon Glass err: 5472e192b24SSimon Glass free(str); 5482e192b24SSimon Glass free(*str_disk_guid); 5492e192b24SSimon Glass free(parts); 5502e192b24SSimon Glass 5512e192b24SSimon Glass return errno; 5522e192b24SSimon Glass } 5532e192b24SSimon Glass 5544101f687SSimon Glass static int gpt_default(struct blk_desc *blk_dev_desc, const char *str_part) 5552e192b24SSimon Glass { 5562e192b24SSimon Glass int ret; 5572e192b24SSimon Glass char *str_disk_guid; 5582e192b24SSimon Glass u8 part_count = 0; 5592e192b24SSimon Glass disk_partition_t *partitions = NULL; 5602e192b24SSimon Glass 5612e192b24SSimon Glass /* fill partitions */ 5622e192b24SSimon Glass ret = set_gpt_info(blk_dev_desc, str_part, 5632e192b24SSimon Glass &str_disk_guid, &partitions, &part_count); 5642e192b24SSimon Glass if (ret) { 5652e192b24SSimon Glass if (ret == -1) 5662e192b24SSimon Glass printf("No partition list provided\n"); 5672e192b24SSimon Glass if (ret == -2) 5682e192b24SSimon Glass printf("Missing disk guid\n"); 5692e192b24SSimon Glass if ((ret == -3) || (ret == -4)) 5702e192b24SSimon Glass printf("Partition list incomplete\n"); 5712e192b24SSimon Glass return -1; 5722e192b24SSimon Glass } 5732e192b24SSimon Glass 5742e192b24SSimon Glass /* save partitions layout to disk */ 5752e192b24SSimon Glass ret = gpt_restore(blk_dev_desc, str_disk_guid, partitions, part_count); 5762e192b24SSimon Glass free(str_disk_guid); 5772e192b24SSimon Glass free(partitions); 5782e192b24SSimon Glass 5792e192b24SSimon Glass return ret; 5802e192b24SSimon Glass } 5812e192b24SSimon Glass 5824101f687SSimon Glass static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part) 5832e192b24SSimon Glass { 5842e192b24SSimon Glass ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, 5852e192b24SSimon Glass blk_dev_desc->blksz); 5862e192b24SSimon Glass disk_partition_t *partitions = NULL; 5872e192b24SSimon Glass gpt_entry *gpt_pte = NULL; 5882e192b24SSimon Glass char *str_disk_guid; 5892e192b24SSimon Glass u8 part_count = 0; 5902e192b24SSimon Glass int ret = 0; 5912e192b24SSimon Glass 5922e192b24SSimon Glass /* fill partitions */ 5932e192b24SSimon Glass ret = set_gpt_info(blk_dev_desc, str_part, 5942e192b24SSimon Glass &str_disk_guid, &partitions, &part_count); 5952e192b24SSimon Glass if (ret) { 5962e192b24SSimon Glass if (ret == -1) { 5972e192b24SSimon Glass printf("No partition list provided - only basic check\n"); 5982e192b24SSimon Glass ret = gpt_verify_headers(blk_dev_desc, gpt_head, 5992e192b24SSimon Glass &gpt_pte); 6002e192b24SSimon Glass goto out; 6012e192b24SSimon Glass } 6022e192b24SSimon Glass if (ret == -2) 6032e192b24SSimon Glass printf("Missing disk guid\n"); 6042e192b24SSimon Glass if ((ret == -3) || (ret == -4)) 6052e192b24SSimon Glass printf("Partition list incomplete\n"); 6062e192b24SSimon Glass return -1; 6072e192b24SSimon Glass } 6082e192b24SSimon Glass 6092e192b24SSimon Glass /* Check partition layout with provided pattern */ 6102e192b24SSimon Glass ret = gpt_verify_partitions(blk_dev_desc, partitions, part_count, 6112e192b24SSimon Glass gpt_head, &gpt_pte); 6122e192b24SSimon Glass free(str_disk_guid); 6132e192b24SSimon Glass free(partitions); 6142e192b24SSimon Glass out: 6152e192b24SSimon Glass free(gpt_pte); 6162e192b24SSimon Glass return ret; 6172e192b24SSimon Glass } 6182e192b24SSimon Glass 61973d6d18bSAlison Chaiken static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr) 62073d6d18bSAlison Chaiken { 62173d6d18bSAlison Chaiken int ret; 62273d6d18bSAlison Chaiken char disk_guid[UUID_STR_LEN + 1]; 62373d6d18bSAlison Chaiken 62473d6d18bSAlison Chaiken ret = get_disk_guid(dev_desc, disk_guid); 62573d6d18bSAlison Chaiken if (ret < 0) 62673d6d18bSAlison Chaiken return CMD_RET_FAILURE; 62773d6d18bSAlison Chaiken 62873d6d18bSAlison Chaiken if (namestr) 62973d6d18bSAlison Chaiken setenv(namestr, disk_guid); 63073d6d18bSAlison Chaiken else 63173d6d18bSAlison Chaiken printf("%s\n", disk_guid); 63273d6d18bSAlison Chaiken 63373d6d18bSAlison Chaiken return ret; 63473d6d18bSAlison Chaiken } 63573d6d18bSAlison Chaiken 636203f9b48SAlison Chaiken #ifdef CONFIG_CMD_GPT_RENAME 637203f9b48SAlison Chaiken static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm, 638203f9b48SAlison Chaiken char *name1, char *name2) 639203f9b48SAlison Chaiken { 640203f9b48SAlison Chaiken struct list_head *pos; 641203f9b48SAlison Chaiken struct disk_part *curr; 642203f9b48SAlison Chaiken disk_partition_t *new_partitions = NULL; 643203f9b48SAlison Chaiken char disk_guid[UUID_STR_LEN + 1]; 644203f9b48SAlison Chaiken char *partitions_list, *str_disk_guid; 645203f9b48SAlison Chaiken u8 part_count = 0; 646203f9b48SAlison Chaiken int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0; 647203f9b48SAlison Chaiken 648203f9b48SAlison Chaiken if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) || 649203f9b48SAlison Chaiken (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename")))) 650203f9b48SAlison Chaiken return -EINVAL; 651203f9b48SAlison Chaiken 652203f9b48SAlison Chaiken ret = get_disk_guid(dev_desc, disk_guid); 653203f9b48SAlison Chaiken if (ret < 0) 654203f9b48SAlison Chaiken return ret; 655203f9b48SAlison Chaiken numparts = get_gpt_info(dev_desc); 656203f9b48SAlison Chaiken if (numparts <= 0) 657203f9b48SAlison Chaiken return numparts ? numparts : -ENODEV; 658203f9b48SAlison Chaiken 659203f9b48SAlison Chaiken partlistlen = calc_parts_list_len(numparts); 660203f9b48SAlison Chaiken partitions_list = malloc(partlistlen); 661203f9b48SAlison Chaiken if (partitions_list == NULL) 662203f9b48SAlison Chaiken return -ENOMEM; 663203f9b48SAlison Chaiken memset(partitions_list, '\0', partlistlen); 664203f9b48SAlison Chaiken 665203f9b48SAlison Chaiken ret = create_gpt_partitions_list(numparts, disk_guid, partitions_list); 666203f9b48SAlison Chaiken if (ret < 0) 667203f9b48SAlison Chaiken return ret; 668203f9b48SAlison Chaiken /* 669203f9b48SAlison Chaiken * Uncomment the following line to print a string that 'gpt write' 670203f9b48SAlison Chaiken * or 'gpt verify' will accept as input. 671203f9b48SAlison Chaiken */ 672203f9b48SAlison Chaiken debug("OLD partitions_list is %s with %u chars\n", partitions_list, 673203f9b48SAlison Chaiken (unsigned)strlen(partitions_list)); 674203f9b48SAlison Chaiken 675203f9b48SAlison Chaiken ret = set_gpt_info(dev_desc, partitions_list, &str_disk_guid, 676203f9b48SAlison Chaiken &new_partitions, &part_count); 677203f9b48SAlison Chaiken if (ret < 0) 678203f9b48SAlison Chaiken return ret; 679203f9b48SAlison Chaiken 680203f9b48SAlison Chaiken if (!strcmp(subcomm, "swap")) { 681203f9b48SAlison Chaiken if ((strlen(name1) > PART_NAME_LEN) || (strlen(name2) > PART_NAME_LEN)) { 682203f9b48SAlison Chaiken printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN); 683203f9b48SAlison Chaiken return -EINVAL; 684203f9b48SAlison Chaiken } 685203f9b48SAlison Chaiken list_for_each(pos, &disk_partitions) { 686203f9b48SAlison Chaiken curr = list_entry(pos, struct disk_part, list); 687203f9b48SAlison Chaiken if (!strcmp((char *)curr->gpt_part_info.name, name1)) { 688203f9b48SAlison Chaiken strcpy((char *)curr->gpt_part_info.name, name2); 689203f9b48SAlison Chaiken ctr1++; 690203f9b48SAlison Chaiken } else if (!strcmp((char *)curr->gpt_part_info.name, name2)) { 691203f9b48SAlison Chaiken strcpy((char *)curr->gpt_part_info.name, name1); 692203f9b48SAlison Chaiken ctr2++; 693203f9b48SAlison Chaiken } 694203f9b48SAlison Chaiken } 695203f9b48SAlison Chaiken if ((ctr1 + ctr2 < 2) || (ctr1 != ctr2)) { 696203f9b48SAlison Chaiken printf("Cannot swap partition names except in pairs.\n"); 697203f9b48SAlison Chaiken return -EINVAL; 698203f9b48SAlison Chaiken } 699203f9b48SAlison Chaiken } else { /* rename */ 700203f9b48SAlison Chaiken if (strlen(name2) > PART_NAME_LEN) { 701203f9b48SAlison Chaiken printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN); 702203f9b48SAlison Chaiken return -EINVAL; 703203f9b48SAlison Chaiken } 704203f9b48SAlison Chaiken partnum = (int)simple_strtol(name1, NULL, 10); 705203f9b48SAlison Chaiken if ((partnum < 0) || (partnum > numparts)) { 706203f9b48SAlison Chaiken printf("Illegal partition number %s\n", name1); 707203f9b48SAlison Chaiken return -EINVAL; 708203f9b48SAlison Chaiken } 709203f9b48SAlison Chaiken ret = part_get_info(dev_desc, partnum, new_partitions); 710203f9b48SAlison Chaiken if (ret < 0) 711203f9b48SAlison Chaiken return ret; 712203f9b48SAlison Chaiken 713203f9b48SAlison Chaiken /* U-Boot partition numbering starts at 1 */ 714203f9b48SAlison Chaiken list_for_each(pos, &disk_partitions) { 715203f9b48SAlison Chaiken curr = list_entry(pos, struct disk_part, list); 716203f9b48SAlison Chaiken if (i == partnum) { 717203f9b48SAlison Chaiken strcpy((char *)curr->gpt_part_info.name, name2); 718203f9b48SAlison Chaiken break; 719203f9b48SAlison Chaiken } 720203f9b48SAlison Chaiken i++; 721203f9b48SAlison Chaiken } 722203f9b48SAlison Chaiken } 723203f9b48SAlison Chaiken 724203f9b48SAlison Chaiken ret = create_gpt_partitions_list(numparts, disk_guid, partitions_list); 725203f9b48SAlison Chaiken if (ret < 0) 726203f9b48SAlison Chaiken return ret; 727203f9b48SAlison Chaiken debug("NEW partitions_list is %s with %u chars\n", partitions_list, 728203f9b48SAlison Chaiken (unsigned)strlen(partitions_list)); 729203f9b48SAlison Chaiken 730203f9b48SAlison Chaiken ret = set_gpt_info(dev_desc, partitions_list, &str_disk_guid, 731203f9b48SAlison Chaiken &new_partitions, &part_count); 732203f9b48SAlison Chaiken if (ret < 0) 733203f9b48SAlison Chaiken return ret; 734203f9b48SAlison Chaiken 735203f9b48SAlison Chaiken debug("Writing new partition table\n"); 736203f9b48SAlison Chaiken ret = gpt_restore(dev_desc, disk_guid, new_partitions, numparts); 737203f9b48SAlison Chaiken if (ret < 0) { 738203f9b48SAlison Chaiken printf("Writing new partition table failed\n"); 739203f9b48SAlison Chaiken return ret; 740203f9b48SAlison Chaiken } 741203f9b48SAlison Chaiken 742203f9b48SAlison Chaiken debug("Reading back new partition table\n"); 743203f9b48SAlison Chaiken numparts = get_gpt_info(dev_desc); 744203f9b48SAlison Chaiken if (numparts <= 0) 745203f9b48SAlison Chaiken return numparts ? numparts : -ENODEV; 746203f9b48SAlison Chaiken printf("new partition table with %d partitions is:\n", numparts); 747203f9b48SAlison Chaiken print_gpt_info(); 748203f9b48SAlison Chaiken 749203f9b48SAlison Chaiken del_gpt_info(); 750203f9b48SAlison Chaiken free(partitions_list); 751203f9b48SAlison Chaiken free(str_disk_guid); 752203f9b48SAlison Chaiken free(new_partitions); 753203f9b48SAlison Chaiken return ret; 754203f9b48SAlison Chaiken } 755203f9b48SAlison Chaiken #endif 756203f9b48SAlison Chaiken 7572e192b24SSimon Glass /** 7582e192b24SSimon Glass * do_gpt(): Perform GPT operations 7592e192b24SSimon Glass * 7602e192b24SSimon Glass * @param cmdtp - command name 7612e192b24SSimon Glass * @param flag 7622e192b24SSimon Glass * @param argc 7632e192b24SSimon Glass * @param argv 7642e192b24SSimon Glass * 7652e192b24SSimon Glass * @return zero on success; otherwise error 7662e192b24SSimon Glass */ 7672e192b24SSimon Glass static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 7682e192b24SSimon Glass { 7692e192b24SSimon Glass int ret = CMD_RET_SUCCESS; 7702e192b24SSimon Glass int dev = 0; 7712e192b24SSimon Glass char *ep; 7724101f687SSimon Glass struct blk_desc *blk_dev_desc = NULL; 7732e192b24SSimon Glass 774203f9b48SAlison Chaiken #ifndef CONFIG_CMD_GPT_RENAME 7752e192b24SSimon Glass if (argc < 4 || argc > 5) 776203f9b48SAlison Chaiken #else 777203f9b48SAlison Chaiken if (argc < 4 || argc > 6) 778203f9b48SAlison Chaiken #endif 7792e192b24SSimon Glass return CMD_RET_USAGE; 7802e192b24SSimon Glass 7812e192b24SSimon Glass dev = (int)simple_strtoul(argv[3], &ep, 10); 7822e192b24SSimon Glass if (!ep || ep[0] != '\0') { 7832e192b24SSimon Glass printf("'%s' is not a number\n", argv[3]); 7842e192b24SSimon Glass return CMD_RET_USAGE; 7852e192b24SSimon Glass } 786db1d9e78SSimon Glass blk_dev_desc = blk_get_dev(argv[2], dev); 7872e192b24SSimon Glass if (!blk_dev_desc) { 7882e192b24SSimon Glass printf("%s: %s dev %d NOT available\n", 7892e192b24SSimon Glass __func__, argv[2], dev); 7902e192b24SSimon Glass return CMD_RET_FAILURE; 7912e192b24SSimon Glass } 7922e192b24SSimon Glass 7932e192b24SSimon Glass if ((strcmp(argv[1], "write") == 0) && (argc == 5)) { 7942e192b24SSimon Glass printf("Writing GPT: "); 7952e192b24SSimon Glass ret = gpt_default(blk_dev_desc, argv[4]); 7962e192b24SSimon Glass } else if ((strcmp(argv[1], "verify") == 0)) { 7972e192b24SSimon Glass ret = gpt_verify(blk_dev_desc, argv[4]); 7982e192b24SSimon Glass printf("Verify GPT: "); 79973d6d18bSAlison Chaiken } else if (strcmp(argv[1], "guid") == 0) { 80073d6d18bSAlison Chaiken ret = do_disk_guid(blk_dev_desc, argv[4]); 80109a49930SAlison Chaiken #ifdef CONFIG_CMD_GPT_RENAME 80209a49930SAlison Chaiken } else if (strcmp(argv[1], "read") == 0) { 80309a49930SAlison Chaiken ret = do_get_gpt_info(blk_dev_desc); 804203f9b48SAlison Chaiken } else if ((strcmp(argv[1], "swap") == 0) || 805203f9b48SAlison Chaiken (strcmp(argv[1], "rename") == 0)) { 806203f9b48SAlison Chaiken ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]); 80709a49930SAlison Chaiken #endif 8082e192b24SSimon Glass } else { 8092e192b24SSimon Glass return CMD_RET_USAGE; 8102e192b24SSimon Glass } 8112e192b24SSimon Glass 8122e192b24SSimon Glass if (ret) { 8132e192b24SSimon Glass printf("error!\n"); 8142e192b24SSimon Glass return CMD_RET_FAILURE; 8152e192b24SSimon Glass } 8162e192b24SSimon Glass 8172e192b24SSimon Glass printf("success!\n"); 8182e192b24SSimon Glass return CMD_RET_SUCCESS; 8192e192b24SSimon Glass } 8202e192b24SSimon Glass 8212e192b24SSimon Glass U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt, 8222e192b24SSimon Glass "GUID Partition Table", 8232e192b24SSimon Glass "<command> <interface> <dev> <partitions_list>\n" 8242e192b24SSimon Glass " - GUID partition table restoration and validity check\n" 8252e192b24SSimon Glass " Restore or verify GPT information on a device connected\n" 8262e192b24SSimon Glass " to interface\n" 8272e192b24SSimon Glass " Example usage:\n" 8282e192b24SSimon Glass " gpt write mmc 0 $partitions\n" 8292e192b24SSimon Glass " gpt verify mmc 0 $partitions\n" 83009a49930SAlison Chaiken " read <interface> <dev>\n" 83109a49930SAlison Chaiken " - read GPT into a data structure for manipulation\n" 83273d6d18bSAlison Chaiken " guid <interface> <dev>\n" 83373d6d18bSAlison Chaiken " - print disk GUID\n" 83473d6d18bSAlison Chaiken " guid <interface> <dev> <varname>\n" 83573d6d18bSAlison Chaiken " - set environment variable to disk GUID\n" 83673d6d18bSAlison Chaiken " Example usage:\n" 83773d6d18bSAlison Chaiken " gpt guid mmc 0\n" 83873d6d18bSAlison Chaiken " gpt guid mmc 0 varname\n" 839203f9b48SAlison Chaiken #ifdef CONFIG_CMD_GPT_RENAME 840203f9b48SAlison Chaiken "gpt partition renaming commands:\n" 841203f9b48SAlison Chaiken "gpt swap <interface> <dev> <name1> <name2>\n" 842203f9b48SAlison Chaiken " - change all partitions named name1 to name2\n" 843203f9b48SAlison Chaiken " and vice-versa\n" 844203f9b48SAlison Chaiken "gpt rename <interface> <dev> <part> <name>\n" 845203f9b48SAlison Chaiken " - rename the specified partition\n" 846203f9b48SAlison Chaiken " Example usage:\n" 847203f9b48SAlison Chaiken " gpt swap mmc 0 foo bar\n" 848203f9b48SAlison Chaiken " gpt rename mmc 0 3 foo\n" 849203f9b48SAlison Chaiken #endif 8502e192b24SSimon Glass ); 851