1*2e192b24SSimon Glass /* 2*2e192b24SSimon Glass * cmd_gpt.c -- GPT (GUID Partition Table) handling command 3*2e192b24SSimon Glass * 4*2e192b24SSimon Glass * Copyright (C) 2015 5*2e192b24SSimon Glass * Lukasz Majewski <l.majewski@majess.pl> 6*2e192b24SSimon Glass * 7*2e192b24SSimon Glass * Copyright (C) 2012 Samsung Electronics 8*2e192b24SSimon Glass * author: Lukasz Majewski <l.majewski@samsung.com> 9*2e192b24SSimon Glass * author: Piotr Wilczek <p.wilczek@samsung.com> 10*2e192b24SSimon Glass * 11*2e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 12*2e192b24SSimon Glass */ 13*2e192b24SSimon Glass 14*2e192b24SSimon Glass #include <common.h> 15*2e192b24SSimon Glass #include <malloc.h> 16*2e192b24SSimon Glass #include <command.h> 17*2e192b24SSimon Glass #include <part_efi.h> 18*2e192b24SSimon Glass #include <exports.h> 19*2e192b24SSimon Glass #include <linux/ctype.h> 20*2e192b24SSimon Glass #include <div64.h> 21*2e192b24SSimon Glass #include <memalign.h> 22*2e192b24SSimon Glass 23*2e192b24SSimon Glass #ifndef CONFIG_PARTITION_UUIDS 24*2e192b24SSimon Glass #error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled 25*2e192b24SSimon Glass #endif 26*2e192b24SSimon Glass 27*2e192b24SSimon Glass /** 28*2e192b24SSimon Glass * extract_env(): Expand env name from string format '&{env_name}' 29*2e192b24SSimon Glass * and return pointer to the env (if the env is set) 30*2e192b24SSimon Glass * 31*2e192b24SSimon Glass * @param str - pointer to string 32*2e192b24SSimon Glass * @param env - pointer to pointer to extracted env 33*2e192b24SSimon Glass * 34*2e192b24SSimon Glass * @return - zero on successful expand and env is set 35*2e192b24SSimon Glass */ 36*2e192b24SSimon Glass static int extract_env(const char *str, char **env) 37*2e192b24SSimon Glass { 38*2e192b24SSimon Glass int ret = -1; 39*2e192b24SSimon Glass char *e, *s; 40*2e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 41*2e192b24SSimon Glass char uuid_str[UUID_STR_LEN + 1]; 42*2e192b24SSimon Glass #endif 43*2e192b24SSimon Glass 44*2e192b24SSimon Glass if (!str || strlen(str) < 4) 45*2e192b24SSimon Glass return -1; 46*2e192b24SSimon Glass 47*2e192b24SSimon Glass if (!((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}'))) 48*2e192b24SSimon Glass return -1; 49*2e192b24SSimon Glass 50*2e192b24SSimon Glass s = strdup(str); 51*2e192b24SSimon Glass if (s == NULL) 52*2e192b24SSimon Glass return -1; 53*2e192b24SSimon Glass 54*2e192b24SSimon Glass memset(s + strlen(s) - 1, '\0', 1); 55*2e192b24SSimon Glass memmove(s, s + 2, strlen(s) - 1); 56*2e192b24SSimon Glass 57*2e192b24SSimon Glass e = getenv(s); 58*2e192b24SSimon Glass if (e == NULL) { 59*2e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 60*2e192b24SSimon Glass debug("%s unset. ", str); 61*2e192b24SSimon Glass gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_STD); 62*2e192b24SSimon Glass setenv(s, uuid_str); 63*2e192b24SSimon Glass 64*2e192b24SSimon Glass e = getenv(s); 65*2e192b24SSimon Glass if (e) { 66*2e192b24SSimon Glass debug("Set to random.\n"); 67*2e192b24SSimon Glass ret = 0; 68*2e192b24SSimon Glass } else { 69*2e192b24SSimon Glass debug("Can't get random UUID.\n"); 70*2e192b24SSimon Glass } 71*2e192b24SSimon Glass #else 72*2e192b24SSimon Glass debug("%s unset.\n", str); 73*2e192b24SSimon Glass #endif 74*2e192b24SSimon Glass } else { 75*2e192b24SSimon Glass debug("%s get from environment.\n", str); 76*2e192b24SSimon Glass ret = 0; 77*2e192b24SSimon Glass } 78*2e192b24SSimon Glass 79*2e192b24SSimon Glass *env = e; 80*2e192b24SSimon Glass free(s); 81*2e192b24SSimon Glass 82*2e192b24SSimon Glass return ret; 83*2e192b24SSimon Glass } 84*2e192b24SSimon Glass 85*2e192b24SSimon Glass /** 86*2e192b24SSimon Glass * extract_val(): Extract value from a key=value pair list (comma separated). 87*2e192b24SSimon Glass * Only value for the given key is returend. 88*2e192b24SSimon Glass * Function allocates memory for the value, remember to free! 89*2e192b24SSimon Glass * 90*2e192b24SSimon Glass * @param str - pointer to string with key=values pairs 91*2e192b24SSimon Glass * @param key - pointer to the key to search for 92*2e192b24SSimon Glass * 93*2e192b24SSimon Glass * @return - pointer to allocated string with the value 94*2e192b24SSimon Glass */ 95*2e192b24SSimon Glass static char *extract_val(const char *str, const char *key) 96*2e192b24SSimon Glass { 97*2e192b24SSimon Glass char *v, *k; 98*2e192b24SSimon Glass char *s, *strcopy; 99*2e192b24SSimon Glass char *new = NULL; 100*2e192b24SSimon Glass 101*2e192b24SSimon Glass strcopy = strdup(str); 102*2e192b24SSimon Glass if (strcopy == NULL) 103*2e192b24SSimon Glass return NULL; 104*2e192b24SSimon Glass 105*2e192b24SSimon Glass s = strcopy; 106*2e192b24SSimon Glass while (s) { 107*2e192b24SSimon Glass v = strsep(&s, ","); 108*2e192b24SSimon Glass if (!v) 109*2e192b24SSimon Glass break; 110*2e192b24SSimon Glass k = strsep(&v, "="); 111*2e192b24SSimon Glass if (!k) 112*2e192b24SSimon Glass break; 113*2e192b24SSimon Glass if (strcmp(k, key) == 0) { 114*2e192b24SSimon Glass new = strdup(v); 115*2e192b24SSimon Glass break; 116*2e192b24SSimon Glass } 117*2e192b24SSimon Glass } 118*2e192b24SSimon Glass 119*2e192b24SSimon Glass free(strcopy); 120*2e192b24SSimon Glass 121*2e192b24SSimon Glass return new; 122*2e192b24SSimon Glass } 123*2e192b24SSimon Glass 124*2e192b24SSimon Glass /** 125*2e192b24SSimon Glass * found_key(): Found key without value in parameter list (comma separated). 126*2e192b24SSimon Glass * 127*2e192b24SSimon Glass * @param str - pointer to string with key 128*2e192b24SSimon Glass * @param key - pointer to the key to search for 129*2e192b24SSimon Glass * 130*2e192b24SSimon Glass * @return - true on found key 131*2e192b24SSimon Glass */ 132*2e192b24SSimon Glass static bool found_key(const char *str, const char *key) 133*2e192b24SSimon Glass { 134*2e192b24SSimon Glass char *k; 135*2e192b24SSimon Glass char *s, *strcopy; 136*2e192b24SSimon Glass bool result = false; 137*2e192b24SSimon Glass 138*2e192b24SSimon Glass strcopy = strdup(str); 139*2e192b24SSimon Glass if (!strcopy) 140*2e192b24SSimon Glass return NULL; 141*2e192b24SSimon Glass 142*2e192b24SSimon Glass s = strcopy; 143*2e192b24SSimon Glass while (s) { 144*2e192b24SSimon Glass k = strsep(&s, ","); 145*2e192b24SSimon Glass if (!k) 146*2e192b24SSimon Glass break; 147*2e192b24SSimon Glass if (strcmp(k, key) == 0) { 148*2e192b24SSimon Glass result = true; 149*2e192b24SSimon Glass break; 150*2e192b24SSimon Glass } 151*2e192b24SSimon Glass } 152*2e192b24SSimon Glass 153*2e192b24SSimon Glass free(strcopy); 154*2e192b24SSimon Glass 155*2e192b24SSimon Glass return result; 156*2e192b24SSimon Glass } 157*2e192b24SSimon Glass 158*2e192b24SSimon Glass /** 159*2e192b24SSimon Glass * set_gpt_info(): Fill partition information from string 160*2e192b24SSimon Glass * function allocates memory, remember to free! 161*2e192b24SSimon Glass * 162*2e192b24SSimon Glass * @param dev_desc - pointer block device descriptor 163*2e192b24SSimon Glass * @param str_part - pointer to string with partition information 164*2e192b24SSimon Glass * @param str_disk_guid - pointer to pointer to allocated string with disk guid 165*2e192b24SSimon Glass * @param partitions - pointer to pointer to allocated partitions array 166*2e192b24SSimon Glass * @param parts_count - number of partitions 167*2e192b24SSimon Glass * 168*2e192b24SSimon Glass * @return - zero on success, otherwise error 169*2e192b24SSimon Glass * 170*2e192b24SSimon Glass */ 171*2e192b24SSimon Glass static int set_gpt_info(block_dev_desc_t *dev_desc, 172*2e192b24SSimon Glass const char *str_part, 173*2e192b24SSimon Glass char **str_disk_guid, 174*2e192b24SSimon Glass disk_partition_t **partitions, 175*2e192b24SSimon Glass u8 *parts_count) 176*2e192b24SSimon Glass { 177*2e192b24SSimon Glass char *tok, *str, *s; 178*2e192b24SSimon Glass int i; 179*2e192b24SSimon Glass char *val, *p; 180*2e192b24SSimon Glass int p_count; 181*2e192b24SSimon Glass disk_partition_t *parts; 182*2e192b24SSimon Glass int errno = 0; 183*2e192b24SSimon Glass uint64_t size_ll, start_ll; 184*2e192b24SSimon Glass 185*2e192b24SSimon Glass debug("%s: lba num: 0x%x %d\n", __func__, 186*2e192b24SSimon Glass (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba); 187*2e192b24SSimon Glass 188*2e192b24SSimon Glass if (str_part == NULL) 189*2e192b24SSimon Glass return -1; 190*2e192b24SSimon Glass 191*2e192b24SSimon Glass str = strdup(str_part); 192*2e192b24SSimon Glass 193*2e192b24SSimon Glass /* extract disk guid */ 194*2e192b24SSimon Glass s = str; 195*2e192b24SSimon Glass val = extract_val(str, "uuid_disk"); 196*2e192b24SSimon Glass if (!val) { 197*2e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 198*2e192b24SSimon Glass *str_disk_guid = malloc(UUID_STR_LEN + 1); 199*2e192b24SSimon Glass gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD); 200*2e192b24SSimon Glass #else 201*2e192b24SSimon Glass free(str); 202*2e192b24SSimon Glass return -2; 203*2e192b24SSimon Glass #endif 204*2e192b24SSimon Glass } else { 205*2e192b24SSimon Glass val = strsep(&val, ";"); 206*2e192b24SSimon Glass if (extract_env(val, &p)) 207*2e192b24SSimon Glass p = val; 208*2e192b24SSimon Glass *str_disk_guid = strdup(p); 209*2e192b24SSimon Glass free(val); 210*2e192b24SSimon Glass /* Move s to first partition */ 211*2e192b24SSimon Glass strsep(&s, ";"); 212*2e192b24SSimon Glass } 213*2e192b24SSimon Glass if (strlen(s) == 0) 214*2e192b24SSimon Glass return -3; 215*2e192b24SSimon Glass 216*2e192b24SSimon Glass i = strlen(s) - 1; 217*2e192b24SSimon Glass if (s[i] == ';') 218*2e192b24SSimon Glass s[i] = '\0'; 219*2e192b24SSimon Glass 220*2e192b24SSimon Glass /* calculate expected number of partitions */ 221*2e192b24SSimon Glass p_count = 1; 222*2e192b24SSimon Glass p = s; 223*2e192b24SSimon Glass while (*p) { 224*2e192b24SSimon Glass if (*p++ == ';') 225*2e192b24SSimon Glass p_count++; 226*2e192b24SSimon Glass } 227*2e192b24SSimon Glass 228*2e192b24SSimon Glass /* allocate memory for partitions */ 229*2e192b24SSimon Glass parts = calloc(sizeof(disk_partition_t), p_count); 230*2e192b24SSimon Glass 231*2e192b24SSimon Glass /* retrieve partitions data from string */ 232*2e192b24SSimon Glass for (i = 0; i < p_count; i++) { 233*2e192b24SSimon Glass tok = strsep(&s, ";"); 234*2e192b24SSimon Glass 235*2e192b24SSimon Glass if (tok == NULL) 236*2e192b24SSimon Glass break; 237*2e192b24SSimon Glass 238*2e192b24SSimon Glass /* uuid */ 239*2e192b24SSimon Glass val = extract_val(tok, "uuid"); 240*2e192b24SSimon Glass if (!val) { 241*2e192b24SSimon Glass /* 'uuid' is optional if random uuid's are enabled */ 242*2e192b24SSimon Glass #ifdef CONFIG_RANDOM_UUID 243*2e192b24SSimon Glass gen_rand_uuid_str(parts[i].uuid, UUID_STR_FORMAT_STD); 244*2e192b24SSimon Glass #else 245*2e192b24SSimon Glass errno = -4; 246*2e192b24SSimon Glass goto err; 247*2e192b24SSimon Glass #endif 248*2e192b24SSimon Glass } else { 249*2e192b24SSimon Glass if (extract_env(val, &p)) 250*2e192b24SSimon Glass p = val; 251*2e192b24SSimon Glass if (strlen(p) >= sizeof(parts[i].uuid)) { 252*2e192b24SSimon Glass printf("Wrong uuid format for partition %d\n", i); 253*2e192b24SSimon Glass errno = -4; 254*2e192b24SSimon Glass goto err; 255*2e192b24SSimon Glass } 256*2e192b24SSimon Glass strcpy((char *)parts[i].uuid, p); 257*2e192b24SSimon Glass free(val); 258*2e192b24SSimon Glass } 259*2e192b24SSimon Glass #ifdef CONFIG_PARTITION_TYPE_GUID 260*2e192b24SSimon Glass /* guid */ 261*2e192b24SSimon Glass val = extract_val(tok, "type"); 262*2e192b24SSimon Glass if (val) { 263*2e192b24SSimon Glass /* 'type' is optional */ 264*2e192b24SSimon Glass if (extract_env(val, &p)) 265*2e192b24SSimon Glass p = val; 266*2e192b24SSimon Glass if (strlen(p) >= sizeof(parts[i].type_guid)) { 267*2e192b24SSimon Glass printf("Wrong type guid format for partition %d\n", 268*2e192b24SSimon Glass i); 269*2e192b24SSimon Glass errno = -4; 270*2e192b24SSimon Glass goto err; 271*2e192b24SSimon Glass } 272*2e192b24SSimon Glass strcpy((char *)parts[i].type_guid, p); 273*2e192b24SSimon Glass free(val); 274*2e192b24SSimon Glass } 275*2e192b24SSimon Glass #endif 276*2e192b24SSimon Glass /* name */ 277*2e192b24SSimon Glass val = extract_val(tok, "name"); 278*2e192b24SSimon Glass if (!val) { /* name is mandatory */ 279*2e192b24SSimon Glass errno = -4; 280*2e192b24SSimon Glass goto err; 281*2e192b24SSimon Glass } 282*2e192b24SSimon Glass if (extract_env(val, &p)) 283*2e192b24SSimon Glass p = val; 284*2e192b24SSimon Glass if (strlen(p) >= sizeof(parts[i].name)) { 285*2e192b24SSimon Glass errno = -4; 286*2e192b24SSimon Glass goto err; 287*2e192b24SSimon Glass } 288*2e192b24SSimon Glass strcpy((char *)parts[i].name, p); 289*2e192b24SSimon Glass free(val); 290*2e192b24SSimon Glass 291*2e192b24SSimon Glass /* size */ 292*2e192b24SSimon Glass val = extract_val(tok, "size"); 293*2e192b24SSimon Glass if (!val) { /* 'size' is mandatory */ 294*2e192b24SSimon Glass errno = -4; 295*2e192b24SSimon Glass goto err; 296*2e192b24SSimon Glass } 297*2e192b24SSimon Glass if (extract_env(val, &p)) 298*2e192b24SSimon Glass p = val; 299*2e192b24SSimon Glass size_ll = ustrtoull(p, &p, 0); 300*2e192b24SSimon Glass parts[i].size = lldiv(size_ll, dev_desc->blksz); 301*2e192b24SSimon Glass free(val); 302*2e192b24SSimon Glass 303*2e192b24SSimon Glass /* start address */ 304*2e192b24SSimon Glass val = extract_val(tok, "start"); 305*2e192b24SSimon Glass if (val) { /* start address is optional */ 306*2e192b24SSimon Glass if (extract_env(val, &p)) 307*2e192b24SSimon Glass p = val; 308*2e192b24SSimon Glass start_ll = ustrtoull(p, &p, 0); 309*2e192b24SSimon Glass parts[i].start = lldiv(start_ll, dev_desc->blksz); 310*2e192b24SSimon Glass free(val); 311*2e192b24SSimon Glass } 312*2e192b24SSimon Glass 313*2e192b24SSimon Glass /* bootable */ 314*2e192b24SSimon Glass if (found_key(tok, "bootable")) 315*2e192b24SSimon Glass parts[i].bootable = 1; 316*2e192b24SSimon Glass } 317*2e192b24SSimon Glass 318*2e192b24SSimon Glass *parts_count = p_count; 319*2e192b24SSimon Glass *partitions = parts; 320*2e192b24SSimon Glass free(str); 321*2e192b24SSimon Glass 322*2e192b24SSimon Glass return 0; 323*2e192b24SSimon Glass err: 324*2e192b24SSimon Glass free(str); 325*2e192b24SSimon Glass free(*str_disk_guid); 326*2e192b24SSimon Glass free(parts); 327*2e192b24SSimon Glass 328*2e192b24SSimon Glass return errno; 329*2e192b24SSimon Glass } 330*2e192b24SSimon Glass 331*2e192b24SSimon Glass static int gpt_default(block_dev_desc_t *blk_dev_desc, const char *str_part) 332*2e192b24SSimon Glass { 333*2e192b24SSimon Glass int ret; 334*2e192b24SSimon Glass char *str_disk_guid; 335*2e192b24SSimon Glass u8 part_count = 0; 336*2e192b24SSimon Glass disk_partition_t *partitions = NULL; 337*2e192b24SSimon Glass 338*2e192b24SSimon Glass /* fill partitions */ 339*2e192b24SSimon Glass ret = set_gpt_info(blk_dev_desc, str_part, 340*2e192b24SSimon Glass &str_disk_guid, &partitions, &part_count); 341*2e192b24SSimon Glass if (ret) { 342*2e192b24SSimon Glass if (ret == -1) 343*2e192b24SSimon Glass printf("No partition list provided\n"); 344*2e192b24SSimon Glass if (ret == -2) 345*2e192b24SSimon Glass printf("Missing disk guid\n"); 346*2e192b24SSimon Glass if ((ret == -3) || (ret == -4)) 347*2e192b24SSimon Glass printf("Partition list incomplete\n"); 348*2e192b24SSimon Glass return -1; 349*2e192b24SSimon Glass } 350*2e192b24SSimon Glass 351*2e192b24SSimon Glass /* save partitions layout to disk */ 352*2e192b24SSimon Glass ret = gpt_restore(blk_dev_desc, str_disk_guid, partitions, part_count); 353*2e192b24SSimon Glass free(str_disk_guid); 354*2e192b24SSimon Glass free(partitions); 355*2e192b24SSimon Glass 356*2e192b24SSimon Glass return ret; 357*2e192b24SSimon Glass } 358*2e192b24SSimon Glass 359*2e192b24SSimon Glass static int gpt_verify(block_dev_desc_t *blk_dev_desc, const char *str_part) 360*2e192b24SSimon Glass { 361*2e192b24SSimon Glass ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, 362*2e192b24SSimon Glass blk_dev_desc->blksz); 363*2e192b24SSimon Glass disk_partition_t *partitions = NULL; 364*2e192b24SSimon Glass gpt_entry *gpt_pte = NULL; 365*2e192b24SSimon Glass char *str_disk_guid; 366*2e192b24SSimon Glass u8 part_count = 0; 367*2e192b24SSimon Glass int ret = 0; 368*2e192b24SSimon Glass 369*2e192b24SSimon Glass /* fill partitions */ 370*2e192b24SSimon Glass ret = set_gpt_info(blk_dev_desc, str_part, 371*2e192b24SSimon Glass &str_disk_guid, &partitions, &part_count); 372*2e192b24SSimon Glass if (ret) { 373*2e192b24SSimon Glass if (ret == -1) { 374*2e192b24SSimon Glass printf("No partition list provided - only basic check\n"); 375*2e192b24SSimon Glass ret = gpt_verify_headers(blk_dev_desc, gpt_head, 376*2e192b24SSimon Glass &gpt_pte); 377*2e192b24SSimon Glass goto out; 378*2e192b24SSimon Glass } 379*2e192b24SSimon Glass if (ret == -2) 380*2e192b24SSimon Glass printf("Missing disk guid\n"); 381*2e192b24SSimon Glass if ((ret == -3) || (ret == -4)) 382*2e192b24SSimon Glass printf("Partition list incomplete\n"); 383*2e192b24SSimon Glass return -1; 384*2e192b24SSimon Glass } 385*2e192b24SSimon Glass 386*2e192b24SSimon Glass /* Check partition layout with provided pattern */ 387*2e192b24SSimon Glass ret = gpt_verify_partitions(blk_dev_desc, partitions, part_count, 388*2e192b24SSimon Glass gpt_head, &gpt_pte); 389*2e192b24SSimon Glass free(str_disk_guid); 390*2e192b24SSimon Glass free(partitions); 391*2e192b24SSimon Glass out: 392*2e192b24SSimon Glass free(gpt_pte); 393*2e192b24SSimon Glass return ret; 394*2e192b24SSimon Glass } 395*2e192b24SSimon Glass 396*2e192b24SSimon Glass /** 397*2e192b24SSimon Glass * do_gpt(): Perform GPT operations 398*2e192b24SSimon Glass * 399*2e192b24SSimon Glass * @param cmdtp - command name 400*2e192b24SSimon Glass * @param flag 401*2e192b24SSimon Glass * @param argc 402*2e192b24SSimon Glass * @param argv 403*2e192b24SSimon Glass * 404*2e192b24SSimon Glass * @return zero on success; otherwise error 405*2e192b24SSimon Glass */ 406*2e192b24SSimon Glass static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 407*2e192b24SSimon Glass { 408*2e192b24SSimon Glass int ret = CMD_RET_SUCCESS; 409*2e192b24SSimon Glass int dev = 0; 410*2e192b24SSimon Glass char *ep; 411*2e192b24SSimon Glass block_dev_desc_t *blk_dev_desc = NULL; 412*2e192b24SSimon Glass 413*2e192b24SSimon Glass if (argc < 4 || argc > 5) 414*2e192b24SSimon Glass return CMD_RET_USAGE; 415*2e192b24SSimon Glass 416*2e192b24SSimon Glass dev = (int)simple_strtoul(argv[3], &ep, 10); 417*2e192b24SSimon Glass if (!ep || ep[0] != '\0') { 418*2e192b24SSimon Glass printf("'%s' is not a number\n", argv[3]); 419*2e192b24SSimon Glass return CMD_RET_USAGE; 420*2e192b24SSimon Glass } 421*2e192b24SSimon Glass blk_dev_desc = get_dev(argv[2], dev); 422*2e192b24SSimon Glass if (!blk_dev_desc) { 423*2e192b24SSimon Glass printf("%s: %s dev %d NOT available\n", 424*2e192b24SSimon Glass __func__, argv[2], dev); 425*2e192b24SSimon Glass return CMD_RET_FAILURE; 426*2e192b24SSimon Glass } 427*2e192b24SSimon Glass 428*2e192b24SSimon Glass if ((strcmp(argv[1], "write") == 0) && (argc == 5)) { 429*2e192b24SSimon Glass printf("Writing GPT: "); 430*2e192b24SSimon Glass ret = gpt_default(blk_dev_desc, argv[4]); 431*2e192b24SSimon Glass } else if ((strcmp(argv[1], "verify") == 0)) { 432*2e192b24SSimon Glass ret = gpt_verify(blk_dev_desc, argv[4]); 433*2e192b24SSimon Glass printf("Verify GPT: "); 434*2e192b24SSimon Glass } else { 435*2e192b24SSimon Glass return CMD_RET_USAGE; 436*2e192b24SSimon Glass } 437*2e192b24SSimon Glass 438*2e192b24SSimon Glass if (ret) { 439*2e192b24SSimon Glass printf("error!\n"); 440*2e192b24SSimon Glass return CMD_RET_FAILURE; 441*2e192b24SSimon Glass } 442*2e192b24SSimon Glass 443*2e192b24SSimon Glass printf("success!\n"); 444*2e192b24SSimon Glass return CMD_RET_SUCCESS; 445*2e192b24SSimon Glass } 446*2e192b24SSimon Glass 447*2e192b24SSimon Glass U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt, 448*2e192b24SSimon Glass "GUID Partition Table", 449*2e192b24SSimon Glass "<command> <interface> <dev> <partitions_list>\n" 450*2e192b24SSimon Glass " - GUID partition table restoration and validity check\n" 451*2e192b24SSimon Glass " Restore or verify GPT information on a device connected\n" 452*2e192b24SSimon Glass " to interface\n" 453*2e192b24SSimon Glass " Example usage:\n" 454*2e192b24SSimon Glass " gpt write mmc 0 $partitions\n" 455*2e192b24SSimon Glass " gpt verify mmc 0 $partitions\n" 456*2e192b24SSimon Glass ); 457