1 /* 2 * Copyright (C) 2008 RuggedCom, Inc. 3 * Richard Retanubun <RichardRetanubun@RuggedCom.com> 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 /* 25 * Problems with CONFIG_SYS_64BIT_LBA: 26 * 27 * struct disk_partition.start in include/part.h is sized as ulong. 28 * When CONFIG_SYS_64BIT_LBA is activated, lbaint_t changes from ulong to uint64_t. 29 * For now, it is cast back to ulong at assignment. 30 * 31 * This limits the maximum size of addressable storage to < 2 Terra Bytes 32 */ 33 #include <common.h> 34 #include <command.h> 35 #include <ide.h> 36 #include <malloc.h> 37 #include <part_efi.h> 38 #include <linux/ctype.h> 39 40 DECLARE_GLOBAL_DATA_PTR; 41 42 #if defined(CONFIG_CMD_IDE) || \ 43 defined(CONFIG_CMD_SATA) || \ 44 defined(CONFIG_CMD_SCSI) || \ 45 defined(CONFIG_CMD_USB) || \ 46 defined(CONFIG_MMC) || \ 47 defined(CONFIG_SYSTEMACE) 48 49 /** 50 * efi_crc32() - EFI version of crc32 function 51 * @buf: buffer to calculate crc32 of 52 * @len - length of buf 53 * 54 * Description: Returns EFI-style CRC32 value for @buf 55 */ 56 static inline u32 efi_crc32(const void *buf, u32 len) 57 { 58 return crc32(0, buf, len); 59 } 60 61 /* 62 * Private function prototypes 63 */ 64 65 static int pmbr_part_valid(struct partition *part); 66 static int is_pmbr_valid(legacy_mbr * mbr); 67 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, 68 gpt_header * pgpt_head, gpt_entry ** pgpt_pte); 69 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, 70 gpt_header * pgpt_head); 71 static int is_pte_valid(gpt_entry * pte); 72 73 static char *print_efiname(gpt_entry *pte) 74 { 75 static char name[PARTNAME_SZ + 1]; 76 int i; 77 for (i = 0; i < PARTNAME_SZ; i++) { 78 u8 c; 79 c = pte->partition_name[i] & 0xff; 80 c = (c && !isprint(c)) ? '.' : c; 81 name[i] = c; 82 } 83 name[PARTNAME_SZ] = 0; 84 return name; 85 } 86 87 static void uuid_string(unsigned char *uuid, char *str) 88 { 89 static const u8 le[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 90 12, 13, 14, 15}; 91 int i; 92 93 for (i = 0; i < 16; i++) { 94 sprintf(str, "%02x", uuid[le[i]]); 95 str += 2; 96 switch (i) { 97 case 3: 98 case 5: 99 case 7: 100 case 9: 101 *str++ = '-'; 102 break; 103 } 104 } 105 } 106 107 static efi_guid_t system_guid = PARTITION_SYSTEM_GUID; 108 109 static inline int is_bootable(gpt_entry *p) 110 { 111 return p->attributes.fields.legacy_bios_bootable || 112 !memcmp(&(p->partition_type_guid), &system_guid, 113 sizeof(efi_guid_t)); 114 } 115 116 #ifdef CONFIG_EFI_PARTITION 117 /* 118 * Public Functions (include/part.h) 119 */ 120 121 void print_part_efi(block_dev_desc_t * dev_desc) 122 { 123 ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1); 124 gpt_entry *gpt_pte = NULL; 125 int i = 0; 126 char uuid[37]; 127 128 if (!dev_desc) { 129 printf("%s: Invalid Argument(s)\n", __func__); 130 return; 131 } 132 /* This function validates AND fills in the GPT header and PTE */ 133 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, 134 gpt_head, &gpt_pte) != 1) { 135 printf("%s: *** ERROR: Invalid GPT ***\n", __func__); 136 return; 137 } 138 139 debug("%s: gpt-entry at %p\n", __func__, gpt_pte); 140 141 printf("Part\tStart LBA\tEnd LBA\t\tName\n"); 142 printf("\tAttributes\n"); 143 printf("\tType UUID\n"); 144 printf("\tPartition UUID\n"); 145 146 for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) { 147 /* Stop at the first non valid PTE */ 148 if (!is_pte_valid(&gpt_pte[i])) 149 break; 150 151 printf("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n", (i + 1), 152 le64_to_cpu(gpt_pte[i].starting_lba), 153 le64_to_cpu(gpt_pte[i].ending_lba), 154 print_efiname(&gpt_pte[i])); 155 printf("\tattrs:\t0x%016llx\n", gpt_pte[i].attributes.raw); 156 uuid_string(gpt_pte[i].partition_type_guid.b, uuid); 157 printf("\ttype:\t%s\n", uuid); 158 uuid_string(gpt_pte[i].unique_partition_guid.b, uuid); 159 printf("\tuuid:\t%s\n", uuid); 160 } 161 162 /* Remember to free pte */ 163 free(gpt_pte); 164 return; 165 } 166 167 int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, 168 disk_partition_t * info) 169 { 170 ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1); 171 gpt_entry *gpt_pte = NULL; 172 173 /* "part" argument must be at least 1 */ 174 if (!dev_desc || !info || part < 1) { 175 printf("%s: Invalid Argument(s)\n", __func__); 176 return -1; 177 } 178 179 /* This function validates AND fills in the GPT header and PTE */ 180 if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, 181 gpt_head, &gpt_pte) != 1) { 182 printf("%s: *** ERROR: Invalid GPT ***\n", __func__); 183 return -1; 184 } 185 186 if (part > le32_to_cpu(gpt_head->num_partition_entries) || 187 !is_pte_valid(&gpt_pte[part - 1])) { 188 printf("%s: *** ERROR: Invalid partition number %d ***\n", 189 __func__, part); 190 return -1; 191 } 192 193 /* The ulong casting limits the maximum disk size to 2 TB */ 194 info->start = (u64)le64_to_cpu(gpt_pte[part - 1].starting_lba); 195 /* The ending LBA is inclusive, to calculate size, add 1 to it */ 196 info->size = ((u64)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1) 197 - info->start; 198 info->blksz = GPT_BLOCK_SIZE; 199 200 sprintf((char *)info->name, "%s", 201 print_efiname(&gpt_pte[part - 1])); 202 sprintf((char *)info->type, "U-Boot"); 203 info->bootable = is_bootable(&gpt_pte[part - 1]); 204 #ifdef CONFIG_PARTITION_UUIDS 205 uuid_string(gpt_pte[part - 1].unique_partition_guid.b, info->uuid); 206 #endif 207 208 debug("%s: start 0x%lX, size 0x%lX, name %s", __func__, 209 info->start, info->size, info->name); 210 211 /* Remember to free pte */ 212 free(gpt_pte); 213 return 0; 214 } 215 216 int test_part_efi(block_dev_desc_t * dev_desc) 217 { 218 ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, legacymbr, 1); 219 220 /* Read legacy MBR from block 0 and validate it */ 221 if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)legacymbr) != 1) 222 || (is_pmbr_valid(legacymbr) != 1)) { 223 return -1; 224 } 225 return 0; 226 } 227 228 /** 229 * set_protective_mbr(): Set the EFI protective MBR 230 * @param dev_desc - block device descriptor 231 * 232 * @return - zero on success, otherwise error 233 */ 234 static int set_protective_mbr(block_dev_desc_t *dev_desc) 235 { 236 legacy_mbr *p_mbr; 237 238 /* Setup the Protective MBR */ 239 p_mbr = calloc(1, sizeof(p_mbr)); 240 if (p_mbr == NULL) { 241 printf("%s: calloc failed!\n", __func__); 242 return -1; 243 } 244 /* Append signature */ 245 p_mbr->signature = MSDOS_MBR_SIGNATURE; 246 p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT; 247 p_mbr->partition_record[0].start_sect = 1; 248 p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba; 249 250 /* Write MBR sector to the MMC device */ 251 if (dev_desc->block_write(dev_desc->dev, 0, 1, p_mbr) != 1) { 252 printf("** Can't write to device %d **\n", 253 dev_desc->dev); 254 free(p_mbr); 255 return -1; 256 } 257 258 free(p_mbr); 259 return 0; 260 } 261 262 /** 263 * string_uuid(); Convert UUID stored as string to bytes 264 * 265 * @param uuid - UUID represented as string 266 * @param dst - GUID buffer 267 * 268 * @return return 0 on successful conversion 269 */ 270 static int string_uuid(char *uuid, u8 *dst) 271 { 272 efi_guid_t guid; 273 u16 b, c, d; 274 u64 e; 275 u32 a; 276 u8 *p; 277 u8 i; 278 279 const u8 uuid_str_len = 36; 280 281 /* The UUID is written in text: */ 282 /* 1 9 14 19 24 */ 283 /* xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */ 284 285 debug("%s: uuid: %s\n", __func__, uuid); 286 287 if (strlen(uuid) != uuid_str_len) 288 return -1; 289 290 for (i = 0; i < uuid_str_len; i++) { 291 if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) { 292 if (uuid[i] != '-') 293 return -1; 294 } else { 295 if (!isxdigit(uuid[i])) 296 return -1; 297 } 298 } 299 300 a = (u32)simple_strtoul(uuid, NULL, 16); 301 b = (u16)simple_strtoul(uuid + 9, NULL, 16); 302 c = (u16)simple_strtoul(uuid + 14, NULL, 16); 303 d = (u16)simple_strtoul(uuid + 19, NULL, 16); 304 e = (u64)simple_strtoull(uuid + 24, NULL, 16); 305 306 p = (u8 *) &e; 307 guid = EFI_GUID(a, b, c, d >> 8, d & 0xFF, 308 *(p + 5), *(p + 4), *(p + 3), 309 *(p + 2), *(p + 1) , *p); 310 311 memcpy(dst, guid.b, sizeof(efi_guid_t)); 312 313 return 0; 314 } 315 316 int write_gpt_table(block_dev_desc_t *dev_desc, 317 gpt_header *gpt_h, gpt_entry *gpt_e) 318 { 319 const int pte_blk_num = (gpt_h->num_partition_entries 320 * sizeof(gpt_entry)) / dev_desc->blksz; 321 322 u32 calc_crc32; 323 u64 val; 324 325 debug("max lba: %x\n", (u32) dev_desc->lba); 326 /* Setup the Protective MBR */ 327 if (set_protective_mbr(dev_desc) < 0) 328 goto err; 329 330 /* Generate CRC for the Primary GPT Header */ 331 calc_crc32 = efi_crc32((const unsigned char *)gpt_e, 332 le32_to_cpu(gpt_h->num_partition_entries) * 333 le32_to_cpu(gpt_h->sizeof_partition_entry)); 334 gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32); 335 336 calc_crc32 = efi_crc32((const unsigned char *)gpt_h, 337 le32_to_cpu(gpt_h->header_size)); 338 gpt_h->header_crc32 = cpu_to_le32(calc_crc32); 339 340 /* Write the First GPT to the block right after the Legacy MBR */ 341 if (dev_desc->block_write(dev_desc->dev, 1, 1, gpt_h) != 1) 342 goto err; 343 344 if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_num, gpt_e) 345 != pte_blk_num) 346 goto err; 347 348 /* recalculate the values for the Second GPT Header */ 349 val = le64_to_cpu(gpt_h->my_lba); 350 gpt_h->my_lba = gpt_h->alternate_lba; 351 gpt_h->alternate_lba = cpu_to_le64(val); 352 gpt_h->header_crc32 = 0; 353 354 calc_crc32 = efi_crc32((const unsigned char *)gpt_h, 355 le32_to_cpu(gpt_h->header_size)); 356 gpt_h->header_crc32 = cpu_to_le32(calc_crc32); 357 358 if (dev_desc->block_write(dev_desc->dev, 359 le32_to_cpu(gpt_h->last_usable_lba + 1), 360 pte_blk_num, gpt_e) != pte_blk_num) 361 goto err; 362 363 if (dev_desc->block_write(dev_desc->dev, 364 le32_to_cpu(gpt_h->my_lba), 1, gpt_h) != 1) 365 goto err; 366 367 debug("GPT successfully written to block device!\n"); 368 return 0; 369 370 err: 371 printf("** Can't write to device %d **\n", dev_desc->dev); 372 return -1; 373 } 374 375 int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, 376 disk_partition_t *partitions, int parts) 377 { 378 u32 offset = (u32)le32_to_cpu(gpt_h->first_usable_lba); 379 ulong start; 380 int i, k; 381 size_t name_len; 382 #ifdef CONFIG_PARTITION_UUIDS 383 char *str_uuid; 384 #endif 385 386 for (i = 0; i < parts; i++) { 387 /* partition starting lba */ 388 start = partitions[i].start; 389 if (start && (start < offset)) { 390 printf("Partition overlap\n"); 391 return -1; 392 } 393 if (start) { 394 gpt_e[i].starting_lba = cpu_to_le64(start); 395 offset = start + partitions[i].size; 396 } else { 397 gpt_e[i].starting_lba = cpu_to_le64(offset); 398 offset += partitions[i].size; 399 } 400 if (offset >= gpt_h->last_usable_lba) { 401 printf("Partitions layout exceds disk size\n"); 402 return -1; 403 } 404 /* partition ending lba */ 405 if ((i == parts - 1) && (partitions[i].size == 0)) 406 /* extend the last partition to maximuim */ 407 gpt_e[i].ending_lba = gpt_h->last_usable_lba; 408 else 409 gpt_e[i].ending_lba = cpu_to_le64(offset - 1); 410 411 /* partition type GUID */ 412 memcpy(gpt_e[i].partition_type_guid.b, 413 &PARTITION_BASIC_DATA_GUID, 16); 414 415 #ifdef CONFIG_PARTITION_UUIDS 416 str_uuid = partitions[i].uuid; 417 if (string_uuid(str_uuid, gpt_e[i].unique_partition_guid.b)) { 418 printf("Partition no. %d: invalid guid: %s\n", 419 i, str_uuid); 420 return -1; 421 } 422 #endif 423 424 /* partition attributes */ 425 memset(&gpt_e[i].attributes, 0, 426 sizeof(gpt_entry_attributes)); 427 428 /* partition name */ 429 name_len = sizeof(gpt_e[i].partition_name) 430 / sizeof(efi_char16_t); 431 for (k = 0; k < name_len; k++) 432 gpt_e[i].partition_name[k] = 433 (efi_char16_t)(partitions[i].name[k]); 434 435 debug("%s: name: %s offset[%d]: 0x%x size[%d]: 0x%lx\n", 436 __func__, partitions[i].name, i, 437 offset, i, partitions[i].size); 438 } 439 440 return 0; 441 } 442 443 int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h, 444 char *str_guid, int parts_count) 445 { 446 gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE); 447 gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1); 448 gpt_h->header_size = cpu_to_le32(sizeof(gpt_header)); 449 gpt_h->my_lba = cpu_to_le64(1); 450 gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1); 451 gpt_h->first_usable_lba = cpu_to_le64(34); 452 gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34); 453 gpt_h->partition_entry_lba = cpu_to_le64(2); 454 gpt_h->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS); 455 gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry)); 456 gpt_h->header_crc32 = 0; 457 gpt_h->partition_entry_array_crc32 = 0; 458 459 if (string_uuid(str_guid, gpt_h->disk_guid.b)) 460 return -1; 461 462 return 0; 463 } 464 465 int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid, 466 disk_partition_t *partitions, int parts_count) 467 { 468 int ret; 469 470 gpt_header *gpt_h = calloc(1, sizeof(gpt_header)); 471 if (gpt_h == NULL) { 472 printf("%s: calloc failed!\n", __func__); 473 return -1; 474 } 475 476 gpt_entry *gpt_e = calloc(GPT_ENTRY_NUMBERS, sizeof(gpt_entry)); 477 if (gpt_e == NULL) { 478 printf("%s: calloc failed!\n", __func__); 479 free(gpt_h); 480 return -1; 481 } 482 483 /* Generate Primary GPT header (LBA1) */ 484 ret = gpt_fill_header(dev_desc, gpt_h, str_disk_guid, parts_count); 485 if (ret) 486 goto err; 487 488 /* Generate partition entries */ 489 ret = gpt_fill_pte(gpt_h, gpt_e, partitions, parts_count); 490 if (ret) 491 goto err; 492 493 /* Write GPT partition table */ 494 ret = write_gpt_table(dev_desc, gpt_h, gpt_e); 495 496 err: 497 free(gpt_e); 498 free(gpt_h); 499 return ret; 500 } 501 #endif 502 503 /* 504 * Private functions 505 */ 506 /* 507 * pmbr_part_valid(): Check for EFI partition signature 508 * 509 * Returns: 1 if EFI GPT partition type is found. 510 */ 511 static int pmbr_part_valid(struct partition *part) 512 { 513 if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT && 514 le32_to_cpu(part->start_sect) == 1UL) { 515 return 1; 516 } 517 518 return 0; 519 } 520 521 /* 522 * is_pmbr_valid(): test Protective MBR for validity 523 * 524 * Returns: 1 if PMBR is valid, 0 otherwise. 525 * Validity depends on two things: 526 * 1) MSDOS signature is in the last two bytes of the MBR 527 * 2) One partition of type 0xEE is found, checked by pmbr_part_valid() 528 */ 529 static int is_pmbr_valid(legacy_mbr * mbr) 530 { 531 int i = 0; 532 533 if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) 534 return 0; 535 536 for (i = 0; i < 4; i++) { 537 if (pmbr_part_valid(&mbr->partition_record[i])) { 538 return 1; 539 } 540 } 541 return 0; 542 } 543 544 /** 545 * is_gpt_valid() - tests one GPT header and PTEs for validity 546 * 547 * lba is the logical block address of the GPT header to test 548 * gpt is a GPT header ptr, filled on return. 549 * ptes is a PTEs ptr, filled on return. 550 * 551 * Description: returns 1 if valid, 0 on error. 552 * If valid, returns pointers to PTEs. 553 */ 554 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba, 555 gpt_header * pgpt_head, gpt_entry ** pgpt_pte) 556 { 557 u32 crc32_backup = 0; 558 u32 calc_crc32; 559 unsigned long long lastlba; 560 561 if (!dev_desc || !pgpt_head) { 562 printf("%s: Invalid Argument(s)\n", __func__); 563 return 0; 564 } 565 566 /* Read GPT Header from device */ 567 if (dev_desc->block_read(dev_desc->dev, lba, 1, pgpt_head) != 1) { 568 printf("*** ERROR: Can't read GPT header ***\n"); 569 return 0; 570 } 571 572 /* Check the GPT header signature */ 573 if (le64_to_cpu(pgpt_head->signature) != GPT_HEADER_SIGNATURE) { 574 printf("GUID Partition Table Header signature is wrong:" 575 "0x%llX != 0x%llX\n", 576 le64_to_cpu(pgpt_head->signature), 577 GPT_HEADER_SIGNATURE); 578 return 0; 579 } 580 581 /* Check the GUID Partition Table CRC */ 582 memcpy(&crc32_backup, &pgpt_head->header_crc32, sizeof(crc32_backup)); 583 memset(&pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32)); 584 585 calc_crc32 = efi_crc32((const unsigned char *)pgpt_head, 586 le32_to_cpu(pgpt_head->header_size)); 587 588 memcpy(&pgpt_head->header_crc32, &crc32_backup, sizeof(crc32_backup)); 589 590 if (calc_crc32 != le32_to_cpu(crc32_backup)) { 591 printf("GUID Partition Table Header CRC is wrong:" 592 "0x%x != 0x%x\n", 593 le32_to_cpu(crc32_backup), calc_crc32); 594 return 0; 595 } 596 597 /* Check that the my_lba entry points to the LBA that contains the GPT */ 598 if (le64_to_cpu(pgpt_head->my_lba) != lba) { 599 printf("GPT: my_lba incorrect: %llX != %llX\n", 600 le64_to_cpu(pgpt_head->my_lba), 601 lba); 602 return 0; 603 } 604 605 /* Check the first_usable_lba and last_usable_lba are within the disk. */ 606 lastlba = (unsigned long long)dev_desc->lba; 607 if (le64_to_cpu(pgpt_head->first_usable_lba) > lastlba) { 608 printf("GPT: first_usable_lba incorrect: %llX > %llX\n", 609 le64_to_cpu(pgpt_head->first_usable_lba), lastlba); 610 return 0; 611 } 612 if (le64_to_cpu(pgpt_head->last_usable_lba) > lastlba) { 613 printf("GPT: last_usable_lba incorrect: %llX > %llX\n", 614 (u64) le64_to_cpu(pgpt_head->last_usable_lba), lastlba); 615 return 0; 616 } 617 618 debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n", 619 le64_to_cpu(pgpt_head->first_usable_lba), 620 le64_to_cpu(pgpt_head->last_usable_lba), lastlba); 621 622 /* Read and allocate Partition Table Entries */ 623 *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head); 624 if (*pgpt_pte == NULL) { 625 printf("GPT: Failed to allocate memory for PTE\n"); 626 return 0; 627 } 628 629 /* Check the GUID Partition Table Entry Array CRC */ 630 calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte, 631 le32_to_cpu(pgpt_head->num_partition_entries) * 632 le32_to_cpu(pgpt_head->sizeof_partition_entry)); 633 634 if (calc_crc32 != le32_to_cpu(pgpt_head->partition_entry_array_crc32)) { 635 printf("GUID Partition Table Entry Array CRC is wrong:" 636 "0x%x != 0x%x\n", 637 le32_to_cpu(pgpt_head->partition_entry_array_crc32), 638 calc_crc32); 639 640 free(*pgpt_pte); 641 return 0; 642 } 643 644 /* We're done, all's well */ 645 return 1; 646 } 647 648 /** 649 * alloc_read_gpt_entries(): reads partition entries from disk 650 * @dev_desc 651 * @gpt - GPT header 652 * 653 * Description: Returns ptes on success, NULL on error. 654 * Allocates space for PTEs based on information found in @gpt. 655 * Notes: remember to free pte when you're done! 656 */ 657 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, 658 gpt_header * pgpt_head) 659 { 660 size_t count = 0; 661 gpt_entry *pte = NULL; 662 663 if (!dev_desc || !pgpt_head) { 664 printf("%s: Invalid Argument(s)\n", __func__); 665 return NULL; 666 } 667 668 count = le32_to_cpu(pgpt_head->num_partition_entries) * 669 le32_to_cpu(pgpt_head->sizeof_partition_entry); 670 671 debug("%s: count = %u * %u = %zu\n", __func__, 672 (u32) le32_to_cpu(pgpt_head->num_partition_entries), 673 (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry), count); 674 675 /* Allocate memory for PTE, remember to FREE */ 676 if (count != 0) { 677 pte = memalign(ARCH_DMA_MINALIGN, count); 678 } 679 680 if (count == 0 || pte == NULL) { 681 printf("%s: ERROR: Can't allocate 0x%zX " 682 "bytes for GPT Entries\n", 683 __func__, count); 684 return NULL; 685 } 686 687 /* Read GPT Entries from device */ 688 if (dev_desc->block_read (dev_desc->dev, 689 le64_to_cpu(pgpt_head->partition_entry_lba), 690 (lbaint_t) (count / GPT_BLOCK_SIZE), pte) 691 != (count / GPT_BLOCK_SIZE)) { 692 693 printf("*** ERROR: Can't read GPT Entries ***\n"); 694 free(pte); 695 return NULL; 696 } 697 return pte; 698 } 699 700 /** 701 * is_pte_valid(): validates a single Partition Table Entry 702 * @gpt_entry - Pointer to a single Partition Table Entry 703 * 704 * Description: returns 1 if valid, 0 on error. 705 */ 706 static int is_pte_valid(gpt_entry * pte) 707 { 708 efi_guid_t unused_guid; 709 710 if (!pte) { 711 printf("%s: Invalid Argument(s)\n", __func__); 712 return 0; 713 } 714 715 /* Only one validation for now: 716 * The GUID Partition Type != Unused Entry (ALL-ZERO) 717 */ 718 memset(unused_guid.b, 0, sizeof(unused_guid.b)); 719 720 if (memcmp(pte->partition_type_guid.b, unused_guid.b, 721 sizeof(unused_guid.b)) == 0) { 722 723 debug("%s: Found an unused PTE GUID at 0x%08X\n", __func__, 724 (unsigned int)(uintptr_t)pte); 725 726 return 0; 727 } else { 728 return 1; 729 } 730 } 731 #endif 732