Home | History | Annotate | Download | only in disk
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2008 RuggedCom, Inc.
      4  * Richard Retanubun <RichardRetanubun (at) RuggedCom.com>
      5  */
      6 
      7 /*
      8  * NOTE:
      9  *   when CONFIG_SYS_64BIT_LBA is not defined, lbaint_t is 32 bits; this
     10  *   limits the maximum size of addressable storage to < 2 Terra Bytes
     11  */
     12 #include <asm/unaligned.h>
     13 #include <common.h>
     14 #include <command.h>
     15 #include <fdtdec.h>
     16 #include <ide.h>
     17 #include <inttypes.h>
     18 #include <malloc.h>
     19 #include <memalign.h>
     20 #include <part_efi.h>
     21 #include <linux/compiler.h>
     22 #include <linux/ctype.h>
     23 
     24 DECLARE_GLOBAL_DATA_PTR;
     25 
     26 /*
     27  * GUID for basic data partions.
     28  */
     29 static const efi_guid_t partition_basic_data_guid = PARTITION_BASIC_DATA_GUID;
     30 
     31 #ifdef CONFIG_HAVE_BLOCK_DEVICE
     32 /**
     33  * efi_crc32() - EFI version of crc32 function
     34  * @buf: buffer to calculate crc32 of
     35  * @len - length of buf
     36  *
     37  * Description: Returns EFI-style CRC32 value for @buf
     38  */
     39 static inline u32 efi_crc32(const void *buf, u32 len)
     40 {
     41 	return crc32(0, buf, len);
     42 }
     43 
     44 /*
     45  * Private function prototypes
     46  */
     47 
     48 static int pmbr_part_valid(struct partition *part);
     49 static int is_pmbr_valid(legacy_mbr * mbr);
     50 static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba,
     51 				gpt_header *pgpt_head, gpt_entry **pgpt_pte);
     52 static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc,
     53 					 gpt_header *pgpt_head);
     54 static int is_pte_valid(gpt_entry * pte);
     55 
     56 static char *print_efiname(gpt_entry *pte)
     57 {
     58 	static char name[PARTNAME_SZ + 1];
     59 	int i;
     60 	for (i = 0; i < PARTNAME_SZ; i++) {
     61 		u8 c;
     62 		c = pte->partition_name[i] & 0xff;
     63 		c = (c && !isprint(c)) ? '.' : c;
     64 		name[i] = c;
     65 	}
     66 	name[PARTNAME_SZ] = 0;
     67 	return name;
     68 }
     69 
     70 static efi_guid_t system_guid = PARTITION_SYSTEM_GUID;
     71 
     72 static inline int is_bootable(gpt_entry *p)
     73 {
     74 	return p->attributes.fields.legacy_bios_bootable ||
     75 		!memcmp(&(p->partition_type_guid), &system_guid,
     76 			sizeof(efi_guid_t));
     77 }
     78 
     79 static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba,
     80 		lbaint_t lastlba)
     81 {
     82 	uint32_t crc32_backup = 0;
     83 	uint32_t calc_crc32;
     84 
     85 	/* Check the GPT header signature */
     86 	if (le64_to_cpu(gpt_h->signature) != GPT_HEADER_SIGNATURE) {
     87 		printf("%s signature is wrong: 0x%llX != 0x%llX\n",
     88 		       "GUID Partition Table Header",
     89 		       le64_to_cpu(gpt_h->signature),
     90 		       GPT_HEADER_SIGNATURE);
     91 		return -1;
     92 	}
     93 
     94 	/* Check the GUID Partition Table CRC */
     95 	memcpy(&crc32_backup, &gpt_h->header_crc32, sizeof(crc32_backup));
     96 	memset(&gpt_h->header_crc32, 0, sizeof(gpt_h->header_crc32));
     97 
     98 	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
     99 		le32_to_cpu(gpt_h->header_size));
    100 
    101 	memcpy(&gpt_h->header_crc32, &crc32_backup, sizeof(crc32_backup));
    102 
    103 	if (calc_crc32 != le32_to_cpu(crc32_backup)) {
    104 		printf("%s CRC is wrong: 0x%x != 0x%x\n",
    105 		       "GUID Partition Table Header",
    106 		       le32_to_cpu(crc32_backup), calc_crc32);
    107 		return -1;
    108 	}
    109 
    110 	/*
    111 	 * Check that the my_lba entry points to the LBA that contains the GPT
    112 	 */
    113 	if (le64_to_cpu(gpt_h->my_lba) != lba) {
    114 		printf("GPT: my_lba incorrect: %llX != " LBAF "\n",
    115 		       le64_to_cpu(gpt_h->my_lba),
    116 		       lba);
    117 		return -1;
    118 	}
    119 
    120 	/*
    121 	 * Check that the first_usable_lba and that the last_usable_lba are
    122 	 * within the disk.
    123 	 */
    124 	if (le64_to_cpu(gpt_h->first_usable_lba) > lastlba) {
    125 		printf("GPT: first_usable_lba incorrect: %llX > " LBAF "\n",
    126 		       le64_to_cpu(gpt_h->first_usable_lba), lastlba);
    127 		return -1;
    128 	}
    129 	if (le64_to_cpu(gpt_h->last_usable_lba) > lastlba) {
    130 		printf("GPT: last_usable_lba incorrect: %llX > " LBAF "\n",
    131 		       le64_to_cpu(gpt_h->last_usable_lba), lastlba);
    132 		return -1;
    133 	}
    134 
    135 	debug("GPT: first_usable_lba: %llX last_usable_lba: %llX last lba: "
    136 	      LBAF "\n", le64_to_cpu(gpt_h->first_usable_lba),
    137 	      le64_to_cpu(gpt_h->last_usable_lba), lastlba);
    138 
    139 	return 0;
    140 }
    141 
    142 static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e)
    143 {
    144 	uint32_t calc_crc32;
    145 
    146 	/* Check the GUID Partition Table Entry Array CRC */
    147 	calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
    148 		le32_to_cpu(gpt_h->num_partition_entries) *
    149 		le32_to_cpu(gpt_h->sizeof_partition_entry));
    150 
    151 	if (calc_crc32 != le32_to_cpu(gpt_h->partition_entry_array_crc32)) {
    152 		printf("%s: 0x%x != 0x%x\n",
    153 		       "GUID Partition Table Entry Array CRC is wrong",
    154 		       le32_to_cpu(gpt_h->partition_entry_array_crc32),
    155 		       calc_crc32);
    156 		return -1;
    157 	}
    158 
    159 	return 0;
    160 }
    161 
    162 static void prepare_backup_gpt_header(gpt_header *gpt_h)
    163 {
    164 	uint32_t calc_crc32;
    165 	uint64_t val;
    166 
    167 	/* recalculate the values for the Backup GPT Header */
    168 	val = le64_to_cpu(gpt_h->my_lba);
    169 	gpt_h->my_lba = gpt_h->alternate_lba;
    170 	gpt_h->alternate_lba = cpu_to_le64(val);
    171 	gpt_h->partition_entry_lba =
    172 			cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1);
    173 	gpt_h->header_crc32 = 0;
    174 
    175 	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
    176 			       le32_to_cpu(gpt_h->header_size));
    177 	gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
    178 }
    179 
    180 #if CONFIG_IS_ENABLED(EFI_PARTITION)
    181 /*
    182  * Public Functions (include/part.h)
    183  */
    184 
    185 /*
    186  * UUID is displayed as 32 hexadecimal digits, in 5 groups,
    187  * separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters
    188  */
    189 int get_disk_guid(struct blk_desc * dev_desc, char *guid)
    190 {
    191 	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
    192 	gpt_entry *gpt_pte = NULL;
    193 	unsigned char *guid_bin;
    194 
    195 	/* This function validates AND fills in the GPT header and PTE */
    196 	if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
    197 			 gpt_head, &gpt_pte) != 1) {
    198 		printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
    199 		if (is_gpt_valid(dev_desc, dev_desc->lba - 1,
    200 				 gpt_head, &gpt_pte) != 1) {
    201 			printf("%s: *** ERROR: Invalid Backup GPT ***\n",
    202 			       __func__);
    203 			return -EINVAL;
    204 		} else {
    205 			printf("%s: ***        Using Backup GPT ***\n",
    206 			       __func__);
    207 		}
    208 	}
    209 
    210 	guid_bin = gpt_head->disk_guid.b;
    211 	uuid_bin_to_str(guid_bin, guid, UUID_STR_FORMAT_GUID);
    212 
    213 	return 0;
    214 }
    215 
    216 void part_print_efi(struct blk_desc *dev_desc)
    217 {
    218 	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
    219 	gpt_entry *gpt_pte = NULL;
    220 	int i = 0;
    221 	char uuid[UUID_STR_LEN + 1];
    222 	unsigned char *uuid_bin;
    223 
    224 	/* This function validates AND fills in the GPT header and PTE */
    225 	if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
    226 			 gpt_head, &gpt_pte) != 1) {
    227 		printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
    228 		if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
    229 				 gpt_head, &gpt_pte) != 1) {
    230 			printf("%s: *** ERROR: Invalid Backup GPT ***\n",
    231 			       __func__);
    232 			return;
    233 		} else {
    234 			printf("%s: ***        Using Backup GPT ***\n",
    235 			       __func__);
    236 		}
    237 	}
    238 
    239 	debug("%s: gpt-entry at %p\n", __func__, gpt_pte);
    240 
    241 	printf("Part\tStart LBA\tEnd LBA\t\tName\n");
    242 	printf("\tAttributes\n");
    243 	printf("\tType GUID\n");
    244 	printf("\tPartition GUID\n");
    245 
    246 	for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) {
    247 		/* Stop at the first non valid PTE */
    248 		if (!is_pte_valid(&gpt_pte[i]))
    249 			break;
    250 
    251 		printf("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n", (i + 1),
    252 			le64_to_cpu(gpt_pte[i].starting_lba),
    253 			le64_to_cpu(gpt_pte[i].ending_lba),
    254 			print_efiname(&gpt_pte[i]));
    255 		printf("\tattrs:\t0x%016llx\n", gpt_pte[i].attributes.raw);
    256 		uuid_bin = (unsigned char *)gpt_pte[i].partition_type_guid.b;
    257 		uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID);
    258 		printf("\ttype:\t%s\n", uuid);
    259 #ifdef CONFIG_PARTITION_TYPE_GUID
    260 		if (!uuid_guid_get_str(uuid_bin, uuid))
    261 			printf("\ttype:\t%s\n", uuid);
    262 #endif
    263 		uuid_bin = (unsigned char *)gpt_pte[i].unique_partition_guid.b;
    264 		uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID);
    265 		printf("\tguid:\t%s\n", uuid);
    266 	}
    267 
    268 	/* Remember to free pte */
    269 	free(gpt_pte);
    270 	return;
    271 }
    272 
    273 int part_get_info_efi(struct blk_desc *dev_desc, int part,
    274 		      disk_partition_t *info)
    275 {
    276 	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
    277 	gpt_entry *gpt_pte = NULL;
    278 
    279 	/* "part" argument must be at least 1 */
    280 	if (part < 1) {
    281 		printf("%s: Invalid Argument(s)\n", __func__);
    282 		return -1;
    283 	}
    284 
    285 	/* This function validates AND fills in the GPT header and PTE */
    286 	if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
    287 			gpt_head, &gpt_pte) != 1) {
    288 		printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
    289 		if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
    290 				 gpt_head, &gpt_pte) != 1) {
    291 			printf("%s: *** ERROR: Invalid Backup GPT ***\n",
    292 			       __func__);
    293 			return -1;
    294 		} else {
    295 			printf("%s: ***        Using Backup GPT ***\n",
    296 			       __func__);
    297 		}
    298 	}
    299 
    300 	if (part > le32_to_cpu(gpt_head->num_partition_entries) ||
    301 	    !is_pte_valid(&gpt_pte[part - 1])) {
    302 		debug("%s: *** ERROR: Invalid partition number %d ***\n",
    303 			__func__, part);
    304 		free(gpt_pte);
    305 		return -1;
    306 	}
    307 
    308 	/* The 'lbaint_t' casting may limit the maximum disk size to 2 TB */
    309 	info->start = (lbaint_t)le64_to_cpu(gpt_pte[part - 1].starting_lba);
    310 	/* The ending LBA is inclusive, to calculate size, add 1 to it */
    311 	info->size = (lbaint_t)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1
    312 		     - info->start;
    313 	info->blksz = dev_desc->blksz;
    314 
    315 	sprintf((char *)info->name, "%s",
    316 			print_efiname(&gpt_pte[part - 1]));
    317 	strcpy((char *)info->type, "U-Boot");
    318 	info->bootable = is_bootable(&gpt_pte[part - 1]);
    319 #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
    320 	uuid_bin_to_str(gpt_pte[part - 1].unique_partition_guid.b, info->uuid,
    321 			UUID_STR_FORMAT_GUID);
    322 #endif
    323 #ifdef CONFIG_PARTITION_TYPE_GUID
    324 	uuid_bin_to_str(gpt_pte[part - 1].partition_type_guid.b,
    325 			info->type_guid, UUID_STR_FORMAT_GUID);
    326 #endif
    327 
    328 	debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__,
    329 	      info->start, info->size, info->name);
    330 
    331 	/* Remember to free pte */
    332 	free(gpt_pte);
    333 	return 0;
    334 }
    335 
    336 static int part_test_efi(struct blk_desc *dev_desc)
    337 {
    338 	ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blksz);
    339 
    340 	/* Read legacy MBR from block 0 and validate it */
    341 	if ((blk_dread(dev_desc, 0, 1, (ulong *)legacymbr) != 1)
    342 		|| (is_pmbr_valid(legacymbr) != 1)) {
    343 		return -1;
    344 	}
    345 	return 0;
    346 }
    347 
    348 /**
    349  * set_protective_mbr(): Set the EFI protective MBR
    350  * @param dev_desc - block device descriptor
    351  *
    352  * @return - zero on success, otherwise error
    353  */
    354 static int set_protective_mbr(struct blk_desc *dev_desc)
    355 {
    356 	/* Setup the Protective MBR */
    357 	ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, p_mbr, 1, dev_desc->blksz);
    358 	if (p_mbr == NULL) {
    359 		printf("%s: calloc failed!\n", __func__);
    360 		return -1;
    361 	}
    362 
    363 	/* Read MBR to backup boot code if it exists */
    364 	if (blk_dread(dev_desc, 0, 1, p_mbr) != 1) {
    365 		pr_err("** Can't read from device %d **\n", dev_desc->devnum);
    366 		return -1;
    367 	}
    368 
    369 	/* Clear all data in MBR except of backed up boot code */
    370 	memset((char *)p_mbr + MSDOS_MBR_BOOT_CODE_SIZE, 0, sizeof(*p_mbr) -
    371 			MSDOS_MBR_BOOT_CODE_SIZE);
    372 
    373 	/* Append signature */
    374 	p_mbr->signature = MSDOS_MBR_SIGNATURE;
    375 	p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
    376 	p_mbr->partition_record[0].start_sect = 1;
    377 	p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba - 1;
    378 
    379 	/* Write MBR sector to the MMC device */
    380 	if (blk_dwrite(dev_desc, 0, 1, p_mbr) != 1) {
    381 		printf("** Can't write to device %d **\n",
    382 			dev_desc->devnum);
    383 		return -1;
    384 	}
    385 
    386 	return 0;
    387 }
    388 
    389 int write_gpt_table(struct blk_desc *dev_desc,
    390 		gpt_header *gpt_h, gpt_entry *gpt_e)
    391 {
    392 	const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries
    393 					   * sizeof(gpt_entry)), dev_desc);
    394 	u32 calc_crc32;
    395 
    396 	debug("max lba: %x\n", (u32) dev_desc->lba);
    397 	/* Setup the Protective MBR */
    398 	if (set_protective_mbr(dev_desc) < 0)
    399 		goto err;
    400 
    401 	/* Generate CRC for the Primary GPT Header */
    402 	calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
    403 			      le32_to_cpu(gpt_h->num_partition_entries) *
    404 			      le32_to_cpu(gpt_h->sizeof_partition_entry));
    405 	gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32);
    406 
    407 	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
    408 			      le32_to_cpu(gpt_h->header_size));
    409 	gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
    410 
    411 	/* Write the First GPT to the block right after the Legacy MBR */
    412 	if (blk_dwrite(dev_desc, 1, 1, gpt_h) != 1)
    413 		goto err;
    414 
    415 	if (blk_dwrite(dev_desc, le64_to_cpu(gpt_h->partition_entry_lba),
    416 		       pte_blk_cnt, gpt_e) != pte_blk_cnt)
    417 		goto err;
    418 
    419 	prepare_backup_gpt_header(gpt_h);
    420 
    421 	if (blk_dwrite(dev_desc, (lbaint_t)le64_to_cpu(gpt_h->last_usable_lba)
    422 		       + 1, pte_blk_cnt, gpt_e) != pte_blk_cnt)
    423 		goto err;
    424 
    425 	if (blk_dwrite(dev_desc, (lbaint_t)le64_to_cpu(gpt_h->my_lba), 1,
    426 		       gpt_h) != 1)
    427 		goto err;
    428 
    429 	debug("GPT successfully written to block device!\n");
    430 	return 0;
    431 
    432  err:
    433 	printf("** Can't write to device %d **\n", dev_desc->devnum);
    434 	return -1;
    435 }
    436 
    437 int gpt_fill_pte(struct blk_desc *dev_desc,
    438 		 gpt_header *gpt_h, gpt_entry *gpt_e,
    439 		 disk_partition_t *partitions, int parts)
    440 {
    441 	lbaint_t offset = (lbaint_t)le64_to_cpu(gpt_h->first_usable_lba);
    442 	lbaint_t last_usable_lba = (lbaint_t)
    443 			le64_to_cpu(gpt_h->last_usable_lba);
    444 	int i, k;
    445 	size_t efiname_len, dosname_len;
    446 #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
    447 	char *str_uuid;
    448 	unsigned char *bin_uuid;
    449 #endif
    450 #ifdef CONFIG_PARTITION_TYPE_GUID
    451 	char *str_type_guid;
    452 	unsigned char *bin_type_guid;
    453 #endif
    454 	size_t hdr_start = gpt_h->my_lba;
    455 	size_t hdr_end = hdr_start + 1;
    456 
    457 	size_t pte_start = gpt_h->partition_entry_lba;
    458 	size_t pte_end = pte_start +
    459 		gpt_h->num_partition_entries * gpt_h->sizeof_partition_entry /
    460 		dev_desc->blksz;
    461 
    462 	for (i = 0; i < parts; i++) {
    463 		/* partition starting lba */
    464 		lbaint_t start = partitions[i].start;
    465 		lbaint_t size = partitions[i].size;
    466 
    467 		if (start) {
    468 			offset = start + size;
    469 		} else {
    470 			start = offset;
    471 			offset += size;
    472 		}
    473 
    474 		/*
    475 		 * If our partition overlaps with either the GPT
    476 		 * header, or the partition entry, reject it.
    477 		 */
    478 		if (((start < hdr_end && hdr_start < (start + size)) ||
    479 		     (start < pte_end && pte_start < (start + size)))) {
    480 			printf("Partition overlap\n");
    481 			return -1;
    482 		}
    483 
    484 		gpt_e[i].starting_lba = cpu_to_le64(start);
    485 
    486 		if (offset > (last_usable_lba + 1)) {
    487 			printf("Partitions layout exceds disk size\n");
    488 			return -1;
    489 		}
    490 		/* partition ending lba */
    491 		if ((i == parts - 1) && (size == 0))
    492 			/* extend the last partition to maximuim */
    493 			gpt_e[i].ending_lba = gpt_h->last_usable_lba;
    494 		else
    495 			gpt_e[i].ending_lba = cpu_to_le64(offset - 1);
    496 
    497 #ifdef CONFIG_PARTITION_TYPE_GUID
    498 		str_type_guid = partitions[i].type_guid;
    499 		bin_type_guid = gpt_e[i].partition_type_guid.b;
    500 		if (strlen(str_type_guid)) {
    501 			if (uuid_str_to_bin(str_type_guid, bin_type_guid,
    502 					    UUID_STR_FORMAT_GUID)) {
    503 				printf("Partition no. %d: invalid type guid: %s\n",
    504 				       i, str_type_guid);
    505 				return -1;
    506 			}
    507 		} else {
    508 			/* default partition type GUID */
    509 			memcpy(bin_type_guid,
    510 			       &partition_basic_data_guid, 16);
    511 		}
    512 #else
    513 		/* partition type GUID */
    514 		memcpy(gpt_e[i].partition_type_guid.b,
    515 			&partition_basic_data_guid, 16);
    516 #endif
    517 
    518 #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
    519 		str_uuid = partitions[i].uuid;
    520 		bin_uuid = gpt_e[i].unique_partition_guid.b;
    521 
    522 		if (uuid_str_to_bin(str_uuid, bin_uuid, UUID_STR_FORMAT_GUID)) {
    523 			printf("Partition no. %d: invalid guid: %s\n",
    524 				i, str_uuid);
    525 			return -1;
    526 		}
    527 #endif
    528 
    529 		/* partition attributes */
    530 		memset(&gpt_e[i].attributes, 0,
    531 		       sizeof(gpt_entry_attributes));
    532 
    533 		if (partitions[i].bootable)
    534 			gpt_e[i].attributes.fields.legacy_bios_bootable = 1;
    535 
    536 		/* partition name */
    537 		efiname_len = sizeof(gpt_e[i].partition_name)
    538 			/ sizeof(efi_char16_t);
    539 		dosname_len = sizeof(partitions[i].name);
    540 
    541 		memset(gpt_e[i].partition_name, 0,
    542 		       sizeof(gpt_e[i].partition_name));
    543 
    544 		for (k = 0; k < min(dosname_len, efiname_len); k++)
    545 			gpt_e[i].partition_name[k] =
    546 				(efi_char16_t)(partitions[i].name[k]);
    547 
    548 		debug("%s: name: %s offset[%d]: 0x" LBAF
    549 		      " size[%d]: 0x" LBAF "\n",
    550 		      __func__, partitions[i].name, i,
    551 		      offset, i, size);
    552 	}
    553 
    554 	return 0;
    555 }
    556 
    557 static uint32_t partition_entries_offset(struct blk_desc *dev_desc)
    558 {
    559 	uint32_t offset_blks = 2;
    560 	uint32_t __maybe_unused offset_bytes;
    561 	int __maybe_unused config_offset;
    562 
    563 #if defined(CONFIG_EFI_PARTITION_ENTRIES_OFF)
    564 	/*
    565 	 * Some architectures require their SPL loader at a fixed
    566 	 * address within the first 16KB of the disk.  To avoid an
    567 	 * overlap with the partition entries of the EFI partition
    568 	 * table, the first safe offset (in bytes, from the start of
    569 	 * the disk) for the entries can be set in
    570 	 * CONFIG_EFI_PARTITION_ENTRIES_OFF.
    571 	 */
    572 	offset_bytes =
    573 		PAD_TO_BLOCKSIZE(CONFIG_EFI_PARTITION_ENTRIES_OFF, dev_desc);
    574 	offset_blks = offset_bytes / dev_desc->blksz;
    575 #endif
    576 
    577 #if defined(CONFIG_OF_CONTROL)
    578 	/*
    579 	 * Allow the offset of the first partition entires (in bytes
    580 	 * from the start of the device) to be specified as a property
    581 	 * of the device tree '/config' node.
    582 	 */
    583 	config_offset = fdtdec_get_config_int(gd->fdt_blob,
    584 					      "u-boot,efi-partition-entries-offset",
    585 					      -EINVAL);
    586 	if (config_offset != -EINVAL) {
    587 		offset_bytes = PAD_TO_BLOCKSIZE(config_offset, dev_desc);
    588 		offset_blks = offset_bytes / dev_desc->blksz;
    589 	}
    590 #endif
    591 
    592 	debug("efi: partition entries offset (in blocks): %d\n", offset_blks);
    593 
    594 	/*
    595 	 * The earliest LBA this can be at is LBA#2 (i.e. right behind
    596 	 * the (protective) MBR and the GPT header.
    597 	 */
    598 	if (offset_blks < 2)
    599 		offset_blks = 2;
    600 
    601 	return offset_blks;
    602 }
    603 
    604 int gpt_fill_header(struct blk_desc *dev_desc, gpt_header *gpt_h,
    605 		char *str_guid, int parts_count)
    606 {
    607 	gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
    608 	gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
    609 	gpt_h->header_size = cpu_to_le32(sizeof(gpt_header));
    610 	gpt_h->my_lba = cpu_to_le64(1);
    611 	gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1);
    612 	gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34);
    613 	gpt_h->partition_entry_lba =
    614 		cpu_to_le64(partition_entries_offset(dev_desc));
    615 	gpt_h->first_usable_lba =
    616 		cpu_to_le64(le64_to_cpu(gpt_h->partition_entry_lba) + 32);
    617 	gpt_h->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
    618 	gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry));
    619 	gpt_h->header_crc32 = 0;
    620 	gpt_h->partition_entry_array_crc32 = 0;
    621 
    622 	if (uuid_str_to_bin(str_guid, gpt_h->disk_guid.b, UUID_STR_FORMAT_GUID))
    623 		return -1;
    624 
    625 	return 0;
    626 }
    627 
    628 int gpt_restore(struct blk_desc *dev_desc, char *str_disk_guid,
    629 		disk_partition_t *partitions, int parts_count)
    630 {
    631 	gpt_header *gpt_h;
    632 	gpt_entry *gpt_e;
    633 	int ret, size;
    634 
    635 	size = PAD_TO_BLOCKSIZE(sizeof(gpt_header), dev_desc);
    636 	gpt_h = malloc_cache_aligned(size);
    637 	if (gpt_h == NULL) {
    638 		printf("%s: calloc failed!\n", __func__);
    639 		return -1;
    640 	}
    641 	memset(gpt_h, 0, size);
    642 
    643 	size = PAD_TO_BLOCKSIZE(GPT_ENTRY_NUMBERS * sizeof(gpt_entry),
    644 				dev_desc);
    645 	gpt_e = malloc_cache_aligned(size);
    646 	if (gpt_e == NULL) {
    647 		printf("%s: calloc failed!\n", __func__);
    648 		free(gpt_h);
    649 		return -1;
    650 	}
    651 	memset(gpt_e, 0, size);
    652 
    653 	/* Generate Primary GPT header (LBA1) */
    654 	ret = gpt_fill_header(dev_desc, gpt_h, str_disk_guid, parts_count);
    655 	if (ret)
    656 		goto err;
    657 
    658 	/* Generate partition entries */
    659 	ret = gpt_fill_pte(dev_desc, gpt_h, gpt_e, partitions, parts_count);
    660 	if (ret)
    661 		goto err;
    662 
    663 	/* Write GPT partition table */
    664 	ret = write_gpt_table(dev_desc, gpt_h, gpt_e);
    665 
    666 err:
    667 	free(gpt_e);
    668 	free(gpt_h);
    669 	return ret;
    670 }
    671 
    672 static void gpt_convert_efi_name_to_char(char *s, efi_char16_t *es, int n)
    673 {
    674 	char *ess = (char *)es;
    675 	int i, j;
    676 
    677 	memset(s, '\0', n);
    678 
    679 	for (i = 0, j = 0; j < n; i += 2, j++) {
    680 		s[j] = ess[i];
    681 		if (!ess[i])
    682 			return;
    683 	}
    684 }
    685 
    686 int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,
    687 		       gpt_entry **gpt_pte)
    688 {
    689 	/*
    690 	 * This function validates AND
    691 	 * fills in the GPT header and PTE
    692 	 */
    693 	if (is_gpt_valid(dev_desc,
    694 			 GPT_PRIMARY_PARTITION_TABLE_LBA,
    695 			 gpt_head, gpt_pte) != 1) {
    696 		printf("%s: *** ERROR: Invalid GPT ***\n",
    697 		       __func__);
    698 		return -1;
    699 	}
    700 	if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
    701 			 gpt_head, gpt_pte) != 1) {
    702 		printf("%s: *** ERROR: Invalid Backup GPT ***\n",
    703 		       __func__);
    704 		return -1;
    705 	}
    706 
    707 	return 0;
    708 }
    709 
    710 int gpt_verify_partitions(struct blk_desc *dev_desc,
    711 			  disk_partition_t *partitions, int parts,
    712 			  gpt_header *gpt_head, gpt_entry **gpt_pte)
    713 {
    714 	char efi_str[PARTNAME_SZ + 1];
    715 	u64 gpt_part_size;
    716 	gpt_entry *gpt_e;
    717 	int ret, i;
    718 
    719 	ret = gpt_verify_headers(dev_desc, gpt_head, gpt_pte);
    720 	if (ret)
    721 		return ret;
    722 
    723 	gpt_e = *gpt_pte;
    724 
    725 	for (i = 0; i < parts; i++) {
    726 		if (i == gpt_head->num_partition_entries) {
    727 			pr_err("More partitions than allowed!\n");
    728 			return -1;
    729 		}
    730 
    731 		/* Check if GPT and ENV partition names match */
    732 		gpt_convert_efi_name_to_char(efi_str, gpt_e[i].partition_name,
    733 					     PARTNAME_SZ + 1);
    734 
    735 		debug("%s: part: %2d name - GPT: %16s, ENV: %16s ",
    736 		      __func__, i, efi_str, partitions[i].name);
    737 
    738 		if (strncmp(efi_str, (char *)partitions[i].name,
    739 			    sizeof(partitions->name))) {
    740 			pr_err("Partition name: %s does not match %s!\n",
    741 			      efi_str, (char *)partitions[i].name);
    742 			return -1;
    743 		}
    744 
    745 		/* Check if GPT and ENV sizes match */
    746 		gpt_part_size = le64_to_cpu(gpt_e[i].ending_lba) -
    747 			le64_to_cpu(gpt_e[i].starting_lba) + 1;
    748 		debug("size(LBA) - GPT: %8llu, ENV: %8llu ",
    749 		      (unsigned long long)gpt_part_size,
    750 		      (unsigned long long)partitions[i].size);
    751 
    752 		if (le64_to_cpu(gpt_part_size) != partitions[i].size) {
    753 			/* We do not check the extend partition size */
    754 			if ((i == parts - 1) && (partitions[i].size == 0))
    755 				continue;
    756 
    757 			pr_err("Partition %s size: %llu does not match %llu!\n",
    758 			      efi_str, (unsigned long long)gpt_part_size,
    759 			      (unsigned long long)partitions[i].size);
    760 			return -1;
    761 		}
    762 
    763 		/*
    764 		 * Start address is optional - check only if provided
    765 		 * in '$partition' variable
    766 		 */
    767 		if (!partitions[i].start) {
    768 			debug("\n");
    769 			continue;
    770 		}
    771 
    772 		/* Check if GPT and ENV start LBAs match */
    773 		debug("start LBA - GPT: %8llu, ENV: %8llu\n",
    774 		      le64_to_cpu(gpt_e[i].starting_lba),
    775 		      (unsigned long long)partitions[i].start);
    776 
    777 		if (le64_to_cpu(gpt_e[i].starting_lba) != partitions[i].start) {
    778 			pr_err("Partition %s start: %llu does not match %llu!\n",
    779 			      efi_str, le64_to_cpu(gpt_e[i].starting_lba),
    780 			      (unsigned long long)partitions[i].start);
    781 			return -1;
    782 		}
    783 	}
    784 
    785 	return 0;
    786 }
    787 
    788 int is_valid_gpt_buf(struct blk_desc *dev_desc, void *buf)
    789 {
    790 	gpt_header *gpt_h;
    791 	gpt_entry *gpt_e;
    792 
    793 	/* determine start of GPT Header in the buffer */
    794 	gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
    795 		       dev_desc->blksz);
    796 	if (validate_gpt_header(gpt_h, GPT_PRIMARY_PARTITION_TABLE_LBA,
    797 				dev_desc->lba))
    798 		return -1;
    799 
    800 	/* determine start of GPT Entries in the buffer */
    801 	gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
    802 		       dev_desc->blksz);
    803 	if (validate_gpt_entries(gpt_h, gpt_e))
    804 		return -1;
    805 
    806 	return 0;
    807 }
    808 
    809 int write_mbr_and_gpt_partitions(struct blk_desc *dev_desc, void *buf)
    810 {
    811 	gpt_header *gpt_h;
    812 	gpt_entry *gpt_e;
    813 	int gpt_e_blk_cnt;
    814 	lbaint_t lba;
    815 	int cnt;
    816 
    817 	if (is_valid_gpt_buf(dev_desc, buf))
    818 		return -1;
    819 
    820 	/* determine start of GPT Header in the buffer */
    821 	gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
    822 		       dev_desc->blksz);
    823 
    824 	/* determine start of GPT Entries in the buffer */
    825 	gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
    826 		       dev_desc->blksz);
    827 	gpt_e_blk_cnt = BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) *
    828 				   le32_to_cpu(gpt_h->sizeof_partition_entry)),
    829 				  dev_desc);
    830 
    831 	/* write MBR */
    832 	lba = 0;	/* MBR is always at 0 */
    833 	cnt = 1;	/* MBR (1 block) */
    834 	if (blk_dwrite(dev_desc, lba, cnt, buf) != cnt) {
    835 		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
    836 		       __func__, "MBR", cnt, lba);
    837 		return 1;
    838 	}
    839 
    840 	/* write Primary GPT */
    841 	lba = GPT_PRIMARY_PARTITION_TABLE_LBA;
    842 	cnt = 1;	/* GPT Header (1 block) */
    843 	if (blk_dwrite(dev_desc, lba, cnt, gpt_h) != cnt) {
    844 		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
    845 		       __func__, "Primary GPT Header", cnt, lba);
    846 		return 1;
    847 	}
    848 
    849 	lba = le64_to_cpu(gpt_h->partition_entry_lba);
    850 	cnt = gpt_e_blk_cnt;
    851 	if (blk_dwrite(dev_desc, lba, cnt, gpt_e) != cnt) {
    852 		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
    853 		       __func__, "Primary GPT Entries", cnt, lba);
    854 		return 1;
    855 	}
    856 
    857 	prepare_backup_gpt_header(gpt_h);
    858 
    859 	/* write Backup GPT */
    860 	lba = le64_to_cpu(gpt_h->partition_entry_lba);
    861 	cnt = gpt_e_blk_cnt;
    862 	if (blk_dwrite(dev_desc, lba, cnt, gpt_e) != cnt) {
    863 		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
    864 		       __func__, "Backup GPT Entries", cnt, lba);
    865 		return 1;
    866 	}
    867 
    868 	lba = le64_to_cpu(gpt_h->my_lba);
    869 	cnt = 1;	/* GPT Header (1 block) */
    870 	if (blk_dwrite(dev_desc, lba, cnt, gpt_h) != cnt) {
    871 		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
    872 		       __func__, "Backup GPT Header", cnt, lba);
    873 		return 1;
    874 	}
    875 
    876 	return 0;
    877 }
    878 #endif
    879 
    880 /*
    881  * Private functions
    882  */
    883 /*
    884  * pmbr_part_valid(): Check for EFI partition signature
    885  *
    886  * Returns: 1 if EFI GPT partition type is found.
    887  */
    888 static int pmbr_part_valid(struct partition *part)
    889 {
    890 	if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
    891 		get_unaligned_le32(&part->start_sect) == 1UL) {
    892 		return 1;
    893 	}
    894 
    895 	return 0;
    896 }
    897 
    898 /*
    899  * is_pmbr_valid(): test Protective MBR for validity
    900  *
    901  * Returns: 1 if PMBR is valid, 0 otherwise.
    902  * Validity depends on two things:
    903  *  1) MSDOS signature is in the last two bytes of the MBR
    904  *  2) One partition of type 0xEE is found, checked by pmbr_part_valid()
    905  */
    906 static int is_pmbr_valid(legacy_mbr * mbr)
    907 {
    908 	int i = 0;
    909 
    910 	if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
    911 		return 0;
    912 
    913 	for (i = 0; i < 4; i++) {
    914 		if (pmbr_part_valid(&mbr->partition_record[i])) {
    915 			return 1;
    916 		}
    917 	}
    918 	return 0;
    919 }
    920 
    921 /**
    922  * is_gpt_valid() - tests one GPT header and PTEs for validity
    923  *
    924  * lba is the logical block address of the GPT header to test
    925  * gpt is a GPT header ptr, filled on return.
    926  * ptes is a PTEs ptr, filled on return.
    927  *
    928  * Description: returns 1 if valid,  0 on error.
    929  * If valid, returns pointers to PTEs.
    930  */
    931 static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba,
    932 			gpt_header *pgpt_head, gpt_entry **pgpt_pte)
    933 {
    934 	/* Confirm valid arguments prior to allocation. */
    935 	if (!dev_desc || !pgpt_head) {
    936 		printf("%s: Invalid Argument(s)\n", __func__);
    937 		return 0;
    938 	}
    939 
    940 	ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, mbr, 1, dev_desc->blksz);
    941 
    942 	/* Read MBR Header from device */
    943 	if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1) {
    944 		printf("*** ERROR: Can't read MBR header ***\n");
    945 		return 0;
    946 	}
    947 
    948 	/* Read GPT Header from device */
    949 	if (blk_dread(dev_desc, (lbaint_t)lba, 1, pgpt_head) != 1) {
    950 		printf("*** ERROR: Can't read GPT header ***\n");
    951 		return 0;
    952 	}
    953 
    954 	if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba))
    955 		return 0;
    956 
    957 	if (dev_desc->sig_type == SIG_TYPE_NONE) {
    958 		efi_guid_t empty = {};
    959 		if (memcmp(&pgpt_head->disk_guid, &empty, sizeof(empty))) {
    960 			dev_desc->sig_type = SIG_TYPE_GUID;
    961 			memcpy(&dev_desc->guid_sig, &pgpt_head->disk_guid,
    962 			      sizeof(empty));
    963 		} else if (mbr->unique_mbr_signature != 0) {
    964 			dev_desc->sig_type = SIG_TYPE_MBR;
    965 			dev_desc->mbr_sig = mbr->unique_mbr_signature;
    966 		}
    967 	}
    968 
    969 	/* Read and allocate Partition Table Entries */
    970 	*pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
    971 	if (*pgpt_pte == NULL) {
    972 		printf("GPT: Failed to allocate memory for PTE\n");
    973 		return 0;
    974 	}
    975 
    976 	if (validate_gpt_entries(pgpt_head, *pgpt_pte)) {
    977 		free(*pgpt_pte);
    978 		return 0;
    979 	}
    980 
    981 	/* We're done, all's well */
    982 	return 1;
    983 }
    984 
    985 /**
    986  * alloc_read_gpt_entries(): reads partition entries from disk
    987  * @dev_desc
    988  * @gpt - GPT header
    989  *
    990  * Description: Returns ptes on success,  NULL on error.
    991  * Allocates space for PTEs based on information found in @gpt.
    992  * Notes: remember to free pte when you're done!
    993  */
    994 static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc,
    995 					 gpt_header *pgpt_head)
    996 {
    997 	size_t count = 0, blk_cnt;
    998 	lbaint_t blk;
    999 	gpt_entry *pte = NULL;
   1000 
   1001 	if (!dev_desc || !pgpt_head) {
   1002 		printf("%s: Invalid Argument(s)\n", __func__);
   1003 		return NULL;
   1004 	}
   1005 
   1006 	count = le32_to_cpu(pgpt_head->num_partition_entries) *
   1007 		le32_to_cpu(pgpt_head->sizeof_partition_entry);
   1008 
   1009 	debug("%s: count = %u * %u = %lu\n", __func__,
   1010 	      (u32) le32_to_cpu(pgpt_head->num_partition_entries),
   1011 	      (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry),
   1012 	      (ulong)count);
   1013 
   1014 	/* Allocate memory for PTE, remember to FREE */
   1015 	if (count != 0) {
   1016 		pte = memalign(ARCH_DMA_MINALIGN,
   1017 			       PAD_TO_BLOCKSIZE(count, dev_desc));
   1018 	}
   1019 
   1020 	if (count == 0 || pte == NULL) {
   1021 		printf("%s: ERROR: Can't allocate %#lX bytes for GPT Entries\n",
   1022 		       __func__, (ulong)count);
   1023 		return NULL;
   1024 	}
   1025 
   1026 	/* Read GPT Entries from device */
   1027 	blk = le64_to_cpu(pgpt_head->partition_entry_lba);
   1028 	blk_cnt = BLOCK_CNT(count, dev_desc);
   1029 	if (blk_dread(dev_desc, blk, (lbaint_t)blk_cnt, pte) != blk_cnt) {
   1030 		printf("*** ERROR: Can't read GPT Entries ***\n");
   1031 		free(pte);
   1032 		return NULL;
   1033 	}
   1034 	return pte;
   1035 }
   1036 
   1037 /**
   1038  * is_pte_valid(): validates a single Partition Table Entry
   1039  * @gpt_entry - Pointer to a single Partition Table Entry
   1040  *
   1041  * Description: returns 1 if valid,  0 on error.
   1042  */
   1043 static int is_pte_valid(gpt_entry * pte)
   1044 {
   1045 	efi_guid_t unused_guid;
   1046 
   1047 	if (!pte) {
   1048 		printf("%s: Invalid Argument(s)\n", __func__);
   1049 		return 0;
   1050 	}
   1051 
   1052 	/* Only one validation for now:
   1053 	 * The GUID Partition Type != Unused Entry (ALL-ZERO)
   1054 	 */
   1055 	memset(unused_guid.b, 0, sizeof(unused_guid.b));
   1056 
   1057 	if (memcmp(pte->partition_type_guid.b, unused_guid.b,
   1058 		sizeof(unused_guid.b)) == 0) {
   1059 
   1060 		debug("%s: Found an unused PTE GUID at 0x%08X\n", __func__,
   1061 		      (unsigned int)(uintptr_t)pte);
   1062 
   1063 		return 0;
   1064 	} else {
   1065 		return 1;
   1066 	}
   1067 }
   1068 
   1069 /*
   1070  * Add an 'a_' prefix so it comes before 'dos' in the linker list. We need to
   1071  * check EFI first, since a DOS partition is often used as a 'protective MBR'
   1072  * with EFI.
   1073  */
   1074 U_BOOT_PART_TYPE(a_efi) = {
   1075 	.name		= "EFI",
   1076 	.part_type	= PART_TYPE_EFI,
   1077 	.max_entries	= GPT_ENTRY_NUMBERS,
   1078 	.get_info	= part_get_info_ptr(part_get_info_efi),
   1079 	.print		= part_print_ptr(part_print_efi),
   1080 	.test		= part_test_efi,
   1081 };
   1082 #endif
   1083